| Paul Mundt | 9cfc9a9 | 2008-11-26 14:31:03 +0900 | [diff] [blame] | 1 | /* | 
|  | 2 | * Disassemble SuperH instructions. | 
|  | 3 | * | 
|  | 4 | * Copyright (C) 1999 kaz Kojima | 
|  | 5 | * Copyright (C) 2008 Paul Mundt | 
|  | 6 | * | 
|  | 7 | * This file is subject to the terms and conditions of the GNU General Public | 
|  | 8 | * License.  See the file "COPYING" in the main directory of this archive | 
|  | 9 | * for more details. | 
|  | 10 | */ | 
|  | 11 | #include <linux/kernel.h> | 
|  | 12 | #include <linux/string.h> | 
|  | 13 | #include <linux/uaccess.h> | 
|  | 14 |  | 
|  | 15 | /* | 
|  | 16 | * Format of an instruction in memory. | 
|  | 17 | */ | 
|  | 18 | typedef enum { | 
|  | 19 | HEX_0, HEX_1, HEX_2, HEX_3, HEX_4, HEX_5, HEX_6, HEX_7, | 
|  | 20 | HEX_8, HEX_9, HEX_A, HEX_B, HEX_C, HEX_D, HEX_E, HEX_F, | 
|  | 21 | REG_N, REG_M, REG_NM, REG_B, | 
|  | 22 | BRANCH_12, BRANCH_8, | 
|  | 23 | DISP_8, DISP_4, | 
|  | 24 | IMM_4, IMM_4BY2, IMM_4BY4, PCRELIMM_8BY2, PCRELIMM_8BY4, | 
|  | 25 | IMM_8, IMM_8BY2, IMM_8BY4, | 
|  | 26 | } sh_nibble_type; | 
|  | 27 |  | 
|  | 28 | typedef enum { | 
|  | 29 | A_END, A_BDISP12, A_BDISP8, | 
|  | 30 | A_DEC_M, A_DEC_N, | 
|  | 31 | A_DISP_GBR, A_DISP_PC, A_DISP_REG_M, A_DISP_REG_N, | 
|  | 32 | A_GBR, | 
|  | 33 | A_IMM, | 
|  | 34 | A_INC_M, A_INC_N, | 
|  | 35 | A_IND_M, A_IND_N, A_IND_R0_REG_M, A_IND_R0_REG_N, | 
|  | 36 | A_MACH, A_MACL, | 
|  | 37 | A_PR, A_R0, A_R0_GBR, A_REG_M, A_REG_N, A_REG_B, | 
|  | 38 | A_SR, A_VBR, A_SSR, A_SPC, A_SGR, A_DBR, | 
|  | 39 | F_REG_N, F_REG_M, D_REG_N, D_REG_M, | 
|  | 40 | X_REG_N, /* Only used for argument parsing */ | 
|  | 41 | X_REG_M, /* Only used for argument parsing */ | 
|  | 42 | DX_REG_N, DX_REG_M, V_REG_N, V_REG_M, | 
|  | 43 | FD_REG_N, | 
|  | 44 | XMTRX_M4, | 
|  | 45 | F_FR0, | 
|  | 46 | FPUL_N, FPUL_M, FPSCR_N, FPSCR_M, | 
|  | 47 | } sh_arg_type; | 
|  | 48 |  | 
|  | 49 | static struct sh_opcode_info { | 
|  | 50 | char *name; | 
|  | 51 | sh_arg_type arg[7]; | 
|  | 52 | sh_nibble_type nibbles[4]; | 
|  | 53 | } sh_table[] = { | 
|  | 54 | {"add",{A_IMM,A_REG_N},{HEX_7,REG_N,IMM_8}}, | 
|  | 55 | {"add",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_C}}, | 
|  | 56 | {"addc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_E}}, | 
|  | 57 | {"addv",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_F}}, | 
|  | 58 | {"and",{A_IMM,A_R0},{HEX_C,HEX_9,IMM_8}}, | 
|  | 59 | {"and",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_9}}, | 
|  | 60 | {"and.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_D,IMM_8}}, | 
|  | 61 | {"bra",{A_BDISP12},{HEX_A,BRANCH_12}}, | 
|  | 62 | {"bsr",{A_BDISP12},{HEX_B,BRANCH_12}}, | 
|  | 63 | {"bt",{A_BDISP8},{HEX_8,HEX_9,BRANCH_8}}, | 
|  | 64 | {"bf",{A_BDISP8},{HEX_8,HEX_B,BRANCH_8}}, | 
|  | 65 | {"bt.s",{A_BDISP8},{HEX_8,HEX_D,BRANCH_8}}, | 
|  | 66 | {"bt/s",{A_BDISP8},{HEX_8,HEX_D,BRANCH_8}}, | 
|  | 67 | {"bf.s",{A_BDISP8},{HEX_8,HEX_F,BRANCH_8}}, | 
|  | 68 | {"bf/s",{A_BDISP8},{HEX_8,HEX_F,BRANCH_8}}, | 
|  | 69 | {"clrmac",{0},{HEX_0,HEX_0,HEX_2,HEX_8}}, | 
|  | 70 | {"clrs",{0},{HEX_0,HEX_0,HEX_4,HEX_8}}, | 
|  | 71 | {"clrt",{0},{HEX_0,HEX_0,HEX_0,HEX_8}}, | 
|  | 72 | {"cmp/eq",{A_IMM,A_R0},{HEX_8,HEX_8,IMM_8}}, | 
|  | 73 | {"cmp/eq",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_0}}, | 
|  | 74 | {"cmp/ge",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_3}}, | 
|  | 75 | {"cmp/gt",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_7}}, | 
|  | 76 | {"cmp/hi",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_6}}, | 
|  | 77 | {"cmp/hs",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_2}}, | 
|  | 78 | {"cmp/pl",{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_5}}, | 
|  | 79 | {"cmp/pz",{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_1}}, | 
|  | 80 | {"cmp/str",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_C}}, | 
|  | 81 | {"div0s",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_7}}, | 
|  | 82 | {"div0u",{0},{HEX_0,HEX_0,HEX_1,HEX_9}}, | 
|  | 83 | {"div1",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_4}}, | 
|  | 84 | {"exts.b",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_E}}, | 
|  | 85 | {"exts.w",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_F}}, | 
|  | 86 | {"extu.b",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_C}}, | 
|  | 87 | {"extu.w",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_D}}, | 
|  | 88 | {"jmp",{A_IND_N},{HEX_4,REG_N,HEX_2,HEX_B}}, | 
|  | 89 | {"jsr",{A_IND_N},{HEX_4,REG_N,HEX_0,HEX_B}}, | 
|  | 90 | {"ldc",{A_REG_N,A_SR},{HEX_4,REG_N,HEX_0,HEX_E}}, | 
|  | 91 | {"ldc",{A_REG_N,A_GBR},{HEX_4,REG_N,HEX_1,HEX_E}}, | 
|  | 92 | {"ldc",{A_REG_N,A_VBR},{HEX_4,REG_N,HEX_2,HEX_E}}, | 
|  | 93 | {"ldc",{A_REG_N,A_SSR},{HEX_4,REG_N,HEX_3,HEX_E}}, | 
|  | 94 | {"ldc",{A_REG_N,A_SPC},{HEX_4,REG_N,HEX_4,HEX_E}}, | 
|  | 95 | {"ldc",{A_REG_N,A_DBR},{HEX_4,REG_N,HEX_7,HEX_E}}, | 
|  | 96 | {"ldc",{A_REG_N,A_REG_B},{HEX_4,REG_N,REG_B,HEX_E}}, | 
|  | 97 | {"ldc.l",{A_INC_N,A_SR},{HEX_4,REG_N,HEX_0,HEX_7}}, | 
|  | 98 | {"ldc.l",{A_INC_N,A_GBR},{HEX_4,REG_N,HEX_1,HEX_7}}, | 
|  | 99 | {"ldc.l",{A_INC_N,A_VBR},{HEX_4,REG_N,HEX_2,HEX_7}}, | 
|  | 100 | {"ldc.l",{A_INC_N,A_SSR},{HEX_4,REG_N,HEX_3,HEX_7}}, | 
|  | 101 | {"ldc.l",{A_INC_N,A_SPC},{HEX_4,REG_N,HEX_4,HEX_7}}, | 
|  | 102 | {"ldc.l",{A_INC_N,A_DBR},{HEX_4,REG_N,HEX_7,HEX_7}}, | 
|  | 103 | {"ldc.l",{A_INC_N,A_REG_B},{HEX_4,REG_N,REG_B,HEX_7}}, | 
|  | 104 | {"lds",{A_REG_N,A_MACH},{HEX_4,REG_N,HEX_0,HEX_A}}, | 
|  | 105 | {"lds",{A_REG_N,A_MACL},{HEX_4,REG_N,HEX_1,HEX_A}}, | 
|  | 106 | {"lds",{A_REG_N,A_PR},{HEX_4,REG_N,HEX_2,HEX_A}}, | 
|  | 107 | {"lds",{A_REG_M,FPUL_N},{HEX_4,REG_M,HEX_5,HEX_A}}, | 
|  | 108 | {"lds",{A_REG_M,FPSCR_N},{HEX_4,REG_M,HEX_6,HEX_A}}, | 
|  | 109 | {"lds.l",{A_INC_N,A_MACH},{HEX_4,REG_N,HEX_0,HEX_6}}, | 
|  | 110 | {"lds.l",{A_INC_N,A_MACL},{HEX_4,REG_N,HEX_1,HEX_6}}, | 
|  | 111 | {"lds.l",{A_INC_N,A_PR},{HEX_4,REG_N,HEX_2,HEX_6}}, | 
|  | 112 | {"lds.l",{A_INC_M,FPUL_N},{HEX_4,REG_M,HEX_5,HEX_6}}, | 
|  | 113 | {"lds.l",{A_INC_M,FPSCR_N},{HEX_4,REG_M,HEX_6,HEX_6}}, | 
|  | 114 | {"ldtlb",{0},{HEX_0,HEX_0,HEX_3,HEX_8}}, | 
|  | 115 | {"mac.w",{A_INC_M,A_INC_N},{HEX_4,REG_N,REG_M,HEX_F}}, | 
|  | 116 | {"mov",{A_IMM,A_REG_N},{HEX_E,REG_N,IMM_8}}, | 
|  | 117 | {"mov",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_3}}, | 
|  | 118 | {"mov.b",{ A_REG_M,A_IND_R0_REG_N},{HEX_0,REG_N,REG_M,HEX_4}}, | 
|  | 119 | {"mov.b",{ A_REG_M,A_DEC_N},{HEX_2,REG_N,REG_M,HEX_4}}, | 
|  | 120 | {"mov.b",{ A_REG_M,A_IND_N},{HEX_2,REG_N,REG_M,HEX_0}}, | 
|  | 121 | {"mov.b",{A_DISP_REG_M,A_R0},{HEX_8,HEX_4,REG_M,IMM_4}}, | 
|  | 122 | {"mov.b",{A_DISP_GBR,A_R0},{HEX_C,HEX_4,IMM_8}}, | 
|  | 123 | {"mov.b",{A_IND_R0_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_C}}, | 
|  | 124 | {"mov.b",{A_INC_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_4}}, | 
|  | 125 | {"mov.b",{A_IND_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_0}}, | 
|  | 126 | {"mov.b",{A_R0,A_DISP_REG_M},{HEX_8,HEX_0,REG_M,IMM_4}}, | 
|  | 127 | {"mov.b",{A_R0,A_DISP_GBR},{HEX_C,HEX_0,IMM_8}}, | 
|  | 128 | {"mov.l",{ A_REG_M,A_DISP_REG_N},{HEX_1,REG_N,REG_M,IMM_4BY4}}, | 
|  | 129 | {"mov.l",{ A_REG_M,A_IND_R0_REG_N},{HEX_0,REG_N,REG_M,HEX_6}}, | 
|  | 130 | {"mov.l",{ A_REG_M,A_DEC_N},{HEX_2,REG_N,REG_M,HEX_6}}, | 
|  | 131 | {"mov.l",{ A_REG_M,A_IND_N},{HEX_2,REG_N,REG_M,HEX_2}}, | 
|  | 132 | {"mov.l",{A_DISP_REG_M,A_REG_N},{HEX_5,REG_N,REG_M,IMM_4BY4}}, | 
|  | 133 | {"mov.l",{A_DISP_GBR,A_R0},{HEX_C,HEX_6,IMM_8BY4}}, | 
|  | 134 | {"mov.l",{A_DISP_PC,A_REG_N},{HEX_D,REG_N,PCRELIMM_8BY4}}, | 
|  | 135 | {"mov.l",{A_IND_R0_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_E}}, | 
|  | 136 | {"mov.l",{A_INC_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_6}}, | 
|  | 137 | {"mov.l",{A_IND_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_2}}, | 
|  | 138 | {"mov.l",{A_R0,A_DISP_GBR},{HEX_C,HEX_2,IMM_8BY4}}, | 
|  | 139 | {"mov.w",{ A_REG_M,A_IND_R0_REG_N},{HEX_0,REG_N,REG_M,HEX_5}}, | 
|  | 140 | {"mov.w",{ A_REG_M,A_DEC_N},{HEX_2,REG_N,REG_M,HEX_5}}, | 
|  | 141 | {"mov.w",{ A_REG_M,A_IND_N},{HEX_2,REG_N,REG_M,HEX_1}}, | 
|  | 142 | {"mov.w",{A_DISP_REG_M,A_R0},{HEX_8,HEX_5,REG_M,IMM_4BY2}}, | 
|  | 143 | {"mov.w",{A_DISP_GBR,A_R0},{HEX_C,HEX_5,IMM_8BY2}}, | 
|  | 144 | {"mov.w",{A_DISP_PC,A_REG_N},{HEX_9,REG_N,PCRELIMM_8BY2}}, | 
|  | 145 | {"mov.w",{A_IND_R0_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_D}}, | 
|  | 146 | {"mov.w",{A_INC_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_5}}, | 
|  | 147 | {"mov.w",{A_IND_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_1}}, | 
|  | 148 | {"mov.w",{A_R0,A_DISP_REG_M},{HEX_8,HEX_1,REG_M,IMM_4BY2}}, | 
|  | 149 | {"mov.w",{A_R0,A_DISP_GBR},{HEX_C,HEX_1,IMM_8BY2}}, | 
|  | 150 | {"mova",{A_DISP_PC,A_R0},{HEX_C,HEX_7,PCRELIMM_8BY4}}, | 
|  | 151 | {"movca.l",{A_R0,A_IND_N},{HEX_0,REG_N,HEX_C,HEX_3}}, | 
|  | 152 | {"movt",{A_REG_N},{HEX_0,REG_N,HEX_2,HEX_9}}, | 
|  | 153 | {"muls",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_F}}, | 
|  | 154 | {"mul.l",{ A_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_7}}, | 
|  | 155 | {"mulu",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_E}}, | 
|  | 156 | {"neg",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_B}}, | 
|  | 157 | {"negc",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_A}}, | 
|  | 158 | {"nop",{0},{HEX_0,HEX_0,HEX_0,HEX_9}}, | 
|  | 159 | {"not",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_7}}, | 
|  | 160 | {"ocbi",{A_IND_N},{HEX_0,REG_N,HEX_9,HEX_3}}, | 
|  | 161 | {"ocbp",{A_IND_N},{HEX_0,REG_N,HEX_A,HEX_3}}, | 
|  | 162 | {"ocbwb",{A_IND_N},{HEX_0,REG_N,HEX_B,HEX_3}}, | 
|  | 163 | {"or",{A_IMM,A_R0},{HEX_C,HEX_B,IMM_8}}, | 
|  | 164 | {"or",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_B}}, | 
|  | 165 | {"or.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_F,IMM_8}}, | 
|  | 166 | {"pref",{A_IND_N},{HEX_0,REG_N,HEX_8,HEX_3}}, | 
|  | 167 | {"rotcl",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_4}}, | 
|  | 168 | {"rotcr",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_5}}, | 
|  | 169 | {"rotl",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_4}}, | 
|  | 170 | {"rotr",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_5}}, | 
|  | 171 | {"rte",{0},{HEX_0,HEX_0,HEX_2,HEX_B}}, | 
|  | 172 | {"rts",{0},{HEX_0,HEX_0,HEX_0,HEX_B}}, | 
|  | 173 | {"sets",{0},{HEX_0,HEX_0,HEX_5,HEX_8}}, | 
|  | 174 | {"sett",{0},{HEX_0,HEX_0,HEX_1,HEX_8}}, | 
|  | 175 | {"shad",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_C}}, | 
|  | 176 | {"shld",{ A_REG_M,A_REG_N},{HEX_4,REG_N,REG_M,HEX_D}}, | 
|  | 177 | {"shal",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_0}}, | 
|  | 178 | {"shar",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_1}}, | 
|  | 179 | {"shll",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_0}}, | 
|  | 180 | {"shll16",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_8}}, | 
|  | 181 | {"shll2",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_8}}, | 
|  | 182 | {"shll8",{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_8}}, | 
|  | 183 | {"shlr",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_1}}, | 
|  | 184 | {"shlr16",{A_REG_N},{HEX_4,REG_N,HEX_2,HEX_9}}, | 
|  | 185 | {"shlr2",{A_REG_N},{HEX_4,REG_N,HEX_0,HEX_9}}, | 
|  | 186 | {"shlr8",{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_9}}, | 
|  | 187 | {"sleep",{0},{HEX_0,HEX_0,HEX_1,HEX_B}}, | 
|  | 188 | {"stc",{A_SR,A_REG_N},{HEX_0,REG_N,HEX_0,HEX_2}}, | 
|  | 189 | {"stc",{A_GBR,A_REG_N},{HEX_0,REG_N,HEX_1,HEX_2}}, | 
|  | 190 | {"stc",{A_VBR,A_REG_N},{HEX_0,REG_N,HEX_2,HEX_2}}, | 
|  | 191 | {"stc",{A_SSR,A_REG_N},{HEX_0,REG_N,HEX_3,HEX_2}}, | 
|  | 192 | {"stc",{A_SPC,A_REG_N},{HEX_0,REG_N,HEX_4,HEX_2}}, | 
|  | 193 | {"stc",{A_SGR,A_REG_N},{HEX_0,REG_N,HEX_6,HEX_2}}, | 
|  | 194 | {"stc",{A_DBR,A_REG_N},{HEX_0,REG_N,HEX_7,HEX_2}}, | 
|  | 195 | {"stc",{A_REG_B,A_REG_N},{HEX_0,REG_N,REG_B,HEX_2}}, | 
|  | 196 | {"stc.l",{A_SR,A_DEC_N},{HEX_4,REG_N,HEX_0,HEX_3}}, | 
|  | 197 | {"stc.l",{A_GBR,A_DEC_N},{HEX_4,REG_N,HEX_1,HEX_3}}, | 
|  | 198 | {"stc.l",{A_VBR,A_DEC_N},{HEX_4,REG_N,HEX_2,HEX_3}}, | 
|  | 199 | {"stc.l",{A_SSR,A_DEC_N},{HEX_4,REG_N,HEX_3,HEX_3}}, | 
|  | 200 | {"stc.l",{A_SPC,A_DEC_N},{HEX_4,REG_N,HEX_4,HEX_3}}, | 
|  | 201 | {"stc.l",{A_SGR,A_DEC_N},{HEX_4,REG_N,HEX_6,HEX_3}}, | 
|  | 202 | {"stc.l",{A_DBR,A_DEC_N},{HEX_4,REG_N,HEX_7,HEX_3}}, | 
|  | 203 | {"stc.l",{A_REG_B,A_DEC_N},{HEX_4,REG_N,REG_B,HEX_3}}, | 
|  | 204 | {"sts",{A_MACH,A_REG_N},{HEX_0,REG_N,HEX_0,HEX_A}}, | 
|  | 205 | {"sts",{A_MACL,A_REG_N},{HEX_0,REG_N,HEX_1,HEX_A}}, | 
|  | 206 | {"sts",{A_PR,A_REG_N},{HEX_0,REG_N,HEX_2,HEX_A}}, | 
|  | 207 | {"sts",{FPUL_M,A_REG_N},{HEX_0,REG_N,HEX_5,HEX_A}}, | 
|  | 208 | {"sts",{FPSCR_M,A_REG_N},{HEX_0,REG_N,HEX_6,HEX_A}}, | 
|  | 209 | {"sts.l",{A_MACH,A_DEC_N},{HEX_4,REG_N,HEX_0,HEX_2}}, | 
|  | 210 | {"sts.l",{A_MACL,A_DEC_N},{HEX_4,REG_N,HEX_1,HEX_2}}, | 
|  | 211 | {"sts.l",{A_PR,A_DEC_N},{HEX_4,REG_N,HEX_2,HEX_2}}, | 
|  | 212 | {"sts.l",{FPUL_M,A_DEC_N},{HEX_4,REG_N,HEX_5,HEX_2}}, | 
|  | 213 | {"sts.l",{FPSCR_M,A_DEC_N},{HEX_4,REG_N,HEX_6,HEX_2}}, | 
|  | 214 | {"sub",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_8}}, | 
|  | 215 | {"subc",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_A}}, | 
|  | 216 | {"subv",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_B}}, | 
|  | 217 | {"swap.b",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_8}}, | 
|  | 218 | {"swap.w",{ A_REG_M,A_REG_N},{HEX_6,REG_N,REG_M,HEX_9}}, | 
|  | 219 | {"tas.b",{A_IND_N},{HEX_4,REG_N,HEX_1,HEX_B}}, | 
|  | 220 | {"trapa",{A_IMM},{HEX_C,HEX_3,IMM_8}}, | 
|  | 221 | {"tst",{A_IMM,A_R0},{HEX_C,HEX_8,IMM_8}}, | 
|  | 222 | {"tst",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_8}}, | 
|  | 223 | {"tst.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_C,IMM_8}}, | 
|  | 224 | {"xor",{A_IMM,A_R0},{HEX_C,HEX_A,IMM_8}}, | 
|  | 225 | {"xor",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_A}}, | 
|  | 226 | {"xor.b",{A_IMM,A_R0_GBR},{HEX_C,HEX_E,IMM_8}}, | 
|  | 227 | {"xtrct",{ A_REG_M,A_REG_N},{HEX_2,REG_N,REG_M,HEX_D}}, | 
|  | 228 | {"mul.l",{ A_REG_M,A_REG_N},{HEX_0,REG_N,REG_M,HEX_7}}, | 
|  | 229 | {"dt",{A_REG_N},{HEX_4,REG_N,HEX_1,HEX_0}}, | 
|  | 230 | {"dmuls.l",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_D}}, | 
|  | 231 | {"dmulu.l",{ A_REG_M,A_REG_N},{HEX_3,REG_N,REG_M,HEX_5}}, | 
|  | 232 | {"mac.l",{A_INC_M,A_INC_N},{HEX_0,REG_N,REG_M,HEX_F}}, | 
|  | 233 | {"braf",{A_REG_N},{HEX_0,REG_N,HEX_2,HEX_3}}, | 
|  | 234 | {"bsrf",{A_REG_N},{HEX_0,REG_N,HEX_0,HEX_3}}, | 
|  | 235 | {"fabs",{FD_REG_N},{HEX_F,REG_N,HEX_5,HEX_D}}, | 
|  | 236 | {"fadd",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_0}}, | 
|  | 237 | {"fadd",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_0}}, | 
|  | 238 | {"fcmp/eq",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_4}}, | 
|  | 239 | {"fcmp/eq",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_4}}, | 
|  | 240 | {"fcmp/gt",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_5}}, | 
|  | 241 | {"fcmp/gt",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_5}}, | 
|  | 242 | {"fcnvds",{D_REG_N,FPUL_M},{HEX_F,REG_N,HEX_B,HEX_D}}, | 
|  | 243 | {"fcnvsd",{FPUL_M,D_REG_N},{HEX_F,REG_N,HEX_A,HEX_D}}, | 
|  | 244 | {"fdiv",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_3}}, | 
|  | 245 | {"fdiv",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_3}}, | 
|  | 246 | {"fipr",{V_REG_M,V_REG_N},{HEX_F,REG_NM,HEX_E,HEX_D}}, | 
|  | 247 | {"fldi0",{F_REG_N},{HEX_F,REG_N,HEX_8,HEX_D}}, | 
|  | 248 | {"fldi1",{F_REG_N},{HEX_F,REG_N,HEX_9,HEX_D}}, | 
|  | 249 | {"flds",{F_REG_N,FPUL_M},{HEX_F,REG_N,HEX_1,HEX_D}}, | 
|  | 250 | {"float",{FPUL_M,FD_REG_N},{HEX_F,REG_N,HEX_2,HEX_D}}, | 
|  | 251 | {"fmac",{F_FR0,F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_E}}, | 
|  | 252 | {"fmov",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_C}}, | 
|  | 253 | {"fmov",{DX_REG_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_C}}, | 
|  | 254 | {"fmov",{A_IND_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_8}}, | 
|  | 255 | {"fmov",{A_IND_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_8}}, | 
|  | 256 | {"fmov",{F_REG_M,A_IND_N},{HEX_F,REG_N,REG_M,HEX_A}}, | 
|  | 257 | {"fmov",{DX_REG_M,A_IND_N},{HEX_F,REG_N,REG_M,HEX_A}}, | 
|  | 258 | {"fmov",{A_INC_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_9}}, | 
|  | 259 | {"fmov",{A_INC_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_9}}, | 
|  | 260 | {"fmov",{F_REG_M,A_DEC_N},{HEX_F,REG_N,REG_M,HEX_B}}, | 
|  | 261 | {"fmov",{DX_REG_M,A_DEC_N},{HEX_F,REG_N,REG_M,HEX_B}}, | 
|  | 262 | {"fmov",{A_IND_R0_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_6}}, | 
|  | 263 | {"fmov",{A_IND_R0_REG_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_6}}, | 
|  | 264 | {"fmov",{F_REG_M,A_IND_R0_REG_N},{HEX_F,REG_N,REG_M,HEX_7}}, | 
|  | 265 | {"fmov",{DX_REG_M,A_IND_R0_REG_N},{HEX_F,REG_N,REG_M,HEX_7}}, | 
|  | 266 | {"fmov.d",{A_IND_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_8}}, | 
|  | 267 | {"fmov.d",{DX_REG_M,A_IND_N},{HEX_F,REG_N,REG_M,HEX_A}}, | 
|  | 268 | {"fmov.d",{A_INC_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_9}}, | 
|  | 269 | {"fmov.d",{DX_REG_M,A_DEC_N},{HEX_F,REG_N,REG_M,HEX_B}}, | 
|  | 270 | {"fmov.d",{A_IND_R0_REG_M,DX_REG_N},{HEX_F,REG_N,REG_M,HEX_6}}, | 
|  | 271 | {"fmov.d",{DX_REG_M,A_IND_R0_REG_N},{HEX_F,REG_N,REG_M,HEX_7}}, | 
|  | 272 | {"fmov.s",{A_IND_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_8}}, | 
|  | 273 | {"fmov.s",{F_REG_M,A_IND_N},{HEX_F,REG_N,REG_M,HEX_A}}, | 
|  | 274 | {"fmov.s",{A_INC_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_9}}, | 
|  | 275 | {"fmov.s",{F_REG_M,A_DEC_N},{HEX_F,REG_N,REG_M,HEX_B}}, | 
|  | 276 | {"fmov.s",{A_IND_R0_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_6}}, | 
|  | 277 | {"fmov.s",{F_REG_M,A_IND_R0_REG_N},{HEX_F,REG_N,REG_M,HEX_7}}, | 
|  | 278 | {"fmul",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_2}}, | 
|  | 279 | {"fmul",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_2}}, | 
|  | 280 | {"fneg",{FD_REG_N},{HEX_F,REG_N,HEX_4,HEX_D}}, | 
|  | 281 | {"frchg",{0},{HEX_F,HEX_B,HEX_F,HEX_D}}, | 
|  | 282 | {"fschg",{0},{HEX_F,HEX_3,HEX_F,HEX_D}}, | 
|  | 283 | {"fsqrt",{FD_REG_N},{HEX_F,REG_N,HEX_6,HEX_D}}, | 
|  | 284 | {"fsts",{FPUL_M,F_REG_N},{HEX_F,REG_N,HEX_0,HEX_D}}, | 
|  | 285 | {"fsub",{F_REG_M,F_REG_N},{HEX_F,REG_N,REG_M,HEX_1}}, | 
|  | 286 | {"fsub",{D_REG_M,D_REG_N},{HEX_F,REG_N,REG_M,HEX_1}}, | 
|  | 287 | {"ftrc",{FD_REG_N,FPUL_M},{HEX_F,REG_N,HEX_3,HEX_D}}, | 
|  | 288 | {"ftrv",{XMTRX_M4,V_REG_N},{HEX_F,REG_NM,HEX_F,HEX_D}}, | 
|  | 289 | { 0 }, | 
|  | 290 | }; | 
|  | 291 |  | 
|  | 292 | static void print_sh_insn(u32 memaddr, u16 insn) | 
|  | 293 | { | 
|  | 294 | int relmask = ~0; | 
|  | 295 | int nibs[4] = { (insn >> 12) & 0xf, (insn >> 8) & 0xf, (insn >> 4) & 0xf, insn & 0xf}; | 
|  | 296 | int lastsp; | 
|  | 297 | struct sh_opcode_info *op = sh_table; | 
|  | 298 |  | 
|  | 299 | for (; op->name; op++) { | 
|  | 300 | int n; | 
|  | 301 | int imm = 0; | 
|  | 302 | int rn = 0; | 
|  | 303 | int rm = 0; | 
|  | 304 | int rb = 0; | 
|  | 305 | int disp_pc; | 
|  | 306 | int disp_pc_addr = 0; | 
|  | 307 |  | 
|  | 308 | for (n = 0; n < 4; n++) { | 
|  | 309 | int i = op->nibbles[n]; | 
|  | 310 |  | 
|  | 311 | if (i < 16) { | 
|  | 312 | if (nibs[n] == i) | 
|  | 313 | continue; | 
|  | 314 | goto fail; | 
|  | 315 | } | 
|  | 316 | switch (i) { | 
|  | 317 | case BRANCH_8: | 
|  | 318 | imm = (nibs[2] << 4) | (nibs[3]); | 
|  | 319 | if (imm & 0x80) | 
|  | 320 | imm |= ~0xff; | 
|  | 321 | imm = ((char)imm) * 2 + 4 ; | 
|  | 322 | goto ok; | 
|  | 323 | case BRANCH_12: | 
|  | 324 | imm = ((nibs[1]) << 8) | (nibs[2] << 4) | (nibs[3]); | 
|  | 325 | if (imm & 0x800) | 
|  | 326 | imm |= ~0xfff; | 
|  | 327 | imm = imm * 2 + 4; | 
|  | 328 | goto ok; | 
|  | 329 | case IMM_4: | 
|  | 330 | imm = nibs[3]; | 
|  | 331 | goto ok; | 
|  | 332 | case IMM_4BY2: | 
|  | 333 | imm = nibs[3] <<1; | 
|  | 334 | goto ok; | 
|  | 335 | case IMM_4BY4: | 
|  | 336 | imm = nibs[3] <<2; | 
|  | 337 | goto ok; | 
|  | 338 | case IMM_8: | 
|  | 339 | imm = (nibs[2] << 4) | nibs[3]; | 
|  | 340 | goto ok; | 
|  | 341 | case PCRELIMM_8BY2: | 
|  | 342 | imm = ((nibs[2] << 4) | nibs[3]) <<1; | 
|  | 343 | relmask = ~1; | 
|  | 344 | goto ok; | 
|  | 345 | case PCRELIMM_8BY4: | 
|  | 346 | imm = ((nibs[2] << 4) | nibs[3]) <<2; | 
|  | 347 | relmask = ~3; | 
|  | 348 | goto ok; | 
|  | 349 | case IMM_8BY2: | 
|  | 350 | imm = ((nibs[2] << 4) | nibs[3]) <<1; | 
|  | 351 | goto ok; | 
|  | 352 | case IMM_8BY4: | 
|  | 353 | imm = ((nibs[2] << 4) | nibs[3]) <<2; | 
|  | 354 | goto ok; | 
|  | 355 | case DISP_8: | 
|  | 356 | imm = (nibs[2] << 4) | (nibs[3]); | 
|  | 357 | goto ok; | 
|  | 358 | case DISP_4: | 
|  | 359 | imm = nibs[3]; | 
|  | 360 | goto ok; | 
|  | 361 | case REG_N: | 
|  | 362 | rn = nibs[n]; | 
|  | 363 | break; | 
|  | 364 | case REG_M: | 
|  | 365 | rm = nibs[n]; | 
|  | 366 | break; | 
|  | 367 | case REG_NM: | 
|  | 368 | rn = (nibs[n] & 0xc) >> 2; | 
|  | 369 | rm = (nibs[n] & 0x3); | 
|  | 370 | break; | 
|  | 371 | case REG_B: | 
|  | 372 | rb = nibs[n] & 0x07; | 
|  | 373 | break; | 
|  | 374 | default: | 
|  | 375 | return; | 
|  | 376 | } | 
|  | 377 | } | 
|  | 378 |  | 
|  | 379 | ok: | 
|  | 380 | printk("%-8s  ", op->name); | 
|  | 381 | lastsp = (op->arg[0] == A_END); | 
|  | 382 | disp_pc = 0; | 
|  | 383 | for (n = 0; n < 6 && op->arg[n] != A_END; n++) { | 
|  | 384 | if (n && op->arg[1] != A_END) | 
|  | 385 | printk(", "); | 
|  | 386 | switch (op->arg[n]) { | 
|  | 387 | case A_IMM: | 
|  | 388 | printk("#%d", (char)(imm)); | 
|  | 389 | break; | 
|  | 390 | case A_R0: | 
|  | 391 | printk("r0"); | 
|  | 392 | break; | 
|  | 393 | case A_REG_N: | 
|  | 394 | printk("r%d", rn); | 
|  | 395 | break; | 
|  | 396 | case A_INC_N: | 
|  | 397 | printk("@r%d+", rn); | 
|  | 398 | break; | 
|  | 399 | case A_DEC_N: | 
|  | 400 | printk("@-r%d", rn); | 
|  | 401 | break; | 
|  | 402 | case A_IND_N: | 
|  | 403 | printk("@r%d", rn); | 
|  | 404 | break; | 
|  | 405 | case A_DISP_REG_N: | 
|  | 406 | printk("@(%d,r%d)", imm, rn); | 
|  | 407 | break; | 
|  | 408 | case A_REG_M: | 
|  | 409 | printk("r%d", rm); | 
|  | 410 | break; | 
|  | 411 | case A_INC_M: | 
|  | 412 | printk("@r%d+", rm); | 
|  | 413 | break; | 
|  | 414 | case A_DEC_M: | 
|  | 415 | printk("@-r%d", rm); | 
|  | 416 | break; | 
|  | 417 | case A_IND_M: | 
|  | 418 | printk("@r%d", rm); | 
|  | 419 | break; | 
|  | 420 | case A_DISP_REG_M: | 
|  | 421 | printk("@(%d,r%d)", imm, rm); | 
|  | 422 | break; | 
|  | 423 | case A_REG_B: | 
|  | 424 | printk("r%d_bank", rb); | 
|  | 425 | break; | 
|  | 426 | case A_DISP_PC: | 
|  | 427 | disp_pc = 1; | 
|  | 428 | disp_pc_addr = imm + 4 + (memaddr & relmask); | 
|  | 429 | printk("%08x <%pS>", disp_pc_addr, | 
|  | 430 | (void *)disp_pc_addr); | 
|  | 431 | break; | 
|  | 432 | case A_IND_R0_REG_N: | 
|  | 433 | printk("@(r0,r%d)", rn); | 
|  | 434 | break; | 
|  | 435 | case A_IND_R0_REG_M: | 
|  | 436 | printk("@(r0,r%d)", rm); | 
|  | 437 | break; | 
|  | 438 | case A_DISP_GBR: | 
|  | 439 | printk("@(%d,gbr)",imm); | 
|  | 440 | break; | 
|  | 441 | case A_R0_GBR: | 
|  | 442 | printk("@(r0,gbr)"); | 
|  | 443 | break; | 
|  | 444 | case A_BDISP12: | 
|  | 445 | case A_BDISP8: | 
|  | 446 | printk("%08x", imm + memaddr); | 
|  | 447 | break; | 
|  | 448 | case A_SR: | 
|  | 449 | printk("sr"); | 
|  | 450 | break; | 
|  | 451 | case A_GBR: | 
|  | 452 | printk("gbr"); | 
|  | 453 | break; | 
|  | 454 | case A_VBR: | 
|  | 455 | printk("vbr"); | 
|  | 456 | break; | 
|  | 457 | case A_SSR: | 
|  | 458 | printk("ssr"); | 
|  | 459 | break; | 
|  | 460 | case A_SPC: | 
|  | 461 | printk("spc"); | 
|  | 462 | break; | 
|  | 463 | case A_MACH: | 
|  | 464 | printk("mach"); | 
|  | 465 | break; | 
|  | 466 | case A_MACL: | 
|  | 467 | printk("macl"); | 
|  | 468 | break; | 
|  | 469 | case A_PR: | 
|  | 470 | printk("pr"); | 
|  | 471 | break; | 
|  | 472 | case A_SGR: | 
|  | 473 | printk("sgr"); | 
|  | 474 | break; | 
|  | 475 | case A_DBR: | 
|  | 476 | printk("dbr"); | 
|  | 477 | break; | 
|  | 478 | case FD_REG_N: | 
|  | 479 | if (0) | 
|  | 480 | goto d_reg_n; | 
|  | 481 | case F_REG_N: | 
|  | 482 | printk("fr%d", rn); | 
|  | 483 | break; | 
|  | 484 | case F_REG_M: | 
|  | 485 | printk("fr%d", rm); | 
|  | 486 | break; | 
|  | 487 | case DX_REG_N: | 
|  | 488 | if (rn & 1) { | 
|  | 489 | printk("xd%d", rn & ~1); | 
|  | 490 | break; | 
|  | 491 | } | 
|  | 492 | d_reg_n: | 
|  | 493 | case D_REG_N: | 
|  | 494 | printk("dr%d", rn); | 
|  | 495 | break; | 
|  | 496 | case DX_REG_M: | 
|  | 497 | if (rm & 1) { | 
|  | 498 | printk("xd%d", rm & ~1); | 
|  | 499 | break; | 
|  | 500 | } | 
|  | 501 | case D_REG_M: | 
|  | 502 | printk("dr%d", rm); | 
|  | 503 | break; | 
|  | 504 | case FPSCR_M: | 
|  | 505 | case FPSCR_N: | 
|  | 506 | printk("fpscr"); | 
|  | 507 | break; | 
|  | 508 | case FPUL_M: | 
|  | 509 | case FPUL_N: | 
|  | 510 | printk("fpul"); | 
|  | 511 | break; | 
|  | 512 | case F_FR0: | 
|  | 513 | printk("fr0"); | 
|  | 514 | break; | 
|  | 515 | case V_REG_N: | 
|  | 516 | printk("fv%d", rn*4); | 
|  | 517 | break; | 
|  | 518 | case V_REG_M: | 
|  | 519 | printk("fv%d", rm*4); | 
|  | 520 | break; | 
|  | 521 | case XMTRX_M4: | 
|  | 522 | printk("xmtrx"); | 
|  | 523 | break; | 
|  | 524 | default: | 
|  | 525 | return; | 
|  | 526 | } | 
|  | 527 | } | 
|  | 528 |  | 
|  | 529 | if (disp_pc && strcmp(op->name, "mova") != 0) { | 
|  | 530 | u32 val; | 
|  | 531 |  | 
|  | 532 | if (relmask == ~1) | 
|  | 533 | __get_user(val, (u16 *)disp_pc_addr); | 
|  | 534 | else | 
|  | 535 | __get_user(val, (u32 *)disp_pc_addr); | 
|  | 536 |  | 
|  | 537 | printk("  ! %08x <%pS>", val, (void *)val); | 
|  | 538 | } | 
|  | 539 |  | 
|  | 540 | return; | 
|  | 541 | fail: | 
|  | 542 | ; | 
|  | 543 |  | 
|  | 544 | } | 
|  | 545 |  | 
|  | 546 | printk(".word 0x%x%x%x%x", nibs[0], nibs[1], nibs[2], nibs[3]); | 
|  | 547 | } | 
|  | 548 |  | 
|  | 549 | void show_code(struct pt_regs *regs) | 
|  | 550 | { | 
|  | 551 | unsigned short *pc = (unsigned short *)regs->pc; | 
|  | 552 | long i; | 
|  | 553 |  | 
|  | 554 | if (regs->pc & 0x1) | 
|  | 555 | return; | 
|  | 556 |  | 
|  | 557 | printk("Code:\n"); | 
|  | 558 |  | 
|  | 559 | for (i = -3 ; i < 6 ; i++) { | 
|  | 560 | unsigned short insn; | 
|  | 561 |  | 
|  | 562 | if (__get_user(insn, pc + i)) { | 
|  | 563 | printk(" (Bad address in pc)\n"); | 
|  | 564 | break; | 
|  | 565 | } | 
|  | 566 |  | 
|  | 567 | printk("%s%08lx:  ", (i ? "  ": "->"), (unsigned long)(pc + i)); | 
|  | 568 | print_sh_insn((unsigned long)(pc + i), insn); | 
|  | 569 | printk("\n"); | 
|  | 570 | } | 
|  | 571 |  | 
|  | 572 | printk("\n"); | 
|  | 573 | } |