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