OLD | NEW |
(Empty) | |
| 1 // Copyright 2011-2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are |
| 4 // met: |
| 5 // |
| 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided |
| 11 // with the distribution. |
| 12 // * Neither the name of Google Inc. nor the names of its |
| 13 // contributors may be used to endorse or promote products derived |
| 14 // from this software without specific prior written permission. |
| 15 // |
| 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 |
| 28 #include "v8.h" |
| 29 |
| 30 #if defined(V8_TARGET_ARCH_SH4) |
| 31 |
| 32 #include "constants-sh4.h" |
| 33 #include "disasm.h" |
| 34 #include "macro-assembler.h" |
| 35 #include "platform.h" |
| 36 |
| 37 // Due to GPL licencing of the opcodes-disasm-sh4.c file, if you enable the |
| 38 // part of code surrounded by USE_KERNEL_DISASM, the the whole project became |
| 39 // GPL. |
| 40 |
| 41 //------------------------------------------------------------------------------ |
| 42 |
| 43 |
| 44 namespace v8 { |
| 45 namespace internal { |
| 46 |
| 47 |
| 48 //------------------------------------------------------------------------------ |
| 49 |
| 50 #ifdef USE_KERNEL_DISASM |
| 51 # define V8_IN_TYPE_DECLS 1 |
| 52 # include "opcodes-disasm-sh4.c" |
| 53 # undef V8_IN_TYPE_DECLS |
| 54 #endif /* USE_KERNEL_DISASM */ |
| 55 |
| 56 // Decoder decodes and disassembles instructions into an output buffer. |
| 57 // It uses the converter to convert register names and call destinations into |
| 58 // more informative description. |
| 59 class Decoder { |
| 60 public: |
| 61 explicit Decoder(Vector<char> out_buffer) |
| 62 : out_buffer_(out_buffer), |
| 63 out_buffer_pos_(0), |
| 64 last_pool_offset_(0), |
| 65 last_pool_size_(0) { |
| 66 out_buffer_[out_buffer_pos_] = '\0'; |
| 67 } |
| 68 |
| 69 ~Decoder() {} |
| 70 |
| 71 // Writes one disassembled instruction into 'buffer' (0-terminated). |
| 72 // Returns the length of the disassembled machine instruction in bytes. |
| 73 int InstructionDecode(byte* instruction); |
| 74 |
| 75 #ifndef USE_KERNEL_DISASM |
| 76 // All Decode... function are decoding the set of instructions |
| 77 // from the tables defined in thhe architecture manual. |
| 78 // From Architecture Manual ADCS 7182230G SH-4 CPU Core Architecture |
| 79 // Revision: 30 April 2003 |
| 80 // Section 7.3, p. 149: Instruciton set summary |
| 81 |
| 82 // Decode instructions from Table 39, p.150 |
| 83 int DecodeTable39(Instruction* instr); |
| 84 #endif /* !USE_KERNEL_DISASM */ |
| 85 |
| 86 |
| 87 // Returns the offset from the current PC (before the instruction) |
| 88 // and size of the reference if a PC relative dereference was decoded. |
| 89 int LastPoolSize(); |
| 90 int LastPoolReference(); |
| 91 |
| 92 private: |
| 93 // Print a formated stream. |
| 94 void Format(const char *format, ...); |
| 95 |
| 96 #if USE_KERNEL_DISASM |
| 97 // This method is implemented in opcodes-disasm-sh4.c |
| 98 void print_sh_insn(uint32_t memaddr, uint16_t insn); |
| 99 #endif /* USE_KERNEL_DISASM */ |
| 100 |
| 101 Vector<char> out_buffer_; |
| 102 int out_buffer_pos_; |
| 103 int last_pool_offset_; |
| 104 int last_pool_size_; |
| 105 |
| 106 DISALLOW_COPY_AND_ASSIGN(Decoder); |
| 107 }; |
| 108 |
| 109 #if USE_KERNEL_DISASM |
| 110 # define printk Format |
| 111 # define __get_user(val, ptr) \ |
| 112 do { last_pool_offset_ = (u32)(ptr) - memaddr;\ |
| 113 last_pool_size_ = sizeof(*(ptr)); \ |
| 114 ((val) = *(ptr)); } while (0) |
| 115 # define u16 uint16_t |
| 116 # define u32 uint32_t |
| 117 # include "opcodes-disasm-sh4.c" |
| 118 # undef u16 |
| 119 # undef u32 |
| 120 # undef __get_user |
| 121 # undef printk |
| 122 #endif /* USE_KERNEL_DISASM */ |
| 123 |
| 124 |
| 125 void Decoder::Format(const char *format, ...) { |
| 126 va_list args; |
| 127 va_start(args, format); |
| 128 out_buffer_pos_ += OS::VSNPrintF(out_buffer_ + out_buffer_pos_, format, args); |
| 129 va_end(args); |
| 130 } |
| 131 |
| 132 |
| 133 int Decoder::InstructionDecode(byte* instr_ptr) { |
| 134 uint16_t bits = *reinterpret_cast<const uint16_t *>(instr_ptr); |
| 135 // Print raw instruction bytes. |
| 136 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| 137 "%02x %02x ", |
| 138 (bits & 0xff), ((bits>>8) & 0xff)); |
| 139 |
| 140 #ifdef USE_KERNEL_DISASM |
| 141 uint32_t pc = (uint32_t)(instr_ptr); |
| 142 print_sh_insn(pc, bits); |
| 143 #else |
| 144 Instruction* instr = Instruction::At(instr_ptr); |
| 145 DecodeTable39(instr); |
| 146 #endif /* USE_KERNEL_DISASM */ |
| 147 |
| 148 return Instruction::kInstrSize; |
| 149 } |
| 150 |
| 151 |
| 152 #ifndef USE_KERNEL_DISASM |
| 153 |
| 154 #define FMT_T39_1 1 |
| 155 #define FMT_T39_1_FMT "\t%s\t#%d,%s" |
| 156 #define FMT_T39_1_i8(instr) (instr->SBits(7, 0)) |
| 157 #define FMT_T39_1_n(instr) (instr->Bits(11, 8)) |
| 158 #define FMT_T39_1_OPC(instr) (instr->Bits(15, 12)) |
| 159 #define FMT_T39_1_STR "mov" |
| 160 |
| 161 #define FMT_T39_2 2 |
| 162 #define FMT_T39_2_FMT "\t%s\t@(%u,pc),%s" |
| 163 #define FMT_T39_2_d8(instr) (instr->Bits(7, 0)) |
| 164 #define FMT_T39_2_n(instr) FMT_T39_1_n(instr) |
| 165 #define FMT_T39_2_OPC(instr) FMT_T39_1_OPC(instr) |
| 166 #define FMT_T39_2_STR "mov.w" |
| 167 |
| 168 #define FMT_T39_3 3 |
| 169 #define FMT_T39_3_FMT FMT_T39_2_FMT |
| 170 #define FMT_T39_3_d8(instr) FMT_T39_2_d8(instr) |
| 171 #define FMT_T39_3_n(instr) FMT_T39_2_n(instr) |
| 172 #define FMT_T39_3_OPC(instr) FMT_T39_1_OPC(instr) |
| 173 #define FMT_T39_3_STR "mov.l" |
| 174 |
| 175 #define FMT_T39_4 4 |
| 176 #define FMT_T39_4_FMT "\t%s\t%s,%s" |
| 177 #define FMT_T39_4_m(instr) (instr->Bits(7, 4)) |
| 178 #define FMT_T39_4_n(instr) FMT_T39_1_n(instr) |
| 179 #define FMT_T39_4_OPC(instr) FMT_T39_1_OPC(instr) |
| 180 #define FMT_T39_4_OPC2(instr) (instr->Bits(3, 0)) |
| 181 #define FMT_T39_4_STR "mov" |
| 182 |
| 183 #define FMT_T39_5 5 |
| 184 #define FMT_T39_5_FMT "\t%s\t%s,@%s" |
| 185 #define FMT_T39_5_m(instr) FMT_T39_4_m(instr) |
| 186 #define FMT_T39_5_n(instr) FMT_T39_1_n(instr) |
| 187 #define FMT_T39_5_OPC(instr) FMT_T39_1_OPC(instr) |
| 188 #define FMT_T39_5_OPC2(instr) FMT_T39_4_OPC2(instr) |
| 189 #define FMT_T39_5_STR "mov.b" |
| 190 |
| 191 #define FMT_T39_6 6 |
| 192 #define FMT_T39_6_FMT FMT_T39_5_FMT |
| 193 #define FMT_T39_6_m(instr) FMT_T39_4_m(instr) |
| 194 #define FMT_T39_6_n(instr) FMT_T39_1_n(instr) |
| 195 #define FMT_T39_6_OPC(instr) FMT_T39_1_OPC(instr) |
| 196 #define FMT_T39_6_OPC2(instr) FMT_T39_4_OPC2(instr) |
| 197 #define FMT_T39_6_STR "mov.w" |
| 198 |
| 199 #define FMT_T39_7 7 |
| 200 #define FMT_T39_7_FMT FMT_T39_5_FMT |
| 201 #define FMT_T39_7_m(instr) FMT_T39_4_m(instr) |
| 202 #define FMT_T39_7_n(instr) FMT_T39_1_n(instr) |
| 203 #define FMT_T39_7_OPC(instr) FMT_T39_1_OPC(instr) |
| 204 #define FMT_T39_7_OPC2(instr) FMT_T39_4_OPC2(instr) |
| 205 #define FMT_T39_7_STR "mov.l" |
| 206 |
| 207 #define FMT_T39_8 8 |
| 208 #define FMT_T39_8_FMT "\t%s\t@%s,%s" |
| 209 #define FMT_T39_8_m(instr) FMT_T39_4_m(instr) |
| 210 #define FMT_T39_8_n(instr) FMT_T39_1_n(instr) |
| 211 #define FMT_T39_8_OPC(instr) FMT_T39_1_OPC(instr) |
| 212 #define FMT_T39_8_OPC2(instr) FMT_T39_4_OPC2(instr) |
| 213 #define FMT_T39_8_STR "mov.b" |
| 214 |
| 215 #define FMT_T39_9 9 |
| 216 #define FMT_T39_9_FMT FMT_T39_8_FMT |
| 217 #define FMT_T39_9_m(instr) FMT_T39_4_m(instr) |
| 218 #define FMT_T39_9_n(instr) FMT_T39_1_n(instr) |
| 219 #define FMT_T39_9_OPC(instr) FMT_T39_1_OPC(instr) |
| 220 #define FMT_T39_9_OPC2(instr) FMT_T39_4_OPC2(instr) |
| 221 #define FMT_T39_9_STR "mov.w" |
| 222 |
| 223 #define FMT_T39_10 10 |
| 224 #define FMT_T39_10_FMT FMT_T39_8_FMT |
| 225 #define FMT_T39_10_m(instr) FMT_T39_4_m(instr) |
| 226 #define FMT_T39_10_n(instr) FMT_T39_1_n(instr) |
| 227 #define FMT_T39_10_OPC(instr) FMT_T39_1_OPC(instr) |
| 228 #define FMT_T39_10_OPC2(instr) FMT_T39_4_OPC2(instr) |
| 229 #define FMT_T39_10_STR "mov.l" |
| 230 |
| 231 #define FMT_T39_11 11 |
| 232 #define FMT_T39_11_FMT "\t%s\t%s,@-%s" |
| 233 #define FMT_T39_11_m(instr) FMT_T39_4_m(instr) |
| 234 #define FMT_T39_11_n(instr) FMT_T39_1_n(instr) |
| 235 #define FMT_T39_11_OPC(instr) FMT_T39_1_OPC(instr) |
| 236 #define FMT_T39_11_OPC2(instr) FMT_T39_4_OPC2(instr) |
| 237 #define FMT_T39_11_STR "mov.b" |
| 238 |
| 239 #define FMT_T39_12 12 |
| 240 #define FMT_T39_12_FMT FMT_T39_11_FMT |
| 241 #define FMT_T39_12_m(instr) FMT_T39_4_m(instr) |
| 242 #define FMT_T39_12_n(instr) FMT_T39_1_n(instr) |
| 243 #define FMT_T39_12_OPC(instr) FMT_T39_1_OPC(instr) |
| 244 #define FMT_T39_12_OPC2(instr) FMT_T39_4_OPC2(instr) |
| 245 #define FMT_T39_12_STR "mov.w" |
| 246 |
| 247 #define FMT_T39_13 13 |
| 248 #define FMT_T39_13_FMT FMT_T39_11_FMT |
| 249 #define FMT_T39_13_m(instr) FMT_T39_4_m(instr) |
| 250 #define FMT_T39_13_n(instr) FMT_T39_1_n(instr) |
| 251 #define FMT_T39_13_OPC(instr) FMT_T39_1_OPC(instr) |
| 252 #define FMT_T39_13_OPC2(instr) FMT_T39_4_OPC2(instr) |
| 253 #define FMT_T39_13_STR "mov.l" |
| 254 |
| 255 #define FMT_T39_14 14 |
| 256 #define FMT_T39_14_FMT "\t%s\t@%s+,%s" |
| 257 #define FMT_T39_14_m(instr) FMT_T39_4_m(instr) |
| 258 #define FMT_T39_14_n(instr) FMT_T39_1_n(instr) |
| 259 #define FMT_T39_14_OPC(instr) FMT_T39_1_OPC(instr) |
| 260 #define FMT_T39_14_OPC2(instr) FMT_T39_4_OPC2(instr) |
| 261 #define FMT_T39_14_STR "mov.b" |
| 262 |
| 263 #define FMT_T39_15 15 |
| 264 #define FMT_T39_15_FMT FMT_T39_14_FMT |
| 265 #define FMT_T39_15_m(instr) FMT_T39_4_m(instr) |
| 266 #define FMT_T39_15_n(instr) FMT_T39_1_n(instr) |
| 267 #define FMT_T39_15_OPC(instr) FMT_T39_1_OPC(instr) |
| 268 #define FMT_T39_15_OPC2(instr) FMT_T39_4_OPC2(instr) |
| 269 #define FMT_T39_15_STR "mov.w" |
| 270 |
| 271 #define FMT_T39_16 16 |
| 272 #define FMT_T39_16_FMT FMT_T39_14_FMT |
| 273 #define FMT_T39_16_m(instr) FMT_T39_4_m(instr) |
| 274 #define FMT_T39_16_n(instr) FMT_T39_1_n(instr) |
| 275 #define FMT_T39_16_OPC(instr) FMT_T39_1_OPC(instr) |
| 276 #define FMT_T39_16_OPC2(instr) FMT_T39_4_OPC2(instr) |
| 277 #define FMT_T39_16_STR "mov.l" |
| 278 |
| 279 #define FMT_T39_17 17 |
| 280 #define FMT_T39_17_FMT "\t%s\tr0,@(%u,%s)" |
| 281 #define FMT_T39_17_d(instr) (instr->Bits(3, 0)) |
| 282 #define FMT_T39_17_n(instr) (instr->Bits(7, 4)) |
| 283 #define FMT_T39_17_OPC(instr) FMT_T39_1_OPC(instr) |
| 284 #define FMT_T39_17_OPC3(instr) (instr->Bits(11, 8)) |
| 285 #define FMT_T39_17_STR "mov.b" |
| 286 |
| 287 #define FMT_T39_18 18 |
| 288 #define FMT_T39_18_FMT FMT_T39_17_FMT |
| 289 #define FMT_T39_18_d(instr) FMT_T39_17_d(instr) |
| 290 #define FMT_T39_18_n(instr) FMT_T39_17_n(instr) |
| 291 #define FMT_T39_18_OPC(instr) FMT_T39_1_OPC(instr) |
| 292 #define FMT_T39_18_OPC3(instr) FMT_T39_17_OPC3(instr) |
| 293 #define FMT_T39_18_STR "mov.w" |
| 294 |
| 295 #define FMT_T39_19 19 |
| 296 #define FMT_T39_19_FMT "\t%s\t%s,@(%u,%s)" |
| 297 #define FMT_T39_19_d(instr) FMT_T39_17_d(instr) |
| 298 #define FMT_T39_19_m(instr) FMT_T39_4_m(instr) |
| 299 #define FMT_T39_19_n(instr) FMT_T39_1_n(instr) |
| 300 #define FMT_T39_19_OPC(instr) FMT_T39_1_OPC(instr) |
| 301 #define FMT_T39_19_STR "mov.l" |
| 302 |
| 303 #define FMT_T39_20 20 |
| 304 #define FMT_T39_20_FMT "\t%s\t@(%u,%s),r0" |
| 305 #define FMT_T39_20_d(instr) FMT_T39_17_d(instr) |
| 306 #define FMT_T39_20_m(instr) FMT_T39_4_m(instr) |
| 307 #define FMT_T39_20_OPC(instr) FMT_T39_1_OPC(instr) |
| 308 #define FMT_T39_20_OPC3(instr) FMT_T39_17_OPC3(instr) |
| 309 #define FMT_T39_20_STR "mov.b" |
| 310 |
| 311 #define FMT_T39_21 21 |
| 312 #define FMT_T39_21_FMT FMT_T39_20_FMT |
| 313 #define FMT_T39_21_d(instr) FMT_T39_17_d(instr) |
| 314 #define FMT_T39_21_m(instr) FMT_T39_20_m(instr) |
| 315 #define FMT_T39_21_OPC(instr) FMT_T39_1_OPC(instr) |
| 316 #define FMT_T39_21_OPC3(instr) FMT_T39_17_OPC3(instr) |
| 317 #define FMT_T39_21_STR "mov.w" |
| 318 |
| 319 #define FMT_T39_22 22 |
| 320 #define FMT_T39_22_FMT "\t%s\t@(%u,%s),%s" |
| 321 #define FMT_T39_22_d(instr) FMT_T39_17_d(instr) |
| 322 #define FMT_T39_22_m(instr) FMT_T39_4_m(instr) |
| 323 #define FMT_T39_22_n(instr) FMT_T39_1_n(instr) |
| 324 #define FMT_T39_22_OPC(instr) FMT_T39_1_OPC(instr) |
| 325 #define FMT_T39_22_STR "mov.l" |
| 326 |
| 327 #define FMT_T39_23 23 |
| 328 #define FMT_T39_23_FMT "\t%s\t%s,@(r0,%s)" |
| 329 #define FMT_T39_23_m(instr) FMT_T39_4_m(instr) |
| 330 #define FMT_T39_23_n(instr) FMT_T39_1_n(instr) |
| 331 #define FMT_T39_23_OPC(instr) FMT_T39_1_OPC(instr) |
| 332 #define FMT_T39_23_OPC2(instr) FMT_T39_4_OPC2(instr) |
| 333 #define FMT_T39_23_STR "mov.b" |
| 334 |
| 335 #define FMT_T39_24 24 |
| 336 #define FMT_T39_24_FMT FMT_T39_23_FMT |
| 337 #define FMT_T39_24_m(instr) FMT_T39_4_m(instr) |
| 338 #define FMT_T39_24_n(instr) FMT_T39_1_n(instr) |
| 339 #define FMT_T39_24_OPC(instr) FMT_T39_1_OPC(instr) |
| 340 #define FMT_T39_24_OPC2(instr) FMT_T39_4_OPC2(instr) |
| 341 #define FMT_T39_24_STR "mov.w" |
| 342 |
| 343 #define FMT_T39_25 25 |
| 344 #define FMT_T39_25_FMT FMT_T39_23_FMT |
| 345 #define FMT_T39_25_m(instr) FMT_T39_4_m(instr) |
| 346 #define FMT_T39_25_n(instr) FMT_T39_1_n(instr) |
| 347 #define FMT_T39_25_OPC(instr) FMT_T39_1_OPC(instr) |
| 348 #define FMT_T39_25_OPC2(instr) FMT_T39_4_OPC2(instr) |
| 349 #define FMT_T39_25_STR "mov.l" |
| 350 |
| 351 |
| 352 #define FMT_T39_26 26 |
| 353 #define FMT_T39_26_FMT "\t%s\t@(r0,%s),%s" |
| 354 #define FMT_T39_26_m(instr) FMT_T39_4_m(instr) |
| 355 #define FMT_T39_26_n(instr) FMT_T39_1_n(instr) |
| 356 #define FMT_T39_26_OPC(instr) FMT_T39_1_OPC(instr) |
| 357 #define FMT_T39_26_OPC2(instr) FMT_T39_4_OPC2(instr) |
| 358 #define FMT_T39_26_STR "mov.b" |
| 359 |
| 360 #define FMT_T39_27 27 |
| 361 #define FMT_T39_27_FMT FMT_T39_26_FMT |
| 362 #define FMT_T39_27_m(instr) FMT_T39_4_m(instr) |
| 363 #define FMT_T39_27_n(instr) FMT_T39_1_n(instr) |
| 364 #define FMT_T39_27_OPC(instr) FMT_T39_1_OPC(instr) |
| 365 #define FMT_T39_27_OPC2(instr) FMT_T39_4_OPC2(instr) |
| 366 #define FMT_T39_27_STR "mov.w" |
| 367 |
| 368 #define FMT_T39_28 28 |
| 369 #define FMT_T39_28_FMT FMT_T39_23_FMT |
| 370 #define FMT_T39_28_m(instr) FMT_T39_4_m(instr) |
| 371 #define FMT_T39_28_n(instr) FMT_T39_1_n(instr) |
| 372 #define FMT_T39_28_OPC(instr) FMT_T39_1_OPC(instr) |
| 373 #define FMT_T39_28_OPC2(instr) FMT_T39_4_OPC2(instr) |
| 374 #define FMT_T39_28_STR "mov.l" |
| 375 |
| 376 |
| 377 enum OPC { |
| 378 FMT_T39_1_OPC_MOV = 0xe, |
| 379 FMT_T39_2_OPC_MOV_W = 0x9, |
| 380 FMT_T39_3_OPC_MOV_L = 0xd, |
| 381 FMT_T39_4_OPC_MOV = 0x6, |
| 382 FMT_T39_5_OPC_MOV_B = 0x2, |
| 383 FMT_T39_17_OPC_MOV_B = 0x8, |
| 384 FMT_T39_19_OPC_MOV_L = 0x1, |
| 385 FMT_T39_22_OPC_MOV_L = 0x5, |
| 386 FMT_T39_23_OPC_MOV_B = 0x0 |
| 387 }; |
| 388 |
| 389 enum OPC2 { |
| 390 FMT_T39_4_OPC2_MOV = 0x3, |
| 391 FMT_T39_5_OPC2_MOV_B = 0x0, |
| 392 FMT_T39_6_OPC2_MOV_W = 0x1, |
| 393 FMT_T39_7_OPC2_MOV_L = 0x2, |
| 394 FMT_T39_8_OPC2_MOV_B = 0x0, |
| 395 FMT_T39_9_OPC2_MOV_W = 0x1, |
| 396 FMT_T39_10_OPC2_MOV_L = 0x2, |
| 397 FMT_T39_11_OPC2_MOV_B = 0x4, |
| 398 FMT_T39_12_OPC2_MOV_W = 0x5, |
| 399 FMT_T39_13_OPC2_MOV_L = 0x6, |
| 400 FMT_T39_14_OPC2_MOV_B = 0x4, |
| 401 FMT_T39_15_OPC2_MOV_W = 0x5, |
| 402 FMT_T39_16_OPC2_MOV_L = 0x6, |
| 403 FMT_T39_23_OPC2_MOV_B = 0x4, |
| 404 FMT_T39_24_OPC2_MOV_W = 0x5, |
| 405 FMT_T39_25_OPC2_MOV_L = 0x6, |
| 406 FMT_T39_26_OPC2_MOV_B = 0xc, |
| 407 FMT_T39_27_OPC2_MOV_W = 0xd, |
| 408 FMT_T39_28_OPC2_MOV_L = 0xe |
| 409 }; |
| 410 |
| 411 enum OPC3 { |
| 412 FMT_T39_17_OPC3_MOV_B = 0x0, |
| 413 FMT_T39_18_OPC3_MOV_W = 0x1, |
| 414 FMT_T39_20_OPC3_MOV_B = 0x4, |
| 415 FMT_T39_21_OPC3_MOV_W = 0x5 |
| 416 }; |
| 417 |
| 418 int Decoder::DecodeTable39(Instruction *instr) { |
| 419 switch (FMT_T39_1_OPC(instr)) { |
| 420 #ifdef FMT_T39_1 |
| 421 case FMT_T39_1_OPC_MOV: |
| 422 Format(FMT_T39_1_FMT, FMT_T39_1_STR, |
| 423 FMT_T39_1_i8(instr), |
| 424 Registers::Name(FMT_T39_1_n(instr))); |
| 425 break; |
| 426 #endif |
| 427 #ifdef FMT_T39_2 |
| 428 case FMT_T39_2_OPC_MOV_W: |
| 429 Format(FMT_T39_2_FMT, FMT_T39_2_STR, |
| 430 FMT_T39_2_d8(instr), |
| 431 Registers::Name(FMT_T39_2_n(instr))); |
| 432 break; |
| 433 #endif |
| 434 #ifdef FMT_T39_3 |
| 435 case FMT_T39_3_OPC_MOV_L: |
| 436 Format(FMT_T39_3_FMT, FMT_T39_3_STR, |
| 437 FMT_T39_3_d8(instr), |
| 438 Registers::Name(FMT_T39_3_n(instr))); |
| 439 break; |
| 440 #endif |
| 441 case FMT_T39_4_OPC_MOV: |
| 442 switch (FMT_T39_4_OPC2(instr)) { |
| 443 #ifdef FMT_T39_4 |
| 444 case FMT_T39_4_OPC2_MOV: |
| 445 Format(FMT_T39_4_FMT, FMT_T39_4_STR, |
| 446 Registers::Name(FMT_T39_4_m(instr)), |
| 447 Registers::Name(FMT_T39_4_n(instr))); |
| 448 break; |
| 449 #endif |
| 450 #ifdef FMT_T39_8 |
| 451 case FMT_T39_8_OPC2_MOV_B: |
| 452 Format(FMT_T39_8_FMT, FMT_T39_8_STR, |
| 453 Registers::Name(FMT_T39_8_m(instr)), |
| 454 Registers::Name(FMT_T39_8_n(instr))); |
| 455 break; |
| 456 #endif |
| 457 #ifdef FMT_T39_9 |
| 458 case FMT_T39_9_OPC2_MOV_W: |
| 459 Format(FMT_T39_9_FMT, FMT_T39_9_STR, |
| 460 Registers::Name(FMT_T39_9_m(instr)), |
| 461 Registers::Name(FMT_T39_9_n(instr))); |
| 462 break; |
| 463 #endif |
| 464 #ifdef FMT_T39_10 |
| 465 case FMT_T39_10_OPC2_MOV_L: |
| 466 Format(FMT_T39_10_FMT, FMT_T39_10_STR, |
| 467 Registers::Name(FMT_T39_10_m(instr)), |
| 468 Registers::Name(FMT_T39_10_n(instr))); |
| 469 break; |
| 470 #endif |
| 471 #ifdef FMT_T39_14 |
| 472 case FMT_T39_14_OPC2_MOV_B: |
| 473 Format(FMT_T39_14_FMT, FMT_T39_14_STR, |
| 474 Registers::Name(FMT_T39_14_m(instr)), |
| 475 Registers::Name(FMT_T39_14_n(instr))); |
| 476 break; |
| 477 #endif |
| 478 #ifdef FMT_T39_15 |
| 479 case FMT_T39_15_OPC2_MOV_W: |
| 480 Format(FMT_T39_15_FMT, FMT_T39_15_STR, |
| 481 Registers::Name(FMT_T39_15_m(instr)), |
| 482 Registers::Name(FMT_T39_15_n(instr))); |
| 483 break; |
| 484 #endif |
| 485 #ifdef FMT_T39_16 |
| 486 case FMT_T39_16_OPC2_MOV_L: |
| 487 Format(FMT_T39_16_FMT, FMT_T39_16_STR, |
| 488 Registers::Name(FMT_T39_16_m(instr)), |
| 489 Registers::Name(FMT_T39_16_n(instr))); |
| 490 break; |
| 491 #endif |
| 492 default: |
| 493 return 0; |
| 494 } |
| 495 break; |
| 496 case FMT_T39_5_OPC_MOV_B: |
| 497 switch (FMT_T39_5_OPC2(instr)) { |
| 498 #ifdef FMT_T39_5 |
| 499 case FMT_T39_5_OPC2_MOV_B: |
| 500 Format(FMT_T39_5_FMT, FMT_T39_5_STR, |
| 501 Registers::Name(FMT_T39_5_m(instr)), |
| 502 Registers::Name(FMT_T39_5_n(instr))); |
| 503 break; |
| 504 #endif |
| 505 #ifdef FMT_T39_6 |
| 506 case FMT_T39_6_OPC2_MOV_W: |
| 507 Format(FMT_T39_6_FMT, FMT_T39_6_STR, |
| 508 Registers::Name(FMT_T39_6_m(instr)), |
| 509 Registers::Name(FMT_T39_6_n(instr))); |
| 510 break; |
| 511 #endif |
| 512 #ifdef FMT_T39_7 |
| 513 case FMT_T39_7_OPC2_MOV_L: |
| 514 Format(FMT_T39_7_FMT, FMT_T39_7_STR, |
| 515 Registers::Name(FMT_T39_7_m(instr)), |
| 516 Registers::Name(FMT_T39_7_n(instr))); |
| 517 break; |
| 518 #endif |
| 519 #ifdef FMT_T39_11 |
| 520 case FMT_T39_11_OPC2_MOV_B: |
| 521 Format(FMT_T39_11_FMT, FMT_T39_11_STR, |
| 522 Registers::Name(FMT_T39_11_m(instr)), |
| 523 Registers::Name(FMT_T39_11_n(instr))); |
| 524 break; |
| 525 #endif |
| 526 #ifdef FMT_T39_12 |
| 527 case FMT_T39_12_OPC2_MOV_W: |
| 528 Format(FMT_T39_12_FMT, FMT_T39_12_STR, |
| 529 Registers::Name(FMT_T39_12_m(instr)), |
| 530 Registers::Name(FMT_T39_12_n(instr))); |
| 531 break; |
| 532 #endif |
| 533 #ifdef FMT_T39_13 |
| 534 case FMT_T39_13_OPC2_MOV_L: |
| 535 Format(FMT_T39_13_FMT, FMT_T39_13_STR, |
| 536 Registers::Name(FMT_T39_13_m(instr)), |
| 537 Registers::Name(FMT_T39_13_n(instr))); |
| 538 break; |
| 539 #endif |
| 540 default: |
| 541 return 0; |
| 542 } |
| 543 break; |
| 544 case FMT_T39_17_OPC_MOV_B: |
| 545 switch (FMT_T39_17_OPC3(instr)) { |
| 546 #ifdef FMT_T39_17 |
| 547 case FMT_T39_17_OPC3_MOV_B: |
| 548 Format(FMT_T39_17_FMT, FMT_T39_17_STR, |
| 549 FMT_T39_17_d(instr), |
| 550 Registers::Name(FMT_T39_17_n(instr))); |
| 551 break; |
| 552 #endif |
| 553 #ifdef FMT_T39_18 |
| 554 case FMT_T39_18_OPC3_MOV_W: |
| 555 Format(FMT_T39_18_FMT, FMT_T39_18_STR, |
| 556 FMT_T39_18_d(instr), |
| 557 Registers::Name(FMT_T39_18_n(instr))); |
| 558 break; |
| 559 #endif |
| 560 #ifdef FMT_T39_20 |
| 561 case FMT_T39_20_OPC3_MOV_B: |
| 562 Format(FMT_T39_20_FMT, FMT_T39_20_STR, |
| 563 FMT_T39_20_d(instr), |
| 564 Registers::Name(FMT_T39_20_m(instr))); |
| 565 break; |
| 566 #endif |
| 567 #ifdef FMT_T39_21 |
| 568 case FMT_T39_21_OPC3_MOV_W: |
| 569 Format(FMT_T39_21_FMT, FMT_T39_21_STR, |
| 570 FMT_T39_21_d(instr), |
| 571 Registers::Name(FMT_T39_21_m(instr))); |
| 572 break; |
| 573 #endif |
| 574 default: |
| 575 return 0; |
| 576 } |
| 577 break; |
| 578 #ifdef FMT_T39_19 |
| 579 case FMT_T39_19_OPC_MOV_L: |
| 580 Format(FMT_T39_19_FMT, FMT_T39_19_STR, |
| 581 Registers::Name(FMT_T39_19_m(instr)), |
| 582 FMT_T39_19_d(instr), |
| 583 Registers::Name(FMT_T39_19_n(instr))); |
| 584 break; |
| 585 #endif |
| 586 #ifdef FMT_T39_22 |
| 587 case FMT_T39_22_OPC_MOV_L: |
| 588 Format(FMT_T39_22_FMT, FMT_T39_22_STR, |
| 589 FMT_T39_22_d(instr), |
| 590 Registers::Name(FMT_T39_22_m(instr)), |
| 591 Registers::Name(FMT_T39_22_n(instr))); |
| 592 break; |
| 593 #endif |
| 594 case FMT_T39_23_OPC_MOV_B: |
| 595 switch (FMT_T39_23_OPC2(instr)) { |
| 596 #ifdef FMT_T39_23 |
| 597 case FMT_T39_23_OPC2_MOV_B: |
| 598 Format(FMT_T39_23_FMT, FMT_T39_23_STR, |
| 599 Registers::Name(FMT_T39_23_m(instr)), |
| 600 Registers::Name(FMT_T39_23_n(instr))); |
| 601 break; |
| 602 #endif |
| 603 #ifdef FMT_T39_24 |
| 604 case FMT_T39_24_OPC2_MOV_W: |
| 605 Format(FMT_T39_24_FMT, FMT_T39_24_STR, |
| 606 Registers::Name(FMT_T39_24_m(instr)), |
| 607 Registers::Name(FMT_T39_24_n(instr))); |
| 608 break; |
| 609 #endif |
| 610 #ifdef FMT_T39_25 |
| 611 case FMT_T39_25_OPC2_MOV_L: |
| 612 Format(FMT_T39_25_FMT, FMT_T39_25_STR, |
| 613 Registers::Name(FMT_T39_25_m(instr)), |
| 614 Registers::Name(FMT_T39_25_n(instr))); |
| 615 break; |
| 616 #endif |
| 617 #ifdef FMT_T39_26 |
| 618 case FMT_T39_26_OPC2_MOV_B: |
| 619 Format(FMT_T39_26_FMT, FMT_T39_26_STR, |
| 620 Registers::Name(FMT_T39_26_m(instr)), |
| 621 Registers::Name(FMT_T39_26_n(instr))); |
| 622 break; |
| 623 #endif |
| 624 #ifdef FMT_T39_27 |
| 625 case FMT_T39_27_OPC2_MOV_W: |
| 626 Format(FMT_T39_27_FMT, FMT_T39_27_STR, |
| 627 Registers::Name(FMT_T39_27_m(instr)), |
| 628 Registers::Name(FMT_T39_27_n(instr))); |
| 629 break; |
| 630 #endif |
| 631 #ifdef FMT_T39_28 |
| 632 case FMT_T39_28_OPC2_MOV_L: |
| 633 Format(FMT_T39_28_FMT, FMT_T39_28_STR, |
| 634 Registers::Name(FMT_T39_28_m(instr)), |
| 635 Registers::Name(FMT_T39_28_n(instr))); |
| 636 break; |
| 637 #endif |
| 638 default: |
| 639 return 0; |
| 640 } |
| 641 default: |
| 642 return 0; |
| 643 } |
| 644 return 1; |
| 645 } |
| 646 |
| 647 #endif /* !USE_KERNEL_DISASM */ |
| 648 |
| 649 |
| 650 int Decoder::LastPoolReference() { |
| 651 return last_pool_offset_; |
| 652 } |
| 653 |
| 654 int Decoder::LastPoolSize() { |
| 655 return last_pool_size_; |
| 656 } |
| 657 |
| 658 } } // namespace v8::internal |
| 659 |
| 660 |
| 661 //------------------------------------------------------------------------------ |
| 662 |
| 663 |
| 664 namespace disasm { |
| 665 |
| 666 const char* NameConverter::NameOfAddress(byte* addr) const { |
| 667 v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr); |
| 668 return tmp_buffer_.start(); |
| 669 } |
| 670 |
| 671 |
| 672 const char* NameConverter::NameOfConstant(byte* addr) const { |
| 673 return NameOfAddress(addr); |
| 674 } |
| 675 |
| 676 |
| 677 const char* NameConverter::NameOfCPURegister(int reg) const { |
| 678 return v8::internal::Registers::Name(reg); |
| 679 } |
| 680 |
| 681 |
| 682 const char* NameConverter::NameOfByteCPURegister(int reg) const { |
| 683 UNREACHABLE(); // ARM does not have the concept of a byte register |
| 684 return "nobytereg"; |
| 685 } |
| 686 |
| 687 |
| 688 const char* NameConverter::NameOfXMMRegister(int reg) const { |
| 689 UNREACHABLE(); // ARM does not have any XMM registers |
| 690 return "noxmmreg"; |
| 691 } |
| 692 |
| 693 |
| 694 const char* NameConverter::NameInCode(byte* addr) const { |
| 695 // The default name converter is called for unknown code. So we will not try |
| 696 // to access any memory. |
| 697 return ""; |
| 698 } |
| 699 |
| 700 |
| 701 //------------------------------------------------------------------------------ |
| 702 |
| 703 Disassembler::Disassembler(const NameConverter& converter) |
| 704 : converter_(converter) {} |
| 705 |
| 706 |
| 707 Disassembler::~Disassembler() {} |
| 708 |
| 709 |
| 710 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, |
| 711 byte* instruction) { |
| 712 return 0; |
| 713 } |
| 714 |
| 715 |
| 716 |
| 717 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { |
| 718 UNIMPLEMENTED(); |
| 719 } |
| 720 |
| 721 int Disassembler::ConstantPoolSizeAt(byte* instruction) { |
| 722 return 0; |
| 723 } |
| 724 |
| 725 #if 0 |
| 726 class DisassemblerSH4: public DisassemblerInterface { |
| 727 public: |
| 728 explicit DisassemblerSH4() : start_pc_(0) { |
| 729 memset(pools_locs_, 9, sizeof(pools_locs_)); |
| 730 } |
| 731 |
| 732 virtual ~DisassemblerSH4() {} |
| 733 |
| 734 virtual int InstructionDecode(v8::internal::Vector<char> buffer, |
| 735 byte* instruction); |
| 736 |
| 737 virtual int ConstantPoolSizeAt(byte* instruction); |
| 738 |
| 739 private: |
| 740 // Management of pool references. |
| 741 void SetPoolAt(int offset, int size); |
| 742 void ClearPoolAt(int offset, int size); |
| 743 int HasPoolAt(int offset, int size); |
| 744 |
| 745 uint32_t start_pc_; |
| 746 static const int pools_locs_count_ = 1024; |
| 747 uint32_t pools_locs_[pools_locs_count_/sizeof(uint32_t)]; |
| 748 }; |
| 749 |
| 750 |
| 751 int DisassemblerSH4::InstructionDecode(v8::internal::Vector<char> buffer, |
| 752 byte* instruction) { |
| 753 if (start_pc_ == 0) |
| 754 start_pc_ = (uint32_t)instruction; |
| 755 v8::internal::Decoder d(buffer); |
| 756 int n = d.InstructionDecode(instruction); |
| 757 int offset = d.LastPoolReference(); |
| 758 int size = d.LastPoolSize(); |
| 759 if (offset > 0) |
| 760 SetPoolAt((uint32_t)instruction - start_pc_ + offset, size); |
| 761 return n; |
| 762 } |
| 763 |
| 764 |
| 765 int DisassemblerSH4::ConstantPoolSizeAt(byte* instruction) { |
| 766 // Constant pool size is a multiple of 4 from caller point of view, |
| 767 // we make this a post condition. |
| 768 // Though SH4 does not support misaligned pools, hence we |
| 769 // proceed by steps of 2. |
| 770 int size = 0; |
| 771 if (start_pc_ == 0) |
| 772 return -1; |
| 773 for (int offset = (uint32_t)instruction - start_pc_; |
| 774 HasPoolAt(offset, 2); |
| 775 offset += 2) { |
| 776 size += 2; |
| 777 ClearPoolAt(offset, 2); |
| 778 } |
| 779 ASSERT(size % 4 == 0); |
| 780 return size/4 - 1; |
| 781 } |
| 782 |
| 783 |
| 784 void DisassemblerSH4::SetPoolAt(int offset, int size) { |
| 785 ASSERT(size >= 1 && size <= 4); |
| 786 ASSERT(offset/4 == (offset+size-1)/4); |
| 787 int elt = (offset % pools_locs_count_)/(sizeof(*pools_locs_)*8); |
| 788 int pos = (offset % pools_locs_count_)%(sizeof(*pools_locs_)*8); |
| 789 uint32_t mask = ((uint32_t)1<<size)-1; |
| 790 pools_locs_[elt] |= (mask<<pos); |
| 791 } |
| 792 |
| 793 |
| 794 void DisassemblerSH4::ClearPoolAt(int offset, int size) { |
| 795 ASSERT(size >= 1 && size <= 4); |
| 796 ASSERT(offset/4 == (offset+size-1)/4); |
| 797 int elt = (offset % pools_locs_count_)/(sizeof(*pools_locs_)*8); |
| 798 int pos = (offset % pools_locs_count_)%(sizeof(*pools_locs_)*8); |
| 799 uint32_t mask = ((uint32_t)1<<size)-1; |
| 800 pools_locs_[elt] &= ~(mask<<pos); |
| 801 } |
| 802 |
| 803 |
| 804 int DisassemblerSH4::HasPoolAt(int offset, int size) { |
| 805 ASSERT(size >= 1 && size <= 4); |
| 806 ASSERT(offset/4 == (offset+size-1)/4); |
| 807 int elt = (offset % pools_locs_count_)/(sizeof(*pools_locs_)*8); |
| 808 int pos = (offset % pools_locs_count_)%(sizeof(*pools_locs_)*8); |
| 809 uint32_t mask = ((uint32_t)1<<size)-1; |
| 810 return (pools_locs_[elt] & (mask<<pos)) == (mask<<pos); |
| 811 } |
| 812 |
| 813 |
| 814 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { |
| 815 NameConverter converter; |
| 816 DisassemblerInterface *d = DisassemblerFactory::NewDisassembler(converter); |
| 817 for (byte* pc = begin; pc < end;) { |
| 818 v8::internal::EmbeddedVector<char, 128> buffer; |
| 819 buffer[0] = '\0'; |
| 820 byte* prev_pc = pc; |
| 821 pc += d->InstructionDecode(buffer, pc); |
| 822 v8::internal::OS::FPrint(f, "%p %02x %02x %s\n", |
| 823 prev_pc, *reinterpret_cast<const uint8_t*>(prev_pc), |
| 824 *reinterpret_cast<const uint8_t*>(prev_pc+1), buffer.start()); |
| 825 } |
| 826 delete d; |
| 827 } |
| 828 |
| 829 |
| 830 /*static*/ DisassemblerInterface * |
| 831 DisassemblerFactory::NewDisassembler(const NameConverter& converter) { |
| 832 return new DisassemblerSH4(); |
| 833 } |
| 834 |
| 835 #endif |
| 836 } // namespace disasm |
| 837 |
| 838 #endif // V8_TARGET_ARCH_SH4 |
OLD | NEW |