Björn Stenberg | e1715c2 | 2002-03-28 14:34:13 +0000 | [diff] [blame] | 1 | /* |
| 2 | * sh2d |
| 3 | * Bart Trzynadlowski, July 24, 2000 |
| 4 | * Public domain |
Björn Stenberg | 09efa1b | 2002-03-28 14:42:40 +0000 | [diff] [blame] | 5 | * |
| 6 | * Some changes by Björn Stenberg <bjorn@haxx.se> |
| 7 | * $Id$ |
Björn Stenberg | e1715c2 | 2002-03-28 14:34:13 +0000 | [diff] [blame] | 8 | */ |
| 9 | |
| 10 | |
| 11 | #include <stdio.h> |
| 12 | #include <stdlib.h> |
| 13 | #include <string.h> |
| 14 | |
| 15 | #define VERSION "0.2" |
| 16 | |
| 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 */ |
| 29 | |
| 30 | typedef struct |
| 31 | { |
| 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; |
| 39 | |
| 40 | /* register name lookup added by bjorn@haxx.se 2001-12-09 */ |
| 41 | char* regname[] = |
| 42 | { |
| 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 */ |
| 56 | |
| 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 | "","","","","","","","" |
| 94 | }; |
| 95 | |
| 96 | i_descr tab[] = |
| 97 | { |
| 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 } |
| 241 | }; |
| 242 | |
| 243 | |
| 244 | int FindOption(char *option, int p, int h, int u, int argc, char **argv) |
| 245 | { |
| 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; |
| 264 | |
| 265 | if (argc > 128) |
| 266 | argc = 128; /* maximum this function can handle is 128 */ |
| 267 | |
| 268 | /* |
| 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 |
| 273 | */ |
| 274 | |
| 275 | if (u) /* find first untouched element */ |
| 276 | { |
| 277 | for (i = 1; i < argc; i++) |
| 278 | { |
| 279 | if (!t[i]) /* 0 indicates untouched */ |
| 280 | return i; |
| 281 | } |
| 282 | return 0; |
| 283 | } |
| 284 | |
| 285 | if (p) /* find option and return integer value following it */ |
| 286 | { |
| 287 | for (i = 1; i < argc; i++) |
| 288 | { |
| 289 | if (strcmp(argv[i], option) == 0) /* found */ |
| 290 | { |
| 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); |
| 298 | } |
| 299 | } |
| 300 | return 0; /* no match */ |
| 301 | } |
| 302 | else /* find option and return position */ |
| 303 | { |
| 304 | for (i = 1; i < argc; i++) |
| 305 | { |
| 306 | if (strcmp(argv[i], option) == 0) |
| 307 | { |
| 308 | t[i] = 1; |
| 309 | return i; /* found! return position */ |
| 310 | } |
| 311 | } |
| 312 | return 0; |
| 313 | } |
| 314 | } |
| 315 | |
| 316 | /* |
| 317 | * SH2Disasm(): SH-1/SH-2 disassembler routine. If mode = 0 then SH-2 mode, |
| 318 | * otherwise SH-1 mode |
| 319 | */ |
| 320 | |
| 321 | void SH2Disasm(unsigned v_addr, unsigned char *p_addr, int mode, char *m_addr) |
| 322 | { |
| 323 | int i; |
| 324 | unsigned short op; |
| 325 | |
| 326 | op = (unsigned short) (*p_addr << 8) | *(p_addr + 1); |
| 327 | printf("0x%08X: 0x%04X\t", v_addr, op); |
| 328 | |
| 329 | if (m_addr[0]==ND8_F) |
| 330 | { |
| 331 | if (m_addr[2]==-1) |
| 332 | { |
| 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]); |
| 335 | } |
| 336 | else |
| 337 | printf(".short\t0x%08X\t; 0x%08X",op,v_addr - (unsigned)m_addr[1]); |
| 338 | } |
| 339 | else if (m_addr[0] != -1) |
| 340 | { |
| 341 | for (i = 0; tab[i].mnem != NULL; i++) /* 0 format */ |
| 342 | { |
| 343 | if ((op & tab[i].mask) == tab[i].bits) |
| 344 | { |
| 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) |
| 357 | { |
| 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); |
| 364 | } |
| 365 | else if (tab[i].format == ND4_F) |
| 366 | { |
| 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); |
| 373 | } |
| 374 | else if (tab[i].format == NMD_F) |
| 375 | { |
| 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); |
| 384 | } |
| 385 | else if (tab[i].format == D_F) |
| 386 | { |
| 387 | if (tab[i].dat <= 4) |
| 388 | { |
| 389 | if ((op & 0xff00) == 0xc700) |
| 390 | { |
| 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); |
| 398 | } |
| 399 | else |
| 400 | printf(tab[i].mnem, |
| 401 | (op & 0xff) * |
| 402 | tab[i].dat); |
| 403 | } |
| 404 | else |
| 405 | { |
| 406 | if (op & 0x80) /* sign extend */ |
| 407 | printf(tab[i].mnem, |
| 408 | (((op & 0xff) + |
| 409 | 0xffffff00) * 2) + |
| 410 | |
| 411 | v_addr + 4); |
| 412 | else |
| 413 | printf(tab[i].mnem, |
| 414 | ((op & 0xff) * 2) + |
| 415 | v_addr + 4); |
| 416 | } |
| 417 | } |
| 418 | else if (tab[i].format == D12_F) |
| 419 | { |
| 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); |
| 427 | } |
| 428 | else if (tab[i].format == ND8_F) |
| 429 | { |
| 430 | int imm = (op & 0xff) * tab[i].dat + 4; |
| 431 | if ((op & 0xf000) == 0x9000) /* .W */ |
| 432 | { |
| 433 | int dat = (unsigned short) (*(imm + p_addr) << 8) | *(imm + p_addr + 1); |
Björn Stenberg | 09efa1b | 2002-03-28 14:42:40 +0000 | [diff] [blame] | 434 | m_addr[imm+0] = ND8_F; /* this couldn't be an instruction so mark it ! */ |
Björn Stenberg | e1715c2 | 2002-03-28 14:34:13 +0000 | [diff] [blame] | 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); |
| 441 | } |
| 442 | else /* .L */ |
| 443 | { |
| 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]; |
Björn Stenberg | 09efa1b | 2002-03-28 14:42:40 +0000 | [diff] [blame] | 451 | m_addr[imm+(b_addr-p_addr)+0] = ND8_F; /* this couldn't be an instruction so mark it ! */ |
Björn Stenberg | e1715c2 | 2002-03-28 14:34:13 +0000 | [diff] [blame] | 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); |
| 459 | } |
| 460 | } |
| 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; |
| 470 | } |
| 471 | } |
| 472 | |
| 473 | printf("???"); |
| 474 | |
| 475 | } |
| 476 | printf("\n"); |
| 477 | } |
| 478 | |
| 479 | void ShowHelp() |
| 480 | { |
| 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); |
| 491 | } |
| 492 | |
| 493 | int main(int argc, char **argv) |
| 494 | { |
| 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; |
| 500 | |
| 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(); |
| 506 | |
| 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 */ |
| 513 | |
| 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))) |
| 517 | { |
| 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 */ |
| 521 | } |
| 522 | |
| 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 */ |
| 527 | |
| 528 | if (!(file = FindOption(NULL, 0, 0, 1, argc, argv))) |
| 529 | { |
| 530 | fprintf(stderr, "sh2d: No input file specified. Try " |
| 531 | "\"sh2d -h\" for usage instructions\n"); |
| 532 | exit(1); |
| 533 | } |
| 534 | |
| 535 | if ((fp = fopen(argv[file], "rb")) == NULL) |
| 536 | { |
| 537 | fprintf(stderr, "sh2d: Failed to open file: %s\n", |
| 538 | argv[file]); |
| 539 | exit(1); |
| 540 | } |
| 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) |
| 546 | { |
| 547 | fprintf(stderr, "sh2d: Not enough memory to load input " |
| 548 | "file: %s, %lu bytes\n", argv[file], fsize); |
| 549 | exit(1); |
| 550 | } |
| 551 | fread(buffer, sizeof(unsigned char), fsize, fp); |
| 552 | fclose(fp); |
| 553 | |
| 554 | if (calc_len) |
| 555 | len = fsize - start; |
| 556 | |
| 557 | mark = buffer + fsize; |
| 558 | |
| 559 | for (i = start; i < (unsigned) fsize && j < len; i += 2) |
| 560 | { |
| 561 | if (do_org) |
| 562 | { |
| 563 | SH2Disasm(org, &buffer[i], mode, &mark[i]); |
| 564 | org += 2; |
| 565 | } |
| 566 | else |
| 567 | SH2Disasm(i, &buffer[i], mode, &mark[i]); |
| 568 | j += 2; |
| 569 | } |
| 570 | |
| 571 | return 0; |
| 572 | } |