| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/disassembler.h" | 5 #include "vm/disassembler.h" |
| 6 | 6 |
| 7 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. | 7 #include "vm/globals.h" // Needed here to get TARGET_ARCH_ARM64. |
| 8 #if defined(TARGET_ARCH_ARM64) | 8 #if defined(TARGET_ARCH_ARM64) |
| 9 #include "platform/assert.h" | 9 #include "platform/assert.h" |
| 10 #include "vm/instructions.h" | 10 #include "vm/instructions.h" |
| 11 | 11 |
| 12 namespace dart { | 12 namespace dart { |
| 13 | 13 |
| 14 #ifndef PRODUCT | 14 #ifndef PRODUCT |
| 15 | 15 |
| 16 class ARM64Decoder : public ValueObject { | 16 class ARM64Decoder : public ValueObject { |
| 17 public: | 17 public: |
| 18 ARM64Decoder(char* buffer, size_t buffer_size) | 18 ARM64Decoder(char* buffer, size_t buffer_size) |
| 19 : buffer_(buffer), | 19 : buffer_(buffer), buffer_size_(buffer_size), buffer_pos_(0) { |
| 20 buffer_size_(buffer_size), | |
| 21 buffer_pos_(0) { | |
| 22 buffer_[buffer_pos_] = '\0'; | 20 buffer_[buffer_pos_] = '\0'; |
| 23 } | 21 } |
| 24 | 22 |
| 25 ~ARM64Decoder() {} | 23 ~ARM64Decoder() {} |
| 26 | 24 |
| 27 // Writes one disassembled instruction into 'buffer' (0-terminated). | 25 // Writes one disassembled instruction into 'buffer' (0-terminated). |
| 28 // Returns true if the instruction was successfully decoded, false otherwise. | 26 // Returns true if the instruction was successfully decoded, false otherwise. |
| 29 void InstructionDecode(uword pc); | 27 void InstructionDecode(uword pc); |
| 30 | 28 |
| 31 private: | 29 private: |
| 32 // Bottleneck functions to print into the out_buffer. | 30 // Bottleneck functions to print into the out_buffer. |
| 33 void Print(const char* str); | 31 void Print(const char* str); |
| 34 | 32 |
| 35 // Printing of common values. | 33 // Printing of common values. |
| 36 void PrintRegister(int reg, R31Type r31t); | 34 void PrintRegister(int reg, R31Type r31t); |
| 37 void PrintVRegister(int reg); | 35 void PrintVRegister(int reg); |
| 38 void PrintShiftExtendRm(Instr* instr); | 36 void PrintShiftExtendRm(Instr* instr); |
| 39 void PrintMemOperand(Instr* instr); | 37 void PrintMemOperand(Instr* instr); |
| 40 void PrintPairMemOperand(Instr* instr); | 38 void PrintPairMemOperand(Instr* instr); |
| 41 void PrintS(Instr* instr); | 39 void PrintS(Instr* instr); |
| 42 void PrintCondition(Instr* instr); | 40 void PrintCondition(Instr* instr); |
| 43 | 41 |
| 44 // Handle formatting of instructions and their options. | 42 // Handle formatting of instructions and their options. |
| 45 int FormatRegister(Instr* instr, const char* option); | 43 int FormatRegister(Instr* instr, const char* option); |
| 46 int FormatVRegister(Instr*instr, const char* option); | 44 int FormatVRegister(Instr* instr, const char* option); |
| 47 int FormatOption(Instr* instr, const char* format); | 45 int FormatOption(Instr* instr, const char* format); |
| 48 void Format(Instr* instr, const char* format); | 46 void Format(Instr* instr, const char* format); |
| 49 void Unknown(Instr* instr); | 47 void Unknown(Instr* instr); |
| 50 | 48 |
| 51 // Decode instructions. | 49 // Decode instructions. |
| 52 #define DECODE_OP(op) \ | 50 #define DECODE_OP(op) void Decode##op(Instr* instr); |
| 53 void Decode##op(Instr* instr); | |
| 54 APPLY_OP_LIST(DECODE_OP) | 51 APPLY_OP_LIST(DECODE_OP) |
| 55 #undef DECODE_OP | 52 #undef DECODE_OP |
| 56 | 53 |
| 57 | 54 |
| 58 // Convenience functions. | 55 // Convenience functions. |
| 59 char* get_buffer() const { return buffer_; } | 56 char* get_buffer() const { return buffer_; } |
| 60 char* current_position_in_buffer() { return buffer_ + buffer_pos_; } | 57 char* current_position_in_buffer() { return buffer_ + buffer_pos_; } |
| 61 size_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; } | 58 size_t remaining_size_in_buffer() { return buffer_size_ - buffer_pos_; } |
| 62 | 59 |
| 63 char* buffer_; // Decode instructions into this buffer. | 60 char* buffer_; // Decode instructions into this buffer. |
| 64 size_t buffer_size_; // The size of the character buffer. | 61 size_t buffer_size_; // The size of the character buffer. |
| 65 size_t buffer_pos_; // Current character position in buffer. | 62 size_t buffer_pos_; // Current character position in buffer. |
| 66 | 63 |
| 67 DISALLOW_ALLOCATION(); | 64 DISALLOW_ALLOCATION(); |
| 68 DISALLOW_COPY_AND_ASSIGN(ARM64Decoder); | 65 DISALLOW_COPY_AND_ASSIGN(ARM64Decoder); |
| 69 }; | 66 }; |
| 70 | 67 |
| 71 | 68 |
| 72 // Support for assertions in the ARM64Decoder formatting functions. | 69 // Support for assertions in the ARM64Decoder formatting functions. |
| 73 #define STRING_STARTS_WITH(string, compare_string) \ | 70 #define STRING_STARTS_WITH(string, compare_string) \ |
| 74 (strncmp(string, compare_string, strlen(compare_string)) == 0) | 71 (strncmp(string, compare_string, strlen(compare_string)) == 0) |
| 75 | 72 |
| 76 | 73 |
| 77 // Append the str to the output buffer. | 74 // Append the str to the output buffer. |
| 78 void ARM64Decoder::Print(const char* str) { | 75 void ARM64Decoder::Print(const char* str) { |
| 79 char cur = *str++; | 76 char cur = *str++; |
| 80 while (cur != '\0' && (buffer_pos_ < (buffer_size_ - 1))) { | 77 while (cur != '\0' && (buffer_pos_ < (buffer_size_ - 1))) { |
| 81 buffer_[buffer_pos_++] = cur; | 78 buffer_[buffer_pos_++] = cur; |
| 82 cur = *str++; | 79 cur = *str++; |
| 83 } | 80 } |
| 84 buffer_[buffer_pos_] = '\0'; | 81 buffer_[buffer_pos_] = '\0'; |
| 85 } | 82 } |
| 86 | 83 |
| 87 | 84 |
| 88 // These register names are defined in a way to match the native disassembler | 85 // These register names are defined in a way to match the native disassembler |
| 89 // formatting, except for register aliases ctx (r9), pp (r10) and sp (r19). | 86 // formatting, except for register aliases ctx (r9), pp (r10) and sp (r19). |
| 90 // See for example the command "objdump -d <binary file>". | 87 // See for example the command "objdump -d <binary file>". |
| 91 static const char* reg_names[kNumberOfCpuRegisters] = { | 88 static const char* reg_names[kNumberOfCpuRegisters] = { |
| 92 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", | 89 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", |
| 93 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", | 90 "r11", "r12", "r13", "r14", "r15", "ip0", "ip1", "r18", "sp", "r20", "r21", |
| 94 "ip0", "ip1", "r18", "sp", "r20", "r21", "r22", "r23", | 91 "r22", "r23", "r24", "r25", "thr", "pp", "ctx", "fp", "lr", "r31", |
| 95 "r24", "r25", "thr", "pp", "ctx", "fp", "lr", "r31", | |
| 96 }; | 92 }; |
| 97 | 93 |
| 98 | 94 |
| 99 // Print the register name according to the active name converter. | 95 // Print the register name according to the active name converter. |
| 100 void ARM64Decoder::PrintRegister(int reg, R31Type r31t) { | 96 void ARM64Decoder::PrintRegister(int reg, R31Type r31t) { |
| 101 ASSERT(0 <= reg); | 97 ASSERT(0 <= reg); |
| 102 ASSERT(reg < kNumberOfCpuRegisters); | 98 ASSERT(reg < kNumberOfCpuRegisters); |
| 103 if (reg == 31) { | 99 if (reg == 31) { |
| 104 const char* rstr = (r31t == R31IsZR) ? "zr" : "csp"; | 100 const char* rstr = (r31t == R31IsZR) ? "zr" : "csp"; |
| 105 Print(rstr); | 101 Print(rstr); |
| 106 } else { | 102 } else { |
| 107 Print(reg_names[reg]); | 103 Print(reg_names[reg]); |
| 108 } | 104 } |
| 109 } | 105 } |
| 110 | 106 |
| 111 | 107 |
| 112 void ARM64Decoder::PrintVRegister(int reg) { | 108 void ARM64Decoder::PrintVRegister(int reg) { |
| 113 ASSERT(0 <= reg); | 109 ASSERT(0 <= reg); |
| 114 ASSERT(reg < kNumberOfVRegisters); | 110 ASSERT(reg < kNumberOfVRegisters); |
| 115 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 111 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 116 remaining_size_in_buffer(), | 112 remaining_size_in_buffer(), "v%d", reg); |
| 117 "v%d", reg); | |
| 118 } | 113 } |
| 119 | 114 |
| 120 | 115 |
| 121 // These shift names are defined in a way to match the native disassembler | 116 // These shift names are defined in a way to match the native disassembler |
| 122 // formatting. See for example the command "objdump -d <binary file>". | 117 // formatting. See for example the command "objdump -d <binary file>". |
| 123 static const char* shift_names[kMaxShift] = { | 118 static const char* shift_names[kMaxShift] = {"lsl", "lsr", "asr", "ror"}; |
| 124 "lsl", "lsr", "asr", "ror" | |
| 125 }; | |
| 126 | 119 |
| 127 | 120 |
| 128 static const char* extend_names[kMaxExtend] = { | 121 static const char* extend_names[kMaxExtend] = { |
| 129 "uxtb", "uxth", "uxtw", "uxtx", | 122 "uxtb", "uxth", "uxtw", "uxtx", "sxtb", "sxth", "sxtw", "sxtx", |
| 130 "sxtb", "sxth", "sxtw", "sxtx", | |
| 131 }; | 123 }; |
| 132 | 124 |
| 133 | 125 |
| 134 // These condition names are defined in a way to match the native disassembler | 126 // These condition names are defined in a way to match the native disassembler |
| 135 // formatting. See for example the command "objdump -d <binary file>". | 127 // formatting. See for example the command "objdump -d <binary file>". |
| 136 static const char* cond_names[kMaxCondition] = { | 128 static const char* cond_names[kMaxCondition] = { |
| 137 "eq", "ne", "cs" , "cc" , "mi" , "pl" , "vs" , "vc" , | 129 "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", |
| 138 "hi", "ls", "ge", "lt", "gt", "le", "", "invalid", | 130 "hi", "ls", "ge", "lt", "gt", "le", "", "invalid", |
| 139 }; | 131 }; |
| 140 | 132 |
| 141 | 133 |
| 142 // Print the condition guarding the instruction. | 134 // Print the condition guarding the instruction. |
| 143 void ARM64Decoder::PrintCondition(Instr* instr) { | 135 void ARM64Decoder::PrintCondition(Instr* instr) { |
| 144 if (instr->IsConditionalSelectOp()) { | 136 if (instr->IsConditionalSelectOp()) { |
| 145 Print(cond_names[instr->SelectConditionField()]); | 137 Print(cond_names[instr->SelectConditionField()]); |
| 146 } else { | 138 } else { |
| 147 Print(cond_names[instr->ConditionField()]); | 139 Print(cond_names[instr->ConditionField()]); |
| 148 } | 140 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 165 return; | 157 return; |
| 166 } | 158 } |
| 167 if (instr->IsShift()) { | 159 if (instr->IsShift()) { |
| 168 // by immediate | 160 // by immediate |
| 169 if ((shift == ROR) && (shift_amount == 0)) { | 161 if ((shift == ROR) && (shift_amount == 0)) { |
| 170 Print(" RRX"); | 162 Print(" RRX"); |
| 171 return; | 163 return; |
| 172 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { | 164 } else if (((shift == LSR) || (shift == ASR)) && (shift_amount == 0)) { |
| 173 shift_amount = 32; | 165 shift_amount = 32; |
| 174 } | 166 } |
| 175 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 167 buffer_pos_ += |
| 176 remaining_size_in_buffer(), | 168 OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(), |
| 177 " %s #%d", | 169 " %s #%d", shift_names[shift], shift_amount); |
| 178 shift_names[shift], | |
| 179 shift_amount); | |
| 180 } else { | 170 } else { |
| 181 ASSERT(instr->IsExtend()); | 171 ASSERT(instr->IsExtend()); |
| 182 // by register | 172 // by register |
| 183 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 173 buffer_pos_ += |
| 184 remaining_size_in_buffer(), | 174 OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(), |
| 185 " %s", | 175 " %s", extend_names[extend]); |
| 186 extend_names[extend]); | |
| 187 if (((instr->SFField() == 1) && (extend == UXTX)) || | 176 if (((instr->SFField() == 1) && (extend == UXTX)) || |
| 188 ((instr->SFField() == 0) && (extend == UXTW))) { | 177 ((instr->SFField() == 0) && (extend == UXTW))) { |
| 189 // Shift amount. | 178 // Shift amount. |
| 190 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 179 buffer_pos_ += |
| 191 remaining_size_in_buffer(), | 180 OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(), |
| 192 " %d", | 181 " %d", extend_shift_amount); |
| 193 extend_shift_amount); | |
| 194 } | 182 } |
| 195 } | 183 } |
| 196 } | 184 } |
| 197 | 185 |
| 198 | 186 |
| 199 void ARM64Decoder::PrintMemOperand(Instr* instr) { | 187 void ARM64Decoder::PrintMemOperand(Instr* instr) { |
| 200 const Register rn = instr->RnField(); | 188 const Register rn = instr->RnField(); |
| 201 if (instr->Bit(24) == 1) { | 189 if (instr->Bit(24) == 1) { |
| 202 // rn + scaled unsigned 12-bit immediate offset. | 190 // rn + scaled unsigned 12-bit immediate offset. |
| 203 const uint32_t scale = instr->SzField(); | 191 const uint32_t scale = instr->SzField(); |
| 204 const uint32_t imm12 = instr->Imm12Field(); | 192 const uint32_t imm12 = instr->Imm12Field(); |
| 205 const uint32_t off = imm12 << scale; | 193 const uint32_t off = imm12 << scale; |
| 206 Print("["); | 194 Print("["); |
| 207 PrintRegister(rn, R31IsSP); | 195 PrintRegister(rn, R31IsSP); |
| 208 if (off != 0) { | 196 if (off != 0) { |
| 209 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 197 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 210 remaining_size_in_buffer(), | 198 remaining_size_in_buffer(), ", #%d", off); |
| 211 ", #%d", | |
| 212 off); | |
| 213 } | 199 } |
| 214 Print("]"); | 200 Print("]"); |
| 215 } else { | 201 } else { |
| 216 switch (instr->Bits(10, 2)) { | 202 switch (instr->Bits(10, 2)) { |
| 217 case 0: { | 203 case 0: { |
| 218 // rn + signed 9-bit immediate, pre-index, no writeback. | 204 // rn + signed 9-bit immediate, pre-index, no writeback. |
| 219 const int32_t imm9 = instr->SImm9Field(); | 205 const int32_t imm9 = instr->SImm9Field(); |
| 220 Print("["); | 206 Print("["); |
| 221 PrintRegister(rn, R31IsSP); | 207 PrintRegister(rn, R31IsSP); |
| 222 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 208 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 223 remaining_size_in_buffer(), | 209 remaining_size_in_buffer(), ", #%d", imm9); |
| 224 ", #%d", | |
| 225 imm9); | |
| 226 Print("]"); | 210 Print("]"); |
| 227 break; | 211 break; |
| 228 } | 212 } |
| 229 case 1: { | 213 case 1: { |
| 230 const int32_t imm9 = instr->SImm9Field(); | 214 const int32_t imm9 = instr->SImm9Field(); |
| 231 // rn + signed 9-bit immediate, post-index, writeback. | 215 // rn + signed 9-bit immediate, post-index, writeback. |
| 232 Print("["); | 216 Print("["); |
| 233 PrintRegister(rn, R31IsSP); | 217 PrintRegister(rn, R31IsSP); |
| 234 Print("]"); | 218 Print("]"); |
| 235 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 219 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 236 remaining_size_in_buffer(), | 220 remaining_size_in_buffer(), ", #%d !", imm9); |
| 237 ", #%d !", | |
| 238 imm9); | |
| 239 break; | 221 break; |
| 240 } | 222 } |
| 241 case 2: { | 223 case 2: { |
| 242 const Register rm = instr->RmField(); | 224 const Register rm = instr->RmField(); |
| 243 const Extend ext = instr->ExtendTypeField(); | 225 const Extend ext = instr->ExtendTypeField(); |
| 244 const int s = instr->Bit(12); | 226 const int s = instr->Bit(12); |
| 245 Print("["); | 227 Print("["); |
| 246 PrintRegister(rn, R31IsSP); | 228 PrintRegister(rn, R31IsSP); |
| 247 Print(", "); | 229 Print(", "); |
| 248 PrintRegister(rm, R31IsZR); | 230 PrintRegister(rm, R31IsZR); |
| 249 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 231 buffer_pos_ += |
| 250 remaining_size_in_buffer(), | 232 OS::SNPrint(current_position_in_buffer(), |
| 251 " %s", | 233 remaining_size_in_buffer(), " %s", extend_names[ext]); |
| 252 extend_names[ext]); | |
| 253 if (s == 1) { | 234 if (s == 1) { |
| 254 Print(" scaled"); | 235 Print(" scaled"); |
| 255 } | 236 } |
| 256 Print("]"); | 237 Print("]"); |
| 257 break; | 238 break; |
| 258 } | 239 } |
| 259 case 3: { | 240 case 3: { |
| 260 const int32_t imm9 = instr->SImm9Field(); | 241 const int32_t imm9 = instr->SImm9Field(); |
| 261 // rn + signed 9-bit immediate, pre-index, writeback. | 242 // rn + signed 9-bit immediate, pre-index, writeback. |
| 262 Print("["); | 243 Print("["); |
| 263 PrintRegister(rn, R31IsSP); | 244 PrintRegister(rn, R31IsSP); |
| 264 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 245 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 265 remaining_size_in_buffer(), | 246 remaining_size_in_buffer(), ", #%d", imm9); |
| 266 ", #%d", | |
| 267 imm9); | |
| 268 Print("] !"); | 247 Print("] !"); |
| 269 break; | 248 break; |
| 270 } | 249 } |
| 271 default: { | 250 default: { Print("???"); } |
| 272 Print("???"); | |
| 273 } | |
| 274 } | 251 } |
| 275 } | 252 } |
| 276 } | 253 } |
| 277 | 254 |
| 278 | 255 |
| 279 void ARM64Decoder::PrintPairMemOperand(Instr* instr) { | 256 void ARM64Decoder::PrintPairMemOperand(Instr* instr) { |
| 280 const Register rn = instr->RnField(); | 257 const Register rn = instr->RnField(); |
| 281 const int32_t simm7 = instr->SImm7Field(); | 258 const int32_t simm7 = instr->SImm7Field(); |
| 282 const int32_t offset = simm7 << (2 + instr->Bit(31)); | 259 const int32_t offset = simm7 << (2 + instr->Bit(31)); |
| 283 Print("["); | 260 Print("["); |
| 284 PrintRegister(rn, R31IsSP); | 261 PrintRegister(rn, R31IsSP); |
| 285 switch (instr->Bits(23, 3)) { | 262 switch (instr->Bits(23, 3)) { |
| 286 case 1: | 263 case 1: |
| 287 // rn + (imm7 << (2 + B31)), post-index, writeback. | 264 // rn + (imm7 << (2 + B31)), post-index, writeback. |
| 288 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 265 buffer_pos_ += |
| 289 remaining_size_in_buffer(), | 266 OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(), |
| 290 "], #%d !", | 267 "], #%d !", offset); |
| 291 offset); | |
| 292 break; | 268 break; |
| 293 case 2: | 269 case 2: |
| 294 // rn + (imm7 << (2 + B31)), pre-index, no writeback. | 270 // rn + (imm7 << (2 + B31)), pre-index, no writeback. |
| 295 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 271 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 296 remaining_size_in_buffer(), | 272 remaining_size_in_buffer(), ", #%d ]", offset); |
| 297 ", #%d ]", | |
| 298 offset); | |
| 299 break; | 273 break; |
| 300 case 3: | 274 case 3: |
| 301 // rn + (imm7 << (2 + B31)), pre-index, writeback. | 275 // rn + (imm7 << (2 + B31)), pre-index, writeback. |
| 302 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 276 buffer_pos_ += |
| 303 remaining_size_in_buffer(), | 277 OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(), |
| 304 ", #%d ]!", | 278 ", #%d ]!", offset); |
| 305 offset); | |
| 306 break; | 279 break; |
| 307 default: | 280 default: |
| 308 Print(", ???]"); | 281 Print(", ???]"); |
| 309 break; | 282 break; |
| 310 } | 283 } |
| 311 } | 284 } |
| 312 | 285 |
| 313 | 286 |
| 314 // Handle all register based formatting in these functions to reduce the | 287 // Handle all register based formatting in these functions to reduce the |
| 315 // complexity of FormatOption. | 288 // complexity of FormatOption. |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 374 // character of the option string (the option escape has already been | 347 // character of the option string (the option escape has already been |
| 375 // consumed by the caller.) FormatOption returns the number of | 348 // consumed by the caller.) FormatOption returns the number of |
| 376 // characters that were consumed from the formatting string. | 349 // characters that were consumed from the formatting string. |
| 377 int ARM64Decoder::FormatOption(Instr* instr, const char* format) { | 350 int ARM64Decoder::FormatOption(Instr* instr, const char* format) { |
| 378 switch (format[0]) { | 351 switch (format[0]) { |
| 379 case 'b': { | 352 case 'b': { |
| 380 if (format[3] == 'i') { | 353 if (format[3] == 'i') { |
| 381 ASSERT(STRING_STARTS_WITH(format, "bitimm")); | 354 ASSERT(STRING_STARTS_WITH(format, "bitimm")); |
| 382 const uint64_t imm = instr->ImmLogical(); | 355 const uint64_t imm = instr->ImmLogical(); |
| 383 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 356 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 384 remaining_size_in_buffer(), | 357 remaining_size_in_buffer(), "0x%" Px64, imm); |
| 385 "0x%" Px64, | |
| 386 imm); | |
| 387 return 6; | 358 return 6; |
| 388 } else { | 359 } else { |
| 389 ASSERT(STRING_STARTS_WITH(format, "bitpos")); | 360 ASSERT(STRING_STARTS_WITH(format, "bitpos")); |
| 390 int bitpos = instr->Bits(19, 4) | (instr->Bit(31) << 5); | 361 int bitpos = instr->Bits(19, 4) | (instr->Bit(31) << 5); |
| 391 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 362 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 392 remaining_size_in_buffer(), | 363 remaining_size_in_buffer(), "#%d", bitpos); |
| 393 "#%d", | |
| 394 bitpos); | |
| 395 return 6; | 364 return 6; |
| 396 } | 365 } |
| 397 } | 366 } |
| 398 case 'c': { | 367 case 'c': { |
| 399 if (format[1] == 's') { | 368 if (format[1] == 's') { |
| 400 ASSERT(STRING_STARTS_WITH(format, "csz")); | 369 ASSERT(STRING_STARTS_WITH(format, "csz")); |
| 401 const int32_t imm5 = instr->Bits(16, 5); | 370 const int32_t imm5 = instr->Bits(16, 5); |
| 402 char const* typ = "??"; | 371 char const* typ = "??"; |
| 403 if (imm5 & 0x1) { | 372 if (imm5 & 0x1) { |
| 404 typ = "b"; | 373 typ = "b"; |
| 405 } else if (imm5 & 0x2) { | 374 } else if (imm5 & 0x2) { |
| 406 typ = "h"; | 375 typ = "h"; |
| 407 } else if (imm5 & 0x4) { | 376 } else if (imm5 & 0x4) { |
| 408 typ = "s"; | 377 typ = "s"; |
| 409 } else if (imm5 & 0x8) { | 378 } else if (imm5 & 0x8) { |
| 410 typ = "d"; | 379 typ = "d"; |
| 411 } | 380 } |
| 412 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 381 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 413 remaining_size_in_buffer(), | 382 remaining_size_in_buffer(), "%s", typ); |
| 414 "%s", | |
| 415 typ); | |
| 416 return 3; | 383 return 3; |
| 417 } else { | 384 } else { |
| 418 ASSERT(STRING_STARTS_WITH(format, "cond")); | 385 ASSERT(STRING_STARTS_WITH(format, "cond")); |
| 419 PrintCondition(instr); | 386 PrintCondition(instr); |
| 420 return 4; | 387 return 4; |
| 421 } | 388 } |
| 422 } | 389 } |
| 423 case 'd': { | 390 case 'd': { |
| 424 if (format[4] == '2') { | 391 if (format[4] == '2') { |
| 425 ASSERT(STRING_STARTS_WITH(format, "dest26")); | 392 ASSERT(STRING_STARTS_WITH(format, "dest26")); |
| 426 int64_t off = instr->SImm26Field() << 2; | 393 int64_t off = instr->SImm26Field() << 2; |
| 427 uword destination = reinterpret_cast<uword>(instr) + off; | 394 uword destination = reinterpret_cast<uword>(instr) + off; |
| 428 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 395 buffer_pos_ += |
| 429 remaining_size_in_buffer(), | 396 OS::SNPrint(current_position_in_buffer(), |
| 430 "%#" Px "", | 397 remaining_size_in_buffer(), "%#" Px "", destination); |
| 431 destination); | |
| 432 } else { | 398 } else { |
| 433 if (format[5] == '4') { | 399 if (format[5] == '4') { |
| 434 ASSERT(STRING_STARTS_WITH(format, "dest14")); | 400 ASSERT(STRING_STARTS_WITH(format, "dest14")); |
| 435 int64_t off = instr->SImm14Field() << 2; | 401 int64_t off = instr->SImm14Field() << 2; |
| 436 uword destination = reinterpret_cast<uword>(instr) + off; | 402 uword destination = reinterpret_cast<uword>(instr) + off; |
| 437 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 403 buffer_pos_ += |
| 438 remaining_size_in_buffer(), | 404 OS::SNPrint(current_position_in_buffer(), |
| 439 "%#" Px "", | 405 remaining_size_in_buffer(), "%#" Px "", destination); |
| 440 destination); | |
| 441 } else { | 406 } else { |
| 442 ASSERT(STRING_STARTS_WITH(format, "dest19")); | 407 ASSERT(STRING_STARTS_WITH(format, "dest19")); |
| 443 int64_t off = instr->SImm19Field() << 2; | 408 int64_t off = instr->SImm19Field() << 2; |
| 444 uword destination = reinterpret_cast<uword>(instr) + off; | 409 uword destination = reinterpret_cast<uword>(instr) + off; |
| 445 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 410 buffer_pos_ += |
| 446 remaining_size_in_buffer(), | 411 OS::SNPrint(current_position_in_buffer(), |
| 447 "%#" Px "", | 412 remaining_size_in_buffer(), "%#" Px "", destination); |
| 448 destination); | |
| 449 } | 413 } |
| 450 } | 414 } |
| 451 return 6; | 415 return 6; |
| 452 } | 416 } |
| 453 case 'f': { | 417 case 'f': { |
| 454 ASSERT(STRING_STARTS_WITH(format, "fsz")); | 418 ASSERT(STRING_STARTS_WITH(format, "fsz")); |
| 455 const int sz = instr->SzField(); | 419 const int sz = instr->SzField(); |
| 456 char const* sz_str; | 420 char const* sz_str; |
| 457 switch (sz) { | 421 switch (sz) { |
| 458 case 0: | 422 case 0: |
| 459 if (instr->Bit(23) == 1) { | 423 if (instr->Bit(23) == 1) { |
| 460 sz_str = "q"; | 424 sz_str = "q"; |
| 461 } else { | 425 } else { |
| 462 sz_str = "b"; | 426 sz_str = "b"; |
| 463 } | 427 } |
| 464 break; | 428 break; |
| 465 case 1: sz_str = "h"; break; | 429 case 1: |
| 466 case 2: sz_str = "s"; break; | 430 sz_str = "h"; |
| 467 case 3: sz_str = "d"; break; | 431 break; |
| 468 default: sz_str = "?"; break; | 432 case 2: |
| 469 } | 433 sz_str = "s"; |
| 470 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 434 break; |
| 471 remaining_size_in_buffer(), | 435 case 3: |
| 472 "%s", | 436 sz_str = "d"; |
| 473 sz_str); | 437 break; |
| 438 default: |
| 439 sz_str = "?"; |
| 440 break; |
| 441 } |
| 442 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 443 remaining_size_in_buffer(), "%s", sz_str); |
| 474 return 3; | 444 return 3; |
| 475 } | 445 } |
| 476 case 'h': { | 446 case 'h': { |
| 477 ASSERT(STRING_STARTS_WITH(format, "hw")); | 447 ASSERT(STRING_STARTS_WITH(format, "hw")); |
| 478 const int shift = instr->HWField() << 4; | 448 const int shift = instr->HWField() << 4; |
| 479 if (shift != 0) { | 449 if (shift != 0) { |
| 480 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 450 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 481 remaining_size_in_buffer(), | 451 remaining_size_in_buffer(), "lsl %d", shift); |
| 482 "lsl %d", | |
| 483 shift); | |
| 484 } | 452 } |
| 485 return 2; | 453 return 2; |
| 486 } | 454 } |
| 487 case 'i': { // 'imm12, 'imm16, 'immd | 455 case 'i': { // 'imm12, 'imm16, 'immd |
| 488 if (format[1] == 'd') { | 456 if (format[1] == 'd') { |
| 489 // Element index for a SIMD copy instruction. | 457 // Element index for a SIMD copy instruction. |
| 490 ASSERT(STRING_STARTS_WITH(format, "idx")); | 458 ASSERT(STRING_STARTS_WITH(format, "idx")); |
| 491 const int32_t imm4 = instr->Bits(11, 4); | 459 const int32_t imm4 = instr->Bits(11, 4); |
| 492 const int32_t imm5 = instr->Bits(16, 5); | 460 const int32_t imm5 = instr->Bits(16, 5); |
| 493 int32_t shift = 0; | 461 int32_t shift = 0; |
| 494 int32_t imm = -1; | 462 int32_t imm = -1; |
| 495 if (format[3] == '4') { | 463 if (format[3] == '4') { |
| 496 imm = imm4; | 464 imm = imm4; |
| 497 } else if (format[3] == '5') { | 465 } else if (format[3] == '5') { |
| 498 imm = imm5; | 466 imm = imm5; |
| 499 shift = 1; | 467 shift = 1; |
| 500 } | 468 } |
| 501 int32_t idx = -1; | 469 int32_t idx = -1; |
| 502 if (imm5 & 0x1) { | 470 if (imm5 & 0x1) { |
| 503 idx = imm >> shift; | 471 idx = imm >> shift; |
| 504 } else if (imm5 & 0x2) { | 472 } else if (imm5 & 0x2) { |
| 505 idx = imm >> (shift + 1); | 473 idx = imm >> (shift + 1); |
| 506 } else if (imm5 & 0x4) { | 474 } else if (imm5 & 0x4) { |
| 507 idx = imm >> (shift + 2); | 475 idx = imm >> (shift + 2); |
| 508 } else if (imm5 & 0x8) { | 476 } else if (imm5 & 0x8) { |
| 509 idx = imm >> (shift + 3); | 477 idx = imm >> (shift + 3); |
| 510 } | 478 } |
| 511 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 479 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 512 remaining_size_in_buffer(), | 480 remaining_size_in_buffer(), "[%d]", idx); |
| 513 "[%d]", | |
| 514 idx); | |
| 515 return 4; | 481 return 4; |
| 516 } else if (format[3] == '1') { | 482 } else if (format[3] == '1') { |
| 517 uint64_t imm; | 483 uint64_t imm; |
| 518 int ret = 5; | 484 int ret = 5; |
| 519 if (format[4] == '2') { | 485 if (format[4] == '2') { |
| 520 ASSERT(STRING_STARTS_WITH(format, "imm12")); | 486 ASSERT(STRING_STARTS_WITH(format, "imm12")); |
| 521 imm = instr->Imm12Field(); | 487 imm = instr->Imm12Field(); |
| 522 if (format[5] == 's') { | 488 if (format[5] == 's') { |
| 523 // shifted immediate. | 489 // shifted immediate. |
| 524 if (instr->Imm12ShiftField() == 1) { | 490 if (instr->Imm12ShiftField() == 1) { |
| 525 imm = imm << 12; | 491 imm = imm << 12; |
| 526 } else if ((instr->Imm12ShiftField() & 0x2) != 0) { | 492 } else if ((instr->Imm12ShiftField() & 0x2) != 0) { |
| 527 Print("Unknown Shift"); | 493 Print("Unknown Shift"); |
| 528 } | 494 } |
| 529 ret = 6; | 495 ret = 6; |
| 530 } | 496 } |
| 531 } else { | 497 } else { |
| 532 ASSERT(STRING_STARTS_WITH(format, "imm16")); | 498 ASSERT(STRING_STARTS_WITH(format, "imm16")); |
| 533 imm = instr->Imm16Field(); | 499 imm = instr->Imm16Field(); |
| 534 } | 500 } |
| 535 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 501 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 536 remaining_size_in_buffer(), | 502 remaining_size_in_buffer(), "0x%" Px64, imm); |
| 537 "0x%" Px64, | |
| 538 imm); | |
| 539 return ret; | 503 return ret; |
| 540 } else { | 504 } else { |
| 541 ASSERT(STRING_STARTS_WITH(format, "immd")); | 505 ASSERT(STRING_STARTS_WITH(format, "immd")); |
| 542 double dimm = bit_cast<double, int64_t>( | 506 double dimm = |
| 543 Instr::VFPExpandImm(instr->Imm8Field())); | 507 bit_cast<double, int64_t>(Instr::VFPExpandImm(instr->Imm8Field())); |
| 544 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 508 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 545 remaining_size_in_buffer(), | 509 remaining_size_in_buffer(), "%f", dimm); |
| 546 "%f", | |
| 547 dimm); | |
| 548 return 4; | 510 return 4; |
| 549 } | 511 } |
| 550 } | 512 } |
| 551 case 'm': { | 513 case 'm': { |
| 552 ASSERT(STRING_STARTS_WITH(format, "memop")); | 514 ASSERT(STRING_STARTS_WITH(format, "memop")); |
| 553 PrintMemOperand(instr); | 515 PrintMemOperand(instr); |
| 554 return 5; | 516 return 5; |
| 555 } | 517 } |
| 556 case 'p': { | 518 case 'p': { |
| 557 if (format[1] == 'c') { | 519 if (format[1] == 'c') { |
| 558 if (format[2] == 'a') { | 520 if (format[2] == 'a') { |
| 559 ASSERT(STRING_STARTS_WITH(format, "pcadr")); | 521 ASSERT(STRING_STARTS_WITH(format, "pcadr")); |
| 560 const int64_t immhi = instr->SImm19Field(); | 522 const int64_t immhi = instr->SImm19Field(); |
| 561 const int64_t immlo = instr->Bits(29, 2); | 523 const int64_t immlo = instr->Bits(29, 2); |
| 562 const int64_t off = (immhi << 2) | immlo; | 524 const int64_t off = (immhi << 2) | immlo; |
| 563 const int64_t pc = reinterpret_cast<int64_t>(instr); | 525 const int64_t pc = reinterpret_cast<int64_t>(instr); |
| 564 const int64_t dest = pc + off; | 526 const int64_t dest = pc + off; |
| 565 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 527 buffer_pos_ += |
| 566 remaining_size_in_buffer(), | 528 OS::SNPrint(current_position_in_buffer(), |
| 567 "0x%" Px64, | 529 remaining_size_in_buffer(), "0x%" Px64, dest); |
| 568 dest); | |
| 569 } else { | 530 } else { |
| 570 ASSERT(STRING_STARTS_WITH(format, "pcldr")); | 531 ASSERT(STRING_STARTS_WITH(format, "pcldr")); |
| 571 const int64_t off = instr->SImm19Field() << 2; | 532 const int64_t off = instr->SImm19Field() << 2; |
| 572 const int64_t pc = reinterpret_cast<int64_t>(instr); | 533 const int64_t pc = reinterpret_cast<int64_t>(instr); |
| 573 const int64_t dest = pc + off; | 534 const int64_t dest = pc + off; |
| 574 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 535 buffer_pos_ += |
| 575 remaining_size_in_buffer(), | 536 OS::SNPrint(current_position_in_buffer(), |
| 576 "0x%" Px64, | 537 remaining_size_in_buffer(), "0x%" Px64, dest); |
| 577 dest); | |
| 578 } | 538 } |
| 579 return 5; | 539 return 5; |
| 580 } else { | 540 } else { |
| 581 ASSERT(STRING_STARTS_WITH(format, "pmemop")); | 541 ASSERT(STRING_STARTS_WITH(format, "pmemop")); |
| 582 PrintPairMemOperand(instr); | 542 PrintPairMemOperand(instr); |
| 583 return 6; | 543 return 6; |
| 584 } | 544 } |
| 585 } | 545 } |
| 586 case 'r': { | 546 case 'r': { |
| 587 return FormatRegister(instr, format); | 547 return FormatRegister(instr, format); |
| 588 } | 548 } |
| 589 case 'v': { | 549 case 'v': { |
| 590 if (format[1] == 's') { | 550 if (format[1] == 's') { |
| 591 ASSERT(STRING_STARTS_WITH(format, "vsz")); | 551 ASSERT(STRING_STARTS_WITH(format, "vsz")); |
| 592 char const* sz_str = NULL; | 552 char const* sz_str = NULL; |
| 593 if (instr->Bits(14, 2) == 3) { | 553 if (instr->Bits(14, 2) == 3) { |
| 594 switch (instr->Bit(22)) { | 554 switch (instr->Bit(22)) { |
| 595 case 0: sz_str = "s"; break; | 555 case 0: |
| 596 case 1: sz_str = "d"; break; | 556 sz_str = "s"; |
| 597 default: UNREACHABLE(); break; | 557 break; |
| 558 case 1: |
| 559 sz_str = "d"; |
| 560 break; |
| 561 default: |
| 562 UNREACHABLE(); |
| 563 break; |
| 598 } | 564 } |
| 599 } else { | 565 } else { |
| 600 switch (instr->Bit(22)) { | 566 switch (instr->Bit(22)) { |
| 601 case 0: sz_str = "w"; break; | 567 case 0: |
| 602 case 1: sz_str = "x"; break; | 568 sz_str = "w"; |
| 603 default: UNREACHABLE(); break; | 569 break; |
| 570 case 1: |
| 571 sz_str = "x"; |
| 572 break; |
| 573 default: |
| 574 UNREACHABLE(); |
| 575 break; |
| 604 } | 576 } |
| 605 } | 577 } |
| 606 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 578 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 607 remaining_size_in_buffer(), | 579 remaining_size_in_buffer(), "%s", sz_str); |
| 608 "%s", | |
| 609 sz_str); | |
| 610 return 3; | 580 return 3; |
| 611 } else { | 581 } else { |
| 612 return FormatVRegister(instr, format); | 582 return FormatVRegister(instr, format); |
| 613 } | 583 } |
| 614 } | 584 } |
| 615 case 's': { // 's: S flag. | 585 case 's': { // 's: S flag. |
| 616 if (format[1] == 'h') { | 586 if (format[1] == 'h') { |
| 617 ASSERT(STRING_STARTS_WITH(format, "shift_op")); | 587 ASSERT(STRING_STARTS_WITH(format, "shift_op")); |
| 618 PrintShiftExtendRm(instr); | 588 PrintShiftExtendRm(instr); |
| 619 return 8; | 589 return 8; |
| 620 } else if (format[1] == 'f') { | 590 } else if (format[1] == 'f') { |
| 621 ASSERT(STRING_STARTS_WITH(format, "sf")); | 591 ASSERT(STRING_STARTS_WITH(format, "sf")); |
| 622 if (instr->SFField() == 1) { | 592 if (instr->SFField() == 1) { |
| 623 // TODO(zra): If we don't use the w form much, we can omit printing | 593 // TODO(zra): If we don't use the w form much, we can omit printing |
| 624 // this x. | 594 // this x. |
| 625 Print("x"); | 595 Print("x"); |
| 626 } else { | 596 } else { |
| 627 Print("w"); | 597 Print("w"); |
| 628 } | 598 } |
| 629 return 2; | 599 return 2; |
| 630 } else if (format[1] == 'z') { | 600 } else if (format[1] == 'z') { |
| 631 ASSERT(STRING_STARTS_WITH(format, "sz")); | 601 ASSERT(STRING_STARTS_WITH(format, "sz")); |
| 632 const int sz = instr->SzField(); | 602 const int sz = instr->SzField(); |
| 633 char const* sz_str; | 603 char const* sz_str; |
| 634 switch (sz) { | 604 switch (sz) { |
| 635 case 0: sz_str = "b"; break; | 605 case 0: |
| 636 case 1: sz_str = "h"; break; | 606 sz_str = "b"; |
| 637 case 2: sz_str = "w"; break; | 607 break; |
| 638 case 3: sz_str = "x"; break; | 608 case 1: |
| 639 default: sz_str = "?"; break; | 609 sz_str = "h"; |
| 610 break; |
| 611 case 2: |
| 612 sz_str = "w"; |
| 613 break; |
| 614 case 3: |
| 615 sz_str = "x"; |
| 616 break; |
| 617 default: |
| 618 sz_str = "?"; |
| 619 break; |
| 640 } | 620 } |
| 641 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 621 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), |
| 642 remaining_size_in_buffer(), | 622 remaining_size_in_buffer(), "%s", sz_str); |
| 643 "%s", | |
| 644 sz_str); | |
| 645 return 2; | 623 return 2; |
| 646 } else if (format[1] == ' ') { | 624 } else if (format[1] == ' ') { |
| 647 if (instr->HasS()) { | 625 if (instr->HasS()) { |
| 648 Print("s"); | 626 Print("s"); |
| 649 } | 627 } |
| 650 return 1; | 628 return 1; |
| 651 } else { | 629 } else { |
| 652 UNREACHABLE(); | 630 UNREACHABLE(); |
| 653 } | 631 } |
| 654 } | 632 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 668 void ARM64Decoder::Format(Instr* instr, const char* format) { | 646 void ARM64Decoder::Format(Instr* instr, const char* format) { |
| 669 char cur = *format++; | 647 char cur = *format++; |
| 670 while ((cur != 0) && (buffer_pos_ < (buffer_size_ - 1))) { | 648 while ((cur != 0) && (buffer_pos_ < (buffer_size_ - 1))) { |
| 671 if (cur == '\'') { // Single quote is used as the formatting escape. | 649 if (cur == '\'') { // Single quote is used as the formatting escape. |
| 672 format += FormatOption(instr, format); | 650 format += FormatOption(instr, format); |
| 673 } else { | 651 } else { |
| 674 buffer_[buffer_pos_++] = cur; | 652 buffer_[buffer_pos_++] = cur; |
| 675 } | 653 } |
| 676 cur = *format++; | 654 cur = *format++; |
| 677 } | 655 } |
| 678 buffer_[buffer_pos_] = '\0'; | 656 buffer_[buffer_pos_] = '\0'; |
| 679 } | 657 } |
| 680 | 658 |
| 681 | 659 |
| 682 // For currently unimplemented decodings the disassembler calls Unknown(instr) | 660 // For currently unimplemented decodings the disassembler calls Unknown(instr) |
| 683 // which will just print "unknown" of the instruction bits. | 661 // which will just print "unknown" of the instruction bits. |
| 684 void ARM64Decoder::Unknown(Instr* instr) { | 662 void ARM64Decoder::Unknown(Instr* instr) { |
| 685 Format(instr, "unknown"); | 663 Format(instr, "unknown"); |
| 686 } | 664 } |
| 687 | 665 |
| 688 | 666 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 741 } | 719 } |
| 742 if (instr->Bit(30)) { | 720 if (instr->Bit(30)) { |
| 743 Format(instr, "ldrx 'rt, 'pcldr"); | 721 Format(instr, "ldrx 'rt, 'pcldr"); |
| 744 } else { | 722 } else { |
| 745 Format(instr, "ldrw 'rt, 'pcldr"); | 723 Format(instr, "ldrw 'rt, 'pcldr"); |
| 746 } | 724 } |
| 747 } | 725 } |
| 748 | 726 |
| 749 | 727 |
| 750 void ARM64Decoder::DecodeLoadStoreExclusive(Instr* instr) { | 728 void ARM64Decoder::DecodeLoadStoreExclusive(Instr* instr) { |
| 751 if ((instr->Bit(23) != 0) || | 729 if ((instr->Bit(23) != 0) || (instr->Bit(21) != 0) || (instr->Bit(15) != 0)) { |
| 752 (instr->Bit(21) != 0) || | |
| 753 (instr->Bit(15) != 0)) { | |
| 754 Unknown(instr); | 730 Unknown(instr); |
| 755 } | 731 } |
| 756 const int32_t size = instr->Bits(30, 2); | 732 const int32_t size = instr->Bits(30, 2); |
| 757 if (size != 3) { | 733 if (size != 3) { |
| 758 Unknown(instr); | 734 Unknown(instr); |
| 759 } | 735 } |
| 760 | 736 |
| 761 const bool is_load = instr->Bit(22) == 1; | 737 const bool is_load = instr->Bit(22) == 1; |
| 762 if (is_load) { | 738 if (is_load) { |
| 763 Format(instr, "ldxr 'rt, 'rn"); | 739 Format(instr, "ldxr 'rt, 'rn"); |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 852 void ARM64Decoder::DecodeExceptionGen(Instr* instr) { | 828 void ARM64Decoder::DecodeExceptionGen(Instr* instr) { |
| 853 if ((instr->Bits(0, 2) == 1) && (instr->Bits(2, 3) == 0) && | 829 if ((instr->Bits(0, 2) == 1) && (instr->Bits(2, 3) == 0) && |
| 854 (instr->Bits(21, 3) == 0)) { | 830 (instr->Bits(21, 3) == 0)) { |
| 855 Format(instr, "svc 'imm16"); | 831 Format(instr, "svc 'imm16"); |
| 856 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) && | 832 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) && |
| 857 (instr->Bits(21, 3) == 1)) { | 833 (instr->Bits(21, 3) == 1)) { |
| 858 Format(instr, "brk 'imm16"); | 834 Format(instr, "brk 'imm16"); |
| 859 if (instr->Imm16Field() == Instr::kStopMessageCode) { | 835 if (instr->Imm16Field() == Instr::kStopMessageCode) { |
| 860 const char* message = *reinterpret_cast<const char**>( | 836 const char* message = *reinterpret_cast<const char**>( |
| 861 reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize); | 837 reinterpret_cast<intptr_t>(instr) - 2 * Instr::kInstrSize); |
| 862 buffer_pos_ += OS::SNPrint(current_position_in_buffer(), | 838 buffer_pos_ += |
| 863 remaining_size_in_buffer(), | 839 OS::SNPrint(current_position_in_buffer(), remaining_size_in_buffer(), |
| 864 " ; \"%s\"", | 840 " ; \"%s\"", message); |
| 865 message); | |
| 866 } | 841 } |
| 867 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) && | 842 } else if ((instr->Bits(0, 2) == 0) && (instr->Bits(2, 3) == 0) && |
| 868 (instr->Bits(21, 3) == 2)) { | 843 (instr->Bits(21, 3) == 2)) { |
| 869 Format(instr, "hlt 'imm16"); | 844 Format(instr, "hlt 'imm16"); |
| 870 } else { | 845 } else { |
| 871 Unknown(instr); | 846 Unknown(instr); |
| 872 } | 847 } |
| 873 } | 848 } |
| 874 | 849 |
| 875 | 850 |
| (...skipping 304 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1180 const int32_t Q = instr->Bit(30); | 1155 const int32_t Q = instr->Bit(30); |
| 1181 const int32_t op = instr->Bit(29); | 1156 const int32_t op = instr->Bit(29); |
| 1182 const int32_t imm4 = instr->Bits(11, 4); | 1157 const int32_t imm4 = instr->Bits(11, 4); |
| 1183 | 1158 |
| 1184 if ((op == 0) && (imm4 == 7)) { | 1159 if ((op == 0) && (imm4 == 7)) { |
| 1185 if (Q == 0) { | 1160 if (Q == 0) { |
| 1186 Format(instr, "vmovrs 'rd, 'vn'idx5"); | 1161 Format(instr, "vmovrs 'rd, 'vn'idx5"); |
| 1187 } else { | 1162 } else { |
| 1188 Format(instr, "vmovrd 'rd, 'vn'idx5"); | 1163 Format(instr, "vmovrd 'rd, 'vn'idx5"); |
| 1189 } | 1164 } |
| 1190 } else if ((Q == 1) && (op == 0) && (imm4 == 0)) { | 1165 } else if ((Q == 1) && (op == 0) && (imm4 == 0)) { |
| 1191 Format(instr, "vdup'csz 'vd, 'vn'idx5"); | 1166 Format(instr, "vdup'csz 'vd, 'vn'idx5"); |
| 1192 } else if ((Q == 1) && (op == 0) && (imm4 == 3)) { | 1167 } else if ((Q == 1) && (op == 0) && (imm4 == 3)) { |
| 1193 Format(instr, "vins'csz 'vd'idx5, 'rn"); | 1168 Format(instr, "vins'csz 'vd'idx5, 'rn"); |
| 1194 } else if ((Q == 1) && (op == 0) && (imm4 == 1)) { | 1169 } else if ((Q == 1) && (op == 0) && (imm4 == 1)) { |
| 1195 Format(instr, "vdup'csz 'vd, 'rn"); | 1170 Format(instr, "vdup'csz 'vd, 'rn"); |
| 1196 } else if ((Q == 1) && (op == 1)) { | 1171 } else if ((Q == 1) && (op == 1)) { |
| 1197 Format(instr, "vins'csz 'vd'idx5, 'vn'idx4"); | 1172 Format(instr, "vins'csz 'vd'idx5, 'vn'idx4"); |
| 1198 } else { | 1173 } else { |
| 1199 Unknown(instr); | 1174 Unknown(instr); |
| 1200 } | 1175 } |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1480 } else if (instr->IsDPSimd1Op()) { | 1455 } else if (instr->IsDPSimd1Op()) { |
| 1481 DecodeDPSimd1(instr); | 1456 DecodeDPSimd1(instr); |
| 1482 } else if (instr->IsDPSimd2Op()) { | 1457 } else if (instr->IsDPSimd2Op()) { |
| 1483 DecodeDPSimd2(instr); | 1458 DecodeDPSimd2(instr); |
| 1484 } else { | 1459 } else { |
| 1485 Unknown(instr); | 1460 Unknown(instr); |
| 1486 } | 1461 } |
| 1487 } | 1462 } |
| 1488 | 1463 |
| 1489 | 1464 |
| 1490 void Disassembler::DecodeInstruction(char* hex_buffer, intptr_t hex_size, | 1465 void Disassembler::DecodeInstruction(char* hex_buffer, |
| 1491 char* human_buffer, intptr_t human_size, | 1466 intptr_t hex_size, |
| 1492 int* out_instr_size, const Code& code, | 1467 char* human_buffer, |
| 1493 Object** object, uword pc) { | 1468 intptr_t human_size, |
| 1469 int* out_instr_size, |
| 1470 const Code& code, |
| 1471 Object** object, |
| 1472 uword pc) { |
| 1494 ARM64Decoder decoder(human_buffer, human_size); | 1473 ARM64Decoder decoder(human_buffer, human_size); |
| 1495 decoder.InstructionDecode(pc); | 1474 decoder.InstructionDecode(pc); |
| 1496 int32_t instruction_bits = Instr::At(pc)->InstructionBits(); | 1475 int32_t instruction_bits = Instr::At(pc)->InstructionBits(); |
| 1497 OS::SNPrint(hex_buffer, hex_size, "%08x", instruction_bits); | 1476 OS::SNPrint(hex_buffer, hex_size, "%08x", instruction_bits); |
| 1498 if (out_instr_size) { | 1477 if (out_instr_size) { |
| 1499 *out_instr_size = Instr::kInstrSize; | 1478 *out_instr_size = Instr::kInstrSize; |
| 1500 } | 1479 } |
| 1501 | 1480 |
| 1502 *object = NULL; | 1481 *object = NULL; |
| 1503 if (!code.IsNull()) { | 1482 if (!code.IsNull()) { |
| 1504 *object = &Object::Handle(); | 1483 *object = &Object::Handle(); |
| 1505 if (!DecodeLoadObjectFromPoolOrThread(pc, code, *object)) { | 1484 if (!DecodeLoadObjectFromPoolOrThread(pc, code, *object)) { |
| 1506 *object = NULL; | 1485 *object = NULL; |
| 1507 } | 1486 } |
| 1508 } | 1487 } |
| 1509 } | 1488 } |
| 1510 | 1489 |
| 1511 #endif // !PRODUCT | 1490 #endif // !PRODUCT |
| 1512 | 1491 |
| 1513 } // namespace dart | 1492 } // namespace dart |
| 1514 | 1493 |
| 1515 #endif // defined TARGET_ARCH_ARM | 1494 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |