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