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