| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 | 27 |
| 28 // A Disassembler object is used to disassemble a block of code instruction by | 28 // A Disassembler object is used to disassemble a block of code instruction by |
| 29 // instruction. The default implementation of the NameConverter object can be | 29 // instruction. The default implementation of the NameConverter object can be |
| 30 // overriden to modify register names or to do symbol lookup on addresses. | 30 // overriden to modify register names or to do symbol lookup on addresses. |
| 31 // | 31 // |
| 32 // The example below will disassemble a block of code and print it to stdout. | 32 // The example below will disassemble a block of code and print it to stdout. |
| 33 // | 33 // |
| 34 // NameConverter converter; | 34 // NameConverter converter; |
| 35 // Disassembler d(converter); | 35 // Disassembler d(converter); |
| 36 // for (byte_* pc = begin; pc < end;) { | 36 // for (byte_* pc = begin; pc < end;) { |
| 37 // char buffer[128]; | 37 // v8::internal::EmbeddedVector<char, 256> buffer; |
| 38 // buffer[0] = '\0'; | 38 // byte* prev_pc = pc; |
| 39 // byte_* prev_pc = pc; | 39 // pc += d.InstructionDecode(buffer, pc); |
| 40 // pc += d.InstructionDecode(buffer, sizeof buffer, pc); | |
| 41 // printf("%p %08x %s\n", | 40 // printf("%p %08x %s\n", |
| 42 // prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer); | 41 // prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer); |
| 43 // } | 42 // } |
| 44 // | 43 // |
| 45 // The Disassembler class also has a convenience method to disassemble a block | 44 // The Disassembler class also has a convenience method to disassemble a block |
| 46 // of code into a FILE*, meaning that the above functionality could also be | 45 // of code into a FILE*, meaning that the above functionality could also be |
| 47 // achieved by just calling Disassembler::Disassemble(stdout, begin, end); | 46 // achieved by just calling Disassembler::Disassemble(stdout, begin, end); |
| 48 | 47 |
| 49 | 48 |
| 50 #include <assert.h> | 49 #include <assert.h> |
| 51 #include <stdio.h> | 50 #include <stdio.h> |
| 52 #include <stdarg.h> | 51 #include <stdarg.h> |
| 53 #include <string.h> | 52 #include <string.h> |
| 54 #ifndef WIN32 | 53 #ifndef WIN32 |
| 55 #include <stdint.h> | 54 #include <stdint.h> |
| 56 #endif | 55 #endif |
| 57 | 56 |
| 58 #include "v8.h" | 57 #include "v8.h" |
| 59 | 58 |
| 60 #if defined(V8_TARGET_ARCH_MIPS) | 59 #if defined(V8_TARGET_ARCH_MIPS) |
| 61 | 60 |
| 62 #include "constants-mips.h" | 61 #include "mips/constants-mips.h" |
| 63 #include "disasm.h" | 62 #include "disasm.h" |
| 64 #include "macro-assembler.h" | 63 #include "macro-assembler.h" |
| 65 #include "platform.h" | 64 #include "platform.h" |
| 66 | 65 |
| 67 namespace assembler { | 66 namespace v8 { |
| 68 namespace mips { | 67 namespace internal { |
| 69 | |
| 70 | |
| 71 namespace v8i = v8::internal; | |
| 72 | |
| 73 | 68 |
| 74 //------------------------------------------------------------------------------ | 69 //------------------------------------------------------------------------------ |
| 75 | 70 |
| 76 // Decoder decodes and disassembles instructions into an output buffer. | 71 // Decoder decodes and disassembles instructions into an output buffer. |
| 77 // It uses the converter to convert register names and call destinations into | 72 // It uses the converter to convert register names and call destinations into |
| 78 // more informative description. | 73 // more informative description. |
| 79 class Decoder { | 74 class Decoder { |
| 80 public: | 75 public: |
| 81 Decoder(const disasm::NameConverter& converter, | 76 Decoder(const disasm::NameConverter& converter, |
| 82 v8::internal::Vector<char> out_buffer) | 77 v8::internal::Vector<char> out_buffer) |
| 83 : converter_(converter), | 78 : converter_(converter), |
| 84 out_buffer_(out_buffer), | 79 out_buffer_(out_buffer), |
| 85 out_buffer_pos_(0) { | 80 out_buffer_pos_(0) { |
| 86 out_buffer_[out_buffer_pos_] = '\0'; | 81 out_buffer_[out_buffer_pos_] = '\0'; |
| 87 } | 82 } |
| 88 | 83 |
| 89 ~Decoder() {} | 84 ~Decoder() {} |
| 90 | 85 |
| 91 // Writes one disassembled instruction into 'buffer' (0-terminated). | 86 // Writes one disassembled instruction into 'buffer' (0-terminated). |
| 92 // Returns the length of the disassembled machine instruction in bytes. | 87 // Returns the length of the disassembled machine instruction in bytes. |
| 93 int InstructionDecode(byte_* instruction); | 88 int InstructionDecode(byte_* instruction); |
| 94 | 89 |
| 95 private: | 90 private: |
| 96 // Bottleneck functions to print into the out_buffer. | 91 // Bottleneck functions to print into the out_buffer. |
| 97 void PrintChar(const char ch); | 92 void PrintChar(const char ch); |
| 98 void Print(const char* str); | 93 void Print(const char* str); |
| 99 | 94 |
| 100 // Printing of common values. | 95 // Printing of common values. |
| 101 void PrintRegister(int reg); | 96 void PrintRegister(int reg); |
| 102 void PrintCRegister(int creg); | 97 void PrintFPURegister(int freg); |
| 103 void PrintRs(Instruction* instr); | 98 void PrintRs(Instruction* instr); |
| 104 void PrintRt(Instruction* instr); | 99 void PrintRt(Instruction* instr); |
| 105 void PrintRd(Instruction* instr); | 100 void PrintRd(Instruction* instr); |
| 106 void PrintFs(Instruction* instr); | 101 void PrintFs(Instruction* instr); |
| 107 void PrintFt(Instruction* instr); | 102 void PrintFt(Instruction* instr); |
| 108 void PrintFd(Instruction* instr); | 103 void PrintFd(Instruction* instr); |
| 109 void PrintSa(Instruction* instr); | 104 void PrintSa(Instruction* instr); |
| 105 void PrintSd(Instruction* instr); |
| 106 void PrintBc(Instruction* instr); |
| 107 void PrintCc(Instruction* instr); |
| 110 void PrintFunction(Instruction* instr); | 108 void PrintFunction(Instruction* instr); |
| 111 void PrintSecondaryField(Instruction* instr); | 109 void PrintSecondaryField(Instruction* instr); |
| 112 void PrintUImm16(Instruction* instr); | 110 void PrintUImm16(Instruction* instr); |
| 113 void PrintSImm16(Instruction* instr); | 111 void PrintSImm16(Instruction* instr); |
| 114 void PrintXImm16(Instruction* instr); | 112 void PrintXImm16(Instruction* instr); |
| 115 void PrintImm26(Instruction* instr); | 113 void PrintImm26(Instruction* instr); |
| 116 void PrintCode(Instruction* instr); // For break and trap instructions. | 114 void PrintCode(Instruction* instr); // For break and trap instructions. |
| 117 // Printing of instruction name. | 115 // Printing of instruction name. |
| 118 void PrintInstructionName(Instruction* instr); | 116 void PrintInstructionName(Instruction* instr); |
| 119 | 117 |
| 120 // Handle formatting of instructions and their options. | 118 // Handle formatting of instructions and their options. |
| 121 int FormatRegister(Instruction* instr, const char* option); | 119 int FormatRegister(Instruction* instr, const char* option); |
| 122 int FormatCRegister(Instruction* instr, const char* option); | 120 int FormatFPURegister(Instruction* instr, const char* option); |
| 123 int FormatOption(Instruction* instr, const char* option); | 121 int FormatOption(Instruction* instr, const char* option); |
| 124 void Format(Instruction* instr, const char* format); | 122 void Format(Instruction* instr, const char* format); |
| 125 void Unknown(Instruction* instr); | 123 void Unknown(Instruction* instr); |
| 126 | 124 |
| 127 // Each of these functions decodes one particular instruction type. | 125 // Each of these functions decodes one particular instruction type. |
| 128 void DecodeTypeRegister(Instruction* instr); | 126 void DecodeTypeRegister(Instruction* instr); |
| 129 void DecodeTypeImmediate(Instruction* instr); | 127 void DecodeTypeImmediate(Instruction* instr); |
| 130 void DecodeTypeJump(Instruction* instr); | 128 void DecodeTypeJump(Instruction* instr); |
| 131 | 129 |
| 132 const disasm::NameConverter& converter_; | 130 const disasm::NameConverter& converter_; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 159 } | 157 } |
| 160 | 158 |
| 161 | 159 |
| 162 // Print the register name according to the active name converter. | 160 // Print the register name according to the active name converter. |
| 163 void Decoder::PrintRegister(int reg) { | 161 void Decoder::PrintRegister(int reg) { |
| 164 Print(converter_.NameOfCPURegister(reg)); | 162 Print(converter_.NameOfCPURegister(reg)); |
| 165 } | 163 } |
| 166 | 164 |
| 167 | 165 |
| 168 void Decoder::PrintRs(Instruction* instr) { | 166 void Decoder::PrintRs(Instruction* instr) { |
| 169 int reg = instr->RsField(); | 167 int reg = instr->RsValue(); |
| 170 PrintRegister(reg); | 168 PrintRegister(reg); |
| 171 } | 169 } |
| 172 | 170 |
| 173 | 171 |
| 174 void Decoder::PrintRt(Instruction* instr) { | 172 void Decoder::PrintRt(Instruction* instr) { |
| 175 int reg = instr->RtField(); | 173 int reg = instr->RtValue(); |
| 176 PrintRegister(reg); | 174 PrintRegister(reg); |
| 177 } | 175 } |
| 178 | 176 |
| 179 | 177 |
| 180 void Decoder::PrintRd(Instruction* instr) { | 178 void Decoder::PrintRd(Instruction* instr) { |
| 181 int reg = instr->RdField(); | 179 int reg = instr->RdValue(); |
| 182 PrintRegister(reg); | 180 PrintRegister(reg); |
| 183 } | 181 } |
| 184 | 182 |
| 185 | 183 |
| 186 // Print the Cregister name according to the active name converter. | 184 // Print the FPUregister name according to the active name converter. |
| 187 void Decoder::PrintCRegister(int creg) { | 185 void Decoder::PrintFPURegister(int freg) { |
| 188 Print(converter_.NameOfXMMRegister(creg)); | 186 Print(converter_.NameOfXMMRegister(freg)); |
| 189 } | 187 } |
| 190 | 188 |
| 191 | 189 |
| 192 void Decoder::PrintFs(Instruction* instr) { | 190 void Decoder::PrintFs(Instruction* instr) { |
| 193 int creg = instr->RsField(); | 191 int freg = instr->RsValue(); |
| 194 PrintCRegister(creg); | 192 PrintFPURegister(freg); |
| 195 } | 193 } |
| 196 | 194 |
| 197 | 195 |
| 198 void Decoder::PrintFt(Instruction* instr) { | 196 void Decoder::PrintFt(Instruction* instr) { |
| 199 int creg = instr->RtField(); | 197 int freg = instr->RtValue(); |
| 200 PrintCRegister(creg); | 198 PrintFPURegister(freg); |
| 201 } | 199 } |
| 202 | 200 |
| 203 | 201 |
| 204 void Decoder::PrintFd(Instruction* instr) { | 202 void Decoder::PrintFd(Instruction* instr) { |
| 205 int creg = instr->RdField(); | 203 int freg = instr->RdValue(); |
| 206 PrintCRegister(creg); | 204 PrintFPURegister(freg); |
| 207 } | 205 } |
| 208 | 206 |
| 209 | 207 |
| 210 // Print the integer value of the sa field. | 208 // Print the integer value of the sa field. |
| 211 void Decoder::PrintSa(Instruction* instr) { | 209 void Decoder::PrintSa(Instruction* instr) { |
| 212 int sa = instr->SaField(); | 210 int sa = instr->SaValue(); |
| 213 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 211 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sa); |
| 214 "%d", sa); | 212 } |
| 213 |
| 214 |
| 215 // Print the integer value of the rd field, (when it is not used as reg). |
| 216 void Decoder::PrintSd(Instruction* instr) { |
| 217 int sd = instr->RdValue(); |
| 218 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", sd); |
| 219 } |
| 220 |
| 221 |
| 222 // Print the integer value of the cc field for the bc1t/f instructions. |
| 223 void Decoder::PrintBc(Instruction* instr) { |
| 224 int cc = instr->FBccValue(); |
| 225 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", cc); |
| 226 } |
| 227 |
| 228 |
| 229 // Print the integer value of the cc field for the FP compare instructions. |
| 230 void Decoder::PrintCc(Instruction* instr) { |
| 231 int cc = instr->FCccValue(); |
| 232 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "cc(%d)", cc); |
| 215 } | 233 } |
| 216 | 234 |
| 217 | 235 |
| 218 // Print 16-bit unsigned immediate value. | 236 // Print 16-bit unsigned immediate value. |
| 219 void Decoder::PrintUImm16(Instruction* instr) { | 237 void Decoder::PrintUImm16(Instruction* instr) { |
| 220 int32_t imm = instr->Imm16Field(); | 238 int32_t imm = instr->Imm16Value(); |
| 221 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 239 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%u", imm); |
| 222 "%u", imm); | |
| 223 } | 240 } |
| 224 | 241 |
| 225 | 242 |
| 226 // Print 16-bit signed immediate value. | 243 // Print 16-bit signed immediate value. |
| 227 void Decoder::PrintSImm16(Instruction* instr) { | 244 void Decoder::PrintSImm16(Instruction* instr) { |
| 228 int32_t imm = ((instr->Imm16Field())<<16)>>16; | 245 int32_t imm = ((instr->Imm16Value())<<16)>>16; |
| 229 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 246 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); |
| 230 "%d", imm); | |
| 231 } | 247 } |
| 232 | 248 |
| 233 | 249 |
| 234 // Print 16-bit hexa immediate value. | 250 // Print 16-bit hexa immediate value. |
| 235 void Decoder::PrintXImm16(Instruction* instr) { | 251 void Decoder::PrintXImm16(Instruction* instr) { |
| 236 int32_t imm = instr->Imm16Field(); | 252 int32_t imm = instr->Imm16Value(); |
| 237 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 253 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%x", imm); |
| 238 "0x%x", imm); | |
| 239 } | 254 } |
| 240 | 255 |
| 241 | 256 |
| 242 // Print 26-bit immediate value. | 257 // Print 26-bit immediate value. |
| 243 void Decoder::PrintImm26(Instruction* instr) { | 258 void Decoder::PrintImm26(Instruction* instr) { |
| 244 int32_t imm = instr->Imm26Field(); | 259 int32_t imm = instr->Imm26Value(); |
| 245 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 260 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, "%d", imm); |
| 246 "%d", imm); | |
| 247 } | 261 } |
| 248 | 262 |
| 249 | 263 |
| 250 // Print 26-bit immediate value. | 264 // Print 26-bit immediate value. |
| 251 void Decoder::PrintCode(Instruction* instr) { | 265 void Decoder::PrintCode(Instruction* instr) { |
| 252 if (instr->OpcodeFieldRaw() != SPECIAL) | 266 if (instr->OpcodeFieldRaw() != SPECIAL) |
| 253 return; // Not a break or trap instruction. | 267 return; // Not a break or trap instruction. |
| 254 switch (instr->FunctionFieldRaw()) { | 268 switch (instr->FunctionFieldRaw()) { |
| 255 case BREAK: { | 269 case BREAK: { |
| 256 int32_t code = instr->Bits(25, 6); | 270 int32_t code = instr->Bits(25, 6); |
| 257 out_buffer_pos_ += | 271 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| 258 v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%05x", code); | 272 "0x%05x (%d)", code, code); |
| 259 break; | 273 break; |
| 260 } | 274 } |
| 261 case TGE: | 275 case TGE: |
| 262 case TGEU: | 276 case TGEU: |
| 263 case TLT: | 277 case TLT: |
| 264 case TLTU: | 278 case TLTU: |
| 265 case TEQ: | 279 case TEQ: |
| 266 case TNE: { | 280 case TNE: { |
| 267 int32_t code = instr->Bits(15, 6); | 281 int32_t code = instr->Bits(15, 6); |
| 268 out_buffer_pos_ += | 282 out_buffer_pos_ += |
| 269 v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%03x", code); | 283 OS::SNPrintF(out_buffer_ + out_buffer_pos_, "0x%03x", code); |
| 270 break; | 284 break; |
| 271 } | 285 } |
| 272 default: // Not a break or trap instruction. | 286 default: // Not a break or trap instruction. |
| 273 break; | 287 break; |
| 274 }; | 288 }; |
| 275 } | 289 } |
| 276 | 290 |
| 277 | 291 |
| 278 // Printing of instruction name. | 292 // Printing of instruction name. |
| 279 void Decoder::PrintInstructionName(Instruction* instr) { | 293 void Decoder::PrintInstructionName(Instruction* instr) { |
| 280 } | 294 } |
| 281 | 295 |
| 282 | 296 |
| 283 // Handle all register based formatting in this function to reduce the | 297 // Handle all register based formatting in this function to reduce the |
| 284 // complexity of FormatOption. | 298 // complexity of FormatOption. |
| 285 int Decoder::FormatRegister(Instruction* instr, const char* format) { | 299 int Decoder::FormatRegister(Instruction* instr, const char* format) { |
| 286 ASSERT(format[0] == 'r'); | 300 ASSERT(format[0] == 'r'); |
| 287 if (format[1] == 's') { // 'rs: Rs register | 301 if (format[1] == 's') { // 'rs: Rs register |
| 288 int reg = instr->RsField(); | 302 int reg = instr->RsValue(); |
| 289 PrintRegister(reg); | 303 PrintRegister(reg); |
| 290 return 2; | 304 return 2; |
| 291 } else if (format[1] == 't') { // 'rt: rt register | 305 } else if (format[1] == 't') { // 'rt: rt register |
| 292 int reg = instr->RtField(); | 306 int reg = instr->RtValue(); |
| 293 PrintRegister(reg); | 307 PrintRegister(reg); |
| 294 return 2; | 308 return 2; |
| 295 } else if (format[1] == 'd') { // 'rd: rd register | 309 } else if (format[1] == 'd') { // 'rd: rd register |
| 296 int reg = instr->RdField(); | 310 int reg = instr->RdValue(); |
| 297 PrintRegister(reg); | 311 PrintRegister(reg); |
| 298 return 2; | 312 return 2; |
| 299 } | 313 } |
| 300 UNREACHABLE(); | 314 UNREACHABLE(); |
| 301 return -1; | 315 return -1; |
| 302 } | 316 } |
| 303 | 317 |
| 304 | 318 |
| 305 // Handle all Cregister based formatting in this function to reduce the | 319 // Handle all FPUregister based formatting in this function to reduce the |
| 306 // complexity of FormatOption. | 320 // complexity of FormatOption. |
| 307 int Decoder::FormatCRegister(Instruction* instr, const char* format) { | 321 int Decoder::FormatFPURegister(Instruction* instr, const char* format) { |
| 308 ASSERT(format[0] == 'f'); | 322 ASSERT(format[0] == 'f'); |
| 309 if (format[1] == 's') { // 'fs: fs register | 323 if (format[1] == 's') { // 'fs: fs register |
| 310 int reg = instr->RsField(); | 324 int reg = instr->FsValue(); |
| 311 PrintCRegister(reg); | 325 PrintFPURegister(reg); |
| 312 return 2; | 326 return 2; |
| 313 } else if (format[1] == 't') { // 'ft: ft register | 327 } else if (format[1] == 't') { // 'ft: ft register |
| 314 int reg = instr->RtField(); | 328 int reg = instr->FtValue(); |
| 315 PrintCRegister(reg); | 329 PrintFPURegister(reg); |
| 316 return 2; | 330 return 2; |
| 317 } else if (format[1] == 'd') { // 'fd: fd register | 331 } else if (format[1] == 'd') { // 'fd: fd register |
| 318 int reg = instr->RdField(); | 332 int reg = instr->FdValue(); |
| 319 PrintCRegister(reg); | 333 PrintFPURegister(reg); |
| 320 return 2; | 334 return 2; |
| 321 } | 335 } |
| 322 UNREACHABLE(); | 336 UNREACHABLE(); |
| 323 return -1; | 337 return -1; |
| 324 } | 338 } |
| 325 | 339 |
| 326 | 340 |
| 327 // FormatOption takes a formatting string and interprets it based on | 341 // FormatOption takes a formatting string and interprets it based on |
| 328 // the current instructions. The format string points to the first | 342 // the current instructions. The format string points to the first |
| 329 // character of the option string (the option escape has already been | 343 // character of the option string (the option escape has already been |
| (...skipping 22 matching lines...) Expand all Loading... |
| 352 return 6; | 366 return 6; |
| 353 } else { | 367 } else { |
| 354 ASSERT(STRING_STARTS_WITH(format, "imm26")); | 368 ASSERT(STRING_STARTS_WITH(format, "imm26")); |
| 355 PrintImm26(instr); | 369 PrintImm26(instr); |
| 356 return 5; | 370 return 5; |
| 357 } | 371 } |
| 358 } | 372 } |
| 359 case 'r': { // 'r: registers | 373 case 'r': { // 'r: registers |
| 360 return FormatRegister(instr, format); | 374 return FormatRegister(instr, format); |
| 361 } | 375 } |
| 362 case 'f': { // 'f: Cregisters | 376 case 'f': { // 'f: FPUregisters |
| 363 return FormatCRegister(instr, format); | 377 return FormatFPURegister(instr, format); |
| 364 } | 378 } |
| 365 case 's': { // 'sa | 379 case 's': { // 'sa |
| 366 ASSERT(STRING_STARTS_WITH(format, "sa")); | 380 switch (format[1]) { |
| 367 PrintSa(instr); | 381 case 'a': { |
| 382 ASSERT(STRING_STARTS_WITH(format, "sa")); |
| 383 PrintSa(instr); |
| 384 return 2; |
| 385 } |
| 386 case 'd': { |
| 387 ASSERT(STRING_STARTS_WITH(format, "sd")); |
| 388 PrintSd(instr); |
| 389 return 2; |
| 390 } |
| 391 } |
| 392 } |
| 393 case 'b': { // 'bc - Special for bc1 cc field. |
| 394 ASSERT(STRING_STARTS_WITH(format, "bc")); |
| 395 PrintBc(instr); |
| 396 return 2; |
| 397 } |
| 398 case 'C': { // 'Cc - Special for c.xx.d cc field. |
| 399 ASSERT(STRING_STARTS_WITH(format, "Cc")); |
| 400 PrintCc(instr); |
| 368 return 2; | 401 return 2; |
| 369 } | 402 } |
| 370 }; | 403 }; |
| 371 UNREACHABLE(); | 404 UNREACHABLE(); |
| 372 return -1; | 405 return -1; |
| 373 } | 406 } |
| 374 | 407 |
| 375 | 408 |
| 376 // Format takes a formatting string for a whole instruction and prints it into | 409 // Format takes a formatting string for a whole instruction and prints it into |
| 377 // the output buffer. All escaped options are handed to FormatOption to be | 410 // the output buffer. All escaped options are handed to FormatOption to be |
| (...skipping 16 matching lines...) Expand all Loading... |
| 394 // which will just print "unknown" of the instruction bits. | 427 // which will just print "unknown" of the instruction bits. |
| 395 void Decoder::Unknown(Instruction* instr) { | 428 void Decoder::Unknown(Instruction* instr) { |
| 396 Format(instr, "unknown"); | 429 Format(instr, "unknown"); |
| 397 } | 430 } |
| 398 | 431 |
| 399 | 432 |
| 400 void Decoder::DecodeTypeRegister(Instruction* instr) { | 433 void Decoder::DecodeTypeRegister(Instruction* instr) { |
| 401 switch (instr->OpcodeFieldRaw()) { | 434 switch (instr->OpcodeFieldRaw()) { |
| 402 case COP1: // Coprocessor instructions | 435 case COP1: // Coprocessor instructions |
| 403 switch (instr->RsFieldRaw()) { | 436 switch (instr->RsFieldRaw()) { |
| 404 case BC1: // branch on coprocessor condition | 437 case BC1: // bc1 handled in DecodeTypeImmediate. |
| 405 UNREACHABLE(); | 438 UNREACHABLE(); |
| 406 break; | 439 break; |
| 407 case MFC1: | 440 case MFC1: |
| 408 Format(instr, "mfc1 'rt, 'fs"); | 441 Format(instr, "mfc1 'rt, 'fs"); |
| 409 break; | 442 break; |
| 410 case MFHC1: | 443 case MFHC1: |
| 411 Format(instr, "mfhc1 rt, 'fs"); | 444 Format(instr, "mfhc1 'rt, 'fs"); |
| 412 break; | 445 break; |
| 413 case MTC1: | 446 case MTC1: |
| 414 Format(instr, "mtc1 'rt, 'fs"); | 447 Format(instr, "mtc1 'rt, 'fs"); |
| 448 break; |
| 449 // These are called "fs" too, although they are not FPU registers. |
| 450 case CTC1: |
| 451 Format(instr, "ctc1 'rt, 'fs"); |
| 452 break; |
| 453 case CFC1: |
| 454 Format(instr, "cfc1 'rt, 'fs"); |
| 415 break; | 455 break; |
| 416 case MTHC1: | 456 case MTHC1: |
| 417 Format(instr, "mthc1 rt, 'fs"); | 457 Format(instr, "mthc1 'rt, 'fs"); |
| 458 break; |
| 459 case D: |
| 460 switch (instr->FunctionFieldRaw()) { |
| 461 case ADD_D: |
| 462 Format(instr, "add.d 'fd, 'fs, 'ft"); |
| 463 break; |
| 464 case SUB_D: |
| 465 Format(instr, "sub.d 'fd, 'fs, 'ft"); |
| 466 break; |
| 467 case MUL_D: |
| 468 Format(instr, "mul.d 'fd, 'fs, 'ft"); |
| 469 break; |
| 470 case DIV_D: |
| 471 Format(instr, "div.d 'fd, 'fs, 'ft"); |
| 472 break; |
| 473 case ABS_D: |
| 474 Format(instr, "abs.d 'fd, 'fs"); |
| 475 break; |
| 476 case MOV_D: |
| 477 Format(instr, "mov.d 'fd, 'fs"); |
| 478 break; |
| 479 case NEG_D: |
| 480 Format(instr, "neg.d 'fd, 'fs"); |
| 481 break; |
| 482 case SQRT_D: |
| 483 Format(instr, "sqrt.d 'fd, 'fs"); |
| 484 break; |
| 485 case CVT_W_D: |
| 486 Format(instr, "cvt.w.d 'fd, 'fs"); |
| 487 break; |
| 488 case CVT_L_D: { |
| 489 if (mips32r2) { |
| 490 Format(instr, "cvt.l.d 'fd, 'fs"); |
| 491 } else { |
| 492 Unknown(instr); |
| 493 } |
| 494 break; |
| 495 } |
| 496 case TRUNC_W_D: |
| 497 Format(instr, "trunc.w.d 'fd, 'fs"); |
| 498 break; |
| 499 case TRUNC_L_D: { |
| 500 if (mips32r2) { |
| 501 Format(instr, "trunc.l.d 'fd, 'fs"); |
| 502 } else { |
| 503 Unknown(instr); |
| 504 } |
| 505 break; |
| 506 } |
| 507 case ROUND_W_D: |
| 508 Format(instr, "round.w.d 'fd, 'fs"); |
| 509 break; |
| 510 case FLOOR_W_D: |
| 511 Format(instr, "floor.w.d 'fd, 'fs"); |
| 512 break; |
| 513 case CEIL_W_D: |
| 514 Format(instr, "ceil.w.d 'fd, 'fs"); |
| 515 break; |
| 516 case CVT_S_D: |
| 517 Format(instr, "cvt.s.d 'fd, 'fs"); |
| 518 break; |
| 519 case C_F_D: |
| 520 Format(instr, "c.f.d 'fs, 'ft, 'Cc"); |
| 521 break; |
| 522 case C_UN_D: |
| 523 Format(instr, "c.un.d 'fs, 'ft, 'Cc"); |
| 524 break; |
| 525 case C_EQ_D: |
| 526 Format(instr, "c.eq.d 'fs, 'ft, 'Cc"); |
| 527 break; |
| 528 case C_UEQ_D: |
| 529 Format(instr, "c.ueq.d 'fs, 'ft, 'Cc"); |
| 530 break; |
| 531 case C_OLT_D: |
| 532 Format(instr, "c.olt.d 'fs, 'ft, 'Cc"); |
| 533 break; |
| 534 case C_ULT_D: |
| 535 Format(instr, "c.ult.d 'fs, 'ft, 'Cc"); |
| 536 break; |
| 537 case C_OLE_D: |
| 538 Format(instr, "c.ole.d 'fs, 'ft, 'Cc"); |
| 539 break; |
| 540 case C_ULE_D: |
| 541 Format(instr, "c.ule.d 'fs, 'ft, 'Cc"); |
| 542 break; |
| 543 default: |
| 544 Format(instr, "unknown.cop1.d"); |
| 545 break; |
| 546 } |
| 418 break; | 547 break; |
| 419 case S: | 548 case S: |
| 420 case D: | |
| 421 UNIMPLEMENTED_MIPS(); | 549 UNIMPLEMENTED_MIPS(); |
| 422 break; | 550 break; |
| 423 case W: | 551 case W: |
| 424 switch (instr->FunctionFieldRaw()) { | 552 switch (instr->FunctionFieldRaw()) { |
| 425 case CVT_S_W: | 553 case CVT_S_W: // Convert word to float (single). |
| 426 UNIMPLEMENTED_MIPS(); | 554 Format(instr, "cvt.s.w 'fd, 'fs"); |
| 427 break; | 555 break; |
| 428 case CVT_D_W: // Convert word to double. | 556 case CVT_D_W: // Convert word to double. |
| 429 Format(instr, "cvt.d.w 'fd, 'fs"); | 557 Format(instr, "cvt.d.w 'fd, 'fs"); |
| 430 break; | 558 break; |
| 431 default: | 559 default: |
| 432 UNREACHABLE(); | 560 UNREACHABLE(); |
| 433 }; | 561 } |
| 434 break; | 562 break; |
| 435 case L: | 563 case L: |
| 564 switch (instr->FunctionFieldRaw()) { |
| 565 case CVT_D_L: { |
| 566 if (mips32r2) { |
| 567 Format(instr, "cvt.d.l 'fd, 'fs"); |
| 568 } else { |
| 569 Unknown(instr); |
| 570 } |
| 571 break; |
| 572 } |
| 573 case CVT_S_L: { |
| 574 if (mips32r2) { |
| 575 Format(instr, "cvt.s.l 'fd, 'fs"); |
| 576 } else { |
| 577 Unknown(instr); |
| 578 } |
| 579 break; |
| 580 } |
| 581 default: |
| 582 UNREACHABLE(); |
| 583 } |
| 584 break; |
| 436 case PS: | 585 case PS: |
| 437 UNIMPLEMENTED_MIPS(); | 586 UNIMPLEMENTED_MIPS(); |
| 438 break; | 587 break; |
| 439 break; | |
| 440 default: | 588 default: |
| 441 UNREACHABLE(); | 589 UNREACHABLE(); |
| 442 }; | 590 } |
| 443 break; | 591 break; |
| 444 case SPECIAL: | 592 case SPECIAL: |
| 445 switch (instr->FunctionFieldRaw()) { | 593 switch (instr->FunctionFieldRaw()) { |
| 446 case JR: | 594 case JR: |
| 447 Format(instr, "jr 'rs"); | 595 Format(instr, "jr 'rs"); |
| 448 break; | 596 break; |
| 449 case JALR: | 597 case JALR: |
| 450 Format(instr, "jalr 'rs"); | 598 Format(instr, "jalr 'rs"); |
| 451 break; | 599 break; |
| 452 case SLL: | 600 case SLL: |
| 453 if ( 0x0 == static_cast<int>(instr->InstructionBits())) | 601 if ( 0x0 == static_cast<int>(instr->InstructionBits())) |
| 454 Format(instr, "nop"); | 602 Format(instr, "nop"); |
| 455 else | 603 else |
| 456 Format(instr, "sll 'rd, 'rt, 'sa"); | 604 Format(instr, "sll 'rd, 'rt, 'sa"); |
| 457 break; | 605 break; |
| 458 case SRL: | 606 case SRL: |
| 459 Format(instr, "srl 'rd, 'rt, 'sa"); | 607 if (instr->RsValue() == 0) { |
| 608 Format(instr, "srl 'rd, 'rt, 'sa"); |
| 609 } else { |
| 610 if (mips32r2) { |
| 611 Format(instr, "rotr 'rd, 'rt, 'sa"); |
| 612 } else { |
| 613 Unknown(instr); |
| 614 } |
| 615 } |
| 460 break; | 616 break; |
| 461 case SRA: | 617 case SRA: |
| 462 Format(instr, "sra 'rd, 'rt, 'sa"); | 618 Format(instr, "sra 'rd, 'rt, 'sa"); |
| 463 break; | 619 break; |
| 464 case SLLV: | 620 case SLLV: |
| 465 Format(instr, "sllv 'rd, 'rt, 'rs"); | 621 Format(instr, "sllv 'rd, 'rt, 'rs"); |
| 466 break; | 622 break; |
| 467 case SRLV: | 623 case SRLV: |
| 468 Format(instr, "srlv 'rd, 'rt, 'rs"); | 624 if (instr->SaValue() == 0) { |
| 625 Format(instr, "srlv 'rd, 'rt, 'rs"); |
| 626 } else { |
| 627 if (mips32r2) { |
| 628 Format(instr, "rotrv 'rd, 'rt, 'rs"); |
| 629 } else { |
| 630 Unknown(instr); |
| 631 } |
| 632 } |
| 469 break; | 633 break; |
| 470 case SRAV: | 634 case SRAV: |
| 471 Format(instr, "srav 'rd, 'rt, 'rs"); | 635 Format(instr, "srav 'rd, 'rt, 'rs"); |
| 472 break; | 636 break; |
| 473 case MFHI: | 637 case MFHI: |
| 474 Format(instr, "mfhi 'rd"); | 638 Format(instr, "mfhi 'rd"); |
| 475 break; | 639 break; |
| 476 case MFLO: | 640 case MFLO: |
| 477 Format(instr, "mflo 'rd"); | 641 Format(instr, "mflo 'rd"); |
| 478 break; | 642 break; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 497 case SUB: | 661 case SUB: |
| 498 Format(instr, "sub 'rd, 'rs, 'rt"); | 662 Format(instr, "sub 'rd, 'rs, 'rt"); |
| 499 break; | 663 break; |
| 500 case SUBU: | 664 case SUBU: |
| 501 Format(instr, "sub 'rd, 'rs, 'rt"); | 665 Format(instr, "sub 'rd, 'rs, 'rt"); |
| 502 break; | 666 break; |
| 503 case AND: | 667 case AND: |
| 504 Format(instr, "and 'rd, 'rs, 'rt"); | 668 Format(instr, "and 'rd, 'rs, 'rt"); |
| 505 break; | 669 break; |
| 506 case OR: | 670 case OR: |
| 507 if (0 == instr->RsField()) { | 671 if (0 == instr->RsValue()) { |
| 508 Format(instr, "mov 'rd, 'rt"); | 672 Format(instr, "mov 'rd, 'rt"); |
| 509 } else if (0 == instr->RtField()) { | 673 } else if (0 == instr->RtValue()) { |
| 510 Format(instr, "mov 'rd, 'rs"); | 674 Format(instr, "mov 'rd, 'rs"); |
| 511 } else { | 675 } else { |
| 512 Format(instr, "or 'rd, 'rs, 'rt"); | 676 Format(instr, "or 'rd, 'rs, 'rt"); |
| 513 } | 677 } |
| 514 break; | 678 break; |
| 515 case XOR: | 679 case XOR: |
| 516 Format(instr, "xor 'rd, 'rs, 'rt"); | 680 Format(instr, "xor 'rd, 'rs, 'rt"); |
| 517 break; | 681 break; |
| 518 case NOR: | 682 case NOR: |
| 519 Format(instr, "nor 'rd, 'rs, 'rt"); | 683 Format(instr, "nor 'rd, 'rs, 'rt"); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 538 break; | 702 break; |
| 539 case TLTU: | 703 case TLTU: |
| 540 Format(instr, "tltu 'rs, 'rt, code: 'code"); | 704 Format(instr, "tltu 'rs, 'rt, code: 'code"); |
| 541 break; | 705 break; |
| 542 case TEQ: | 706 case TEQ: |
| 543 Format(instr, "teq 'rs, 'rt, code: 'code"); | 707 Format(instr, "teq 'rs, 'rt, code: 'code"); |
| 544 break; | 708 break; |
| 545 case TNE: | 709 case TNE: |
| 546 Format(instr, "tne 'rs, 'rt, code: 'code"); | 710 Format(instr, "tne 'rs, 'rt, code: 'code"); |
| 547 break; | 711 break; |
| 712 case MOVZ: |
| 713 Format(instr, "movz 'rd, 'rs, 'rt"); |
| 714 break; |
| 715 case MOVN: |
| 716 Format(instr, "movn 'rd, 'rs, 'rt"); |
| 717 break; |
| 718 case MOVCI: |
| 719 if (instr->Bit(16)) { |
| 720 Format(instr, "movt 'rd, 'rs, 'Cc"); |
| 721 } else { |
| 722 Format(instr, "movf 'rd, 'rs, 'Cc"); |
| 723 } |
| 724 break; |
| 548 default: | 725 default: |
| 549 UNREACHABLE(); | 726 UNREACHABLE(); |
| 550 }; | 727 } |
| 551 break; | 728 break; |
| 552 case SPECIAL2: | 729 case SPECIAL2: |
| 553 switch (instr->FunctionFieldRaw()) { | 730 switch (instr->FunctionFieldRaw()) { |
| 554 case MUL: | 731 case MUL: |
| 732 Format(instr, "mul 'rd, 'rs, 'rt"); |
| 733 break; |
| 734 case CLZ: |
| 735 Format(instr, "clz 'rd, 'rs"); |
| 555 break; | 736 break; |
| 556 default: | 737 default: |
| 557 UNREACHABLE(); | 738 UNREACHABLE(); |
| 558 }; | 739 } |
| 740 break; |
| 741 case SPECIAL3: |
| 742 switch (instr->FunctionFieldRaw()) { |
| 743 case INS: { |
| 744 if (mips32r2) { |
| 745 Format(instr, "ins 'rt, 'rs, 'sd, 'sa"); |
| 746 } else { |
| 747 Unknown(instr); |
| 748 } |
| 749 break; |
| 750 } |
| 751 case EXT: { |
| 752 if (mips32r2) { |
| 753 Format(instr, "ext 'rt, 'rs, 'sd, 'sa"); |
| 754 } else { |
| 755 Unknown(instr); |
| 756 } |
| 757 break; |
| 758 } |
| 759 default: |
| 760 UNREACHABLE(); |
| 761 } |
| 559 break; | 762 break; |
| 560 default: | 763 default: |
| 561 UNREACHABLE(); | 764 UNREACHABLE(); |
| 562 }; | 765 } |
| 563 } | 766 } |
| 564 | 767 |
| 565 | 768 |
| 566 void Decoder::DecodeTypeImmediate(Instruction* instr) { | 769 void Decoder::DecodeTypeImmediate(Instruction* instr) { |
| 567 switch (instr->OpcodeFieldRaw()) { | 770 switch (instr->OpcodeFieldRaw()) { |
| 568 // ------------- REGIMM class. | 771 // ------------- REGIMM class. |
| 772 case COP1: |
| 773 switch (instr->RsFieldRaw()) { |
| 774 case BC1: |
| 775 if (instr->FBtrueValue()) { |
| 776 Format(instr, "bc1t 'bc, 'imm16u"); |
| 777 } else { |
| 778 Format(instr, "bc1f 'bc, 'imm16u"); |
| 779 } |
| 780 break; |
| 781 default: |
| 782 UNREACHABLE(); |
| 783 }; |
| 784 break; // Case COP1. |
| 569 case REGIMM: | 785 case REGIMM: |
| 570 switch (instr->RtFieldRaw()) { | 786 switch (instr->RtFieldRaw()) { |
| 571 case BLTZ: | 787 case BLTZ: |
| 572 Format(instr, "bltz 'rs, 'imm16u"); | 788 Format(instr, "bltz 'rs, 'imm16u"); |
| 573 break; | 789 break; |
| 574 case BLTZAL: | 790 case BLTZAL: |
| 575 Format(instr, "bltzal 'rs, 'imm16u"); | 791 Format(instr, "bltzal 'rs, 'imm16u"); |
| 576 break; | 792 break; |
| 577 case BGEZ: | 793 case BGEZ: |
| 578 Format(instr, "bgez 'rs, 'imm16u"); | 794 Format(instr, "bgez 'rs, 'imm16u"); |
| 579 break; | 795 break; |
| 580 case BGEZAL: | 796 case BGEZAL: |
| 581 Format(instr, "bgezal 'rs, 'imm16u"); | 797 Format(instr, "bgezal 'rs, 'imm16u"); |
| 582 break; | 798 break; |
| 583 default: | 799 default: |
| 584 UNREACHABLE(); | 800 UNREACHABLE(); |
| 585 }; | 801 } |
| 586 break; // case REGIMM | 802 break; // Case REGIMM. |
| 587 // ------------- Branch instructions. | 803 // ------------- Branch instructions. |
| 588 case BEQ: | 804 case BEQ: |
| 589 Format(instr, "beq 'rs, 'rt, 'imm16u"); | 805 Format(instr, "beq 'rs, 'rt, 'imm16u"); |
| 590 break; | 806 break; |
| 591 case BNE: | 807 case BNE: |
| 592 Format(instr, "bne 'rs, 'rt, 'imm16u"); | 808 Format(instr, "bne 'rs, 'rt, 'imm16u"); |
| 593 break; | 809 break; |
| 594 case BLEZ: | 810 case BLEZ: |
| 595 Format(instr, "blez 'rs, 'imm16u"); | 811 Format(instr, "blez 'rs, 'imm16u"); |
| 596 break; | 812 break; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 619 case XORI: | 835 case XORI: |
| 620 Format(instr, "xori 'rt, 'rs, 'imm16x"); | 836 Format(instr, "xori 'rt, 'rs, 'imm16x"); |
| 621 break; | 837 break; |
| 622 case LUI: | 838 case LUI: |
| 623 Format(instr, "lui 'rt, 'imm16x"); | 839 Format(instr, "lui 'rt, 'imm16x"); |
| 624 break; | 840 break; |
| 625 // ------------- Memory instructions. | 841 // ------------- Memory instructions. |
| 626 case LB: | 842 case LB: |
| 627 Format(instr, "lb 'rt, 'imm16s('rs)"); | 843 Format(instr, "lb 'rt, 'imm16s('rs)"); |
| 628 break; | 844 break; |
| 845 case LH: |
| 846 Format(instr, "lh 'rt, 'imm16s('rs)"); |
| 847 break; |
| 848 case LWL: |
| 849 Format(instr, "lwl 'rt, 'imm16s('rs)"); |
| 850 break; |
| 629 case LW: | 851 case LW: |
| 630 Format(instr, "lw 'rt, 'imm16s('rs)"); | 852 Format(instr, "lw 'rt, 'imm16s('rs)"); |
| 631 break; | 853 break; |
| 632 case LBU: | 854 case LBU: |
| 633 Format(instr, "lbu 'rt, 'imm16s('rs)"); | 855 Format(instr, "lbu 'rt, 'imm16s('rs)"); |
| 634 break; | 856 break; |
| 857 case LHU: |
| 858 Format(instr, "lhu 'rt, 'imm16s('rs)"); |
| 859 break; |
| 860 case LWR: |
| 861 Format(instr, "lwr 'rt, 'imm16s('rs)"); |
| 862 break; |
| 635 case SB: | 863 case SB: |
| 636 Format(instr, "sb 'rt, 'imm16s('rs)"); | 864 Format(instr, "sb 'rt, 'imm16s('rs)"); |
| 637 break; | 865 break; |
| 866 case SH: |
| 867 Format(instr, "sh 'rt, 'imm16s('rs)"); |
| 868 break; |
| 869 case SWL: |
| 870 Format(instr, "swl 'rt, 'imm16s('rs)"); |
| 871 break; |
| 638 case SW: | 872 case SW: |
| 639 Format(instr, "sw 'rt, 'imm16s('rs)"); | 873 Format(instr, "sw 'rt, 'imm16s('rs)"); |
| 640 break; | 874 break; |
| 875 case SWR: |
| 876 Format(instr, "swr 'rt, 'imm16s('rs)"); |
| 877 break; |
| 641 case LWC1: | 878 case LWC1: |
| 642 Format(instr, "lwc1 'ft, 'imm16s('rs)"); | 879 Format(instr, "lwc1 'ft, 'imm16s('rs)"); |
| 643 break; | 880 break; |
| 644 case LDC1: | 881 case LDC1: |
| 645 Format(instr, "ldc1 'ft, 'imm16s('rs)"); | 882 Format(instr, "ldc1 'ft, 'imm16s('rs)"); |
| 646 break; | 883 break; |
| 647 case SWC1: | 884 case SWC1: |
| 648 Format(instr, "swc1 'rt, 'imm16s('fs)"); | 885 Format(instr, "swc1 'ft, 'imm16s('rs)"); |
| 649 break; | 886 break; |
| 650 case SDC1: | 887 case SDC1: |
| 651 Format(instr, "sdc1 'rt, 'imm16s('fs)"); | 888 Format(instr, "sdc1 'ft, 'imm16s('rs)"); |
| 652 break; | 889 break; |
| 653 default: | 890 default: |
| 654 UNREACHABLE(); | 891 UNREACHABLE(); |
| 655 break; | 892 break; |
| 656 }; | 893 }; |
| 657 } | 894 } |
| 658 | 895 |
| 659 | 896 |
| 660 void Decoder::DecodeTypeJump(Instruction* instr) { | 897 void Decoder::DecodeTypeJump(Instruction* instr) { |
| 661 switch (instr->OpcodeFieldRaw()) { | 898 switch (instr->OpcodeFieldRaw()) { |
| 662 case J: | 899 case J: |
| 663 Format(instr, "j 'imm26"); | 900 Format(instr, "j 'imm26"); |
| 664 break; | 901 break; |
| 665 case JAL: | 902 case JAL: |
| 666 Format(instr, "jal 'imm26"); | 903 Format(instr, "jal 'imm26"); |
| 667 break; | 904 break; |
| 668 default: | 905 default: |
| 669 UNREACHABLE(); | 906 UNREACHABLE(); |
| 670 } | 907 } |
| 671 } | 908 } |
| 672 | 909 |
| 673 | 910 |
| 674 // Disassemble the instruction at *instr_ptr into the output buffer. | 911 // Disassemble the instruction at *instr_ptr into the output buffer. |
| 675 int Decoder::InstructionDecode(byte_* instr_ptr) { | 912 int Decoder::InstructionDecode(byte_* instr_ptr) { |
| 676 Instruction* instr = Instruction::At(instr_ptr); | 913 Instruction* instr = Instruction::At(instr_ptr); |
| 677 // Print raw instruction bytes. | 914 // Print raw instruction bytes. |
| 678 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, | 915 out_buffer_pos_ += OS::SNPrintF(out_buffer_ + out_buffer_pos_, |
| 679 "%08x ", | 916 "%08x ", |
| 680 instr->InstructionBits()); | 917 instr->InstructionBits()); |
| 681 switch (instr->InstructionType()) { | 918 switch (instr->InstructionType()) { |
| 682 case Instruction::kRegisterType: { | 919 case Instruction::kRegisterType: { |
| 683 DecodeTypeRegister(instr); | 920 DecodeTypeRegister(instr); |
| 684 break; | 921 break; |
| 685 } | 922 } |
| 686 case Instruction::kImmediateType: { | 923 case Instruction::kImmediateType: { |
| 687 DecodeTypeImmediate(instr); | 924 DecodeTypeImmediate(instr); |
| 688 break; | 925 break; |
| 689 } | 926 } |
| 690 case Instruction::kJumpType: { | 927 case Instruction::kJumpType: { |
| 691 DecodeTypeJump(instr); | 928 DecodeTypeJump(instr); |
| 692 break; | 929 break; |
| 693 } | 930 } |
| 694 default: { | 931 default: { |
| 695 UNSUPPORTED_MIPS(); | 932 UNSUPPORTED_MIPS(); |
| 696 } | 933 } |
| 697 } | 934 } |
| 698 return Instruction::kInstructionSize; | 935 return Instruction::kInstrSize; |
| 699 } | 936 } |
| 700 | 937 |
| 701 | 938 |
| 702 } } // namespace assembler::mips | 939 } } // namespace v8::internal |
| 703 | 940 |
| 704 | 941 |
| 705 | 942 |
| 706 //------------------------------------------------------------------------------ | 943 //------------------------------------------------------------------------------ |
| 707 | 944 |
| 708 namespace disasm { | 945 namespace disasm { |
| 709 | 946 |
| 710 namespace v8i = v8::internal; | 947 using v8::internal::byte_; |
| 711 | |
| 712 | 948 |
| 713 const char* NameConverter::NameOfAddress(byte_* addr) const { | 949 const char* NameConverter::NameOfAddress(byte_* addr) const { |
| 714 v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr); | 950 v8::internal::OS::SNPrintF(tmp_buffer_, "%p", addr); |
| 715 return tmp_buffer_.start(); | 951 return tmp_buffer_.start(); |
| 716 } | 952 } |
| 717 | 953 |
| 718 | 954 |
| 719 const char* NameConverter::NameOfConstant(byte_* addr) const { | 955 const char* NameConverter::NameOfConstant(byte_* addr) const { |
| 720 return NameOfAddress(addr); | 956 return NameOfAddress(addr); |
| 721 } | 957 } |
| 722 | 958 |
| 723 | 959 |
| 724 const char* NameConverter::NameOfCPURegister(int reg) const { | 960 const char* NameConverter::NameOfCPURegister(int reg) const { |
| 725 return assembler::mips::Registers::Name(reg); | 961 return v8::internal::Registers::Name(reg); |
| 726 } | 962 } |
| 727 | 963 |
| 728 | 964 |
| 729 const char* NameConverter::NameOfXMMRegister(int reg) const { | 965 const char* NameConverter::NameOfXMMRegister(int reg) const { |
| 730 return assembler::mips::FPURegister::Name(reg); | 966 return v8::internal::FPURegisters::Name(reg); |
| 731 } | 967 } |
| 732 | 968 |
| 733 | 969 |
| 734 const char* NameConverter::NameOfByteCPURegister(int reg) const { | 970 const char* NameConverter::NameOfByteCPURegister(int reg) const { |
| 735 UNREACHABLE(); // MIPS does not have the concept of a byte register | 971 UNREACHABLE(); // MIPS does not have the concept of a byte register |
| 736 return "nobytereg"; | 972 return "nobytereg"; |
| 737 } | 973 } |
| 738 | 974 |
| 739 | 975 |
| 740 const char* NameConverter::NameInCode(byte_* addr) const { | 976 const char* NameConverter::NameInCode(byte_* addr) const { |
| 741 // The default name converter is called for unknown code. So we will not try | 977 // The default name converter is called for unknown code. So we will not try |
| 742 // to access any memory. | 978 // to access any memory. |
| 743 return ""; | 979 return ""; |
| 744 } | 980 } |
| 745 | 981 |
| 746 | 982 |
| 747 //------------------------------------------------------------------------------ | 983 //------------------------------------------------------------------------------ |
| 748 | 984 |
| 749 Disassembler::Disassembler(const NameConverter& converter) | 985 Disassembler::Disassembler(const NameConverter& converter) |
| 750 : converter_(converter) {} | 986 : converter_(converter) {} |
| 751 | 987 |
| 752 | 988 |
| 753 Disassembler::~Disassembler() {} | 989 Disassembler::~Disassembler() {} |
| 754 | 990 |
| 755 | 991 |
| 756 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, | 992 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, |
| 757 byte_* instruction) { | 993 byte_* instruction) { |
| 758 assembler::mips::Decoder d(converter_, buffer); | 994 v8::internal::Decoder d(converter_, buffer); |
| 759 return d.InstructionDecode(instruction); | 995 return d.InstructionDecode(instruction); |
| 760 } | 996 } |
| 761 | 997 |
| 762 | 998 |
| 999 // The MIPS assembler does not currently use constant pools. |
| 763 int Disassembler::ConstantPoolSizeAt(byte_* instruction) { | 1000 int Disassembler::ConstantPoolSizeAt(byte_* instruction) { |
| 764 UNIMPLEMENTED_MIPS(); | |
| 765 return -1; | 1001 return -1; |
| 766 } | 1002 } |
| 767 | 1003 |
| 768 | 1004 |
| 769 void Disassembler::Disassemble(FILE* f, byte_* begin, byte_* end) { | 1005 void Disassembler::Disassemble(FILE* f, byte_* begin, byte_* end) { |
| 770 NameConverter converter; | 1006 NameConverter converter; |
| 771 Disassembler d(converter); | 1007 Disassembler d(converter); |
| 772 for (byte_* pc = begin; pc < end;) { | 1008 for (byte_* pc = begin; pc < end;) { |
| 773 v8::internal::EmbeddedVector<char, 128> buffer; | 1009 v8::internal::EmbeddedVector<char, 128> buffer; |
| 774 buffer[0] = '\0'; | 1010 buffer[0] = '\0'; |
| 775 byte_* prev_pc = pc; | 1011 byte_* prev_pc = pc; |
| 776 pc += d.InstructionDecode(buffer, pc); | 1012 pc += d.InstructionDecode(buffer, pc); |
| 777 fprintf(f, "%p %08x %s\n", | 1013 fprintf(f, "%p %08x %s\n", |
| 778 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); | 1014 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); |
| 779 } | 1015 } |
| 780 } | 1016 } |
| 781 | 1017 |
| 1018 |
| 782 #undef UNSUPPORTED | 1019 #undef UNSUPPORTED |
| 783 | 1020 |
| 784 } // namespace disasm | 1021 } // namespace disasm |
| 785 | 1022 |
| 786 #endif // V8_TARGET_ARCH_MIPS | 1023 #endif // V8_TARGET_ARCH_MIPS |
| OLD | NEW |