summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/Makefile7
-rw-r--r--tools/descramble.c83
-rw-r--r--tools/scramble.c101
-rw-r--r--tools/sh2d.c569
4 files changed, 760 insertions, 0 deletions
diff --git a/tools/Makefile b/tools/Makefile
new file mode 100644
index 0000000000..67c48afb79
--- /dev/null
+++ b/tools/Makefile
@@ -0,0 +1,7 @@
1all: scramble descramble sh2d
2
3scramble: scramble.c
4
5descramble: descramble.c
6
7sh2d: sh2d.c
diff --git a/tools/descramble.c b/tools/descramble.c
new file mode 100644
index 0000000000..d9a4bf59d9
--- /dev/null
+++ b/tools/descramble.c
@@ -0,0 +1,83 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Björn Stenberg
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include <stdio.h>
21#include <stdlib.h>
22
23int main (int argc, char** argv)
24{
25 unsigned long length,i,slen;
26 unsigned char *inbuf,*outbuf;
27 FILE* file;
28
29 if (argc < 3) {
30 printf("usage: %s <input file> <output file>\n",argv[0]);
31 return -1;
32 }
33
34 /* open file and check size */
35 file = fopen(argv[1],"rb");
36 if (!file) {
37 perror(argv[1]);
38 return -1;
39 }
40 fseek(file,0,SEEK_END);
41 length = ftell(file) - 6; /* skip 6-byte header */
42 fseek(file,6,SEEK_SET);
43 inbuf = malloc(length);
44 outbuf = malloc(length);
45 if ( !inbuf || !outbuf ) {
46 printf("out of memory!\n");
47 return -1;
48 }
49
50 /* read file */
51 i=fread(inbuf,1,length,file);
52 if ( !i ) {
53 perror(argv[1]);
54 return -1;
55 }
56 fclose(file);
57
58 /* descramble */
59 slen = length/4;
60 for (i = 0; i < length; i++) {
61 unsigned long addr = ((i % slen) << 2) + i/slen;
62 unsigned char data = inbuf[i];
63 data = ~((data >> 1) | ((data << 7) & 0x80)); /* poor man's ROR */
64 outbuf[addr] = data;
65 }
66
67 /* write file */
68 file = fopen(argv[2],"wb");
69 if ( !file ) {
70 perror(argv[2]);
71 return -1;
72 }
73 if ( !fwrite(outbuf,length,1,file) ) {
74 perror(argv[2]);
75 return -1;
76 }
77 fclose(file);
78
79 free(inbuf);
80 free(outbuf);
81
82 return 0;
83}
diff --git a/tools/scramble.c b/tools/scramble.c
new file mode 100644
index 0000000000..5b59cf3d64
--- /dev/null
+++ b/tools/scramble.c
@@ -0,0 +1,101 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Björn Stenberg
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include <stdio.h>
21#include <stdlib.h>
22
23int main (int argc, char** argv)
24{
25 unsigned long length,i,slen;
26 unsigned char *inbuf,*outbuf;
27 unsigned short crc=0;
28 unsigned char header[6];
29 FILE* file;
30
31 if (argc < 3) {
32 printf("usage: %s <input file> <output file>\n",argv[0]);
33 return -1;
34 }
35
36 /* open file */
37 file = fopen(argv[1],"rb");
38 if (!file) {
39 perror(argv[1]);
40 return -1;
41 }
42 fseek(file,0,SEEK_END);
43 length = ftell(file);
44 fseek(file,0,SEEK_SET);
45 inbuf = malloc(length);
46 outbuf = malloc(length);
47 if ( !inbuf || !outbuf ) {
48 printf("out of memory!\n");
49 return -1;
50 }
51
52 /* read file */
53 i=fread(inbuf,1,length,file);
54 if ( !i ) {
55 perror(argv[1]);
56 return -1;
57 }
58 fclose(file);
59
60 /* scramble */
61 slen = length/4;
62 for (i = 0; i < length; i++) {
63 unsigned long addr = (i >> 2) + ((i % 4) * slen);
64 unsigned char data = inbuf[i];
65 data = ~((data << 1) | ((data >> 7) & 1)); /* poor man's ROL */
66 outbuf[addr] = data;
67 }
68
69 /* calculate checksum */
70 for (i=0;i<length;i++)
71 crc += inbuf[i];
72
73 /* make header */
74 header[0] = (length >> 24) & 0xff;
75 header[1] = (length >> 16) & 0xff;
76 header[2] = (length >> 8) & 0xff;
77 header[3] = length & 0xff;
78 header[4] = (crc >> 8) & 0xff;
79 header[5] = crc & 0xff;
80
81 /* write file */
82 file = fopen(argv[2],"wb");
83 if ( !file ) {
84 perror(argv[2]);
85 return -1;
86 }
87 if ( !fwrite(header,6,1,file) ) {
88 perror(argv[2]);
89 return -1;
90 }
91 if ( !fwrite(outbuf,length,1,file) ) {
92 perror(argv[2]);
93 return -1;
94 }
95 fclose(file);
96
97 free(inbuf);
98 free(outbuf);
99
100 return 0;
101}
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
27typedef 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 */
38char* 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
93i_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
241int 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
318void 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
476void 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
490int 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}