Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(110)

Side by Side Diff: src/disasm-arm.cc

Issue 8939: Backport the changes from the readability. (Closed) Base URL: http://v8.googlecode.com/svn/branches/bleeding_edge/
Patch Set: Created 12 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/disasm.h ('k') | src/disasm-ia32.cc » ('j') | src/v8.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2007-2008 the V8 project authors. All rights reserved. 1 // Copyright 2007-2008 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
11 // with the distribution. 11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its 12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived 13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission. 14 // from this software without specific prior written permission.
15 // 15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 27
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
30 // overriden to modify register names or to do symbol lookup on addresses.
31 //
32 // The example below will disassemble a block of code and print it to stdout.
33 //
34 // NameConverter converter;
35 // Disassembler d(converter);
36 // for (byte* pc = begin; pc < end;) {
37 // char buffer[128];
38 // buffer[0] = '\0';
39 // byte* prev_pc = pc;
40 // pc += d.InstructionDecode(buffer, sizeof buffer, pc);
41 // printf("%p %08x %s\n",
42 // prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer);
43 // }
44 //
45 // 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
47 // achieved by just calling Disassembler::Disassemble(stdout, begin, end);
48
49
28 #include <assert.h> 50 #include <assert.h>
29 #include <stdio.h> 51 #include <stdio.h>
30 #include <stdarg.h> 52 #include <stdarg.h>
31 #include <string.h> 53 #include <string.h>
32 #ifndef WIN32 54 #ifndef WIN32
33 #include <stdint.h> 55 #include <stdint.h>
34 #endif 56 #endif
35 57
36 #include "v8.h" 58 #include "v8.h"
37 59
38 #include "disasm.h" 60 #include "disasm.h"
39 #include "macro-assembler.h" 61 #include "macro-assembler.h"
40 #include "platform.h" 62 #include "platform.h"
41 63
64
42 namespace assembler { namespace arm { 65 namespace assembler { namespace arm {
43 66
44 namespace v8i = v8::internal; 67 namespace v8i = v8::internal;
45 68
46 69
47 //------------------------------------------------------------------------------ 70 //------------------------------------------------------------------------------
48 71
49 // Decoder decodes and disassembles instructions into an output buffer. 72 // Decoder decodes and disassembles instructions into an output buffer.
50 // It uses the converter to convert register names and call destinations into 73 // It uses the converter to convert register names and call destinations into
51 // more informative description. 74 // more informative description.
52 class Decoder { 75 class Decoder {
53 public: 76 public:
54 Decoder(const disasm::NameConverter& converter, 77 Decoder(const disasm::NameConverter& converter,
55 v8::internal::Vector<char> out_buffer) 78 v8::internal::Vector<char> out_buffer)
56 : converter_(converter), 79 : converter_(converter),
57 out_buffer_(out_buffer), 80 out_buffer_(out_buffer),
58 out_buffer_pos_(0) { 81 out_buffer_pos_(0) {
59 out_buffer_[out_buffer_pos_] = '\0'; 82 out_buffer_[out_buffer_pos_] = '\0';
60 } 83 }
61 84
62 ~Decoder() {} 85 ~Decoder() {}
63 86
64 // Writes one disassembled instruction into 'buffer' (0-terminated). 87 // Writes one disassembled instruction into 'buffer' (0-terminated).
65 // Returns the length of the disassembled machine instruction in bytes. 88 // Returns the length of the disassembled machine instruction in bytes.
66 int InstructionDecode(byte* instruction); 89 int InstructionDecode(byte* instruction);
67 90
68 private: 91 private:
69 const disasm::NameConverter& converter_; 92 // Bottleneck functions to print into the out_buffer.
70 v8::internal::Vector<char> out_buffer_;
71 int out_buffer_pos_;
72
73 void PrintChar(const char ch); 93 void PrintChar(const char ch);
74 void Print(const char* str); 94 void Print(const char* str);
75 95
96 // Printing of common values.
76 void PrintRegister(int reg); 97 void PrintRegister(int reg);
77 void PrintCondition(Instr* instr); 98 void PrintCondition(Instr* instr);
78 void PrintShiftRm(Instr* instr); 99 void PrintShiftRm(Instr* instr);
79 void PrintShiftImm(Instr* instr); 100 void PrintShiftImm(Instr* instr);
101 void PrintPU(Instr* instr);
102 void PrintSoftwareInterrupt(SoftwareInterruptCodes swi);
80 103
104 // Handle formatting of instructions and their options.
105 int FormatRegister(Instr* instr, const char* option);
81 int FormatOption(Instr* instr, const char* option); 106 int FormatOption(Instr* instr, const char* option);
82 void Format(Instr* instr, const char* format); 107 void Format(Instr* instr, const char* format);
83 void Unknown(Instr* instr); 108 void Unknown(Instr* instr);
84 109
85 void DecodeType0(Instr* instr); 110 // Each of these functions decodes one particular instruction type, a 3-bit
86 void DecodeType1(Instr* instr); 111 // field in the instruction encoding.
112 // Types 0 and 1 are combined as they are largely the same except for the way
113 // they interpret the shifter operand.
114 void DecodeType01(Instr* instr);
87 void DecodeType2(Instr* instr); 115 void DecodeType2(Instr* instr);
88 void DecodeType3(Instr* instr); 116 void DecodeType3(Instr* instr);
89 void DecodeType4(Instr* instr); 117 void DecodeType4(Instr* instr);
90 void DecodeType5(Instr* instr); 118 void DecodeType5(Instr* instr);
91 void DecodeType6(Instr* instr); 119 void DecodeType6(Instr* instr);
92 void DecodeType7(Instr* instr); 120 void DecodeType7(Instr* instr);
121
122 const disasm::NameConverter& converter_;
123 v8::internal::Vector<char> out_buffer_;
124 int out_buffer_pos_;
125
126 DISALLOW_COPY_AND_ASSIGN(Decoder);
93 }; 127 };
94 128
95 129
130 // Support for assertions in the Decoder formatting functions.
131 #define STRING_STARTS_WITH(string, compare_string) \
132 (strncmp(string, compare_string, strlen(compare_string)) == 0)
133
134
96 // Append the ch to the output buffer. 135 // Append the ch to the output buffer.
97 void Decoder::PrintChar(const char ch) { 136 void Decoder::PrintChar(const char ch) {
98 out_buffer_[out_buffer_pos_++] = ch; 137 out_buffer_[out_buffer_pos_++] = ch;
99 } 138 }
100 139
101 140
102 // Append the str to the output buffer. 141 // Append the str to the output buffer.
103 void Decoder::Print(const char* str) { 142 void Decoder::Print(const char* str) {
104 char cur = *str++; 143 char cur = *str++;
105 while (cur != 0 && (out_buffer_pos_ < (out_buffer_.length()-1))) { 144 while (cur != '\0' && (out_buffer_pos_ < (out_buffer_.length() - 1))) {
106 PrintChar(cur); 145 PrintChar(cur);
107 cur = *str++; 146 cur = *str++;
108 } 147 }
109 out_buffer_[out_buffer_pos_] = 0; 148 out_buffer_[out_buffer_pos_] = 0;
110 } 149 }
111 150
112 151
113 static const char* cond_names[16] = { 152 // These condition names are defined in a way to match the native disassembler
114 "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" , 153 // formatting. See for example the command "objdump -d <binary file>".
115 "hi", "ls", "ge", "lt", "gt", "le", "", "invalid", 154 static const char* cond_names[max_condition] = {
155 "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" ,
156 "hi", "ls", "ge", "lt", "gt", "le", "", "invalid",
116 }; 157 };
117 158
118 159
119 // Print the condition guarding the instruction. 160 // Print the condition guarding the instruction.
120 void Decoder::PrintCondition(Instr* instr) { 161 void Decoder::PrintCondition(Instr* instr) {
121 Print(cond_names[instr->ConditionField()]); 162 Print(cond_names[instr->ConditionField()]);
122 } 163 }
123 164
124 165
125 // Print the register name according to the active name converter. 166 // Print the register name according to the active name converter.
126 void Decoder::PrintRegister(int reg) { 167 void Decoder::PrintRegister(int reg) {
127 Print(converter_.NameOfCPURegister(reg)); 168 Print(converter_.NameOfCPURegister(reg));
128 } 169 }
129 170
130 171
131 static const char* shift_names[4] = { 172 // These shift names are defined in a way to match the native disassembler
173 // formatting. See for example the command "objdump -d <binary file>".
174 static const char* shift_names[max_shift] = {
132 "lsl", "lsr", "asr", "ror" 175 "lsl", "lsr", "asr", "ror"
133 }; 176 };
134 177
135 178
136 // Print the register shift operands for the instruction. Generally used for 179 // Print the register shift operands for the instruction. Generally used for
137 // data processing instructions. 180 // data processing instructions.
138 void Decoder::PrintShiftRm(Instr* instr) { 181 void Decoder::PrintShiftRm(Instr* instr) {
139 Shift shift = instr->ShiftField(); 182 Shift shift = instr->ShiftField();
140 int shift_amount = instr->ShiftAmountField(); 183 int shift_amount = instr->ShiftAmountField();
141 int rm = instr->RmField(); 184 int rm = instr->RmField();
(...skipping 29 matching lines...) Expand all
171 // processing instructions. 214 // processing instructions.
172 void Decoder::PrintShiftImm(Instr* instr) { 215 void Decoder::PrintShiftImm(Instr* instr) {
173 int rotate = instr->RotateField() * 2; 216 int rotate = instr->RotateField() * 2;
174 int immed8 = instr->Immed8Field(); 217 int immed8 = instr->Immed8Field();
175 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate)); 218 int imm = (immed8 >> rotate) | (immed8 << (32 - rotate));
176 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, 219 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
177 "#%d", imm); 220 "#%d", imm);
178 } 221 }
179 222
180 223
224 // Print PU formatting to reduce complexity of FormatOption.
225 void Decoder::PrintPU(Instr* instr) {
226 switch (instr->PUField()) {
227 case 0: {
228 Print("da");
229 break;
230 }
231 case 1: {
232 Print("ia");
233 break;
234 }
235 case 2: {
236 Print("db");
237 break;
238 }
239 case 3: {
240 Print("ib");
241 break;
242 }
243 default: {
244 UNREACHABLE();
245 break;
246 }
247 }
248 }
249
250
251 // Print SoftwareInterrupt codes. Factoring this out reduces the complexity of
252 // the FormatOption method.
253 void Decoder::PrintSoftwareInterrupt(SoftwareInterruptCodes swi) {
254 switch (swi) {
255 case call_rt_r5:
256 Print("call_rt_r5");
257 return;
258 case call_rt_r2:
259 Print("call_rt_r2");
260 return;
261 case break_point:
262 Print("break_point");
263 return;
264 default:
265 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
266 "%d",
267 swi);
268 return;
269 }
270 }
271
272
273 // Handle all register based formatting in this function to reduce the
274 // complexity of FormatOption.
275 int Decoder::FormatRegister(Instr* instr, const char* format) {
276 ASSERT(format[0] == 'r');
277 if (format[1] == 'n') { // 'rn: Rn register
278 int reg = instr->RnField();
279 PrintRegister(reg);
280 return 2;
281 } else if (format[1] == 'd') { // 'rd: Rd register
282 int reg = instr->RdField();
283 PrintRegister(reg);
284 return 2;
285 } else if (format[1] == 's') { // 'rs: Rs register
286 int reg = instr->RsField();
287 PrintRegister(reg);
288 return 2;
289 } else if (format[1] == 'm') { // 'rm: Rm register
290 int reg = instr->RmField();
291 PrintRegister(reg);
292 return 2;
293 } else if (format[1] == 'l') {
294 // 'rlist: register list for load and store multiple instructions
295 ASSERT(STRING_STARTS_WITH(format, "rlist"));
296 int rlist = instr->RlistField();
297 int reg = 0;
298 Print("{");
299 // Print register list in ascending order, by scanning the bit mask.
300 while (rlist != 0) {
301 if ((rlist & 1) != 0) {
302 PrintRegister(reg);
303 if ((rlist >> 1) != 0) {
304 Print(", ");
305 }
306 }
307 reg++;
308 rlist >>= 1;
309 }
310 Print("}");
311 return 5;
312 }
313 UNREACHABLE();
314 return -1;
315 }
316
317
181 // FormatOption takes a formatting string and interprets it based on 318 // FormatOption takes a formatting string and interprets it based on
182 // the current instructions. The format string points to the first 319 // the current instructions. The format string points to the first
183 // character of the option string (the option escape has already been 320 // character of the option string (the option escape has already been
184 // consumed by the caller.) FormatOption returns the number of 321 // consumed by the caller.) FormatOption returns the number of
185 // characters that were consumed from the formatting string. 322 // characters that were consumed from the formatting string.
186 int Decoder::FormatOption(Instr* instr, const char* format) { 323 int Decoder::FormatOption(Instr* instr, const char* format) {
187 switch (format[0]) { 324 switch (format[0]) {
188 case 'a': { // 'a: accumulate multiplies 325 case 'a': { // 'a: accumulate multiplies
189 if (instr->Bit(21) == 0) { 326 if (instr->Bit(21) == 0) {
190 Print("ul"); 327 Print("ul");
191 } else { 328 } else {
192 Print("la"); 329 Print("la");
193 } 330 }
194 return 1; 331 return 1;
195 break;
196 } 332 }
197 case 'b': { // 'b: byte loads or stores 333 case 'b': { // 'b: byte loads or stores
198 if (instr->HasB()) { 334 if (instr->HasB()) {
199 Print("b"); 335 Print("b");
200 } 336 }
201 return 1; 337 return 1;
202 break;
203 } 338 }
204 case 'c': { // 'cond: conditional execution 339 case 'c': { // 'cond: conditional execution
205 ASSERT((format[1] == 'o') && (format[2] == 'n') && (format[3] =='d')); 340 ASSERT(STRING_STARTS_WITH(format, "cond"));
206 PrintCondition(instr); 341 PrintCondition(instr);
207 return 4; 342 return 4;
208 break;
209 } 343 }
210 case 'h': { // 'h: halfword operation for extra loads and stores 344 case 'h': { // 'h: halfword operation for extra loads and stores
211 if (instr->HasH()) { 345 if (instr->HasH()) {
212 Print("h"); 346 Print("h");
213 } else { 347 } else {
214 Print("b"); 348 Print("b");
215 } 349 }
216 return 1; 350 return 1;
217 break;
218 }
219 case 'i': { // 'imm: immediate value for data processing instructions
220 ASSERT((format[1] == 'm') && (format[2] == 'm'));
221 PrintShiftImm(instr);
222 return 3;
223 break;
224 } 351 }
225 case 'l': { // 'l: branch and link 352 case 'l': { // 'l: branch and link
226 if (instr->HasLink()) { 353 if (instr->HasLink()) {
227 Print("l"); 354 Print("l");
228 } 355 }
229 return 1; 356 return 1;
230 break;
231 } 357 }
232 case 'm': { // 'msg: for simulator break instructions 358 case 'm': {
233 if (format[1] == 'e') { 359 if (format[1] == 'e') { // 'memop: load/store instructions
234 ASSERT((format[2] == 'm') && (format[3] == 'o') && (format[4] == 'p')); 360 ASSERT(STRING_STARTS_WITH(format, "memop"));
235 if (instr->HasL()) { 361 if (instr->HasL()) {
236 Print("ldr"); 362 Print("ldr");
237 } else { 363 } else {
238 Print("str"); 364 Print("str");
239 } 365 }
240 return 5; 366 return 5;
241 } else {
242 ASSERT(format[1] == 's' && format[2] == 'g');
243 byte* str =
244 reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff);
245 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
246 "%s", converter_.NameInCode(str));
247 return 3;
248 } 367 }
249 break; 368 // 'msg: for simulator break instructions
369 ASSERT(STRING_STARTS_WITH(format, "msg"));
370 byte* str =
371 reinterpret_cast<byte*>(instr->InstructionBits() & 0x0fffffff);
372 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
373 "%s", converter_.NameInCode(str));
374 return 3;
250 } 375 }
251 case 'o': { 376 case 'o': {
252 ASSERT(format[1] == 'f' && format[2] == 'f');
253 if (format[3] == '1') { 377 if (format[3] == '1') {
254 // 'off12: 12-bit offset for load and store instructions 378 // 'off12: 12-bit offset for load and store instructions
255 ASSERT(format[4] == '2'); 379 ASSERT(STRING_STARTS_WITH(format, "off12"));
256 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, 380 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
257 "%d", instr->Offset12Field()); 381 "%d", instr->Offset12Field());
258 return 5; 382 return 5;
259 } else {
260 // 'off8: 8-bit offset for extra load and store instructions
261 ASSERT(format[3] == '8');
262 int offs8 = (instr->ImmedHField() << 4) | instr->ImmedLField();
263 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
264 "%d", offs8);
265 return 4;
266 } 383 }
267 break; 384 // 'off8: 8-bit offset for extra load and store instructions
385 ASSERT(STRING_STARTS_WITH(format, "off8"));
386 int offs8 = (instr->ImmedHField() << 4) | instr->ImmedLField();
387 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
388 "%d", offs8);
389 return 4;
268 } 390 }
269 case 'p': { // 'pu: P and U bits for load and store instructions 391 case 'p': { // 'pu: P and U bits for load and store instructions
270 ASSERT(format[1] == 'u'); 392 ASSERT(STRING_STARTS_WITH(format, "pu"));
271 switch (instr->PUField()) { 393 PrintPU(instr);
272 case 0: {
273 Print("da");
274 break;
275 }
276 case 1: {
277 Print("ia");
278 break;
279 }
280 case 2: {
281 Print("db");
282 break;
283 }
284 case 3: {
285 Print("ib");
286 break;
287 }
288 default: {
289 UNREACHABLE();
290 break;
291 }
292 }
293 return 2; 394 return 2;
294 break;
295 } 395 }
296 case 'r': { 396 case 'r': {
297 if (format[1] == 'n') { // 'rn: Rn register 397 return FormatRegister(instr, format);
298 int reg = instr->RnField();
299 PrintRegister(reg);
300 return 2;
301 } else if (format[1] == 'd') { // 'rd: Rd register
302 int reg = instr->RdField();
303 PrintRegister(reg);
304 return 2;
305 } else if (format[1] == 's') { // 'rs: Rs register
306 int reg = instr->RsField();
307 PrintRegister(reg);
308 return 2;
309 } else if (format[1] == 'm') { // 'rm: Rm register
310 int reg = instr->RmField();
311 PrintRegister(reg);
312 return 2;
313 } else if (format[1] == 'l') {
314 // 'rlist: register list for load and store multiple instructions
315 ASSERT(format[2] == 'i' && format[3] == 's' && format[4] == 't');
316 int rlist = instr->RlistField();
317 int reg = 0;
318 Print("{");
319 while (rlist != 0) {
320 if ((rlist & 1) != 0) {
321 PrintRegister(reg);
322 if ((rlist >> 1) != 0) {
323 Print(", ");
324 }
325 }
326 reg++;
327 rlist >>= 1;
328 }
329 Print("}");
330 return 5;
331 } else {
332 UNREACHABLE();
333 }
334 UNREACHABLE();
335 return -1;
336 break;
337 } 398 }
338 case 's': { 399 case 's': {
339 if (format[1] == 'h') { // 'shift_rm: register shift operands 400 if (format[1] == 'h') { // 'shift_op or 'shift_rm
340 ASSERT(format[2] == 'i' && format[3] == 'f' && format[4] == 't' 401 if (format[6] == 'o') { // 'shift_op
341 && format[5] == '_' && format[6] == 'r' && format[7] == 'm'); 402 ASSERT(STRING_STARTS_WITH(format, "shift_op"));
342 PrintShiftRm(instr); 403 if (instr->TypeField() == 0) {
343 return 8; 404 PrintShiftRm(instr);
344 } else if (format[1] == 'w') { 405 } else {
345 ASSERT(format[2] == 'i'); 406 ASSERT(instr->TypeField() == 1);
346 SoftwareInterruptCodes swi = instr->SwiField(); 407 PrintShiftImm(instr);
347 switch (swi) { 408 }
348 case call_rt_r5: 409 return 8;
349 Print("call_rt_r5"); 410 } else { // 'shift_rm
350 break; 411 ASSERT(STRING_STARTS_WITH(format, "shift_rm"));
351 case call_rt_r2: 412 PrintShiftRm(instr);
352 Print("call_rt_r2"); 413 return 8;
353 break;
354 case break_point:
355 Print("break_point");
356 break;
357 default:
358 out_buffer_pos_ += v8i::OS::SNPrintF(
359 out_buffer_ + out_buffer_pos_,
360 "%d",
361 swi);
362 break;
363 } 414 }
415 } else if (format[1] == 'w') { // 'swi
416 ASSERT(STRING_STARTS_WITH(format, "swi"));
417 PrintSoftwareInterrupt(instr->SwiField());
364 return 3; 418 return 3;
365 } else if (format[1] == 'i') { // 'sign: signed extra loads and stores 419 } else if (format[1] == 'i') { // 'sign: signed extra loads and stores
366 ASSERT(format[2] == 'g' && format[3] == 'n'); 420 ASSERT(STRING_STARTS_WITH(format, "sign"));
367 if (instr->HasSign()) { 421 if (instr->HasSign()) {
368 Print("s"); 422 Print("s");
369 } 423 }
370 return 4; 424 return 4;
371 break;
372 } else { // 's: S field of data processing instructions
373 if (instr->HasS()) {
374 Print("s");
375 }
376 return 1;
377 } 425 }
378 break; 426 // 's: S field of data processing instructions
427 if (instr->HasS()) {
428 Print("s");
429 }
430 return 1;
379 } 431 }
380 case 't': { // 'target: target of branch instructions 432 case 't': { // 'target: target of branch instructions
381 ASSERT(format[1] == 'a' && format[2] == 'r' && format[3] == 'g' 433 ASSERT(STRING_STARTS_WITH(format, "target"));
382 && format[4] == 'e' && format[5] == 't');
383 int off = (instr->SImmed24Field() << 2) + 8; 434 int off = (instr->SImmed24Field() << 2) + 8;
384 out_buffer_pos_ += v8i::OS::SNPrintF( 435 out_buffer_pos_ += v8i::OS::SNPrintF(
385 out_buffer_ + out_buffer_pos_, 436 out_buffer_ + out_buffer_pos_,
386 "%+d -> %s", 437 "%+d -> %s",
387 off, 438 off,
388 converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off)); 439 converter_.NameOfAddress(reinterpret_cast<byte*>(instr) + off));
389 return 6; 440 return 6;
390 break;
391 } 441 }
392 case 'u': { // 'u: signed or unsigned multiplies 442 case 'u': { // 'u: signed or unsigned multiplies
393 if (instr->Bit(22) == 0) { 443 if (instr->Bit(22) == 0) {
394 Print("u"); 444 Print("u");
395 } else { 445 } else {
396 Print("s"); 446 Print("s");
397 } 447 }
398 return 1; 448 return 1;
399 break;
400 } 449 }
401 case 'w': { // 'w: W field of load and store instructions 450 case 'w': { // 'w: W field of load and store instructions
402 if (instr->HasW()) { 451 if (instr->HasW()) {
403 Print("!"); 452 Print("!");
404 } 453 }
405 return 1; 454 return 1;
406 break;
407 } 455 }
408 default: { 456 default: {
409 UNREACHABLE(); 457 UNREACHABLE();
410 break; 458 break;
411 } 459 }
412 } 460 }
413 UNREACHABLE(); 461 UNREACHABLE();
414 return -1; 462 return -1;
415 } 463 }
416 464
(...skipping 15 matching lines...) Expand all
432 } 480 }
433 481
434 482
435 // For currently unimplemented decodings the disassembler calls Unknown(instr) 483 // For currently unimplemented decodings the disassembler calls Unknown(instr)
436 // which will just print "unknown" of the instruction bits. 484 // which will just print "unknown" of the instruction bits.
437 void Decoder::Unknown(Instr* instr) { 485 void Decoder::Unknown(Instr* instr) {
438 Format(instr, "unknown"); 486 Format(instr, "unknown");
439 } 487 }
440 488
441 489
442 void Decoder::DecodeType0(Instr* instr) { 490 void Decoder::DecodeType01(Instr* instr) {
443 if (instr->IsSpecialType0()) { 491 int type = instr->TypeField();
492 if ((type == 0) && instr->IsSpecialType0()) {
444 // multiply instruction or extra loads and stores 493 // multiply instruction or extra loads and stores
445 if (instr->Bits(7, 4) == 9) { 494 if (instr->Bits(7, 4) == 9) {
446 if (instr->Bit(24) == 0) { 495 if (instr->Bit(24) == 0) {
447 // multiply instructions 496 // multiply instructions
448 if (instr->Bit(23) == 0) { 497 if (instr->Bit(23) == 0) {
449 if (instr->Bit(21) == 0) { 498 if (instr->Bit(21) == 0) {
450 Format(instr, "mul'cond's 'rd, 'rm, 'rs"); 499 Format(instr, "mul'cond's 'rd, 'rm, 'rs");
451 } else { 500 } else {
452 Format(instr, "mla'cond's 'rd, 'rm, 'rs, 'rn"); 501 Format(instr, "mla'cond's 'rd, 'rm, 'rs, 'rn");
453 } 502 }
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 // The PU field is a 2-bit field. 545 // The PU field is a 2-bit field.
497 UNREACHABLE(); 546 UNREACHABLE();
498 break; 547 break;
499 } 548 }
500 } 549 }
501 return; 550 return;
502 } 551 }
503 } else { 552 } else {
504 switch (instr->OpcodeField()) { 553 switch (instr->OpcodeField()) {
505 case AND: { 554 case AND: {
506 Format(instr, "and'cond's 'rd, 'rn, 'shift_rm"); 555 Format(instr, "and'cond's 'rd, 'rn, 'shift_op");
507 break; 556 break;
508 } 557 }
509 case EOR: { 558 case EOR: {
510 Format(instr, "eor'cond's 'rd, 'rn, 'shift_rm"); 559 Format(instr, "eor'cond's 'rd, 'rn, 'shift_op");
511 break; 560 break;
512 } 561 }
513 case SUB: { 562 case SUB: {
514 Format(instr, "sub'cond's 'rd, 'rn, 'shift_rm"); 563 Format(instr, "sub'cond's 'rd, 'rn, 'shift_op");
515 break; 564 break;
516 } 565 }
517 case RSB: { 566 case RSB: {
518 Format(instr, "rsb'cond's 'rd, 'rn, 'shift_rm"); 567 Format(instr, "rsb'cond's 'rd, 'rn, 'shift_op");
519 break; 568 break;
520 } 569 }
521 case ADD: { 570 case ADD: {
522 Format(instr, "add'cond's 'rd, 'rn, 'shift_rm"); 571 Format(instr, "add'cond's 'rd, 'rn, 'shift_op");
523 break; 572 break;
524 } 573 }
525 case ADC: { 574 case ADC: {
526 Format(instr, "adc'cond's 'rd, 'rn, 'shift_rm"); 575 Format(instr, "adc'cond's 'rd, 'rn, 'shift_op");
527 break; 576 break;
528 } 577 }
529 case SBC: { 578 case SBC: {
530 Format(instr, "sbc'cond's 'rd, 'rn, 'shift_rm"); 579 Format(instr, "sbc'cond's 'rd, 'rn, 'shift_op");
531 break; 580 break;
532 } 581 }
533 case RSC: { 582 case RSC: {
534 Format(instr, "rsc'cond's 'rd, 'rn, 'shift_rm"); 583 Format(instr, "rsc'cond's 'rd, 'rn, 'shift_op");
535 break; 584 break;
536 } 585 }
537 case TST: { 586 case TST: {
538 if (instr->HasS()) { 587 if (instr->HasS()) {
539 Format(instr, "tst'cond 'rn, 'shift_rm"); 588 Format(instr, "tst'cond 'rn, 'shift_op");
540 } else { 589 } else {
541 Unknown(instr); // not used by V8 590 Unknown(instr); // not used by V8
542 return;
543 } 591 }
544 break; 592 break;
545 } 593 }
546 case TEQ: { 594 case TEQ: {
547 if (instr->HasS()) { 595 if (instr->HasS()) {
548 Format(instr, "teq'cond 'rn, 'shift_rm"); 596 Format(instr, "teq'cond 'rn, 'shift_op");
549 } else { 597 } else {
550 Unknown(instr); // not used by V8 598 Unknown(instr); // not used by V8
551 return;
552 } 599 }
553 break; 600 break;
554 } 601 }
555 case CMP: { 602 case CMP: {
556 if (instr->HasS()) { 603 if (instr->HasS()) {
557 Format(instr, "cmp'cond 'rn, 'shift_rm"); 604 Format(instr, "cmp'cond 'rn, 'shift_op");
558 } else { 605 } else {
559 Unknown(instr); // not used by V8 606 Unknown(instr); // not used by V8
560 return;
561 } 607 }
562 break; 608 break;
563 } 609 }
564 case CMN: { 610 case CMN: {
565 if (instr->HasS()) { 611 if (instr->HasS()) {
566 Format(instr, "cmn'cond 'rn, 'shift_rm"); 612 Format(instr, "cmn'cond 'rn, 'shift_op");
567 } else { 613 } else {
568 Unknown(instr); // not used by V8 614 Unknown(instr); // not used by V8
569 return;
570 } 615 }
571 break; 616 break;
572 } 617 }
573 case ORR: { 618 case ORR: {
574 Format(instr, "orr'cond's 'rd, 'rn, 'shift_rm"); 619 Format(instr, "orr'cond's 'rd, 'rn, 'shift_op");
575 break; 620 break;
576 } 621 }
577 case MOV: { 622 case MOV: {
578 Format(instr, "mov'cond's 'rd, 'shift_rm"); 623 Format(instr, "mov'cond's 'rd, 'shift_op");
579 break; 624 break;
580 } 625 }
581 case BIC: { 626 case BIC: {
582 Format(instr, "bic'cond's 'rd, 'rn, 'shift_rm"); 627 Format(instr, "bic'cond's 'rd, 'rn, 'shift_op");
583 break; 628 break;
584 } 629 }
585 case MVN: { 630 case MVN: {
586 Format(instr, "mvn'cond's 'rd, 'shift_rm"); 631 Format(instr, "mvn'cond's 'rd, 'shift_op");
587 break; 632 break;
588 } 633 }
589 default: { 634 default: {
590 // The Opcode field is a 4-bit field. 635 // The Opcode field is a 4-bit field.
591 UNREACHABLE(); 636 UNREACHABLE();
592 break; 637 break;
593 } 638 }
594 } 639 }
595 } 640 }
596 } 641 }
597 642
598 643
599 void Decoder::DecodeType1(Instr* instr) {
600 switch (instr->OpcodeField()) {
601 case AND: {
602 Format(instr, "and'cond's 'rd, 'rn, 'imm");
603 break;
604 }
605 case EOR: {
606 Format(instr, "eor'cond's 'rd, 'rn, 'imm");
607 break;
608 }
609 case SUB: {
610 Format(instr, "sub'cond's 'rd, 'rn, 'imm");
611 break;
612 }
613 case RSB: {
614 Format(instr, "rsb'cond's 'rd, 'rn, 'imm");
615 break;
616 }
617 case ADD: {
618 Format(instr, "add'cond's 'rd, 'rn, 'imm");
619 break;
620 }
621 case ADC: {
622 Format(instr, "adc'cond's 'rd, 'rn, 'imm");
623 break;
624 }
625 case SBC: {
626 Format(instr, "sbc'cond's 'rd, 'rn, 'imm");
627 break;
628 }
629 case RSC: {
630 Format(instr, "rsc'cond's 'rd, 'rn, 'imm");
631 break;
632 }
633 case TST: {
634 if (instr->HasS()) {
635 Format(instr, "tst'cond 'rn, 'imm");
636 } else {
637 Unknown(instr); // not used by V8
638 return;
639 }
640 break;
641 }
642 case TEQ: {
643 if (instr->HasS()) {
644 Format(instr, "teq'cond 'rn, 'imm");
645 } else {
646 Unknown(instr); // not used by V8
647 return;
648 }
649 break;
650 }
651 case CMP: {
652 if (instr->HasS()) {
653 Format(instr, "cmp'cond 'rn, 'imm");
654 } else {
655 Unknown(instr); // not used by V8
656 return;
657 }
658 break;
659 }
660 case CMN: {
661 if (instr->HasS()) {
662 Format(instr, "cmn'cond 'rn, 'imm");
663 } else {
664 Unknown(instr); // not used by V8
665 return;
666 }
667 break;
668 }
669 case ORR: {
670 Format(instr, "orr'cond's 'rd, 'rn, 'imm");
671 break;
672 }
673 case MOV: {
674 Format(instr, "mov'cond's 'rd, 'imm");
675 break;
676 }
677 case BIC: {
678 Format(instr, "bic'cond's 'rd, 'rn, 'imm");
679 break;
680 }
681 case MVN: {
682 Format(instr, "mvn'cond's 'rd, 'imm");
683 break;
684 }
685 default: {
686 // The Opcode field is a 4-bit field.
687 UNREACHABLE();
688 break;
689 }
690 }
691 }
692
693
694 void Decoder::DecodeType2(Instr* instr) { 644 void Decoder::DecodeType2(Instr* instr) {
695 switch (instr->PUField()) { 645 switch (instr->PUField()) {
696 case 0: { 646 case 0: {
697 if (instr->HasW()) { 647 if (instr->HasW()) {
698 Unknown(instr); // not used in V8 648 Unknown(instr); // not used in V8
699 return;
700 } 649 }
701 Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12"); 650 Format(instr, "'memop'cond'b 'rd, ['rn], #-'off12");
702 break; 651 break;
703 } 652 }
704 case 1: { 653 case 1: {
705 if (instr->HasW()) { 654 if (instr->HasW()) {
706 Unknown(instr); // not used in V8 655 Unknown(instr); // not used in V8
707 return;
708 } 656 }
709 Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12"); 657 Format(instr, "'memop'cond'b 'rd, ['rn], #+'off12");
710 break; 658 break;
711 } 659 }
712 case 2: { 660 case 2: {
713 Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w"); 661 Format(instr, "'memop'cond'b 'rd, ['rn, #-'off12]'w");
714 break; 662 break;
715 } 663 }
716 case 3: { 664 case 3: {
717 Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w"); 665 Format(instr, "'memop'cond'b 'rd, ['rn, #+'off12]'w");
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
791 Instr* instr = Instr::At(instr_ptr); 739 Instr* instr = Instr::At(instr_ptr);
792 // Print raw instruction bytes. 740 // Print raw instruction bytes.
793 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_, 741 out_buffer_pos_ += v8i::OS::SNPrintF(out_buffer_ + out_buffer_pos_,
794 "%08x ", 742 "%08x ",
795 instr->InstructionBits()); 743 instr->InstructionBits());
796 if (instr->ConditionField() == special_condition) { 744 if (instr->ConditionField() == special_condition) {
797 Format(instr, "break 'msg"); 745 Format(instr, "break 'msg");
798 return Instr::kInstrSize; 746 return Instr::kInstrSize;
799 } 747 }
800 switch (instr->TypeField()) { 748 switch (instr->TypeField()) {
801 case 0: { 749 case 0:
802 DecodeType0(instr);
803 break;
804 }
805 case 1: { 750 case 1: {
806 DecodeType1(instr); 751 DecodeType01(instr);
807 break; 752 break;
808 } 753 }
809 case 2: { 754 case 2: {
810 DecodeType2(instr); 755 DecodeType2(instr);
811 break; 756 break;
812 } 757 }
813 case 3: { 758 case 3: {
814 DecodeType3(instr); 759 DecodeType3(instr);
815 break; 760 break;
816 } 761 }
(...skipping 24 matching lines...) Expand all
841 786
842 787
843 } } // namespace assembler::arm 788 } } // namespace assembler::arm
844 789
845 790
846 791
847 //------------------------------------------------------------------------------ 792 //------------------------------------------------------------------------------
848 793
849 namespace disasm { 794 namespace disasm {
850 795
851 static const char* reg_names[16] = { 796 namespace v8i = v8::internal;
852 "r0", "r1", "r2" , "r3" , "r4" , "r5" , "r6" , "r7" , 797
798
799 static const int kMaxRegisters = 16;
800
801 // These register names are defined in a way to match the native disassembler
802 // formatting. See for example the command "objdump -d <binary file>".
803 static const char* reg_names[kMaxRegisters] = {
804 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
853 "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc", 805 "r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc",
854 }; 806 };
855 807
856 808
857 const char* NameConverter::NameOfAddress(byte* addr) const { 809 const char* NameConverter::NameOfAddress(byte* addr) const {
858 static v8::internal::EmbeddedVector<char, 32> tmp_buffer; 810 static v8::internal::EmbeddedVector<char, 32> tmp_buffer;
859 v8::internal::OS::SNPrintF(tmp_buffer, "%p", addr); 811 v8::internal::OS::SNPrintF(tmp_buffer, "%p", addr);
860 return tmp_buffer.start(); 812 return tmp_buffer.start();
861 } 813 }
862 814
863 815
864 const char* NameConverter::NameOfConstant(byte* addr) const { 816 const char* NameConverter::NameOfConstant(byte* addr) const {
865 return NameOfAddress(addr); 817 return NameOfAddress(addr);
866 } 818 }
867 819
868 820
869 const char* NameConverter::NameOfCPURegister(int reg) const { 821 const char* NameConverter::NameOfCPURegister(int reg) const {
870 const char* result; 822 const char* result;
871 if ((0 <= reg) && (reg < 16)) { 823 if ((0 <= reg) && (reg < kMaxRegisters)) {
872 result = reg_names[reg]; 824 result = reg_names[reg];
873 } else { 825 } else {
874 result = "noreg"; 826 result = "noreg";
875 } 827 }
876 return result; 828 return result;
877 } 829 }
878 830
879 831
880 const char* NameConverter::NameOfXMMRegister(int reg) const { 832 const char* NameConverter::NameOfXMMRegister(int reg) const {
881 UNREACHABLE(); // ARM does not have any XMM registers 833 UNREACHABLE(); // ARM does not have any XMM registers
882 return "noxmmreg"; 834 return "noxmmreg";
883 } 835 }
884 836
885 837
886 const char* NameConverter::NameInCode(byte* addr) const { 838 const char* NameConverter::NameInCode(byte* addr) const {
887 // The default name converter is called for unknown code. So we will not try 839 // The default name converter is called for unknown code. So we will not try
888 // to access any memory. 840 // to access any memory.
889 return ""; 841 return "";
890 } 842 }
891 843
892 844
893 //------------------------------------------------------------------------------ 845 //------------------------------------------------------------------------------
894 846
895 static NameConverter defaultConverter;
896
897 Disassembler::Disassembler() : converter_(defaultConverter) {}
898
899
900 Disassembler::Disassembler(const NameConverter& converter) 847 Disassembler::Disassembler(const NameConverter& converter)
901 : converter_(converter) {} 848 : converter_(converter) {}
902 849
903 850
904 Disassembler::~Disassembler() {} 851 Disassembler::~Disassembler() {}
905 852
906 853
907 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer, 854 int Disassembler::InstructionDecode(v8::internal::Vector<char> buffer,
908 byte* instruction) { 855 byte* instruction) {
909 assembler::arm::Decoder d(converter_, buffer); 856 assembler::arm::Decoder d(converter_, buffer);
910 return d.InstructionDecode(instruction); 857 return d.InstructionDecode(instruction);
911 } 858 }
912 859
913 860
914 int Disassembler::ConstantPoolSizeAt(byte* instruction) { 861 int Disassembler::ConstantPoolSizeAt(byte* instruction) {
915 int instruction_bits = *(reinterpret_cast<int*>(instruction)); 862 int instruction_bits = *(reinterpret_cast<int*>(instruction));
916 if ((instruction_bits & 0xfff00000) == 0x03000000) { 863 if ((instruction_bits & 0xfff00000) == 0x03000000) {
917 return instruction_bits & 0x0000ffff; 864 return instruction_bits & 0x0000ffff;
918 } else { 865 } else {
919 return -1; 866 return -1;
920 } 867 }
921 } 868 }
922 869
923 870
924 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) { 871 void Disassembler::Disassemble(FILE* f, byte* begin, byte* end) {
925 Disassembler d; 872 NameConverter converter;
873 Disassembler d(converter);
926 for (byte* pc = begin; pc < end;) { 874 for (byte* pc = begin; pc < end;) {
927 v8::internal::EmbeddedVector<char, 128> buffer; 875 v8::internal::EmbeddedVector<char, 128> buffer;
928 buffer[0] = '\0'; 876 buffer[0] = '\0';
929 byte* prev_pc = pc; 877 byte* prev_pc = pc;
930 pc += d.InstructionDecode(buffer, pc); 878 pc += d.InstructionDecode(buffer, pc);
931 fprintf(f, "%p %08x %s\n", 879 fprintf(f, "%p %08x %s\n",
932 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start()); 880 prev_pc, *reinterpret_cast<int32_t*>(prev_pc), buffer.start());
933 } 881 }
934 } 882 }
935 883
936 884
937 } // namespace disasm 885 } // namespace disasm
OLDNEW
« no previous file with comments | « src/disasm.h ('k') | src/disasm-ia32.cc » ('j') | src/v8.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698