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