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