fixes
[kugel-rb.git] / tools / sh2d.c
blob0fcf8b1f6b98748c860908f5969913ca24c97784
1 /*
2 * sh2d
3 * Bart Trzynadlowski, July 24, 2000
4 * Public domain
6 * Some changes by Björn Stenberg <bjorn@haxx.se>
7 * $Id$
8 */
11 #include <stdint.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
16 #define VERSION "0.2"
18 #define ZERO_F 0 /* 0 format */
19 #define N_F 1 /* n format */
20 #define M_F 2 /* m format */
21 #define NM_F 3 /* nm format */
22 #define MD_F 4 /* md format */
23 #define ND4_F 5 /* nd4 format */
24 #define NMD_F 6 /* nmd format */
25 #define D_F 7 /* d format */
26 #define D12_F 8 /* d12 format */
27 #define ND8_F 9 /* nd8 format */
28 #define I_F 10 /* i format */
29 #define NI_F 11 /* ni format */
31 typedef struct
33 int format;
34 const char *mnem;
35 unsigned short mask; /* mask used to obtain opcode bits */
36 unsigned short bits; /* opcode bits */
37 int dat; /* specific data for situation */
38 int sh2; /* SH-2 specific */
39 } i_descr;
41 /* register name lookup added by bjorn@haxx.se 2001-12-09 */
42 char* regname[] =
44 /* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
45 "","","","","","","","","","","","","","","","", /* 0 */
46 "","","","","","","","","","","","","","","","", /* 10 */
47 "","","","","","","","","","","","","","","","", /* 20 */
48 "","","","","","","","","","","","","","","","", /* 30 */
49 "","","","","","","","","","","","","","","","", /* 40 */
50 "","","","","","","","","","","","","","","","", /* 50 */
51 "","","","","","","","","","","","","","","","", /* 60 */
52 "","","","","","","","","","","","","","","","", /* 70 */
53 "","","","","","","","","","","","","","","","", /* 80 */
54 "","","","","","","","","","","","","","","","", /* 90 */
55 "","","","","","","","","","","","","","","","", /* a0 */
56 "","","","","","","","","","","","","","","","", /* b0 */
58 "SMR0","BRR0","SCR0","TDR0","SSR0","RDR0","","", /* c0 */
59 "SMR1","BRR1","SCR1","TDR1","SSR1","RDR1","","", /* c8 */
60 "","","","","","","","","","","","","","","","", /* d0 */
61 "ADDRAH","ADDRAL","ADDRBH","ADDRBL", /* e0 */
62 "ADDRCH","ADDRCL","ADDRDH","ADDRDL", /* e4 */
63 "ADCSR","ADCR","","","","","","", /* e8 */
64 "","","","","","","","","","","","","","","","", /* f0 */
65 "TSTR","TSNC","TMDR","TFCR","TCR0","TIOR0","TIER0","TSR0", /* 100 */
66 "TCNT0","!","GRA0","!","GRB0","!","TCR1","TIORL", /* 108 */
67 "TIERI","TSR1","TCNT1","!","GRA1","!","GRB1","!", /* 110 */
68 "TCR2","TIOR2","TIER2","TSR2","TCNT2","!","GRA2","!", /* 118 */
69 "GRB2","!","TCR3","TIOR3","TIER3","TSR3","TCNT3","!", /* 120 */
70 "GRA3","!","GRB3","!","BRA3","!","BRB3","!", /* 128 */
71 "","TOCR","TCR4","TIOR4","TIER4","TSR4","TCNT4","!", /* 130 */
72 "GRA4","!","GRB4","!","BRA4","!","BRB4","!", /* 138 */
73 "SAR0","!","!","!","DAR0","!","!","!", /* 140 */
74 "DMAOR","!","TCR0","!","","","CHCR0","!", /* 148 */
75 "SAR1","!","!","!","DAR1","!","!","!", /* 150 */
76 "","","TCR1","!","","","CHCR1","!", /* 158 */
77 "SAR2","!","!","!","DAR2","!","!","!", /* 160 */
78 "","","TCR2","!","","","CHCR2","!", /* 168 */
79 "SAR3","!","!","!","DAR3","!","!","!", /* 170 */
80 "","","TCR3","!","","","CHCR3","!", /* 178 */
81 "","","","","IPRA","!","IPRB","!", /* 180 */
82 "IPRC","!","IPRD","!","IPRE","!","ICR","!", /* 188 */
83 "BARH","!","BARL","!","BAMRH","!","BAMRL","!", /* 190 */
84 "BBR","!","","","","","","", /* 198 */
85 "BCR","!","WCR1","!","WCR2","!","WCR3","!", /* 1a0 */
86 "DCR","!","PCR","!","RCR","!","RTCSR","!", /* 1a8 */
87 "RTCNT","!","RTCOR","!","","","","", /* 1b0 */
88 "TCSR","TCNT","","RSTCSR","SBYCR","","","", /* 1b8 */
89 "PADR","!","PBDR","!","PAIOR","!","PBIOR","!", /* 1c0 */
90 "PACR1","!","PACR2","!","PBCR1","!","PBCR2","!", /* 1c8 */
91 "PCDR","!","","","","","","","","","","","","","","", /* 1d0 */
92 "","","","","","","","","","","","","","","CASCR","!", /* 1e0 */
93 "TPMR","TPCR","NDERB","NDERA","NDRB","NDRA","NDRB","NDRA", /* 1f0 */
94 "","","","","","","",""
97 i_descr tab[] =
99 { ZERO_F, "clrt", 0xffff, 0x8, 0, 0 },
100 { ZERO_F, "clrmac", 0xffff, 0x28, 0, 0 },
101 { ZERO_F, "div0u", 0xffff, 0x19, 0, 0 },
102 { ZERO_F, "nop", 0xffff, 0x9, 0, 0 },
103 { ZERO_F, "rte", 0xffff, 0x2b, 0, 0 },
104 { ZERO_F, "rts", 0xffff, 0xb, 0, 0 },
105 { ZERO_F, "sett", 0xffff, 0x18, 0, 0 },
106 { ZERO_F, "sleep", 0xffff, 0x1b, 0, 0 },
107 { N_F, "cmp/pl\tr%d", 0xf0ff, 0x4015, 0, 0 },
108 { N_F, "cmp/pz\tr%d", 0xf0ff, 0x4011, 0, 0 },
109 { N_F, "dt\tr%d", 0xf0ff, 0x4010, 0, 1 },
110 { N_F, "movt\tr%d", 0xf0ff, 0x0029, 0, 0 },
111 { N_F, "rotl\tr%d", 0xf0ff, 0x4004, 0, 0 },
112 { N_F, "rotr\tr%d", 0xf0ff, 0x4005, 0, 0 },
113 { N_F, "rotcl\tr%d", 0xf0ff, 0x4024, 0, 0 },
114 { N_F, "rotcr\tr%d", 0xf0ff, 0x4025, 0, 0 },
115 { N_F, "shal\tr%d", 0xf0ff, 0x4020, 0, 0 },
116 { N_F, "shar\tr%d", 0xf0ff, 0x4021, 0, 0 },
117 { N_F, "shll\tr%d", 0xf0ff, 0x4000, 0, 0 },
118 { N_F, "shlr\tr%d", 0xf0ff, 0x4001, 0, 0 },
119 { N_F, "shll2\tr%d", 0xf0ff, 0x4008, 0, 0 },
120 { N_F, "shlr2\tr%d", 0xf0ff, 0x4009, 0, 0 },
121 { N_F, "shll8\tr%d", 0xf0ff, 0x4018, 0, 0 },
122 { N_F, "shlr8\tr%d", 0xf0ff, 0x4019, 0, 0 },
123 { N_F, "shll16\tr%d", 0xf0ff, 0x4028, 0, 0 },
124 { N_F, "shlr16\tr%d", 0xf0ff, 0x4029, 0, 0 },
125 { N_F, "stc\tsr,r%d", 0xf0ff, 0x0002, 0, 0 },
126 { N_F, "stc\tgbr,r%d", 0xf0ff, 0x0012, 0, 0 },
127 { N_F, "stc\tvbr,r%d", 0xf0ff, 0x0022, 0, 0 },
128 { N_F, "sts\tmach,r%d", 0xf0ff, 0x000a, 0, 0 },
129 { N_F, "sts\tmacl,r%d", 0xf0ff, 0x001a, 0, 0 },
130 { N_F, "sts\tpr,r%d", 0xf0ff, 0x002a, 0, 0 },
131 { N_F, "tas.b\t@r%d", 0xf0ff, 0x401b, 0, 0 },
132 { N_F, "stc.l\tsr,@-r%d", 0xf0ff, 0x4003, 0, 0 },
133 { N_F, "stc.l\tgbr,@-r%d", 0xf0ff, 0x4013, 0, 0 },
134 { N_F, "stc.l\tvbr,@-r%d", 0xf0ff, 0x4023, 0, 0 },
135 { N_F, "sts.l\tmach,@-r%d", 0xf0ff, 0x4002, 0, 0 },
136 { N_F, "sts.l\tmacl,@-r%d", 0xf0ff, 0x4012, 0, 0 },
137 { N_F, "sts.l\tpr,@-r%d", 0xf0ff, 0x4022, 0, 0 },
138 { M_F, "ldc\tr%d,sr", 0xf0ff, 0x400e, 0, 0 },
139 { M_F, "ldc\tr%d,gbr", 0xf0ff, 0x401e, 0, 0 },
140 { M_F, "ldc\tr%d,vbr", 0xf0ff, 0x402e, 0, 0 },
141 { M_F, "lds\tr%d,mach", 0xf0ff, 0x400a, 0, 0 },
142 { M_F, "lds\tr%d,macl", 0xf0ff, 0x401a, 0, 0 },
143 { M_F, "lds\tr%d,pr", 0xf0ff, 0x402a, 0, 0 },
144 { M_F, "jmp\t@r%d", 0xf0ff, 0x402b, 0, 0 },
145 { M_F, "jsr\t@r%d", 0xf0ff, 0x400b, 0, 0 },
146 { M_F, "ldc.l\t@r%d+,sr", 0xf0ff, 0x4007, 0, 0 },
147 { M_F, "ldc.l\t@r%d+,gbr", 0xf0ff, 0x4017, 0, 0 },
148 { M_F, "ldc.l\t@r%d+,vbr", 0xf0ff, 0x4027, 0, 0 },
149 { M_F, "lds.l\t@r%d+,mach", 0xf0ff, 0x4006, 0, 0 },
150 { M_F, "lds.l\t@r%d+,macl", 0xf0ff, 0x4016, 0, 0 },
151 { M_F, "lds.l\t@r%d+,pr", 0xf0ff, 0x4026, 0, 0 },
152 { M_F, "braf\tr%d", 0xf0ff, 0x0023, 0, 1 },
153 { M_F, "bsrf\tr%d", 0xf0ff, 0x0003, 0, 1 },
154 { NM_F, "add\tr%d,r%d", 0xf00f, 0x300c, 0, 0 },
155 { NM_F, "addc\tr%d,r%d", 0xf00f, 0x300e, 0, 0 },
156 { NM_F, "addv\tr%d,r%d", 0xf00f, 0x300f, 0, 0 },
157 { NM_F, "and\tr%d,r%d", 0xf00f, 0x2009, 0, 0 },
158 { NM_F, "cmp/eq\tr%d,r%d", 0xf00f, 0x3000, 0, 0 },
159 { NM_F, "cmp/hs\tr%d,r%d", 0xf00f, 0x3002, 0, 0 },
160 { NM_F, "cmp/ge\tr%d,r%d", 0xf00f, 0x3003, 0, 0 },
161 { NM_F, "cmp/hi\tr%d,r%d", 0xf00f, 0x3006, 0, 0 },
162 { NM_F, "cmp/gt\tr%d,r%d", 0xf00f, 0x3007, 0, 0 },
163 { NM_F, "cmp/str\tr%d,r%d", 0xf00f, 0x200c, 0, 0 },
164 { NM_F, "div1\tr%d,r%d", 0xf00f, 0x3004, 0, 0 },
165 { NM_F, "div0s\tr%d,r%d", 0xf00f, 0x2007, 0, 0 },
166 { NM_F, "dmuls.l\tr%d,r%d", 0xf00f, 0x300d, 0, 1 },
167 { NM_F, "dmulu.l\tr%d,r%d", 0xf00f, 0x3005, 0, 1 },
168 { NM_F, "exts.b\tr%d,r%d", 0xf00f, 0x600e, 0, 0 },
169 { NM_F, "exts.w\tr%d,r%d", 0xf00f, 0x600f, 0, 0 },
170 { NM_F, "extu.b\tr%d,r%d", 0xf00f, 0x600c, 0, 0 },
171 { NM_F, "extu.w\tr%d,r%d", 0xf00f, 0x600d, 0, 0 },
172 { NM_F, "mov\tr%d,r%d", 0xf00f, 0x6003, 0, 0 },
173 { NM_F, "mul.l\tr%d,r%d", 0xf00f, 0x0007, 0, 1 },
174 { NM_F, "muls.w\tr%d,r%d", 0xf00f, 0x200f, 0, 0 },
175 { NM_F, "mulu.w\tr%d,r%d", 0xf00f, 0x200e, 0, 0 },
176 { NM_F, "neg\tr%d,r%d", 0xf00f, 0x600b, 0, 0 },
177 { NM_F, "negc\tr%d,r%d", 0xf00f, 0x600a, 0, 0 },
178 { NM_F, "not\tr%d,r%d", 0xf00f, 0x6007, 0, 0 },
179 { NM_F, "or\tr%d,r%d", 0xf00f, 0x200b, 0, 0 },
180 { NM_F, "sub\tr%d,r%d", 0xf00f, 0x3008, 0, 0 },
181 { NM_F, "subc\tr%d,r%d", 0xf00f, 0x300a, 0, 0 },
182 { NM_F, "subv\tr%d,r%d", 0xf00f, 0x300b, 0, 0 },
183 { NM_F, "swap.b\tr%d,r%d", 0xf00f, 0x6008, 0, 0 },
184 { NM_F, "swap.w\tr%d,r%d", 0xf00f, 0x6009, 0, 0 },
185 { NM_F, "tst\tr%d,r%d", 0xf00f, 0x2008, 0, 0 },
186 { NM_F, "xor\tr%d,r%d", 0xf00f, 0x200a, 0, 0 },
187 { NM_F, "xtrct\tr%d,r%d", 0xf00f, 0x200d, 0, 0 },
188 { NM_F, "mov.b\tr%d,@r%d", 0xf00f, 0x2000, 0, 0 },
189 { NM_F, "mov.w\tr%d,@r%d", 0xf00f, 0x2001, 0, 0 },
190 { NM_F, "mov.l\tr%d,@r%d", 0xf00f, 0x2002, 0, 0 },
191 { NM_F, "mov.b\t@r%d,r%d", 0xf00f, 0x6000, 0, 0 },
192 { NM_F, "mov.w\t@r%d,r%d", 0xf00f, 0x6001, 0, 0 },
193 { NM_F, "mov.l\t@r%d,r%d", 0xf00f, 0x6002, 0, 0 },
194 { NM_F, "mac.l\t@r%d+,@r%d+", 0xf00f, 0x000f, 0, 1 },
195 { NM_F, "mac.w\t@r%d+,@r%d+", 0xf00f, 0x400f, 0, 0 },
196 { NM_F, "mov.b\t@r%d+,r%d", 0xf00f, 0x6004, 0, 0 },
197 { NM_F, "mov.w\t@r%d+,r%d", 0xf00f, 0x6005, 0, 0 },
198 { NM_F, "mov.l\t@r%d+,r%d", 0xf00f, 0x6006, 0, 0 },
199 { NM_F, "mov.b\tr%d,@-r%d", 0xf00f, 0x2004, 0, 0 },
200 { NM_F, "mov.w\tr%d,@-r%d", 0xf00f, 0x2005, 0, 0 },
201 { NM_F, "mov.l\tr%d,@-r%d", 0xf00f, 0x2006, 0, 0 },
202 { NM_F, "mov.b\tr%d,@(r0,r%d)", 0xf00f, 0x0004, 0, 0 },
203 { NM_F, "mov.w\tr%d,@(r0,r%d)", 0xf00f, 0x0005, 0, 0 },
204 { NM_F, "mov.l\tr%d,@(r0,r%d)", 0xf00f, 0x0006, 0, 0 },
205 { NM_F, "mov.b\t@(r0,r%d),r%d", 0xf00f, 0x000c, 0, 0 },
206 { NM_F, "mov.w\t@(r0,r%d),r%d", 0xf00f, 0x000d, 0, 0 },
207 { NM_F, "mov.l\t@(r0,r%d),r%d", 0xf00f, 0x000e, 0, 0 },
208 { MD_F, "mov.b\t@(0x%03X,r%d), r0", 0xff00, 0x8400, 0, 0 },
209 { MD_F, "mov.w\t@(0x%03X,r%d), r0", 0xff00, 0x8500, 0, 0 },
210 { ND4_F, "mov.b\tr0,@(0x%03X,r%d)", 0xff00, 0x8000, 0, 0 },
211 { ND4_F, "mov.w\tr0,@(0x%03X,r%d)", 0xff00, 0x8100, 0, 0 },
212 { NMD_F, "mov.l\tr%d,@(0x%03X,r%d)", 0xf000, 0x1000, 0,0 },
213 { NMD_F, "mov.l\t@(0x%03X,r%d),r%d", 0xf000, 0x5000, 0,0 },
214 { D_F, "mov.b\tr0,@(0x%03X,gbr)", 0xff00, 0xc000, 1, 0 },
215 { D_F, "mov.w\tr0,@(0x%03X,gbr)", 0xff00, 0xc100, 2, 0 },
216 { D_F, "mov.l\tr0,@(0x%03X,gbr)", 0xff00, 0xc200, 4, 0 },
217 { D_F, "mov.b\t@(0x%03X,gbr),r0", 0xff00, 0xc400, 1, 0 },
218 { D_F, "mov.w\t@(0x%03X,gbr),r0", 0xff00, 0xc500, 2, 0 },
219 { D_F, "mov.l\t@(0x%03X,gbr),r0", 0xff00, 0xc600, 4, 0 },
220 { D_F, "mova\t@(0x%03X,pc),r0", 0xff00, 0xc700, 4, 0 },
221 { D_F, "bf\t0x%08X", 0xff00, 0x8b00, 5, 0 },
222 { D_F, "bf/s\t0x%08X", 0xff00, 0x8f00, 5, 1 },
223 { D_F, "bt\t0x%08X", 0xff00, 0x8900, 5, 0 },
224 { D_F, "bt/s\t0x%08X", 0xff00, 0x8d00, 5, 1 },
225 { D12_F, "bra\t0x%08X", 0xf000, 0xa000, 0, 0 },
226 { D12_F, "bsr\t0x%08X", 0xf000, 0xb000, 0, 0 },
227 { ND8_F, "mov.w\t@(0x%03X,pc),r%d", 0xf000, 0x9000, 2, 0 },
228 { ND8_F, "mov.l\t@(0x%03X,pc),r%d", 0xf000, 0xd000, 4, 0 },
229 { I_F, "and.b\t#0x%02X,@(r0,gbr)", 0xff00, 0xcd00, 0,0 },
230 { I_F, "or.b\t#0x%02X,@(r0,gbr)", 0xff00, 0xcf00, 0,0 },
231 { I_F, "tst.b\t#0x%02X,@(r0,gbr)", 0xff00, 0xcc00, 0,0 },
232 { I_F, "xor.b\t#0x%02X,@(r0,gbr)", 0xff00, 0xce00, 0,0 },
233 { I_F, "and\t#0x%02X,r0", 0xff00, 0xc900, 0, 0 },
234 { I_F, "cmp/eq\t#0x%02X,r0", 0xff00, 0x8800, 0, 0 },
235 { I_F, "or\t#0x%02X,r0", 0xff00, 0xcb00, 0, 0 },
236 { I_F, "tst\t#0x%02X,r0", 0xff00, 0xc800, 0, 0 },
237 { I_F, "xor\t#0x%02X,r0", 0xff00, 0xca00, 0, 0 },
238 { I_F, "trapa\t#0x%X", 0xff00, 0xc300, 0, 0 },
239 { NI_F, "add\t#0x%02X,r%d", 0xf000, 0x7000, 0, 0 },
240 { NI_F, "mov\t#0x%02X,r%d", 0xf000, 0xe000, 0, 0 },
241 { 0, NULL, 0, 0, 0, 0 }
245 int FindOption(char *option, int p, int h, int u, int argc, char **argv)
247 static int t[] = { 0, 0, 0, 0, 0, 0, 0, 0,
248 0, 0, 0, 0, 0, 0, 0, 0,
249 0, 0, 0, 0, 0, 0, 0, 0,
250 0, 0, 0, 0, 0, 0, 0, 0,
251 0, 0, 0, 0, 0, 0, 0, 0,
252 0, 0, 0, 0, 0, 0, 0, 0,
253 0, 0, 0, 0, 0, 0, 0, 0,
254 0, 0, 0, 0, 0, 0, 0, 0,
255 0, 0, 0, 0, 0, 0, 0, 0,
256 0, 0, 0, 0, 0, 0, 0, 0,
257 0, 0, 0, 0, 0, 0, 0, 0,
258 0, 0, 0, 0, 0, 0, 0, 0,
259 0, 0, 0, 0, 0, 0, 0, 0,
260 0, 0, 0, 0, 0, 0, 0, 0,
261 0, 0, 0, 0, 0, 0, 0, 0,
262 0, 0, 0, 0, 0, 0, 0, 0 };
263 int i;
264 char *c;
266 if (argc > 128)
267 argc = 128; /* maximum this function can handle is 128 */
270 * if p = 1 and h = 0 will find option and return decimal value of
271 * argv[i+1], if h = 1 will read it as hex.
272 * if p = 0 then it will return index of option in argv[], 0 not found
273 * if u = 1 will return index of first occurance of untouched option
276 if (u) /* find first untouched element */
278 for (i = 1; i < argc; i++)
280 if (!t[i]) /* 0 indicates untouched */
281 return i;
283 return 0;
286 if (p) /* find option and return integer value following it */
288 for (i = 1; i < argc; i++)
290 if (strcmp(argv[i], option) == 0) /* found */
292 if (i >= argc) /* bounds! */
293 return 0;
294 t[i + 1] = t[i] = 1; /* touched */
295 if (!h)
296 return atoi(argv[i + 1]);
297 else
298 return strtoul(argv[i + 1], &c, 16);
301 return 0; /* no match */
303 else /* find option and return position */
305 for (i = 1; i < argc; i++)
307 if (strcmp(argv[i], option) == 0)
309 t[i] = 1;
310 return i; /* found! return position */
313 return 0;
318 * SH2Disasm(): SH-1/SH-2 disassembler routine. If mode = 0 then SH-2 mode,
319 * otherwise SH-1 mode
322 void SH2Disasm(unsigned v_addr, unsigned char *p_addr, int mode, char *m_addr)
324 int i;
325 unsigned short op;
327 op = (unsigned short) (*p_addr << 8) | *(p_addr + 1);
328 printf("0x%08X: 0x%04X\t", v_addr, op);
330 if (m_addr[0]==ND8_F)
332 if (m_addr[2]==-1)
334 unsigned int tmp = (op << 16) | ((unsigned int) (p_addr [2] << 8) | p_addr[3]);
335 printf(".long\t0x%08X\t; 0x%08X",tmp,v_addr - (unsigned)m_addr[1]);
337 else
338 printf(".short\t0x%08X\t; 0x%08X",op,v_addr - (unsigned)m_addr[1]);
340 else if (m_addr[0] != -1)
342 for (i = 0; tab[i].mnem != NULL; i++) /* 0 format */
344 if ((op & tab[i].mask) == tab[i].bits)
346 if (tab[i].sh2 && mode) /* if SH-1 mode, no SH-2 */
347 printf("???");
348 else if (tab[i].format == ZERO_F)
349 printf("%s", tab[i].mnem);
350 else if (tab[i].format == N_F)
351 printf(tab[i].mnem, (op >> 8) & 0xf);
352 else if (tab[i].format == M_F)
353 printf(tab[i].mnem, (op >> 8) & 0xf);
354 else if (tab[i].format == NM_F)
355 printf(tab[i].mnem, (op >> 4) & 0xf,
356 (op >> 8) & 0xf);
357 else if (tab[i].format == MD_F)
359 if (op & 0x100)
360 printf(tab[i].mnem, (op & 0xf) * 2,
361 (op >> 4) & 0xf);
362 else
363 printf(tab[i].mnem, op & 0xf,
364 (op >> 4) & 0xf);
366 else if (tab[i].format == ND4_F)
368 if (op & 0x100)
369 printf(tab[i].mnem, (op & 0xf) * 2,
370 (op >> 4) & 0xf);
371 else
372 printf(tab[i].mnem, (op & 0xf),
373 (op >> 4) & 0xf);
375 else if (tab[i].format == NMD_F)
377 if ((op & 0xf000) == 0x1000)
378 printf(tab[i].mnem, (op >> 4) & 0xf,
379 (op & 0xf) * 4,
380 (op >> 8) & 0xf);
381 else
382 printf(tab[i].mnem, (op & 0xf) * 4,
383 (op >> 4) & 0xf,
384 (op >> 8) & 0xf);
386 else if (tab[i].format == D_F)
388 if (tab[i].dat <= 4)
390 if ((op & 0xff00) == 0xc700)
392 printf(tab[i].mnem,
393 (op & 0xff) *
394 tab[i].dat + 4);
395 printf("\t; 0x%08X",
396 (op & 0xff) *
397 tab[i].dat + 4 +
398 v_addr);
400 else
401 printf(tab[i].mnem,
402 (op & 0xff) *
403 tab[i].dat);
405 else
407 if (op & 0x80) /* sign extend */
408 printf(tab[i].mnem,
409 (((op & 0xff) +
410 0xffffff00) * 2) +
412 v_addr + 4);
413 else
414 printf(tab[i].mnem,
415 ((op & 0xff) * 2) +
416 v_addr + 4);
419 else if (tab[i].format == D12_F)
421 if (op & 0x800) /* sign extend */
422 printf(tab[i].mnem,
423 ((op & 0xfff) + 0xfffff000) * 2
424 + v_addr + 4);
425 else
426 printf(tab[i].mnem, (op & 0xfff) * 2 +
427 v_addr + 4);
429 else if (tab[i].format == ND8_F)
431 int imm = (op & 0xff) * tab[i].dat + 4;
432 if ((op & 0xf000) == 0x9000) /* .W */
434 int dat = (unsigned short) (*(imm + p_addr) << 8) | *(imm + p_addr + 1);
435 m_addr[imm+0] = ND8_F; /* this couldn't be an instruction so mark it ! */
436 m_addr[imm+1] = imm;
437 printf(tab[i].mnem,
438 imm,
439 (op >> 8) & 0xf);
440 printf("\t; 0x%08X (0x%04X)",
441 imm + v_addr, dat);
443 else /* .L */
445 unsigned char *b_addr = (unsigned char *)((intptr_t)p_addr & ~3);
446 int dat = (unsigned int) (*(imm + b_addr) << 24) | (*(imm + b_addr + 1) << 16)
447 | (*(imm + b_addr + 2) << 8) | *(imm + b_addr + 3) ;
448 /* SH-1 register name lookup */
449 char* str = "";
450 if ( (dat & 0xfffffe00) == 0x05fffe00 )
451 str = regname[dat & 0x1ff];
452 m_addr[imm+(b_addr-p_addr)+0] = ND8_F; /* this couldn't be an instruction so mark it ! */
453 m_addr[imm+(b_addr-p_addr)+1] = imm;
454 m_addr[imm+(b_addr-p_addr)+2] = -1;
455 printf(tab[i].mnem,
456 imm,
457 (op >> 8) & 0xf);
458 printf("\t; 0x%08X (0x%08X) %s",
459 imm + (v_addr & 0xfffffffc), dat, str);
462 else if (tab[i].format == I_F)
463 printf(tab[i].mnem, op & 0xff);
464 else if (tab[i].format == NI_F)
465 printf(tab[i].mnem, op & 0xff, (op >> 8) &
466 0xf);
467 else
468 printf("???");
469 printf("\n");
470 return;
474 printf("???");
477 printf("\n");
480 void ShowHelp()
482 printf("sh2d Version %s by Bart Trzynadlowski: A Free SH-1/SH-2 "
483 "Disassembler\n", VERSION);
484 printf("Usage: sh2d <file> [options]\n");
485 printf("Options: -?,-h Show this help text\n");
486 printf(" -s # Start offset (hexadecimal)\n");
487 printf(" -l # Number of bytes (decimal)\n");
488 printf(" -o # Set origin (hexadecimal)\n");
489 printf(" -sh1 SH-1 disassembly only\n");
490 printf(" -sh2 SH-2 disassembly (default)\n");
491 exit(0);
494 int main(int argc, char **argv)
496 FILE *fp;
497 long fsize, file, mode;
498 unsigned start, len, calc_len = 0, org, do_org, i, j = 0;
499 char *buffer;
500 char *mark;
502 if (argc == 1) /* show help */
503 ShowHelp();
504 if (FindOption("-?", 0, 0, 0, argc, argv) ||
505 FindOption("-h", 0, 0, 0, argc, argv))
506 ShowHelp();
508 if (FindOption("-sh1", 0, 0, 0, argc, argv))
509 mode = 1; /* SH-1 mode */
510 else
511 mode = 0; /* SH-2 mode */
512 if (FindOption("-sh2", 0, 0, 0, argc, argv))
513 mode = 0; /* SH-2 mode */
515 start = FindOption("-s", 1, 1, 0, argc, argv);
516 org = FindOption("-o", 1, 1, 0, argc, argv);
517 if (!(len = FindOption("-l", 1, 0, 0, argc, argv)))
519 if (FindOption("-l", 0, 0, 0, argc, argv))
520 return 0; /* -l was actually specified w/ 0 */
521 calc_len = 1; /* no -l, calculate length */
524 if (FindOption("-o", 0, 0, 0, argc, argv))
525 do_org = 1; /* -o was actually 0 */
526 else
527 do_org = 0; /* there was no -o, ignore the org variable */
529 if (!(file = FindOption(NULL, 0, 0, 1, argc, argv)))
531 fprintf(stderr, "sh2d: No input file specified. Try "
532 "\"sh2d -h\" for usage instructions\n");
533 exit(1);
536 if ((fp = fopen(argv[file], "rb")) == NULL)
538 fprintf(stderr, "sh2d: Failed to open file: %s\n",
539 argv[file]);
540 exit(1);
542 fseek(fp, 0, SEEK_END);
543 fsize = ftell(fp);
544 rewind(fp);
545 if ((buffer = (char *) calloc(fsize * 2, sizeof(unsigned short)))
546 == NULL)
548 fprintf(stderr, "sh2d: Not enough memory to load input "
549 "file: %s, %lu bytes\n", argv[file], fsize);
550 exit(1);
552 fread(buffer, sizeof(unsigned char), fsize, fp);
553 fclose(fp);
555 if (calc_len)
556 len = fsize - start;
558 mark = buffer + fsize;
560 for (i = start; i < (unsigned) fsize && j < len; i += 2)
562 if (do_org)
564 SH2Disasm(org, (unsigned char*)&buffer[i], mode, &mark[i]);
565 org += 2;
567 else
568 SH2Disasm(i, (unsigned char *)&buffer[i], mode, &mark[i]);
569 j += 2;
572 return 0;