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

Side by Side Diff: src/arm64/simulator-arm64.cc

Issue 2622643005: ARM64: Add NEON support (Closed)
Patch Set: Created 3 years, 11 months 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
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include <stdlib.h> 5 #include <stdlib.h>
6 #include <cmath> 6 #include <cmath>
7 #include <cstdarg> 7 #include <cstdarg>
8 8
9 #if V8_TARGET_ARCH_ARM64 9 #if V8_TARGET_ARCH_ARM64
10 10
(...skipping 24 matching lines...) Expand all
35 #define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m" 35 #define COLOUR_BOLD(colour_code) "\033[1;" colour_code "m"
36 #define NORMAL "" 36 #define NORMAL ""
37 #define GREY "30" 37 #define GREY "30"
38 #define RED "31" 38 #define RED "31"
39 #define GREEN "32" 39 #define GREEN "32"
40 #define YELLOW "33" 40 #define YELLOW "33"
41 #define BLUE "34" 41 #define BLUE "34"
42 #define MAGENTA "35" 42 #define MAGENTA "35"
43 #define CYAN "36" 43 #define CYAN "36"
44 #define WHITE "37" 44 #define WHITE "37"
45
45 typedef char const * const TEXT_COLOUR; 46 typedef char const * const TEXT_COLOUR;
46 TEXT_COLOUR clr_normal = FLAG_log_colour ? COLOUR(NORMAL) : ""; 47 TEXT_COLOUR clr_normal = FLAG_log_colour ? COLOUR(NORMAL) : "";
47 TEXT_COLOUR clr_flag_name = FLAG_log_colour ? COLOUR_BOLD(WHITE) : ""; 48 TEXT_COLOUR clr_flag_name = FLAG_log_colour ? COLOUR_BOLD(WHITE) : "";
48 TEXT_COLOUR clr_flag_value = FLAG_log_colour ? COLOUR(NORMAL) : ""; 49 TEXT_COLOUR clr_flag_value = FLAG_log_colour ? COLOUR(NORMAL) : "";
49 TEXT_COLOUR clr_reg_name = FLAG_log_colour ? COLOUR_BOLD(CYAN) : ""; 50 TEXT_COLOUR clr_reg_name = FLAG_log_colour ? COLOUR_BOLD(CYAN) : "";
50 TEXT_COLOUR clr_reg_value = FLAG_log_colour ? COLOUR(CYAN) : ""; 51 TEXT_COLOUR clr_reg_value = FLAG_log_colour ? COLOUR(CYAN) : "";
51 TEXT_COLOUR clr_fpreg_name = FLAG_log_colour ? COLOUR_BOLD(MAGENTA) : ""; 52 TEXT_COLOUR clr_vreg_name = FLAG_log_colour ? COLOUR_BOLD(MAGENTA) : "";
52 TEXT_COLOUR clr_fpreg_value = FLAG_log_colour ? COLOUR(MAGENTA) : ""; 53 TEXT_COLOUR clr_vreg_value = FLAG_log_colour ? COLOUR(MAGENTA) : "";
53 TEXT_COLOUR clr_memory_address = FLAG_log_colour ? COLOUR_BOLD(BLUE) : ""; 54 TEXT_COLOUR clr_memory_address = FLAG_log_colour ? COLOUR_BOLD(BLUE) : "";
54 TEXT_COLOUR clr_debug_number = FLAG_log_colour ? COLOUR_BOLD(YELLOW) : ""; 55 TEXT_COLOUR clr_debug_number = FLAG_log_colour ? COLOUR_BOLD(YELLOW) : "";
55 TEXT_COLOUR clr_debug_message = FLAG_log_colour ? COLOUR(YELLOW) : ""; 56 TEXT_COLOUR clr_debug_message = FLAG_log_colour ? COLOUR(YELLOW) : "";
56 TEXT_COLOUR clr_printf = FLAG_log_colour ? COLOUR(GREEN) : ""; 57 TEXT_COLOUR clr_printf = FLAG_log_colour ? COLOUR(GREEN) : "";
57 58
58 59
59 // This is basically the same as PrintF, with a guard for FLAG_trace_sim. 60 // This is basically the same as PrintF, with a guard for FLAG_trace_sim.
60 void Simulator::TraceSim(const char* format, ...) { 61 void Simulator::TraceSim(const char* format, ...) {
61 if (FLAG_trace_sim) { 62 if (FLAG_trace_sim) {
62 va_list arguments; 63 va_list arguments;
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 return CallInt64(entry, args); 223 return CallInt64(entry, args);
223 } 224 }
224 225
225 226
226 void Simulator::CheckPCSComplianceAndRun() { 227 void Simulator::CheckPCSComplianceAndRun() {
227 // Adjust JS-based stack limit to C-based stack limit. 228 // Adjust JS-based stack limit to C-based stack limit.
228 isolate_->stack_guard()->AdjustStackLimitForSimulator(); 229 isolate_->stack_guard()->AdjustStackLimitForSimulator();
229 230
230 #ifdef DEBUG 231 #ifdef DEBUG
231 CHECK_EQ(kNumberOfCalleeSavedRegisters, kCalleeSaved.Count()); 232 CHECK_EQ(kNumberOfCalleeSavedRegisters, kCalleeSaved.Count());
232 CHECK_EQ(kNumberOfCalleeSavedFPRegisters, kCalleeSavedFP.Count()); 233 CHECK_EQ(kNumberOfCalleeSavedVRegisters, kCalleeSavedV.Count());
233 234
234 int64_t saved_registers[kNumberOfCalleeSavedRegisters]; 235 int64_t saved_registers[kNumberOfCalleeSavedRegisters];
235 uint64_t saved_fpregisters[kNumberOfCalleeSavedFPRegisters]; 236 uint64_t saved_fpregisters[kNumberOfCalleeSavedVRegisters];
236 237
237 CPURegList register_list = kCalleeSaved; 238 CPURegList register_list = kCalleeSaved;
238 CPURegList fpregister_list = kCalleeSavedFP; 239 CPURegList fpregister_list = kCalleeSavedV;
239 240
240 for (int i = 0; i < kNumberOfCalleeSavedRegisters; i++) { 241 for (int i = 0; i < kNumberOfCalleeSavedRegisters; i++) {
241 // x31 is not a caller saved register, so no need to specify if we want 242 // x31 is not a caller saved register, so no need to specify if we want
242 // the stack or zero. 243 // the stack or zero.
243 saved_registers[i] = xreg(register_list.PopLowestIndex().code()); 244 saved_registers[i] = xreg(register_list.PopLowestIndex().code());
244 } 245 }
245 for (int i = 0; i < kNumberOfCalleeSavedFPRegisters; i++) { 246 for (int i = 0; i < kNumberOfCalleeSavedVRegisters; i++) {
246 saved_fpregisters[i] = 247 saved_fpregisters[i] =
247 dreg_bits(fpregister_list.PopLowestIndex().code()); 248 dreg_bits(fpregister_list.PopLowestIndex().code());
248 } 249 }
249 int64_t original_stack = sp(); 250 int64_t original_stack = sp();
250 #endif 251 #endif
251 // Start the simulation! 252 // Start the simulation!
252 Run(); 253 Run();
253 #ifdef DEBUG 254 #ifdef DEBUG
254 CHECK_EQ(original_stack, sp()); 255 CHECK_EQ(original_stack, sp());
255 // Check that callee-saved registers have been preserved. 256 // Check that callee-saved registers have been preserved.
256 register_list = kCalleeSaved; 257 register_list = kCalleeSaved;
257 fpregister_list = kCalleeSavedFP; 258 fpregister_list = kCalleeSavedV;
258 for (int i = 0; i < kNumberOfCalleeSavedRegisters; i++) { 259 for (int i = 0; i < kNumberOfCalleeSavedRegisters; i++) {
259 CHECK_EQ(saved_registers[i], xreg(register_list.PopLowestIndex().code())); 260 CHECK_EQ(saved_registers[i], xreg(register_list.PopLowestIndex().code()));
260 } 261 }
261 for (int i = 0; i < kNumberOfCalleeSavedFPRegisters; i++) { 262 for (int i = 0; i < kNumberOfCalleeSavedVRegisters; i++) {
262 DCHECK(saved_fpregisters[i] == 263 DCHECK(saved_fpregisters[i] ==
263 dreg_bits(fpregister_list.PopLowestIndex().code())); 264 dreg_bits(fpregister_list.PopLowestIndex().code()));
264 } 265 }
265 266
266 // Corrupt caller saved register minus the return regiters. 267 // Corrupt caller saved register minus the return regiters.
267 268
268 // In theory x0 to x7 can be used for return values, but V8 only uses x0, x1 269 // In theory x0 to x7 can be used for return values, but V8 only uses x0, x1
269 // for now . 270 // for now .
270 register_list = kCallerSaved; 271 register_list = kCallerSaved;
271 register_list.Remove(x0); 272 register_list.Remove(x0);
272 register_list.Remove(x1); 273 register_list.Remove(x1);
273 274
274 // In theory d0 to d7 can be used for return values, but V8 only uses d0 275 // In theory d0 to d7 can be used for return values, but V8 only uses d0
275 // for now . 276 // for now .
276 fpregister_list = kCallerSavedFP; 277 fpregister_list = kCallerSavedV;
277 fpregister_list.Remove(d0); 278 fpregister_list.Remove(d0);
278 279
279 CorruptRegisters(&register_list, kCallerSavedRegisterCorruptionValue); 280 CorruptRegisters(&register_list, kCallerSavedRegisterCorruptionValue);
280 CorruptRegisters(&fpregister_list, kCallerSavedFPRegisterCorruptionValue); 281 CorruptRegisters(&fpregister_list, kCallerSavedVRegisterCorruptionValue);
281 #endif 282 #endif
282 } 283 }
283 284
284 285
285 #ifdef DEBUG 286 #ifdef DEBUG
286 // The least significant byte of the curruption value holds the corresponding 287 // The least significant byte of the curruption value holds the corresponding
287 // register's code. 288 // register's code.
288 void Simulator::CorruptRegisters(CPURegList* list, uint64_t value) { 289 void Simulator::CorruptRegisters(CPURegList* list, uint64_t value) {
289 if (list->type() == CPURegister::kRegister) { 290 if (list->type() == CPURegister::kRegister) {
290 while (!list->IsEmpty()) { 291 while (!list->IsEmpty()) {
291 unsigned code = list->PopLowestIndex().code(); 292 unsigned code = list->PopLowestIndex().code();
292 set_xreg(code, value | code); 293 set_xreg(code, value | code);
293 } 294 }
294 } else { 295 } else {
295 DCHECK(list->type() == CPURegister::kFPRegister); 296 DCHECK_EQ(list->type(), CPURegister::kVRegister);
296 while (!list->IsEmpty()) { 297 while (!list->IsEmpty()) {
297 unsigned code = list->PopLowestIndex().code(); 298 unsigned code = list->PopLowestIndex().code();
298 set_dreg_bits(code, value | code); 299 set_dreg_bits(code, value | code);
299 } 300 }
300 } 301 }
301 } 302 }
302 303
303 304
304 void Simulator::CorruptAllCallerSavedCPURegisters() { 305 void Simulator::CorruptAllCallerSavedCPURegisters() {
305 // Corrupt alters its parameter so copy them first. 306 // Corrupt alters its parameter so copy them first.
306 CPURegList register_list = kCallerSaved; 307 CPURegList register_list = kCallerSaved;
307 CPURegList fpregister_list = kCallerSavedFP; 308 CPURegList fpregister_list = kCallerSavedV;
308 309
309 CorruptRegisters(&register_list, kCallerSavedRegisterCorruptionValue); 310 CorruptRegisters(&register_list, kCallerSavedRegisterCorruptionValue);
310 CorruptRegisters(&fpregister_list, kCallerSavedFPRegisterCorruptionValue); 311 CorruptRegisters(&fpregister_list, kCallerSavedVRegisterCorruptionValue);
311 } 312 }
312 #endif 313 #endif
313 314
314 315
315 // Extending the stack by 2 * 64 bits is required for stack alignment purposes. 316 // Extending the stack by 2 * 64 bits is required for stack alignment purposes.
316 uintptr_t Simulator::PushAddress(uintptr_t address) { 317 uintptr_t Simulator::PushAddress(uintptr_t address) {
317 DCHECK(sizeof(uintptr_t) < 2 * kXRegSize); 318 DCHECK(sizeof(uintptr_t) < 2 * kXRegSize);
318 intptr_t new_sp = sp() - 2 * kXRegSize; 319 intptr_t new_sp = sp() - 2 * kXRegSize;
319 uintptr_t* alignment_slot = 320 uintptr_t* alignment_slot =
320 reinterpret_cast<uintptr_t*>(new_sp + kXRegSize); 321 reinterpret_cast<uintptr_t*>(new_sp + kXRegSize);
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 void Simulator::ResetState() { 409 void Simulator::ResetState() {
409 // Reset the system registers. 410 // Reset the system registers.
410 nzcv_ = SimSystemRegister::DefaultValueFor(NZCV); 411 nzcv_ = SimSystemRegister::DefaultValueFor(NZCV);
411 fpcr_ = SimSystemRegister::DefaultValueFor(FPCR); 412 fpcr_ = SimSystemRegister::DefaultValueFor(FPCR);
412 413
413 // Reset registers to 0. 414 // Reset registers to 0.
414 pc_ = NULL; 415 pc_ = NULL;
415 for (unsigned i = 0; i < kNumberOfRegisters; i++) { 416 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
416 set_xreg(i, 0xbadbeef); 417 set_xreg(i, 0xbadbeef);
417 } 418 }
418 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) { 419 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
419 // Set FP registers to a value that is NaN in both 32-bit and 64-bit FP. 420 // Set FP registers to a value that is NaN in both 32-bit and 64-bit FP.
420 set_dreg_bits(i, 0x7ff000007f800001UL); 421 set_dreg_bits(i, 0x7ff000007f800001UL);
421 } 422 }
422 // Returning to address 0 exits the Simulator. 423 // Returning to address 0 exits the Simulator.
423 set_lr(kEndOfSimAddress); 424 set_lr(kEndOfSimAddress);
424 425
425 // Reset debug helpers. 426 // Reset debug helpers.
426 breakpoints_.empty(); 427 breakpoints_.empty();
427 break_on_next_ = false; 428 break_on_next_ = false;
428 } 429 }
429 430
430 431
431 Simulator::~Simulator() { 432 Simulator::~Simulator() {
432 delete[] reinterpret_cast<byte*>(stack_); 433 delete[] reinterpret_cast<byte*>(stack_);
433 if (FLAG_log_instruction_stats) { 434 if (FLAG_log_instruction_stats) {
434 delete instrument_; 435 delete instrument_;
435 } 436 }
436 delete disassembler_decoder_; 437 delete disassembler_decoder_;
437 delete print_disasm_; 438 delete print_disasm_;
438 DeleteArray(last_debugger_input_); 439 DeleteArray(last_debugger_input_);
439 delete decoder_; 440 delete decoder_;
440 } 441 }
441 442
442 443
443 void Simulator::Run() { 444 void Simulator::Run() {
445 // Flush any written registers before executing anything, so that
446 // manually-set registers are logged _before_ the first instruction.
447 LogAllWrittenRegisters();
448
444 pc_modified_ = false; 449 pc_modified_ = false;
445 while (pc_ != kEndOfSimAddress) { 450 while (pc_ != kEndOfSimAddress) {
446 ExecuteInstruction(); 451 ExecuteInstruction();
447 } 452 }
448 } 453 }
449 454
450 455
451 void Simulator::RunFrom(Instruction* start) { 456 void Simulator::RunFrom(Instruction* start) {
452 set_pc(start); 457 set_pc(start);
453 Run(); 458 Run();
(...skipping 357 matching lines...) Expand 10 before | Expand all | Expand 10 after
811 "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"}; 816 "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"};
812 817
813 const char* Simulator::vreg_names[] = { 818 const char* Simulator::vreg_names[] = {
814 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7", 819 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
815 "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15", 820 "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
816 "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", 821 "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
817 "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"}; 822 "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"};
818 823
819 824
820 const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) { 825 const char* Simulator::WRegNameForCode(unsigned code, Reg31Mode mode) {
821 STATIC_ASSERT(arraysize(Simulator::wreg_names) == (kNumberOfRegisters + 1)); 826 static_assert(arraysize(Simulator::wreg_names) == (kNumberOfRegisters + 1),
822 DCHECK(code < kNumberOfRegisters); 827 "Array must be large enough to hold all register names.");
828 DCHECK_LT(code, static_cast<unsigned>(kNumberOfRegisters));
823 // The modulo operator has no effect here, but it silences a broken GCC 829 // The modulo operator has no effect here, but it silences a broken GCC
824 // warning about out-of-bounds array accesses. 830 // warning about out-of-bounds array accesses.
825 code %= kNumberOfRegisters; 831 code %= kNumberOfRegisters;
826 832
827 // If the code represents the stack pointer, index the name after zr. 833 // If the code represents the stack pointer, index the name after zr.
828 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) { 834 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
829 code = kZeroRegCode + 1; 835 code = kZeroRegCode + 1;
830 } 836 }
831 return wreg_names[code]; 837 return wreg_names[code];
832 } 838 }
833 839
834 840
835 const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) { 841 const char* Simulator::XRegNameForCode(unsigned code, Reg31Mode mode) {
836 STATIC_ASSERT(arraysize(Simulator::xreg_names) == (kNumberOfRegisters + 1)); 842 static_assert(arraysize(Simulator::xreg_names) == (kNumberOfRegisters + 1),
837 DCHECK(code < kNumberOfRegisters); 843 "Array must be large enough to hold all register names.");
844 DCHECK_LT(code, static_cast<unsigned>(kNumberOfRegisters));
838 code %= kNumberOfRegisters; 845 code %= kNumberOfRegisters;
839 846
840 // If the code represents the stack pointer, index the name after zr. 847 // If the code represents the stack pointer, index the name after zr.
841 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) { 848 if ((code == kZeroRegCode) && (mode == Reg31IsStackPointer)) {
842 code = kZeroRegCode + 1; 849 code = kZeroRegCode + 1;
843 } 850 }
844 return xreg_names[code]; 851 return xreg_names[code];
845 } 852 }
846 853
847 854
848 const char* Simulator::SRegNameForCode(unsigned code) { 855 const char* Simulator::SRegNameForCode(unsigned code) {
849 STATIC_ASSERT(arraysize(Simulator::sreg_names) == kNumberOfFPRegisters); 856 static_assert(arraysize(Simulator::sreg_names) == kNumberOfVRegisters,
850 DCHECK(code < kNumberOfFPRegisters); 857 "Array must be large enough to hold all register names.");
851 return sreg_names[code % kNumberOfFPRegisters]; 858 DCHECK_LT(code, static_cast<unsigned>(kNumberOfVRegisters));
859 return sreg_names[code % kNumberOfVRegisters];
852 } 860 }
853 861
854 862
855 const char* Simulator::DRegNameForCode(unsigned code) { 863 const char* Simulator::DRegNameForCode(unsigned code) {
856 STATIC_ASSERT(arraysize(Simulator::dreg_names) == kNumberOfFPRegisters); 864 static_assert(arraysize(Simulator::dreg_names) == kNumberOfVRegisters,
857 DCHECK(code < kNumberOfFPRegisters); 865 "Array must be large enough to hold all register names.");
858 return dreg_names[code % kNumberOfFPRegisters]; 866 DCHECK_LT(code, static_cast<unsigned>(kNumberOfVRegisters));
867 return dreg_names[code % kNumberOfVRegisters];
859 } 868 }
860 869
861 870
862 const char* Simulator::VRegNameForCode(unsigned code) { 871 const char* Simulator::VRegNameForCode(unsigned code) {
863 STATIC_ASSERT(arraysize(Simulator::vreg_names) == kNumberOfFPRegisters); 872 static_assert(arraysize(Simulator::vreg_names) == kNumberOfVRegisters,
864 DCHECK(code < kNumberOfFPRegisters); 873 "Array must be large enough to hold all register names.");
865 return vreg_names[code % kNumberOfFPRegisters]; 874 DCHECK_LT(code, static_cast<unsigned>(kNumberOfVRegisters));
875 return vreg_names[code % kNumberOfVRegisters];
876 }
877
878 void LogicVRegister::ReadUintFromMem(VectorFormat vform, int index,
879 uint64_t addr) const {
880 switch (LaneSizeInBitsFromFormat(vform)) {
881 case 8:
882 register_.Insert(index, SimMemory::Read<uint8_t>(addr));
883 break;
884 case 16:
885 register_.Insert(index, SimMemory::Read<uint16_t>(addr));
886 break;
887 case 32:
888 register_.Insert(index, SimMemory::Read<uint32_t>(addr));
889 break;
890 case 64:
891 register_.Insert(index, SimMemory::Read<uint64_t>(addr));
892 break;
893 default:
894 UNREACHABLE();
895 return;
896 }
897 }
898
899 void LogicVRegister::WriteUintToMem(VectorFormat vform, int index,
900 uint64_t addr) const {
901 switch (LaneSizeInBitsFromFormat(vform)) {
902 case 8:
903 SimMemory::Write<uint8_t>(addr, static_cast<uint8_t>(Uint(vform, index)));
904 break;
905 case 16:
906 SimMemory::Write<uint16_t>(addr,
907 static_cast<uint16_t>(Uint(vform, index)));
908 break;
909 case 32:
910 SimMemory::Write<uint32_t>(addr,
911 static_cast<uint32_t>(Uint(vform, index)));
912 break;
913 case 64:
914 SimMemory::Write<uint64_t>(addr, Uint(vform, index));
915 break;
916 default:
917 UNREACHABLE();
918 return;
919 }
866 } 920 }
867 921
868 922
869 int Simulator::CodeFromName(const char* name) { 923 int Simulator::CodeFromName(const char* name) {
870 for (unsigned i = 0; i < kNumberOfRegisters; i++) { 924 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
871 if ((strcmp(xreg_names[i], name) == 0) || 925 if ((strcmp(xreg_names[i], name) == 0) ||
872 (strcmp(wreg_names[i], name) == 0)) { 926 (strcmp(wreg_names[i], name) == 0)) {
873 return i; 927 return i;
874 } 928 }
875 } 929 }
876 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) { 930 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
877 if ((strcmp(vreg_names[i], name) == 0) || 931 if ((strcmp(vreg_names[i], name) == 0) ||
878 (strcmp(dreg_names[i], name) == 0) || 932 (strcmp(dreg_names[i], name) == 0) ||
879 (strcmp(sreg_names[i], name) == 0)) { 933 (strcmp(sreg_names[i], name) == 0)) {
880 return i; 934 return i;
881 } 935 }
882 } 936 }
883 if ((strcmp("csp", name) == 0) || (strcmp("wcsp", name) == 0)) { 937 if ((strcmp("csp", name) == 0) || (strcmp("wcsp", name) == 0)) {
884 return kSPRegInternalCode; 938 return kSPRegInternalCode;
885 } 939 }
886 return -1; 940 return -1;
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
1009 T result = op2; 1063 T result = op2;
1010 1064
1011 if (lsb) { 1065 if (lsb) {
1012 T op1 = reg<T>(instr->Rn()); 1066 T op1 = reg<T>(instr->Rn());
1013 result = op2 >> lsb | (op1 << ((sizeof(T) * 8) - lsb)); 1067 result = op2 >> lsb | (op1 << ((sizeof(T) * 8) - lsb));
1014 } 1068 }
1015 set_reg<T>(instr->Rd(), result); 1069 set_reg<T>(instr->Rd(), result);
1016 } 1070 }
1017 1071
1018 1072
1019 template<> double Simulator::FPDefaultNaN<double>() const {
1020 return kFP64DefaultNaN;
1021 }
1022
1023
1024 template<> float Simulator::FPDefaultNaN<float>() const {
1025 return kFP32DefaultNaN;
1026 }
1027
1028
1029 void Simulator::FPCompare(double val0, double val1) { 1073 void Simulator::FPCompare(double val0, double val1) {
1030 AssertSupportedFPCR(); 1074 AssertSupportedFPCR();
1031 1075
1032 // TODO(jbramley): This assumes that the C++ implementation handles 1076 // TODO(jbramley): This assumes that the C++ implementation handles
1033 // comparisons in the way that we expect (as per AssertSupportedFPCR()). 1077 // comparisons in the way that we expect (as per AssertSupportedFPCR()).
1034 if ((std::isnan(val0) != 0) || (std::isnan(val1) != 0)) { 1078 if ((std::isnan(val0) != 0) || (std::isnan(val1) != 0)) {
1035 nzcv().SetRawValue(FPUnorderedFlag); 1079 nzcv().SetRawValue(FPUnorderedFlag);
1036 } else if (val0 < val1) { 1080 } else if (val0 < val1) {
1037 nzcv().SetRawValue(FPLessThanFlag); 1081 nzcv().SetRawValue(FPLessThanFlag);
1038 } else if (val0 > val1) { 1082 } else if (val0 > val1) {
1039 nzcv().SetRawValue(FPGreaterThanFlag); 1083 nzcv().SetRawValue(FPGreaterThanFlag);
1040 } else if (val0 == val1) { 1084 } else if (val0 == val1) {
1041 nzcv().SetRawValue(FPEqualFlag); 1085 nzcv().SetRawValue(FPEqualFlag);
1042 } else { 1086 } else {
1043 UNREACHABLE(); 1087 UNREACHABLE();
1044 } 1088 }
1045 LogSystemRegister(NZCV); 1089 LogSystemRegister(NZCV);
1046 } 1090 }
1047 1091
1092 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatForSize(
1093 size_t reg_size, size_t lane_size) {
1094 DCHECK_GE(reg_size, lane_size);
1095
1096 uint32_t format = 0;
1097 if (reg_size != lane_size) {
1098 switch (reg_size) {
1099 default:
1100 UNREACHABLE();
1101 break;
1102 case kQRegSize:
1103 format = kPrintRegAsQVector;
1104 break;
1105 case kDRegSize:
1106 format = kPrintRegAsDVector;
1107 break;
1108 }
1109 }
1110
1111 switch (lane_size) {
1112 default:
1113 UNREACHABLE();
1114 case kQRegSize:
1115 format |= kPrintReg1Q;
1116 break;
1117 case kDRegSize:
1118 format |= kPrintReg1D;
1119 break;
1120 case kSRegSize:
1121 format |= kPrintReg1S;
1122 break;
1123 case kHRegSize:
1124 format |= kPrintReg1H;
1125 break;
1126 case kBRegSize:
1127 format |= kPrintReg1B;
1128 break;
1129 }
1130
1131 // These sizes would be duplicate case labels.
1132 static_assert(kXRegSize == kDRegSize, "X and D registers must be same size.");
1133 static_assert(kWRegSize == kSRegSize, "W and S registers must be same size.");
1134 static_assert(kPrintXReg == kPrintReg1D,
1135 "X and D register printing code is shared.");
1136 static_assert(kPrintWReg == kPrintReg1S,
1137 "W and S register printing code is shared.");
1138
1139 return static_cast<PrintRegisterFormat>(format);
1140 }
1141
1142 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormat(
1143 VectorFormat vform) {
1144 switch (vform) {
1145 default:
1146 UNREACHABLE();
1147 return kPrintReg16B;
1148 case kFormat16B:
1149 return kPrintReg16B;
1150 case kFormat8B:
1151 return kPrintReg8B;
1152 case kFormat8H:
1153 return kPrintReg8H;
1154 case kFormat4H:
1155 return kPrintReg4H;
1156 case kFormat4S:
1157 return kPrintReg4S;
1158 case kFormat2S:
1159 return kPrintReg2S;
1160 case kFormat2D:
1161 return kPrintReg2D;
1162 case kFormat1D:
1163 return kPrintReg1D;
1164
1165 case kFormatB:
1166 return kPrintReg1B;
1167 case kFormatH:
1168 return kPrintReg1H;
1169 case kFormatS:
1170 return kPrintReg1S;
1171 case kFormatD:
1172 return kPrintReg1D;
1173 }
1174 }
1175
1176 Simulator::PrintRegisterFormat Simulator::GetPrintRegisterFormatFP(
1177 VectorFormat vform) {
1178 switch (vform) {
1179 default:
1180 UNREACHABLE();
1181 return kPrintReg16B;
1182 case kFormat4S:
1183 return kPrintReg4SFP;
1184 case kFormat2S:
1185 return kPrintReg2SFP;
1186 case kFormat2D:
1187 return kPrintReg2DFP;
1188 case kFormat1D:
1189 return kPrintReg1DFP;
1190
1191 case kFormatS:
1192 return kPrintReg1SFP;
1193 case kFormatD:
1194 return kPrintReg1DFP;
1195 }
1196 }
1048 1197
1049 void Simulator::SetBreakpoint(Instruction* location) { 1198 void Simulator::SetBreakpoint(Instruction* location) {
1050 for (unsigned i = 0; i < breakpoints_.size(); i++) { 1199 for (unsigned i = 0; i < breakpoints_.size(); i++) {
1051 if (breakpoints_.at(i).location == location) { 1200 if (breakpoints_.at(i).location == location) {
1052 PrintF(stream_, 1201 PrintF(stream_,
1053 "Existing breakpoint at %p was %s\n", 1202 "Existing breakpoint at %p was %s\n",
1054 reinterpret_cast<void*>(location), 1203 reinterpret_cast<void*>(location),
1055 breakpoints_.at(i).enabled ? "disabled" : "enabled"); 1204 breakpoints_.at(i).enabled ? "disabled" : "enabled");
1056 breakpoints_.at(i).enabled = !breakpoints_.at(i).enabled; 1205 breakpoints_.at(i).enabled = !breakpoints_.at(i).enabled;
1057 return; 1206 return;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
1101 } 1250 }
1102 1251
1103 1252
1104 void Simulator::PrintInstructionsAt(Instruction* start, uint64_t count) { 1253 void Simulator::PrintInstructionsAt(Instruction* start, uint64_t count) {
1105 Instruction* end = start->InstructionAtOffset(count * kInstructionSize); 1254 Instruction* end = start->InstructionAtOffset(count * kInstructionSize);
1106 for (Instruction* pc = start; pc < end; pc = pc->following()) { 1255 for (Instruction* pc = start; pc < end; pc = pc->following()) {
1107 disassembler_decoder_->Decode(pc); 1256 disassembler_decoder_->Decode(pc);
1108 } 1257 }
1109 } 1258 }
1110 1259
1260 void Simulator::PrintWrittenRegisters() {
1261 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
1262 if (registers_[i].WrittenSinceLastLog()) PrintRegister(i);
1263 }
1264 }
1265
1266 void Simulator::PrintWrittenVRegisters() {
1267 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
1268 // At this point there is no type information, so print as a raw 1Q.
1269 if (vregisters_[i].WrittenSinceLastLog()) PrintVRegister(i, kPrintReg1Q);
1270 }
1271 }
1111 1272
1112 void Simulator::PrintSystemRegisters() { 1273 void Simulator::PrintSystemRegisters() {
1113 PrintSystemRegister(NZCV); 1274 PrintSystemRegister(NZCV);
1114 PrintSystemRegister(FPCR); 1275 PrintSystemRegister(FPCR);
1115 } 1276 }
1116 1277
1117 1278
1118 void Simulator::PrintRegisters() { 1279 void Simulator::PrintRegisters() {
1119 for (unsigned i = 0; i < kNumberOfRegisters; i++) { 1280 for (unsigned i = 0; i < kNumberOfRegisters; i++) {
1120 PrintRegister(i); 1281 PrintRegister(i);
1121 } 1282 }
1122 } 1283 }
1123 1284
1124 1285 void Simulator::PrintVRegisters() {
1125 void Simulator::PrintFPRegisters() { 1286 for (unsigned i = 0; i < kNumberOfVRegisters; i++) {
1126 for (unsigned i = 0; i < kNumberOfFPRegisters; i++) { 1287 // At this point there is no type information, so print as a raw 1Q.
1127 PrintFPRegister(i); 1288 PrintVRegister(i, kPrintReg1Q);
1128 } 1289 }
1129 } 1290 }
1130 1291
1131 1292
1132 void Simulator::PrintRegister(unsigned code, Reg31Mode r31mode) { 1293 void Simulator::PrintRegister(unsigned code, Reg31Mode r31mode) {
1294 registers_[code].NotifyRegisterLogged();
1295
1133 // Don't print writes into xzr. 1296 // Don't print writes into xzr.
1134 if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) { 1297 if ((code == kZeroRegCode) && (r31mode == Reg31IsZeroRegister)) {
1135 return; 1298 return;
1136 } 1299 }
1137 1300
1138 // The template is "# x<code>:value". 1301 // The template for all x and w registers:
1139 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s\n", 1302 // "# x{code}: 0x{value}"
1140 clr_reg_name, XRegNameForCode(code, r31mode), 1303 // "# w{code}: 0x{value}"
1141 clr_reg_value, reg<uint64_t>(code, r31mode), clr_normal); 1304
1142 } 1305 PrintRegisterRawHelper(code, r31mode);
1143 1306 fprintf(stream_, "\n");
1144 1307 }
1145 void Simulator::PrintFPRegister(unsigned code, PrintFPRegisterSizes sizes) { 1308
1146 // The template is "# v<code>:bits (d<code>:value, ...)". 1309 // Print a register's name and raw value.
1147 1310 //
1148 DCHECK(sizes != 0); 1311 // The `bytes` and `lsb` arguments can be used to limit the bytes that are
1149 DCHECK((sizes & kPrintAllFPRegValues) == sizes); 1312 // printed. These arguments are intended for use in cases where register hasn't
1150 1313 // actually been updated (such as in PrintVWrite).
1151 // Print the raw bits. 1314 //
1152 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (", 1315 // No newline is printed. This allows the caller to print more details (such as
1153 clr_fpreg_name, VRegNameForCode(code), 1316 // a floating-point interpretation or a memory access annotation).
1154 clr_fpreg_value, fpreg<uint64_t>(code), clr_normal); 1317 void Simulator::PrintVRegisterRawHelper(unsigned code, int bytes, int lsb) {
1155 1318 // The template for vector types:
1156 // Print all requested value interpretations. 1319 // "# v{code}: 0xffeeddccbbaa99887766554433221100".
1157 bool need_separator = false; 1320 // An example with bytes=4 and lsb=8:
1158 if (sizes & kPrintDRegValue) { 1321 // "# v{code}: 0xbbaa9988 ".
1159 fprintf(stream_, "%s%s%s: %s%g%s", 1322 fprintf(stream_, "# %s%5s: %s", clr_vreg_name, VRegNameForCode(code),
1160 need_separator ? ", " : "", 1323 clr_vreg_value);
1161 clr_fpreg_name, DRegNameForCode(code), 1324
1162 clr_fpreg_value, fpreg<double>(code), clr_normal); 1325 int msb = lsb + bytes - 1;
1163 need_separator = true; 1326 int byte = kQRegSize - 1;
1164 } 1327
1165 1328 // Print leading padding spaces. (Two spaces per byte.)
1166 if (sizes & kPrintSRegValue) { 1329 while (byte > msb) {
1167 fprintf(stream_, "%s%s%s: %s%g%s", 1330 fprintf(stream_, " ");
1168 need_separator ? ", " : "", 1331 byte--;
1169 clr_fpreg_name, SRegNameForCode(code), 1332 }
1170 clr_fpreg_value, fpreg<float>(code), clr_normal); 1333
1171 need_separator = true; 1334 // Print the specified part of the value, byte by byte.
1172 } 1335 qreg_t rawbits = qreg(code);
1173 1336 fprintf(stream_, "0x");
1174 // End the value list. 1337 while (byte >= lsb) {
1175 fprintf(stream_, ")\n"); 1338 fprintf(stream_, "%02x", rawbits.val[byte]);
1176 } 1339 byte--;
1177 1340 }
1178 1341
1342 // Print trailing padding spaces.
1343 while (byte >= 0) {
1344 fprintf(stream_, " ");
1345 byte--;
1346 }
1347 fprintf(stream_, "%s", clr_normal);
1348 }
1349
1350 // Print each of the specified lanes of a register as a float or double value.
1351 //
1352 // The `lane_count` and `lslane` arguments can be used to limit the lanes that
1353 // are printed. These arguments are intended for use in cases where register
1354 // hasn't actually been updated (such as in PrintVWrite).
1355 //
1356 // No newline is printed. This allows the caller to print more details (such as
1357 // a memory access annotation).
1358 void Simulator::PrintVRegisterFPHelper(unsigned code,
1359 unsigned lane_size_in_bytes,
1360 int lane_count, int rightmost_lane) {
1361 DCHECK((lane_size_in_bytes == kSRegSize) ||
1362 (lane_size_in_bytes == kDRegSize));
1363
1364 unsigned msb = (lane_count + rightmost_lane) * lane_size_in_bytes;
1365 DCHECK_LE(msb, static_cast<unsigned>(kQRegSize));
1366
1367 // For scalar types ((lane_count == 1) && (rightmost_lane == 0)), a register
1368 // name is used:
1369 // " (s{code}: {value})"
1370 // " (d{code}: {value})"
1371 // For vector types, "..." is used to represent one or more omitted lanes.
1372 // " (..., {value}, {value}, ...)"
1373 if ((lane_count == 1) && (rightmost_lane == 0)) {
1374 const char* name = (lane_size_in_bytes == kSRegSize)
1375 ? SRegNameForCode(code)
1376 : DRegNameForCode(code);
1377 fprintf(stream_, " (%s%s: ", clr_vreg_name, name);
1378 } else {
1379 if (msb < (kQRegSize - 1)) {
1380 fprintf(stream_, " (..., ");
1381 } else {
1382 fprintf(stream_, " (");
1383 }
1384 }
1385
1386 // Print the list of values.
1387 const char* separator = "";
1388 int leftmost_lane = rightmost_lane + lane_count - 1;
1389 for (int lane = leftmost_lane; lane >= rightmost_lane; lane--) {
1390 double value = (lane_size_in_bytes == kSRegSize)
1391 ? vreg(code).Get<float>(lane)
1392 : vreg(code).Get<double>(lane);
1393 fprintf(stream_, "%s%s%#g%s", separator, clr_vreg_value, value, clr_normal);
1394 separator = ", ";
1395 }
1396
1397 if (rightmost_lane > 0) {
1398 fprintf(stream_, ", ...");
1399 }
1400 fprintf(stream_, ")");
1401 }
1402
1403 // Print a register's name and raw value.
1404 //
1405 // Only the least-significant `size_in_bytes` bytes of the register are printed,
1406 // but the value is aligned as if the whole register had been printed.
1407 //
1408 // For typical register updates, size_in_bytes should be set to kXRegSize
1409 // -- the default -- so that the whole register is printed. Other values of
1410 // size_in_bytes are intended for use when the register hasn't actually been
1411 // updated (such as in PrintWrite).
1412 //
1413 // No newline is printed. This allows the caller to print more details (such as
1414 // a memory access annotation).
1415 void Simulator::PrintRegisterRawHelper(unsigned code, Reg31Mode r31mode,
1416 int size_in_bytes) {
1417 // The template for all supported sizes.
1418 // "# x{code}: 0xffeeddccbbaa9988"
1419 // "# w{code}: 0xbbaa9988"
1420 // "# w{code}<15:0>: 0x9988"
1421 // "# w{code}<7:0>: 0x88"
1422 unsigned padding_chars = (kXRegSize - size_in_bytes) * 2;
1423
1424 const char* name = "";
1425 const char* suffix = "";
1426 switch (size_in_bytes) {
1427 case kXRegSize:
1428 name = XRegNameForCode(code, r31mode);
1429 break;
1430 case kWRegSize:
1431 name = WRegNameForCode(code, r31mode);
1432 break;
1433 case 2:
1434 name = WRegNameForCode(code, r31mode);
1435 suffix = "<15:0>";
1436 padding_chars -= strlen(suffix);
1437 break;
1438 case 1:
1439 name = WRegNameForCode(code, r31mode);
1440 suffix = "<7:0>";
1441 padding_chars -= strlen(suffix);
1442 break;
1443 default:
1444 UNREACHABLE();
1445 }
1446 fprintf(stream_, "# %s%5s%s: ", clr_reg_name, name, suffix);
1447
1448 // Print leading padding spaces.
1449 DCHECK_LT(padding_chars, kXRegSize * 2U);
1450 for (unsigned i = 0; i < padding_chars; i++) {
1451 putc(' ', stream_);
1452 }
1453
1454 // Print the specified bits in hexadecimal format.
1455 uint64_t bits = reg<uint64_t>(code, r31mode);
1456 bits &= kXRegMask >> ((kXRegSize - size_in_bytes) * 8);
1457 static_assert(sizeof(bits) == kXRegSize,
1458 "X registers and uint64_t must be the same size.");
1459
1460 int chars = size_in_bytes * 2;
1461 fprintf(stream_, "%s0x%0*" PRIx64 "%s", clr_reg_value, chars, bits,
1462 clr_normal);
1463 }
1464
1465 void Simulator::PrintVRegister(unsigned code, PrintRegisterFormat format) {
1466 vregisters_[code].NotifyRegisterLogged();
1467
1468 int lane_size_log2 = format & kPrintRegLaneSizeMask;
1469
1470 int reg_size_log2;
1471 if (format & kPrintRegAsQVector) {
1472 reg_size_log2 = kQRegSizeLog2;
1473 } else if (format & kPrintRegAsDVector) {
1474 reg_size_log2 = kDRegSizeLog2;
1475 } else {
1476 // Scalar types.
1477 reg_size_log2 = lane_size_log2;
1478 }
1479
1480 int lane_count = 1 << (reg_size_log2 - lane_size_log2);
1481 int lane_size = 1 << lane_size_log2;
1482
1483 // The template for vector types:
1484 // "# v{code}: 0x{rawbits} (..., {value}, ...)".
1485 // The template for scalar types:
1486 // "# v{code}: 0x{rawbits} ({reg}:{value})".
1487 // The values in parentheses after the bit representations are floating-point
1488 // interpretations. They are displayed only if the kPrintVRegAsFP bit is set.
1489
1490 PrintVRegisterRawHelper(code);
1491 if (format & kPrintRegAsFP) {
1492 PrintVRegisterFPHelper(code, lane_size, lane_count);
1493 }
1494
1495 fprintf(stream_, "\n");
1496 }
1497
1498
1179 void Simulator::PrintSystemRegister(SystemRegister id) { 1499 void Simulator::PrintSystemRegister(SystemRegister id) {
1180 switch (id) { 1500 switch (id) {
1181 case NZCV: 1501 case NZCV:
1182 fprintf(stream_, "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n", 1502 fprintf(stream_, "# %sNZCV: %sN:%d Z:%d C:%d V:%d%s\n",
1183 clr_flag_name, clr_flag_value, 1503 clr_flag_name, clr_flag_value,
1184 nzcv().N(), nzcv().Z(), nzcv().C(), nzcv().V(), 1504 nzcv().N(), nzcv().Z(), nzcv().C(), nzcv().V(),
1185 clr_normal); 1505 clr_normal);
1186 break; 1506 break;
1187 case FPCR: { 1507 case FPCR: {
1188 static const char * rmode[] = { 1508 static const char * rmode[] = {
1189 "0b00 (Round to Nearest)", 1509 "0b00 (Round to Nearest)",
1190 "0b01 (Round towards Plus Infinity)", 1510 "0b01 (Round towards Plus Infinity)",
1191 "0b10 (Round towards Minus Infinity)", 1511 "0b10 (Round towards Minus Infinity)",
1192 "0b11 (Round towards Zero)" 1512 "0b11 (Round towards Zero)"
1193 }; 1513 };
1194 DCHECK(fpcr().RMode() < arraysize(rmode)); 1514 DCHECK(fpcr().RMode() < arraysize(rmode));
1195 fprintf(stream_, 1515 fprintf(stream_,
1196 "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n", 1516 "# %sFPCR: %sAHP:%d DN:%d FZ:%d RMode:%s%s\n",
1197 clr_flag_name, clr_flag_value, 1517 clr_flag_name, clr_flag_value,
1198 fpcr().AHP(), fpcr().DN(), fpcr().FZ(), rmode[fpcr().RMode()], 1518 fpcr().AHP(), fpcr().DN(), fpcr().FZ(), rmode[fpcr().RMode()],
1199 clr_normal); 1519 clr_normal);
1200 break; 1520 break;
1201 } 1521 }
1202 default: 1522 default:
1203 UNREACHABLE(); 1523 UNREACHABLE();
1204 } 1524 }
1205 } 1525 }
1206 1526
1527 void Simulator::PrintRead(uintptr_t address, unsigned reg_code,
1528 PrintRegisterFormat format) {
1529 registers_[reg_code].NotifyRegisterLogged();
1207 1530
1208 void Simulator::PrintRead(uintptr_t address, 1531 USE(format);
1209 size_t size,
1210 unsigned reg_code) {
1211 USE(size); // Size is unused here.
1212 1532
1213 // The template is "# x<code>:value <- address". 1533 // The template is "# {reg}: 0x{value} <- {address}".
1214 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s", 1534 PrintRegisterRawHelper(reg_code, Reg31IsZeroRegister);
1215 clr_reg_name, XRegNameForCode(reg_code),
1216 clr_reg_value, reg<uint64_t>(reg_code), clr_normal);
1217
1218 fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n", 1535 fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n",
1219 clr_memory_address, address, clr_normal); 1536 clr_memory_address, address, clr_normal);
1220 } 1537 }
1221 1538
1539 void Simulator::PrintVRead(uintptr_t address, unsigned reg_code,
1540 PrintRegisterFormat format, unsigned lane) {
1541 vregisters_[reg_code].NotifyRegisterLogged();
1222 1542
1223 void Simulator::PrintReadFP(uintptr_t address, 1543 // The template is "# v{code}: 0x{rawbits} <- address".
1224 size_t size, 1544 PrintVRegisterRawHelper(reg_code);
1225 unsigned reg_code) { 1545 if (format & kPrintRegAsFP) {
1226 // The template is "# reg:bits (reg:value) <- address". 1546 PrintVRegisterFPHelper(reg_code, GetPrintRegLaneSizeInBytes(format),
1227 switch (size) { 1547 GetPrintRegLaneCount(format), lane);
1228 case kSRegSize:
1229 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (%s%s: %s%gf%s)",
1230 clr_fpreg_name, VRegNameForCode(reg_code),
1231 clr_fpreg_value, fpreg<uint64_t>(reg_code), clr_normal,
1232 clr_fpreg_name, SRegNameForCode(reg_code),
1233 clr_fpreg_value, fpreg<float>(reg_code), clr_normal);
1234 break;
1235 case kDRegSize:
1236 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (%s%s: %s%g%s)",
1237 clr_fpreg_name, VRegNameForCode(reg_code),
1238 clr_fpreg_value, fpreg<uint64_t>(reg_code), clr_normal,
1239 clr_fpreg_name, DRegNameForCode(reg_code),
1240 clr_fpreg_value, fpreg<double>(reg_code), clr_normal);
1241 break;
1242 default:
1243 UNREACHABLE();
1244 } 1548 }
1245
1246 fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n", 1549 fprintf(stream_, " <- %s0x%016" PRIxPTR "%s\n",
1247 clr_memory_address, address, clr_normal); 1550 clr_memory_address, address, clr_normal);
1248 } 1551 }
1249 1552
1553 void Simulator::PrintWrite(uintptr_t address, unsigned reg_code,
1554 PrintRegisterFormat format) {
1555 DCHECK_EQ(GetPrintRegLaneCount(format), 1U);
1250 1556
1251 void Simulator::PrintWrite(uintptr_t address, 1557 // The template is "# v{code}: 0x{value} -> {address}". To keep the trace tidy
1252 size_t size, 1558 // and readable, the value is aligned with the values in the register trace.
1253 unsigned reg_code) { 1559 PrintRegisterRawHelper(reg_code, Reg31IsZeroRegister,
1254 // The template is "# reg:value -> address". To keep the trace tidy and 1560 GetPrintRegSizeInBytes(format));
1255 // readable, the value is aligned with the values in the register trace.
1256 switch (size) {
1257 case kByteSizeInBytes:
1258 fprintf(stream_, "# %s%5s<7:0>: %s0x%02" PRIx8 "%s",
1259 clr_reg_name, WRegNameForCode(reg_code),
1260 clr_reg_value, reg<uint8_t>(reg_code), clr_normal);
1261 break;
1262 case kHalfWordSizeInBytes:
1263 fprintf(stream_, "# %s%5s<15:0>: %s0x%04" PRIx16 "%s",
1264 clr_reg_name, WRegNameForCode(reg_code),
1265 clr_reg_value, reg<uint16_t>(reg_code), clr_normal);
1266 break;
1267 case kWRegSize:
1268 fprintf(stream_, "# %s%5s: %s0x%08" PRIx32 "%s",
1269 clr_reg_name, WRegNameForCode(reg_code),
1270 clr_reg_value, reg<uint32_t>(reg_code), clr_normal);
1271 break;
1272 case kXRegSize:
1273 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s",
1274 clr_reg_name, XRegNameForCode(reg_code),
1275 clr_reg_value, reg<uint64_t>(reg_code), clr_normal);
1276 break;
1277 default:
1278 UNREACHABLE();
1279 }
1280
1281 fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n", 1561 fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n",
1282 clr_memory_address, address, clr_normal); 1562 clr_memory_address, address, clr_normal);
1283 } 1563 }
1284 1564
1285 1565 void Simulator::PrintVWrite(uintptr_t address, unsigned reg_code,
1286 void Simulator::PrintWriteFP(uintptr_t address, 1566 PrintRegisterFormat format, unsigned lane) {
1287 size_t size, 1567 // The templates:
1288 unsigned reg_code) { 1568 // "# v{code}: 0x{rawbits} -> {address}"
1289 // The template is "# reg:bits (reg:value) -> address". To keep the trace tidy 1569 // "# v{code}: 0x{rawbits} (..., {value}, ...) -> {address}".
1290 // and readable, the value is aligned with the values in the register trace. 1570 // "# v{code}: 0x{rawbits} ({reg}:{value}) -> {address}"
1291 switch (size) { 1571 // Because this trace doesn't represent a change to the source register's
1292 case kSRegSize: 1572 // value, only the relevant part of the value is printed. To keep the trace
1293 fprintf(stream_, "# %s%5s<31:0>: %s0x%08" PRIx32 "%s (%s%s: %s%gf%s)", 1573 // tidy and readable, the raw value is aligned with the other values in the
1294 clr_fpreg_name, VRegNameForCode(reg_code), 1574 // register trace.
1295 clr_fpreg_value, fpreg<uint32_t>(reg_code), clr_normal, 1575 int lane_count = GetPrintRegLaneCount(format);
1296 clr_fpreg_name, SRegNameForCode(reg_code), 1576 int lane_size = GetPrintRegLaneSizeInBytes(format);
1297 clr_fpreg_value, fpreg<float>(reg_code), clr_normal); 1577 int reg_size = GetPrintRegSizeInBytes(format);
1298 break; 1578 PrintVRegisterRawHelper(reg_code, reg_size, lane_size * lane);
1299 case kDRegSize: 1579 if (format & kPrintRegAsFP) {
1300 fprintf(stream_, "# %s%5s: %s0x%016" PRIx64 "%s (%s%s: %s%g%s)", 1580 PrintVRegisterFPHelper(reg_code, lane_size, lane_count, lane);
1301 clr_fpreg_name, VRegNameForCode(reg_code),
1302 clr_fpreg_value, fpreg<uint64_t>(reg_code), clr_normal,
1303 clr_fpreg_name, DRegNameForCode(reg_code),
1304 clr_fpreg_value, fpreg<double>(reg_code), clr_normal);
1305 break;
1306 default:
1307 UNREACHABLE();
1308 } 1581 }
1309
1310 fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n", 1582 fprintf(stream_, " -> %s0x%016" PRIxPTR "%s\n",
1311 clr_memory_address, address, clr_normal); 1583 clr_memory_address, address, clr_normal);
1312 } 1584 }
1313 1585
1314 1586
1315 // Visitors--------------------------------------------------------------------- 1587 // Visitors---------------------------------------------------------------------
1316 1588
1317 void Simulator::VisitUnimplemented(Instruction* instr) { 1589 void Simulator::VisitUnimplemented(Instruction* instr) {
1318 fprintf(stream_, "Unimplemented instruction at %p: 0x%08" PRIx32 "\n", 1590 fprintf(stream_, "Unimplemented instruction at %p: 0x%08" PRIx32 "\n",
1319 reinterpret_cast<void*>(instr), instr->InstructionBits()); 1591 reinterpret_cast<void*>(instr), instr->InstructionBits());
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after
1636 // below ensures that push operations are safe even when interrupted: the 1908 // below ensures that push operations are safe even when interrupted: the
1637 // stack pointer will be decremented before adding an element to the stack. 1909 // stack pointer will be decremented before adding an element to the stack.
1638 if (instr->IsStore()) { 1910 if (instr->IsStore()) {
1639 LoadStoreWriteBack(addr_reg, offset, addrmode); 1911 LoadStoreWriteBack(addr_reg, offset, addrmode);
1640 1912
1641 // For store the address post writeback is used to check access below the 1913 // For store the address post writeback is used to check access below the
1642 // stack. 1914 // stack.
1643 stack = sp(); 1915 stack = sp();
1644 } 1916 }
1645 1917
1646 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreOpMask)); 1918 LoadStoreOp op = static_cast<LoadStoreOp>(instr->Mask(LoadStoreMask));
1647 switch (op) { 1919 switch (op) {
1648 // Use _no_log variants to suppress the register trace (LOG_REGS, 1920 // Use _no_log variants to suppress the register trace (LOG_REGS,
1649 // LOG_FP_REGS). We will print a more detailed log. 1921 // LOG_VREGS). We will print a more detailed log.
1650 case LDRB_w: set_wreg_no_log(srcdst, MemoryRead<uint8_t>(address)); break; 1922 case LDRB_w: set_wreg_no_log(srcdst, MemoryRead<uint8_t>(address)); break;
1651 case LDRH_w: set_wreg_no_log(srcdst, MemoryRead<uint16_t>(address)); break; 1923 case LDRH_w: set_wreg_no_log(srcdst, MemoryRead<uint16_t>(address)); break;
1652 case LDR_w: set_wreg_no_log(srcdst, MemoryRead<uint32_t>(address)); break; 1924 case LDR_w: set_wreg_no_log(srcdst, MemoryRead<uint32_t>(address)); break;
1653 case LDR_x: set_xreg_no_log(srcdst, MemoryRead<uint64_t>(address)); break; 1925 case LDR_x: set_xreg_no_log(srcdst, MemoryRead<uint64_t>(address)); break;
1654 case LDRSB_w: set_wreg_no_log(srcdst, MemoryRead<int8_t>(address)); break; 1926 case LDRSB_w: set_wreg_no_log(srcdst, MemoryRead<int8_t>(address)); break;
1655 case LDRSH_w: set_wreg_no_log(srcdst, MemoryRead<int16_t>(address)); break; 1927 case LDRSH_w: set_wreg_no_log(srcdst, MemoryRead<int16_t>(address)); break;
1656 case LDRSB_x: set_xreg_no_log(srcdst, MemoryRead<int8_t>(address)); break; 1928 case LDRSB_x: set_xreg_no_log(srcdst, MemoryRead<int8_t>(address)); break;
1657 case LDRSH_x: set_xreg_no_log(srcdst, MemoryRead<int16_t>(address)); break; 1929 case LDRSH_x: set_xreg_no_log(srcdst, MemoryRead<int16_t>(address)); break;
1658 case LDRSW_x: set_xreg_no_log(srcdst, MemoryRead<int32_t>(address)); break; 1930 case LDRSW_x: set_xreg_no_log(srcdst, MemoryRead<int32_t>(address)); break;
1931 case LDR_b:
1932 set_breg_no_log(srcdst, MemoryRead<uint8_t>(address));
1933 break;
1934 case LDR_h:
1935 set_hreg_no_log(srcdst, MemoryRead<uint16_t>(address));
1936 break;
1659 case LDR_s: set_sreg_no_log(srcdst, MemoryRead<float>(address)); break; 1937 case LDR_s: set_sreg_no_log(srcdst, MemoryRead<float>(address)); break;
1660 case LDR_d: set_dreg_no_log(srcdst, MemoryRead<double>(address)); break; 1938 case LDR_d: set_dreg_no_log(srcdst, MemoryRead<double>(address)); break;
1939 case LDR_q:
1940 set_qreg_no_log(srcdst, MemoryRead<qreg_t>(address));
1941 break;
1661 1942
1662 case STRB_w: MemoryWrite<uint8_t>(address, wreg(srcdst)); break; 1943 case STRB_w: MemoryWrite<uint8_t>(address, wreg(srcdst)); break;
1663 case STRH_w: MemoryWrite<uint16_t>(address, wreg(srcdst)); break; 1944 case STRH_w: MemoryWrite<uint16_t>(address, wreg(srcdst)); break;
1664 case STR_w: MemoryWrite<uint32_t>(address, wreg(srcdst)); break; 1945 case STR_w: MemoryWrite<uint32_t>(address, wreg(srcdst)); break;
1665 case STR_x: MemoryWrite<uint64_t>(address, xreg(srcdst)); break; 1946 case STR_x: MemoryWrite<uint64_t>(address, xreg(srcdst)); break;
1947 case STR_b:
1948 MemoryWrite<uint8_t>(address, breg(srcdst));
1949 break;
1950 case STR_h:
1951 MemoryWrite<uint16_t>(address, hreg(srcdst));
1952 break;
1666 case STR_s: MemoryWrite<float>(address, sreg(srcdst)); break; 1953 case STR_s: MemoryWrite<float>(address, sreg(srcdst)); break;
1667 case STR_d: MemoryWrite<double>(address, dreg(srcdst)); break; 1954 case STR_d: MemoryWrite<double>(address, dreg(srcdst)); break;
1955 case STR_q:
1956 MemoryWrite<qreg_t>(address, qreg(srcdst));
1957 break;
1668 1958
1669 default: UNIMPLEMENTED(); 1959 default: UNIMPLEMENTED();
1670 } 1960 }
1671 1961
1672 // Print a detailed trace (including the memory address) instead of the basic 1962 // Print a detailed trace (including the memory address) instead of the basic
1673 // register:value trace generated by set_*reg(). 1963 // register:value trace generated by set_*reg().
1674 size_t access_size = 1 << instr->SizeLS(); 1964 unsigned access_size = 1 << instr->SizeLS();
1675 if (instr->IsLoad()) { 1965 if (instr->IsLoad()) {
1676 if ((op == LDR_s) || (op == LDR_d)) { 1966 if ((op == LDR_s) || (op == LDR_d)) {
1677 LogReadFP(address, access_size, srcdst); 1967 LogVRead(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
1968 } else if ((op == LDR_b) || (op == LDR_h) || (op == LDR_q)) {
1969 LogVRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1678 } else { 1970 } else {
1679 LogRead(address, access_size, srcdst); 1971 LogRead(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1680 } 1972 }
1681 } else { 1973 } else {
1682 if ((op == STR_s) || (op == STR_d)) { 1974 if ((op == STR_s) || (op == STR_d)) {
1683 LogWriteFP(address, access_size, srcdst); 1975 LogVWrite(address, srcdst, GetPrintRegisterFormatForSizeFP(access_size));
1976 } else if ((op == STR_b) || (op == STR_h) || (op == STR_q)) {
1977 LogVWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1684 } else { 1978 } else {
1685 LogWrite(address, access_size, srcdst); 1979 LogWrite(address, srcdst, GetPrintRegisterFormatForSize(access_size));
1686 } 1980 }
1687 } 1981 }
1688 1982
1689 // Handle the writeback for loads after the load to ensure safe pop 1983 // Handle the writeback for loads after the load to ensure safe pop
1690 // operation even when interrupted in the middle of it. The stack pointer 1984 // operation even when interrupted in the middle of it. The stack pointer
1691 // is only updated after the load so pop(fp) will never break the invariant 1985 // is only updated after the load so pop(fp) will never break the invariant
1692 // sp <= fp expected while walking the stack in the sampler. 1986 // sp <= fp expected while walking the stack in the sampler.
1693 if (instr->IsLoad()) { 1987 if (instr->IsLoad()) {
1694 // For loads the address pre writeback is used to check access below the 1988 // For loads the address pre writeback is used to check access below the
1695 // stack. 1989 // stack.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1746 } 2040 }
1747 2041
1748 LoadStorePairOp op = 2042 LoadStorePairOp op =
1749 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask)); 2043 static_cast<LoadStorePairOp>(instr->Mask(LoadStorePairMask));
1750 2044
1751 // 'rt' and 'rt2' can only be aliased for stores. 2045 // 'rt' and 'rt2' can only be aliased for stores.
1752 DCHECK(((op & LoadStorePairLBit) == 0) || (rt != rt2)); 2046 DCHECK(((op & LoadStorePairLBit) == 0) || (rt != rt2));
1753 2047
1754 switch (op) { 2048 switch (op) {
1755 // Use _no_log variants to suppress the register trace (LOG_REGS, 2049 // Use _no_log variants to suppress the register trace (LOG_REGS,
1756 // LOG_FP_REGS). We will print a more detailed log. 2050 // LOG_VREGS). We will print a more detailed log.
1757 case LDP_w: { 2051 case LDP_w: {
1758 DCHECK(access_size == kWRegSize); 2052 DCHECK_EQ(access_size, static_cast<unsigned>(kWRegSize));
1759 set_wreg_no_log(rt, MemoryRead<uint32_t>(address)); 2053 set_wreg_no_log(rt, MemoryRead<uint32_t>(address));
1760 set_wreg_no_log(rt2, MemoryRead<uint32_t>(address2)); 2054 set_wreg_no_log(rt2, MemoryRead<uint32_t>(address2));
1761 break; 2055 break;
1762 } 2056 }
1763 case LDP_s: { 2057 case LDP_s: {
1764 DCHECK(access_size == kSRegSize); 2058 DCHECK_EQ(access_size, static_cast<unsigned>(kSRegSize));
1765 set_sreg_no_log(rt, MemoryRead<float>(address)); 2059 set_sreg_no_log(rt, MemoryRead<float>(address));
1766 set_sreg_no_log(rt2, MemoryRead<float>(address2)); 2060 set_sreg_no_log(rt2, MemoryRead<float>(address2));
1767 break; 2061 break;
1768 } 2062 }
1769 case LDP_x: { 2063 case LDP_x: {
1770 DCHECK(access_size == kXRegSize); 2064 DCHECK_EQ(access_size, static_cast<unsigned>(kXRegSize));
1771 set_xreg_no_log(rt, MemoryRead<uint64_t>(address)); 2065 set_xreg_no_log(rt, MemoryRead<uint64_t>(address));
1772 set_xreg_no_log(rt2, MemoryRead<uint64_t>(address2)); 2066 set_xreg_no_log(rt2, MemoryRead<uint64_t>(address2));
1773 break; 2067 break;
1774 } 2068 }
1775 case LDP_d: { 2069 case LDP_d: {
1776 DCHECK(access_size == kDRegSize); 2070 DCHECK_EQ(access_size, static_cast<unsigned>(kDRegSize));
1777 set_dreg_no_log(rt, MemoryRead<double>(address)); 2071 set_dreg_no_log(rt, MemoryRead<double>(address));
1778 set_dreg_no_log(rt2, MemoryRead<double>(address2)); 2072 set_dreg_no_log(rt2, MemoryRead<double>(address2));
1779 break; 2073 break;
1780 } 2074 }
2075 case LDP_q: {
2076 DCHECK_EQ(access_size, static_cast<unsigned>(kQRegSize));
2077 set_qreg(rt, MemoryRead<qreg_t>(address), NoRegLog);
2078 set_qreg(rt2, MemoryRead<qreg_t>(address2), NoRegLog);
2079 break;
2080 }
1781 case LDPSW_x: { 2081 case LDPSW_x: {
1782 DCHECK(access_size == kWRegSize); 2082 DCHECK_EQ(access_size, static_cast<unsigned>(kWRegSize));
1783 set_xreg_no_log(rt, MemoryRead<int32_t>(address)); 2083 set_xreg_no_log(rt, MemoryRead<int32_t>(address));
1784 set_xreg_no_log(rt2, MemoryRead<int32_t>(address2)); 2084 set_xreg_no_log(rt2, MemoryRead<int32_t>(address2));
1785 break; 2085 break;
1786 } 2086 }
1787 case STP_w: { 2087 case STP_w: {
1788 DCHECK(access_size == kWRegSize); 2088 DCHECK_EQ(access_size, static_cast<unsigned>(kWRegSize));
1789 MemoryWrite<uint32_t>(address, wreg(rt)); 2089 MemoryWrite<uint32_t>(address, wreg(rt));
1790 MemoryWrite<uint32_t>(address2, wreg(rt2)); 2090 MemoryWrite<uint32_t>(address2, wreg(rt2));
1791 break; 2091 break;
1792 } 2092 }
1793 case STP_s: { 2093 case STP_s: {
1794 DCHECK(access_size == kSRegSize); 2094 DCHECK_EQ(access_size, static_cast<unsigned>(kSRegSize));
1795 MemoryWrite<float>(address, sreg(rt)); 2095 MemoryWrite<float>(address, sreg(rt));
1796 MemoryWrite<float>(address2, sreg(rt2)); 2096 MemoryWrite<float>(address2, sreg(rt2));
1797 break; 2097 break;
1798 } 2098 }
1799 case STP_x: { 2099 case STP_x: {
1800 DCHECK(access_size == kXRegSize); 2100 DCHECK_EQ(access_size, static_cast<unsigned>(kXRegSize));
1801 MemoryWrite<uint64_t>(address, xreg(rt)); 2101 MemoryWrite<uint64_t>(address, xreg(rt));
1802 MemoryWrite<uint64_t>(address2, xreg(rt2)); 2102 MemoryWrite<uint64_t>(address2, xreg(rt2));
1803 break; 2103 break;
1804 } 2104 }
1805 case STP_d: { 2105 case STP_d: {
1806 DCHECK(access_size == kDRegSize); 2106 DCHECK_EQ(access_size, static_cast<unsigned>(kDRegSize));
1807 MemoryWrite<double>(address, dreg(rt)); 2107 MemoryWrite<double>(address, dreg(rt));
1808 MemoryWrite<double>(address2, dreg(rt2)); 2108 MemoryWrite<double>(address2, dreg(rt2));
1809 break; 2109 break;
1810 } 2110 }
2111 case STP_q: {
2112 DCHECK_EQ(access_size, static_cast<unsigned>(kQRegSize));
2113 MemoryWrite<qreg_t>(address, qreg(rt));
2114 MemoryWrite<qreg_t>(address2, qreg(rt2));
2115 break;
2116 }
1811 default: UNREACHABLE(); 2117 default: UNREACHABLE();
1812 } 2118 }
1813 2119
1814 // Print a detailed trace (including the memory address) instead of the basic 2120 // Print a detailed trace (including the memory address) instead of the basic
1815 // register:value trace generated by set_*reg(). 2121 // register:value trace generated by set_*reg().
1816 if (instr->IsLoad()) { 2122 if (instr->IsLoad()) {
1817 if ((op == LDP_s) || (op == LDP_d)) { 2123 if ((op == LDP_s) || (op == LDP_d)) {
1818 LogReadFP(address, access_size, rt); 2124 LogVRead(address, rt, GetPrintRegisterFormatForSizeFP(access_size));
1819 LogReadFP(address2, access_size, rt2); 2125 LogVRead(address2, rt2, GetPrintRegisterFormatForSizeFP(access_size));
2126 } else if (op == LDP_q) {
2127 LogVRead(address, rt, GetPrintRegisterFormatForSize(access_size));
2128 LogVRead(address2, rt2, GetPrintRegisterFormatForSize(access_size));
1820 } else { 2129 } else {
1821 LogRead(address, access_size, rt); 2130 LogRead(address, rt, GetPrintRegisterFormatForSize(access_size));
1822 LogRead(address2, access_size, rt2); 2131 LogRead(address2, rt2, GetPrintRegisterFormatForSize(access_size));
1823 } 2132 }
1824 } else { 2133 } else {
1825 if ((op == STP_s) || (op == STP_d)) { 2134 if ((op == STP_s) || (op == STP_d)) {
1826 LogWriteFP(address, access_size, rt); 2135 LogVWrite(address, rt, GetPrintRegisterFormatForSizeFP(access_size));
1827 LogWriteFP(address2, access_size, rt2); 2136 LogVWrite(address2, rt2, GetPrintRegisterFormatForSizeFP(access_size));
2137 } else if (op == STP_q) {
2138 LogVWrite(address, rt, GetPrintRegisterFormatForSize(access_size));
2139 LogVWrite(address2, rt2, GetPrintRegisterFormatForSize(access_size));
1828 } else { 2140 } else {
1829 LogWrite(address, access_size, rt); 2141 LogWrite(address, rt, GetPrintRegisterFormatForSize(access_size));
1830 LogWrite(address2, access_size, rt2); 2142 LogWrite(address2, rt2, GetPrintRegisterFormatForSize(access_size));
1831 } 2143 }
1832 } 2144 }
1833 2145
1834 // Handle the writeback for loads after the load to ensure safe pop 2146 // Handle the writeback for loads after the load to ensure safe pop
1835 // operation even when interrupted in the middle of it. The stack pointer 2147 // operation even when interrupted in the middle of it. The stack pointer
1836 // is only updated after the load so pop(fp) will never break the invariant 2148 // is only updated after the load so pop(fp) will never break the invariant
1837 // sp <= fp expected while walking the stack in the sampler. 2149 // sp <= fp expected while walking the stack in the sampler.
1838 if (instr->IsLoad()) { 2150 if (instr->IsLoad()) {
1839 // For loads the address pre writeback is used to check access below the 2151 // For loads the address pre writeback is used to check access below the
1840 // stack. 2152 // stack.
1841 stack = sp(); 2153 stack = sp();
1842 2154
1843 LoadStoreWriteBack(addr_reg, offset, addrmode); 2155 LoadStoreWriteBack(addr_reg, offset, addrmode);
1844 } 2156 }
1845 2157
1846 // Accesses below the stack pointer (but above the platform stack limit) are 2158 // Accesses below the stack pointer (but above the platform stack limit) are
1847 // not allowed in the ABI. 2159 // not allowed in the ABI.
1848 CheckMemoryAccess(address, stack); 2160 CheckMemoryAccess(address, stack);
1849 } 2161 }
1850 2162
1851 2163
1852 void Simulator::VisitLoadLiteral(Instruction* instr) { 2164 void Simulator::VisitLoadLiteral(Instruction* instr) {
1853 uintptr_t address = instr->LiteralAddress(); 2165 uintptr_t address = instr->LiteralAddress();
1854 unsigned rt = instr->Rt(); 2166 unsigned rt = instr->Rt();
1855 2167
1856 switch (instr->Mask(LoadLiteralMask)) { 2168 switch (instr->Mask(LoadLiteralMask)) {
1857 // Use _no_log variants to suppress the register trace (LOG_REGS, 2169 // Use _no_log variants to suppress the register trace (LOG_REGS,
1858 // LOG_FP_REGS), then print a more detailed log. 2170 // LOG_VREGS), then print a more detailed log.
1859 case LDR_w_lit: 2171 case LDR_w_lit:
1860 set_wreg_no_log(rt, MemoryRead<uint32_t>(address)); 2172 set_wreg_no_log(rt, MemoryRead<uint32_t>(address));
1861 LogRead(address, kWRegSize, rt); 2173 LogRead(address, rt, kPrintWReg);
1862 break; 2174 break;
1863 case LDR_x_lit: 2175 case LDR_x_lit:
1864 set_xreg_no_log(rt, MemoryRead<uint64_t>(address)); 2176 set_xreg_no_log(rt, MemoryRead<uint64_t>(address));
1865 LogRead(address, kXRegSize, rt); 2177 LogRead(address, rt, kPrintXReg);
1866 break; 2178 break;
1867 case LDR_s_lit: 2179 case LDR_s_lit:
1868 set_sreg_no_log(rt, MemoryRead<float>(address)); 2180 set_sreg_no_log(rt, MemoryRead<float>(address));
1869 LogReadFP(address, kSRegSize, rt); 2181 LogVRead(address, rt, kPrintSReg);
1870 break; 2182 break;
1871 case LDR_d_lit: 2183 case LDR_d_lit:
1872 set_dreg_no_log(rt, MemoryRead<double>(address)); 2184 set_dreg_no_log(rt, MemoryRead<double>(address));
1873 LogReadFP(address, kDRegSize, rt); 2185 LogVRead(address, rt, kPrintDReg);
1874 break; 2186 break;
1875 default: UNREACHABLE(); 2187 default: UNREACHABLE();
1876 } 2188 }
1877 } 2189 }
1878 2190
1879 2191
1880 uintptr_t Simulator::LoadStoreAddress(unsigned addr_reg, int64_t offset, 2192 uintptr_t Simulator::LoadStoreAddress(unsigned addr_reg, int64_t offset,
1881 AddrMode addrmode) { 2193 AddrMode addrmode) {
1882 const unsigned kSPRegCode = kSPRegInternalCode & kRegCodeMask; 2194 const unsigned kSPRegCode = kSPRegInternalCode & kRegCodeMask;
1883 uint64_t address = xreg(addr_reg, Reg31IsStackPointer); 2195 uint64_t address = xreg(addr_reg, Reg31IsStackPointer);
(...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after
2374 case UCVTF_sw_fixed: { 2686 case UCVTF_sw_fixed: {
2375 set_sreg(dst, 2687 set_sreg(dst,
2376 UFixedToFloat(reg<uint32_t>(src), fbits, round)); 2688 UFixedToFloat(reg<uint32_t>(src), fbits, round));
2377 break; 2689 break;
2378 } 2690 }
2379 default: UNREACHABLE(); 2691 default: UNREACHABLE();
2380 } 2692 }
2381 } 2693 }
2382 2694
2383 2695
2384 int32_t Simulator::FPToInt32(double value, FPRounding rmode) {
2385 value = FPRoundInt(value, rmode);
2386 if (value >= kWMaxInt) {
2387 return kWMaxInt;
2388 } else if (value < kWMinInt) {
2389 return kWMinInt;
2390 }
2391 return std::isnan(value) ? 0 : static_cast<int32_t>(value);
2392 }
2393
2394
2395 int64_t Simulator::FPToInt64(double value, FPRounding rmode) {
2396 value = FPRoundInt(value, rmode);
2397 if (value >= kXMaxInt) {
2398 return kXMaxInt;
2399 } else if (value < kXMinInt) {
2400 return kXMinInt;
2401 }
2402 return std::isnan(value) ? 0 : static_cast<int64_t>(value);
2403 }
2404
2405
2406 uint32_t Simulator::FPToUInt32(double value, FPRounding rmode) {
2407 value = FPRoundInt(value, rmode);
2408 if (value >= kWMaxUInt) {
2409 return kWMaxUInt;
2410 } else if (value < 0.0) {
2411 return 0;
2412 }
2413 return std::isnan(value) ? 0 : static_cast<uint32_t>(value);
2414 }
2415
2416
2417 uint64_t Simulator::FPToUInt64(double value, FPRounding rmode) {
2418 value = FPRoundInt(value, rmode);
2419 if (value >= kXMaxUInt) {
2420 return kXMaxUInt;
2421 } else if (value < 0.0) {
2422 return 0;
2423 }
2424 return std::isnan(value) ? 0 : static_cast<uint64_t>(value);
2425 }
2426
2427
2428 void Simulator::VisitFPCompare(Instruction* instr) { 2696 void Simulator::VisitFPCompare(Instruction* instr) {
2429 AssertSupportedFPCR(); 2697 AssertSupportedFPCR();
2430 2698
2431 unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSizeInBits
2432 : kSRegSizeInBits;
2433 double fn_val = fpreg(reg_size, instr->Rn());
2434
2435 switch (instr->Mask(FPCompareMask)) { 2699 switch (instr->Mask(FPCompareMask)) {
2436 case FCMP_s: 2700 case FCMP_s:
2437 case FCMP_d: FPCompare(fn_val, fpreg(reg_size, instr->Rm())); break; 2701 FPCompare(sreg(instr->Rn()), sreg(instr->Rm()));
2702 break;
2703 case FCMP_d:
2704 FPCompare(dreg(instr->Rn()), dreg(instr->Rm()));
2705 break;
2438 case FCMP_s_zero: 2706 case FCMP_s_zero:
2439 case FCMP_d_zero: FPCompare(fn_val, 0.0); break; 2707 FPCompare(sreg(instr->Rn()), 0.0f);
2708 break;
2709 case FCMP_d_zero:
2710 FPCompare(dreg(instr->Rn()), 0.0);
2711 break;
2440 default: UNIMPLEMENTED(); 2712 default: UNIMPLEMENTED();
2441 } 2713 }
2442 } 2714 }
2443 2715
2444 2716
2445 void Simulator::VisitFPConditionalCompare(Instruction* instr) { 2717 void Simulator::VisitFPConditionalCompare(Instruction* instr) {
2446 AssertSupportedFPCR(); 2718 AssertSupportedFPCR();
2447 2719
2448 switch (instr->Mask(FPConditionalCompareMask)) { 2720 switch (instr->Mask(FPConditionalCompareMask)) {
2449 case FCCMP_s: 2721 case FCCMP_s:
2722 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
2723 FPCompare(sreg(instr->Rn()), sreg(instr->Rm()));
2724 } else {
2725 nzcv().SetFlags(instr->Nzcv());
2726 LogSystemRegister(NZCV);
2727 }
2728 break;
2450 case FCCMP_d: { 2729 case FCCMP_d: {
2451 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) { 2730 if (ConditionPassed(static_cast<Condition>(instr->Condition()))) {
2452 // If the condition passes, set the status flags to the result of 2731 FPCompare(dreg(instr->Rn()), dreg(instr->Rm()));
2453 // comparing the operands.
2454 unsigned reg_size = (instr->Mask(FP64) == FP64) ? kDRegSizeInBits
2455 : kSRegSizeInBits;
2456 FPCompare(fpreg(reg_size, instr->Rn()), fpreg(reg_size, instr->Rm()));
2457 } else { 2732 } else {
2458 // If the condition fails, set the status flags to the nzcv immediate. 2733 // If the condition fails, set the status flags to the nzcv immediate.
2459 nzcv().SetFlags(instr->Nzcv()); 2734 nzcv().SetFlags(instr->Nzcv());
2460 LogSystemRegister(NZCV); 2735 LogSystemRegister(NZCV);
2461 } 2736 }
2462 break; 2737 break;
2463 } 2738 }
2464 default: UNIMPLEMENTED(); 2739 default: UNIMPLEMENTED();
2465 } 2740 }
2466 } 2741 }
(...skipping 13 matching lines...) Expand all
2480 case FCSEL_s: set_sreg(instr->Rd(), sreg(selected)); break; 2755 case FCSEL_s: set_sreg(instr->Rd(), sreg(selected)); break;
2481 case FCSEL_d: set_dreg(instr->Rd(), dreg(selected)); break; 2756 case FCSEL_d: set_dreg(instr->Rd(), dreg(selected)); break;
2482 default: UNIMPLEMENTED(); 2757 default: UNIMPLEMENTED();
2483 } 2758 }
2484 } 2759 }
2485 2760
2486 2761
2487 void Simulator::VisitFPDataProcessing1Source(Instruction* instr) { 2762 void Simulator::VisitFPDataProcessing1Source(Instruction* instr) {
2488 AssertSupportedFPCR(); 2763 AssertSupportedFPCR();
2489 2764
2765 FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
2766 VectorFormat vform = (instr->Mask(FP64) == FP64) ? kFormatD : kFormatS;
2767 SimVRegister& rd = vreg(instr->Rd());
2768 SimVRegister& rn = vreg(instr->Rn());
2769 bool inexact_exception = false;
2770
2490 unsigned fd = instr->Rd(); 2771 unsigned fd = instr->Rd();
2491 unsigned fn = instr->Rn(); 2772 unsigned fn = instr->Rn();
2492 2773
2493 switch (instr->Mask(FPDataProcessing1SourceMask)) { 2774 switch (instr->Mask(FPDataProcessing1SourceMask)) {
2494 case FMOV_s: set_sreg(fd, sreg(fn)); break; 2775 case FMOV_s:
2495 case FMOV_d: set_dreg(fd, dreg(fn)); break; 2776 set_sreg(fd, sreg(fn));
2496 case FABS_s: set_sreg(fd, std::fabs(sreg(fn))); break; 2777 return;
2497 case FABS_d: set_dreg(fd, std::fabs(dreg(fn))); break; 2778 case FMOV_d:
2498 case FNEG_s: set_sreg(fd, -sreg(fn)); break; 2779 set_dreg(fd, dreg(fn));
2499 case FNEG_d: set_dreg(fd, -dreg(fn)); break; 2780 return;
2500 case FSQRT_s: set_sreg(fd, FPSqrt(sreg(fn))); break; 2781 case FABS_s:
2501 case FSQRT_d: set_dreg(fd, FPSqrt(dreg(fn))); break; 2782 case FABS_d:
2502 case FRINTA_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieAway)); break; 2783 fabs_(vform, vreg(fd), vreg(fn));
2503 case FRINTA_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieAway)); break; 2784 // Explicitly log the register update whilst we have type information.
2785 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
2786 return;
2787 case FNEG_s:
2788 case FNEG_d:
2789 fneg(vform, vreg(fd), vreg(fn));
2790 // Explicitly log the register update whilst we have type information.
2791 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
2792 return;
2793 case FCVT_ds:
2794 set_dreg(fd, FPToDouble(sreg(fn)));
2795 return;
2796 case FCVT_sd:
2797 set_sreg(fd, FPToFloat(dreg(fn), FPTieEven));
2798 return;
2799 case FCVT_hs:
2800 set_hreg(fd, FPToFloat16(sreg(fn), FPTieEven));
2801 return;
2802 case FCVT_sh:
2803 set_sreg(fd, FPToFloat(hreg(fn)));
2804 return;
2805 case FCVT_dh:
2806 set_dreg(fd, FPToDouble(FPToFloat(hreg(fn))));
2807 return;
2808 case FCVT_hd:
2809 set_hreg(fd, FPToFloat16(dreg(fn), FPTieEven));
2810 return;
2811 case FSQRT_s:
2812 case FSQRT_d:
2813 fsqrt(vform, rd, rn);
2814 // Explicitly log the register update whilst we have type information.
2815 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
2816 return;
2817 case FRINTI_s:
2818 case FRINTI_d:
2819 break; // Use FPCR rounding mode.
2820 case FRINTX_s:
2821 case FRINTX_d:
2822 inexact_exception = true;
2823 break;
2824 case FRINTA_s:
2825 case FRINTA_d:
2826 fpcr_rounding = FPTieAway;
2827 break;
2504 case FRINTM_s: 2828 case FRINTM_s:
2505 set_sreg(fd, FPRoundInt(sreg(fn), FPNegativeInfinity)); break;
2506 case FRINTM_d: 2829 case FRINTM_d:
2507 set_dreg(fd, FPRoundInt(dreg(fn), FPNegativeInfinity)); break; 2830 fpcr_rounding = FPNegativeInfinity;
2831 break;
2832 case FRINTN_s:
2833 case FRINTN_d:
2834 fpcr_rounding = FPTieEven;
2835 break;
2508 case FRINTP_s: 2836 case FRINTP_s:
2509 set_sreg(fd, FPRoundInt(sreg(fn), FPPositiveInfinity)); 2837 case FRINTP_d:
2838 fpcr_rounding = FPPositiveInfinity;
2510 break; 2839 break;
2511 case FRINTP_d: 2840 case FRINTZ_s:
2512 set_dreg(fd, FPRoundInt(dreg(fn), FPPositiveInfinity)); 2841 case FRINTZ_d:
2842 fpcr_rounding = FPZero;
2513 break; 2843 break;
2514 case FRINTN_s: set_sreg(fd, FPRoundInt(sreg(fn), FPTieEven)); break; 2844 default:
2515 case FRINTN_d: set_dreg(fd, FPRoundInt(dreg(fn), FPTieEven)); break; 2845 UNIMPLEMENTED();
2516 case FRINTZ_s: set_sreg(fd, FPRoundInt(sreg(fn), FPZero)); break;
2517 case FRINTZ_d: set_dreg(fd, FPRoundInt(dreg(fn), FPZero)); break;
2518 case FCVT_ds: set_dreg(fd, FPToDouble(sreg(fn))); break;
2519 case FCVT_sd: set_sreg(fd, FPToFloat(dreg(fn), FPTieEven)); break;
2520 default: UNIMPLEMENTED();
2521 }
2522 }
2523
2524
2525 // Assemble the specified IEEE-754 components into the target type and apply
2526 // appropriate rounding.
2527 // sign: 0 = positive, 1 = negative
2528 // exponent: Unbiased IEEE-754 exponent.
2529 // mantissa: The mantissa of the input. The top bit (which is not encoded for
2530 // normal IEEE-754 values) must not be omitted. This bit has the
2531 // value 'pow(2, exponent)'.
2532 //
2533 // The input value is assumed to be a normalized value. That is, the input may
2534 // not be infinity or NaN. If the source value is subnormal, it must be
2535 // normalized before calling this function such that the highest set bit in the
2536 // mantissa has the value 'pow(2, exponent)'.
2537 //
2538 // Callers should use FPRoundToFloat or FPRoundToDouble directly, rather than
2539 // calling a templated FPRound.
2540 template <class T, int ebits, int mbits>
2541 static T FPRound(int64_t sign, int64_t exponent, uint64_t mantissa,
2542 FPRounding round_mode) {
2543 DCHECK((sign == 0) || (sign == 1));
2544
2545 // Only the FPTieEven rounding mode is implemented.
2546 DCHECK(round_mode == FPTieEven);
2547 USE(round_mode);
2548
2549 // Rounding can promote subnormals to normals, and normals to infinities. For
2550 // example, a double with exponent 127 (FLT_MAX_EXP) would appear to be
2551 // encodable as a float, but rounding based on the low-order mantissa bits
2552 // could make it overflow. With ties-to-even rounding, this value would become
2553 // an infinity.
2554
2555 // ---- Rounding Method ----
2556 //
2557 // The exponent is irrelevant in the rounding operation, so we treat the
2558 // lowest-order bit that will fit into the result ('onebit') as having
2559 // the value '1'. Similarly, the highest-order bit that won't fit into
2560 // the result ('halfbit') has the value '0.5'. The 'point' sits between
2561 // 'onebit' and 'halfbit':
2562 //
2563 // These bits fit into the result.
2564 // |---------------------|
2565 // mantissa = 0bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
2566 // ||
2567 // / |
2568 // / halfbit
2569 // onebit
2570 //
2571 // For subnormal outputs, the range of representable bits is smaller and
2572 // the position of onebit and halfbit depends on the exponent of the
2573 // input, but the method is otherwise similar.
2574 //
2575 // onebit(frac)
2576 // |
2577 // | halfbit(frac) halfbit(adjusted)
2578 // | / /
2579 // | | |
2580 // 0b00.0 (exact) -> 0b00.0 (exact) -> 0b00
2581 // 0b00.0... -> 0b00.0... -> 0b00
2582 // 0b00.1 (exact) -> 0b00.0111..111 -> 0b00
2583 // 0b00.1... -> 0b00.1... -> 0b01
2584 // 0b01.0 (exact) -> 0b01.0 (exact) -> 0b01
2585 // 0b01.0... -> 0b01.0... -> 0b01
2586 // 0b01.1 (exact) -> 0b01.1 (exact) -> 0b10
2587 // 0b01.1... -> 0b01.1... -> 0b10
2588 // 0b10.0 (exact) -> 0b10.0 (exact) -> 0b10
2589 // 0b10.0... -> 0b10.0... -> 0b10
2590 // 0b10.1 (exact) -> 0b10.0111..111 -> 0b10
2591 // 0b10.1... -> 0b10.1... -> 0b11
2592 // 0b11.0 (exact) -> 0b11.0 (exact) -> 0b11
2593 // ... / | / |
2594 // / | / |
2595 // / |
2596 // adjusted = frac - (halfbit(mantissa) & ~onebit(frac)); / |
2597 //
2598 // mantissa = (mantissa >> shift) + halfbit(adjusted);
2599
2600 static const int mantissa_offset = 0;
2601 static const int exponent_offset = mantissa_offset + mbits;
2602 static const int sign_offset = exponent_offset + ebits;
2603 STATIC_ASSERT(sign_offset == (sizeof(T) * kByteSize - 1));
2604
2605 // Bail out early for zero inputs.
2606 if (mantissa == 0) {
2607 return static_cast<T>(sign << sign_offset);
2608 } 2846 }
2609 2847
2610 // If all bits in the exponent are set, the value is infinite or NaN. 2848 // Only FRINT* instructions fall through the switch above.
2611 // This is true for all binary IEEE-754 formats. 2849 frint(vform, rd, rn, fpcr_rounding, inexact_exception);
2612 static const int infinite_exponent = (1 << ebits) - 1; 2850 // Explicitly log the register update whilst we have type information
2613 static const int max_normal_exponent = infinite_exponent - 1; 2851 LogVRegister(fd, GetPrintRegisterFormatFP(vform));
2614
2615 // Apply the exponent bias to encode it for the result. Doing this early makes
2616 // it easy to detect values that will be infinite or subnormal.
2617 exponent += max_normal_exponent >> 1;
2618
2619 if (exponent > max_normal_exponent) {
2620 // Overflow: The input is too large for the result type to represent. The
2621 // FPTieEven rounding mode handles overflows using infinities.
2622 exponent = infinite_exponent;
2623 mantissa = 0;
2624 return static_cast<T>((sign << sign_offset) |
2625 (exponent << exponent_offset) |
2626 (mantissa << mantissa_offset));
2627 }
2628
2629 // Calculate the shift required to move the top mantissa bit to the proper
2630 // place in the destination type.
2631 const int highest_significant_bit = 63 - CountLeadingZeros(mantissa, 64);
2632 int shift = highest_significant_bit - mbits;
2633
2634 if (exponent <= 0) {
2635 // The output will be subnormal (before rounding).
2636
2637 // For subnormal outputs, the shift must be adjusted by the exponent. The +1
2638 // is necessary because the exponent of a subnormal value (encoded as 0) is
2639 // the same as the exponent of the smallest normal value (encoded as 1).
2640 shift += -exponent + 1;
2641
2642 // Handle inputs that would produce a zero output.
2643 //
2644 // Shifts higher than highest_significant_bit+1 will always produce a zero
2645 // result. A shift of exactly highest_significant_bit+1 might produce a
2646 // non-zero result after rounding.
2647 if (shift > (highest_significant_bit + 1)) {
2648 // The result will always be +/-0.0.
2649 return static_cast<T>(sign << sign_offset);
2650 }
2651
2652 // Properly encode the exponent for a subnormal output.
2653 exponent = 0;
2654 } else {
2655 // Clear the topmost mantissa bit, since this is not encoded in IEEE-754
2656 // normal values.
2657 mantissa &= ~(1UL << highest_significant_bit);
2658 }
2659
2660 if (shift > 0) {
2661 // We have to shift the mantissa to the right. Some precision is lost, so we
2662 // need to apply rounding.
2663 uint64_t onebit_mantissa = (mantissa >> (shift)) & 1;
2664 uint64_t halfbit_mantissa = (mantissa >> (shift-1)) & 1;
2665 uint64_t adjusted = mantissa - (halfbit_mantissa & ~onebit_mantissa);
2666 T halfbit_adjusted = (adjusted >> (shift-1)) & 1;
2667
2668 T result =
2669 static_cast<T>((sign << sign_offset) | (exponent << exponent_offset) |
2670 ((mantissa >> shift) << mantissa_offset));
2671
2672 // A very large mantissa can overflow during rounding. If this happens, the
2673 // exponent should be incremented and the mantissa set to 1.0 (encoded as
2674 // 0). Applying halfbit_adjusted after assembling the float has the nice
2675 // side-effect that this case is handled for free.
2676 //
2677 // This also handles cases where a very large finite value overflows to
2678 // infinity, or where a very large subnormal value overflows to become
2679 // normal.
2680 return result + halfbit_adjusted;
2681 } else {
2682 // We have to shift the mantissa to the left (or not at all). The input
2683 // mantissa is exactly representable in the output mantissa, so apply no
2684 // rounding correction.
2685 return static_cast<T>((sign << sign_offset) |
2686 (exponent << exponent_offset) |
2687 ((mantissa << -shift) << mantissa_offset));
2688 }
2689 } 2852 }
2690 2853
2691
2692 // See FPRound for a description of this function.
2693 static inline double FPRoundToDouble(int64_t sign, int64_t exponent,
2694 uint64_t mantissa, FPRounding round_mode) {
2695 int64_t bits =
2696 FPRound<int64_t, kDoubleExponentBits, kDoubleMantissaBits>(sign,
2697 exponent,
2698 mantissa,
2699 round_mode);
2700 return rawbits_to_double(bits);
2701 }
2702
2703
2704 // See FPRound for a description of this function.
2705 static inline float FPRoundToFloat(int64_t sign, int64_t exponent,
2706 uint64_t mantissa, FPRounding round_mode) {
2707 int32_t bits =
2708 FPRound<int32_t, kFloatExponentBits, kFloatMantissaBits>(sign,
2709 exponent,
2710 mantissa,
2711 round_mode);
2712 return rawbits_to_float(bits);
2713 }
2714
2715
2716 double Simulator::FixedToDouble(int64_t src, int fbits, FPRounding round) {
2717 if (src >= 0) {
2718 return UFixedToDouble(src, fbits, round);
2719 } else {
2720 // This works for all negative values, including INT64_MIN.
2721 return -UFixedToDouble(-src, fbits, round);
2722 }
2723 }
2724
2725
2726 double Simulator::UFixedToDouble(uint64_t src, int fbits, FPRounding round) {
2727 // An input of 0 is a special case because the result is effectively
2728 // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit.
2729 if (src == 0) {
2730 return 0.0;
2731 }
2732
2733 // Calculate the exponent. The highest significant bit will have the value
2734 // 2^exponent.
2735 const int highest_significant_bit = 63 - CountLeadingZeros(src, 64);
2736 const int64_t exponent = highest_significant_bit - fbits;
2737
2738 return FPRoundToDouble(0, exponent, src, round);
2739 }
2740
2741
2742 float Simulator::FixedToFloat(int64_t src, int fbits, FPRounding round) {
2743 if (src >= 0) {
2744 return UFixedToFloat(src, fbits, round);
2745 } else {
2746 // This works for all negative values, including INT64_MIN.
2747 return -UFixedToFloat(-src, fbits, round);
2748 }
2749 }
2750
2751
2752 float Simulator::UFixedToFloat(uint64_t src, int fbits, FPRounding round) {
2753 // An input of 0 is a special case because the result is effectively
2754 // subnormal: The exponent is encoded as 0 and there is no implicit 1 bit.
2755 if (src == 0) {
2756 return 0.0f;
2757 }
2758
2759 // Calculate the exponent. The highest significant bit will have the value
2760 // 2^exponent.
2761 const int highest_significant_bit = 63 - CountLeadingZeros(src, 64);
2762 const int32_t exponent = highest_significant_bit - fbits;
2763
2764 return FPRoundToFloat(0, exponent, src, round);
2765 }
2766
2767
2768 double Simulator::FPRoundInt(double value, FPRounding round_mode) {
2769 if ((value == 0.0) || (value == kFP64PositiveInfinity) ||
2770 (value == kFP64NegativeInfinity)) {
2771 return value;
2772 } else if (std::isnan(value)) {
2773 return FPProcessNaN(value);
2774 }
2775
2776 double int_result = floor(value);
2777 double error = value - int_result;
2778 switch (round_mode) {
2779 case FPTieAway: {
2780 // Take care of correctly handling the range ]-0.5, -0.0], which must
2781 // yield -0.0.
2782 if ((-0.5 < value) && (value < 0.0)) {
2783 int_result = -0.0;
2784
2785 } else if ((error > 0.5) || ((error == 0.5) && (int_result >= 0.0))) {
2786 // If the error is greater than 0.5, or is equal to 0.5 and the integer
2787 // result is positive, round up.
2788 int_result++;
2789 }
2790 break;
2791 }
2792 case FPTieEven: {
2793 // Take care of correctly handling the range [-0.5, -0.0], which must
2794 // yield -0.0.
2795 if ((-0.5 <= value) && (value < 0.0)) {
2796 int_result = -0.0;
2797
2798 // If the error is greater than 0.5, or is equal to 0.5 and the integer
2799 // result is odd, round up.
2800 } else if ((error > 0.5) ||
2801 ((error == 0.5) && (modulo(int_result, 2) != 0))) {
2802 int_result++;
2803 }
2804 break;
2805 }
2806 case FPZero: {
2807 // If value > 0 then we take floor(value)
2808 // otherwise, ceil(value)
2809 if (value < 0) {
2810 int_result = ceil(value);
2811 }
2812 break;
2813 }
2814 case FPNegativeInfinity: {
2815 // We always use floor(value).
2816 break;
2817 }
2818 case FPPositiveInfinity: {
2819 int_result = ceil(value);
2820 break;
2821 }
2822 default: UNIMPLEMENTED();
2823 }
2824 return int_result;
2825 }
2826
2827
2828 double Simulator::FPToDouble(float value) {
2829 switch (std::fpclassify(value)) {
2830 case FP_NAN: {
2831 if (fpcr().DN()) return kFP64DefaultNaN;
2832
2833 // Convert NaNs as the processor would:
2834 // - The sign is propagated.
2835 // - The payload (mantissa) is transferred entirely, except that the top
2836 // bit is forced to '1', making the result a quiet NaN. The unused
2837 // (low-order) payload bits are set to 0.
2838 uint32_t raw = float_to_rawbits(value);
2839
2840 uint64_t sign = raw >> 31;
2841 uint64_t exponent = (1 << 11) - 1;
2842 uint64_t payload = unsigned_bitextract_64(21, 0, raw);
2843 payload <<= (52 - 23); // The unused low-order bits should be 0.
2844 payload |= (1L << 51); // Force a quiet NaN.
2845
2846 return rawbits_to_double((sign << 63) | (exponent << 52) | payload);
2847 }
2848
2849 case FP_ZERO:
2850 case FP_NORMAL:
2851 case FP_SUBNORMAL:
2852 case FP_INFINITE: {
2853 // All other inputs are preserved in a standard cast, because every value
2854 // representable using an IEEE-754 float is also representable using an
2855 // IEEE-754 double.
2856 return static_cast<double>(value);
2857 }
2858 }
2859
2860 UNREACHABLE();
2861 return static_cast<double>(value);
2862 }
2863
2864
2865 float Simulator::FPToFloat(double value, FPRounding round_mode) {
2866 // Only the FPTieEven rounding mode is implemented.
2867 DCHECK(round_mode == FPTieEven);
2868 USE(round_mode);
2869
2870 switch (std::fpclassify(value)) {
2871 case FP_NAN: {
2872 if (fpcr().DN()) return kFP32DefaultNaN;
2873
2874 // Convert NaNs as the processor would:
2875 // - The sign is propagated.
2876 // - The payload (mantissa) is transferred as much as possible, except
2877 // that the top bit is forced to '1', making the result a quiet NaN.
2878 uint64_t raw = double_to_rawbits(value);
2879
2880 uint32_t sign = raw >> 63;
2881 uint32_t exponent = (1 << 8) - 1;
2882 uint32_t payload =
2883 static_cast<uint32_t>(unsigned_bitextract_64(50, 52 - 23, raw));
2884 payload |= (1 << 22); // Force a quiet NaN.
2885
2886 return rawbits_to_float((sign << 31) | (exponent << 23) | payload);
2887 }
2888
2889 case FP_ZERO:
2890 case FP_INFINITE: {
2891 // In a C++ cast, any value representable in the target type will be
2892 // unchanged. This is always the case for +/-0.0 and infinities.
2893 return static_cast<float>(value);
2894 }
2895
2896 case FP_NORMAL:
2897 case FP_SUBNORMAL: {
2898 // Convert double-to-float as the processor would, assuming that FPCR.FZ
2899 // (flush-to-zero) is not set.
2900 uint64_t raw = double_to_rawbits(value);
2901 // Extract the IEEE-754 double components.
2902 uint32_t sign = raw >> 63;
2903 // Extract the exponent and remove the IEEE-754 encoding bias.
2904 int32_t exponent =
2905 static_cast<int32_t>(unsigned_bitextract_64(62, 52, raw)) - 1023;
2906 // Extract the mantissa and add the implicit '1' bit.
2907 uint64_t mantissa = unsigned_bitextract_64(51, 0, raw);
2908 if (std::fpclassify(value) == FP_NORMAL) {
2909 mantissa |= (1UL << 52);
2910 }
2911 return FPRoundToFloat(sign, exponent, mantissa, round_mode);
2912 }
2913 }
2914
2915 UNREACHABLE();
2916 return value;
2917 }
2918
2919
2920 void Simulator::VisitFPDataProcessing2Source(Instruction* instr) { 2854 void Simulator::VisitFPDataProcessing2Source(Instruction* instr) {
2921 AssertSupportedFPCR(); 2855 AssertSupportedFPCR();
2922 2856
2923 unsigned fd = instr->Rd(); 2857 VectorFormat vform = (instr->Mask(FP64) == FP64) ? kFormatD : kFormatS;
2924 unsigned fn = instr->Rn(); 2858 SimVRegister& rd = vreg(instr->Rd());
2925 unsigned fm = instr->Rm(); 2859 SimVRegister& rn = vreg(instr->Rn());
2926 2860 SimVRegister& rm = vreg(instr->Rm());
2927 // Fmaxnm and Fminnm have special NaN handling.
2928 switch (instr->Mask(FPDataProcessing2SourceMask)) {
2929 case FMAXNM_s: set_sreg(fd, FPMaxNM(sreg(fn), sreg(fm))); return;
2930 case FMAXNM_d: set_dreg(fd, FPMaxNM(dreg(fn), dreg(fm))); return;
2931 case FMINNM_s: set_sreg(fd, FPMinNM(sreg(fn), sreg(fm))); return;
2932 case FMINNM_d: set_dreg(fd, FPMinNM(dreg(fn), dreg(fm))); return;
2933 default:
2934 break; // Fall through.
2935 }
2936
2937 if (FPProcessNaNs(instr)) return;
2938 2861
2939 switch (instr->Mask(FPDataProcessing2SourceMask)) { 2862 switch (instr->Mask(FPDataProcessing2SourceMask)) {
2940 case FADD_s: set_sreg(fd, FPAdd(sreg(fn), sreg(fm))); break; 2863 case FADD_s:
2941 case FADD_d: set_dreg(fd, FPAdd(dreg(fn), dreg(fm))); break; 2864 case FADD_d:
2942 case FSUB_s: set_sreg(fd, FPSub(sreg(fn), sreg(fm))); break; 2865 fadd(vform, rd, rn, rm);
2943 case FSUB_d: set_dreg(fd, FPSub(dreg(fn), dreg(fm))); break; 2866 break;
2944 case FMUL_s: set_sreg(fd, FPMul(sreg(fn), sreg(fm))); break; 2867 case FSUB_s:
2945 case FMUL_d: set_dreg(fd, FPMul(dreg(fn), dreg(fm))); break; 2868 case FSUB_d:
2946 case FDIV_s: set_sreg(fd, FPDiv(sreg(fn), sreg(fm))); break; 2869 fsub(vform, rd, rn, rm);
2947 case FDIV_d: set_dreg(fd, FPDiv(dreg(fn), dreg(fm))); break; 2870 break;
2948 case FMAX_s: set_sreg(fd, FPMax(sreg(fn), sreg(fm))); break; 2871 case FMUL_s:
2949 case FMAX_d: set_dreg(fd, FPMax(dreg(fn), dreg(fm))); break; 2872 case FMUL_d:
2950 case FMIN_s: set_sreg(fd, FPMin(sreg(fn), sreg(fm))); break; 2873 fmul(vform, rd, rn, rm);
2951 case FMIN_d: set_dreg(fd, FPMin(dreg(fn), dreg(fm))); break; 2874 break;
2875 case FNMUL_s:
2876 case FNMUL_d:
2877 fnmul(vform, rd, rn, rm);
2878 break;
2879 case FDIV_s:
2880 case FDIV_d:
2881 fdiv(vform, rd, rn, rm);
2882 break;
2883 case FMAX_s:
2884 case FMAX_d:
2885 fmax(vform, rd, rn, rm);
2886 break;
2887 case FMIN_s:
2888 case FMIN_d:
2889 fmin(vform, rd, rn, rm);
2890 break;
2952 case FMAXNM_s: 2891 case FMAXNM_s:
2953 case FMAXNM_d: 2892 case FMAXNM_d:
2893 fmaxnm(vform, rd, rn, rm);
2894 break;
2954 case FMINNM_s: 2895 case FMINNM_s:
2955 case FMINNM_d: 2896 case FMINNM_d:
2956 // These were handled before the standard FPProcessNaNs() stage. 2897 fminnm(vform, rd, rn, rm);
2898 break;
2899 default:
2957 UNREACHABLE(); 2900 UNREACHABLE();
2958 default: UNIMPLEMENTED();
2959 } 2901 }
2902 // Explicitly log the register update whilst we have type information.
2903 LogVRegister(instr->Rd(), GetPrintRegisterFormatFP(vform));
2960 } 2904 }
2961 2905
2962
2963 void Simulator::VisitFPDataProcessing3Source(Instruction* instr) { 2906 void Simulator::VisitFPDataProcessing3Source(Instruction* instr) {
2964 AssertSupportedFPCR(); 2907 AssertSupportedFPCR();
2965 2908
2966 unsigned fd = instr->Rd(); 2909 unsigned fd = instr->Rd();
2967 unsigned fn = instr->Rn(); 2910 unsigned fn = instr->Rn();
2968 unsigned fm = instr->Rm(); 2911 unsigned fm = instr->Rm();
2969 unsigned fa = instr->Ra(); 2912 unsigned fa = instr->Ra();
2970 2913
2971 switch (instr->Mask(FPDataProcessing3SourceMask)) { 2914 switch (instr->Mask(FPDataProcessing3SourceMask)) {
2972 // fd = fa +/- (fn * fm) 2915 // fd = fa +/- (fn * fm)
(...skipping 11 matching lines...) Expand all
2984 case FNMADD_d: 2927 case FNMADD_d:
2985 set_dreg(fd, FPMulAdd(-dreg(fa), -dreg(fn), dreg(fm))); 2928 set_dreg(fd, FPMulAdd(-dreg(fa), -dreg(fn), dreg(fm)));
2986 break; 2929 break;
2987 case FNMSUB_d: 2930 case FNMSUB_d:
2988 set_dreg(fd, FPMulAdd(-dreg(fa), dreg(fn), dreg(fm))); 2931 set_dreg(fd, FPMulAdd(-dreg(fa), dreg(fn), dreg(fm)));
2989 break; 2932 break;
2990 default: UNIMPLEMENTED(); 2933 default: UNIMPLEMENTED();
2991 } 2934 }
2992 } 2935 }
2993 2936
2994
2995 template <typename T>
2996 T Simulator::FPAdd(T op1, T op2) {
2997 // NaNs should be handled elsewhere.
2998 DCHECK(!std::isnan(op1) && !std::isnan(op2));
2999
3000 if (std::isinf(op1) && std::isinf(op2) && (op1 != op2)) {
3001 // inf + -inf returns the default NaN.
3002 return FPDefaultNaN<T>();
3003 } else {
3004 // Other cases should be handled by standard arithmetic.
3005 return op1 + op2;
3006 }
3007 }
3008
3009
3010 template <typename T>
3011 T Simulator::FPDiv(T op1, T op2) {
3012 // NaNs should be handled elsewhere.
3013 DCHECK(!std::isnan(op1) && !std::isnan(op2));
3014
3015 if ((std::isinf(op1) && std::isinf(op2)) || ((op1 == 0.0) && (op2 == 0.0))) {
3016 // inf / inf and 0.0 / 0.0 return the default NaN.
3017 return FPDefaultNaN<T>();
3018 } else {
3019 // Other cases should be handled by standard arithmetic.
3020 return op1 / op2;
3021 }
3022 }
3023
3024
3025 template <typename T>
3026 T Simulator::FPMax(T a, T b) {
3027 // NaNs should be handled elsewhere.
3028 DCHECK(!std::isnan(a) && !std::isnan(b));
3029
3030 if ((a == 0.0) && (b == 0.0) &&
3031 (copysign(1.0, a) != copysign(1.0, b))) {
3032 // a and b are zero, and the sign differs: return +0.0.
3033 return 0.0;
3034 } else {
3035 return (a > b) ? a : b;
3036 }
3037 }
3038
3039
3040 template <typename T>
3041 T Simulator::FPMaxNM(T a, T b) {
3042 if (IsQuietNaN(a) && !IsQuietNaN(b)) {
3043 a = kFP64NegativeInfinity;
3044 } else if (!IsQuietNaN(a) && IsQuietNaN(b)) {
3045 b = kFP64NegativeInfinity;
3046 }
3047
3048 T result = FPProcessNaNs(a, b);
3049 return std::isnan(result) ? result : FPMax(a, b);
3050 }
3051
3052 template <typename T>
3053 T Simulator::FPMin(T a, T b) {
3054 // NaNs should be handled elsewhere.
3055 DCHECK(!std::isnan(a) && !std::isnan(b));
3056
3057 if ((a == 0.0) && (b == 0.0) &&
3058 (copysign(1.0, a) != copysign(1.0, b))) {
3059 // a and b are zero, and the sign differs: return -0.0.
3060 return -0.0;
3061 } else {
3062 return (a < b) ? a : b;
3063 }
3064 }
3065
3066
3067 template <typename T>
3068 T Simulator::FPMinNM(T a, T b) {
3069 if (IsQuietNaN(a) && !IsQuietNaN(b)) {
3070 a = kFP64PositiveInfinity;
3071 } else if (!IsQuietNaN(a) && IsQuietNaN(b)) {
3072 b = kFP64PositiveInfinity;
3073 }
3074
3075 T result = FPProcessNaNs(a, b);
3076 return std::isnan(result) ? result : FPMin(a, b);
3077 }
3078
3079
3080 template <typename T>
3081 T Simulator::FPMul(T op1, T op2) {
3082 // NaNs should be handled elsewhere.
3083 DCHECK(!std::isnan(op1) && !std::isnan(op2));
3084
3085 if ((std::isinf(op1) && (op2 == 0.0)) || (std::isinf(op2) && (op1 == 0.0))) {
3086 // inf * 0.0 returns the default NaN.
3087 return FPDefaultNaN<T>();
3088 } else {
3089 // Other cases should be handled by standard arithmetic.
3090 return op1 * op2;
3091 }
3092 }
3093
3094
3095 template<typename T>
3096 T Simulator::FPMulAdd(T a, T op1, T op2) {
3097 T result = FPProcessNaNs3(a, op1, op2);
3098
3099 T sign_a = copysign(1.0, a);
3100 T sign_prod = copysign(1.0, op1) * copysign(1.0, op2);
3101 bool isinf_prod = std::isinf(op1) || std::isinf(op2);
3102 bool operation_generates_nan =
3103 (std::isinf(op1) && (op2 == 0.0)) || // inf * 0.0
3104 (std::isinf(op2) && (op1 == 0.0)) || // 0.0 * inf
3105 (std::isinf(a) && isinf_prod && (sign_a != sign_prod)); // inf - inf
3106
3107 if (std::isnan(result)) {
3108 // Generated NaNs override quiet NaNs propagated from a.
3109 if (operation_generates_nan && IsQuietNaN(a)) {
3110 return FPDefaultNaN<T>();
3111 } else {
3112 return result;
3113 }
3114 }
3115
3116 // If the operation would produce a NaN, return the default NaN.
3117 if (operation_generates_nan) {
3118 return FPDefaultNaN<T>();
3119 }
3120
3121 // Work around broken fma implementations for exact zero results: The sign of
3122 // exact 0.0 results is positive unless both a and op1 * op2 are negative.
3123 if (((op1 == 0.0) || (op2 == 0.0)) && (a == 0.0)) {
3124 return ((sign_a < 0) && (sign_prod < 0)) ? -0.0 : 0.0;
3125 }
3126
3127 result = FusedMultiplyAdd(op1, op2, a);
3128 DCHECK(!std::isnan(result));
3129
3130 // Work around broken fma implementations for rounded zero results: If a is
3131 // 0.0, the sign of the result is the sign of op1 * op2 before rounding.
3132 if ((a == 0.0) && (result == 0.0)) {
3133 return copysign(0.0, sign_prod);
3134 }
3135
3136 return result;
3137 }
3138
3139
3140 template <typename T>
3141 T Simulator::FPSqrt(T op) {
3142 if (std::isnan(op)) {
3143 return FPProcessNaN(op);
3144 } else if (op < 0.0) {
3145 return FPDefaultNaN<T>();
3146 } else {
3147 lazily_initialize_fast_sqrt(isolate_);
3148 return fast_sqrt(op, isolate_);
3149 }
3150 }
3151
3152
3153 template <typename T>
3154 T Simulator::FPSub(T op1, T op2) {
3155 // NaNs should be handled elsewhere.
3156 DCHECK(!std::isnan(op1) && !std::isnan(op2));
3157
3158 if (std::isinf(op1) && std::isinf(op2) && (op1 == op2)) {
3159 // inf - inf returns the default NaN.
3160 return FPDefaultNaN<T>();
3161 } else {
3162 // Other cases should be handled by standard arithmetic.
3163 return op1 - op2;
3164 }
3165 }
3166
3167
3168 template <typename T>
3169 T Simulator::FPProcessNaN(T op) {
3170 DCHECK(std::isnan(op));
3171 return fpcr().DN() ? FPDefaultNaN<T>() : ToQuietNaN(op);
3172 }
3173
3174
3175 template <typename T>
3176 T Simulator::FPProcessNaNs(T op1, T op2) {
3177 if (IsSignallingNaN(op1)) {
3178 return FPProcessNaN(op1);
3179 } else if (IsSignallingNaN(op2)) {
3180 return FPProcessNaN(op2);
3181 } else if (std::isnan(op1)) {
3182 DCHECK(IsQuietNaN(op1));
3183 return FPProcessNaN(op1);
3184 } else if (std::isnan(op2)) {
3185 DCHECK(IsQuietNaN(op2));
3186 return FPProcessNaN(op2);
3187 } else {
3188 return 0.0;
3189 }
3190 }
3191
3192
3193 template <typename T>
3194 T Simulator::FPProcessNaNs3(T op1, T op2, T op3) {
3195 if (IsSignallingNaN(op1)) {
3196 return FPProcessNaN(op1);
3197 } else if (IsSignallingNaN(op2)) {
3198 return FPProcessNaN(op2);
3199 } else if (IsSignallingNaN(op3)) {
3200 return FPProcessNaN(op3);
3201 } else if (std::isnan(op1)) {
3202 DCHECK(IsQuietNaN(op1));
3203 return FPProcessNaN(op1);
3204 } else if (std::isnan(op2)) {
3205 DCHECK(IsQuietNaN(op2));
3206 return FPProcessNaN(op2);
3207 } else if (std::isnan(op3)) {
3208 DCHECK(IsQuietNaN(op3));
3209 return FPProcessNaN(op3);
3210 } else {
3211 return 0.0;
3212 }
3213 }
3214
3215
3216 bool Simulator::FPProcessNaNs(Instruction* instr) { 2937 bool Simulator::FPProcessNaNs(Instruction* instr) {
3217 unsigned fd = instr->Rd(); 2938 unsigned fd = instr->Rd();
3218 unsigned fn = instr->Rn(); 2939 unsigned fn = instr->Rn();
3219 unsigned fm = instr->Rm(); 2940 unsigned fm = instr->Rm();
3220 bool done = false; 2941 bool done = false;
3221 2942
3222 if (instr->Mask(FP64) == FP64) { 2943 if (instr->Mask(FP64) == FP64) {
3223 double result = FPProcessNaNs(dreg(fn), dreg(fm)); 2944 double result = FPProcessNaNs(dreg(fn), dreg(fm));
3224 if (std::isnan(result)) { 2945 if (std::isnan(result)) {
3225 set_dreg(fd, result); 2946 set_dreg(fd, result);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
3315 clr_reg_name, clr_reg_value, xreg(31, Reg31IsStackPointer), clr_normal); 3036 clr_reg_name, clr_reg_value, xreg(31, Reg31IsStackPointer), clr_normal);
3316 return true; 3037 return true;
3317 } else if (strcmp(desc, "wcsp") == 0) { 3038 } else if (strcmp(desc, "wcsp") == 0) {
3318 DCHECK(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode)); 3039 DCHECK(CodeFromName(desc) == static_cast<int>(kSPRegInternalCode));
3319 PrintF(stream_, "%s wcsp:%s 0x%08" PRIx32 "%s\n", 3040 PrintF(stream_, "%s wcsp:%s 0x%08" PRIx32 "%s\n",
3320 clr_reg_name, clr_reg_value, wreg(31, Reg31IsStackPointer), clr_normal); 3041 clr_reg_name, clr_reg_value, wreg(31, Reg31IsStackPointer), clr_normal);
3321 return true; 3042 return true;
3322 } 3043 }
3323 3044
3324 int i = CodeFromName(desc); 3045 int i = CodeFromName(desc);
3325 STATIC_ASSERT(kNumberOfRegisters == kNumberOfFPRegisters); 3046 static_assert(kNumberOfRegisters == kNumberOfVRegisters,
3326 if (i < 0 || static_cast<unsigned>(i) >= kNumberOfFPRegisters) return false; 3047 "Must be same number of Registers as VRegisters.");
3048 if (i < 0 || static_cast<unsigned>(i) >= kNumberOfVRegisters) return false;
3327 3049
3328 if (desc[0] == 'v') { 3050 if (desc[0] == 'v') {
3329 PrintF(stream_, "%s %s:%s 0x%016" PRIx64 "%s (%s%s:%s %g%s %s:%s %g%s)\n", 3051 PrintF(stream_, "%s %s:%s 0x%016" PRIx64 "%s (%s%s:%s %g%s %s:%s %g%s)\n",
3330 clr_fpreg_name, VRegNameForCode(i), 3052 clr_vreg_name, VRegNameForCode(i), clr_vreg_value,
3331 clr_fpreg_value, double_to_rawbits(dreg(i)), 3053 bit_cast<uint64_t>(dreg(i)), clr_normal, clr_vreg_name,
3332 clr_normal, 3054 DRegNameForCode(i), clr_vreg_value, dreg(i), clr_vreg_name,
3333 clr_fpreg_name, DRegNameForCode(i), 3055 SRegNameForCode(i), clr_vreg_value, sreg(i), clr_normal);
3334 clr_fpreg_value, dreg(i),
3335 clr_fpreg_name, SRegNameForCode(i),
3336 clr_fpreg_value, sreg(i),
3337 clr_normal);
3338 return true; 3056 return true;
3339 } else if (desc[0] == 'd') { 3057 } else if (desc[0] == 'd') {
3340 PrintF(stream_, "%s %s:%s %g%s\n", 3058 PrintF(stream_, "%s %s:%s %g%s\n", clr_vreg_name, DRegNameForCode(i),
3341 clr_fpreg_name, DRegNameForCode(i), 3059 clr_vreg_value, dreg(i), clr_normal);
3342 clr_fpreg_value, dreg(i),
3343 clr_normal);
3344 return true; 3060 return true;
3345 } else if (desc[0] == 's') { 3061 } else if (desc[0] == 's') {
3346 PrintF(stream_, "%s %s:%s %g%s\n", 3062 PrintF(stream_, "%s %s:%s %g%s\n", clr_vreg_name, SRegNameForCode(i),
3347 clr_fpreg_name, SRegNameForCode(i), 3063 clr_vreg_value, sreg(i), clr_normal);
3348 clr_fpreg_value, sreg(i),
3349 clr_normal);
3350 return true; 3064 return true;
3351 } else if (desc[0] == 'w') { 3065 } else if (desc[0] == 'w') {
3352 PrintF(stream_, "%s %s:%s 0x%08" PRIx32 "%s\n", 3066 PrintF(stream_, "%s %s:%s 0x%08" PRIx32 "%s\n",
3353 clr_reg_name, WRegNameForCode(i), clr_reg_value, wreg(i), clr_normal); 3067 clr_reg_name, WRegNameForCode(i), clr_reg_value, wreg(i), clr_normal);
3354 return true; 3068 return true;
3355 } else { 3069 } else {
3356 // X register names have a wide variety of starting characters, but anything 3070 // X register names have a wide variety of starting characters, but anything
3357 // else will be an X register. 3071 // else will be an X register.
3358 PrintF(stream_, "%s %s:%s 0x%016" PRIx64 "%s\n", 3072 PrintF(stream_, "%s %s:%s 0x%016" PRIx64 "%s\n",
3359 clr_reg_name, XRegNameForCode(i), clr_reg_value, xreg(i), clr_normal); 3073 clr_reg_name, XRegNameForCode(i), clr_reg_value, xreg(i), clr_normal);
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
3465 // Disassemble. 3179 // Disassemble.
3466 PrintInstructionsAt(reinterpret_cast<Instruction*>(address), 3180 PrintInstructionsAt(reinterpret_cast<Instruction*>(address),
3467 n_of_instrs_to_disasm); 3181 n_of_instrs_to_disasm);
3468 PrintF("\n"); 3182 PrintF("\n");
3469 3183
3470 // print / p ------------------------------------------------------------- 3184 // print / p -------------------------------------------------------------
3471 } else if ((strcmp(cmd, "print") == 0) || (strcmp(cmd, "p") == 0)) { 3185 } else if ((strcmp(cmd, "print") == 0) || (strcmp(cmd, "p") == 0)) {
3472 if (argc == 2) { 3186 if (argc == 2) {
3473 if (strcmp(arg1, "all") == 0) { 3187 if (strcmp(arg1, "all") == 0) {
3474 PrintRegisters(); 3188 PrintRegisters();
3475 PrintFPRegisters(); 3189 PrintVRegisters();
3476 } else { 3190 } else {
3477 if (!PrintValue(arg1)) { 3191 if (!PrintValue(arg1)) {
3478 PrintF("%s unrecognized\n", arg1); 3192 PrintF("%s unrecognized\n", arg1);
3479 } 3193 }
3480 } 3194 }
3481 } else { 3195 } else {
3482 PrintF( 3196 PrintF(
3483 "print <register>\n" 3197 "print <register>\n"
3484 " Print the content of a register. (alias 'p')\n" 3198 " Print the content of a register. (alias 'p')\n"
3485 " 'print all' will print all registers.\n" 3199 " 'print all' will print all registers.\n"
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
3691 clr_normal); 3405 clr_normal);
3692 } 3406 }
3693 } 3407 }
3694 3408
3695 // Other options. 3409 // Other options.
3696 switch (parameters & kDebuggerTracingDirectivesMask) { 3410 switch (parameters & kDebuggerTracingDirectivesMask) {
3697 case TRACE_ENABLE: 3411 case TRACE_ENABLE:
3698 set_log_parameters(log_parameters() | parameters); 3412 set_log_parameters(log_parameters() | parameters);
3699 if (parameters & LOG_SYS_REGS) { PrintSystemRegisters(); } 3413 if (parameters & LOG_SYS_REGS) { PrintSystemRegisters(); }
3700 if (parameters & LOG_REGS) { PrintRegisters(); } 3414 if (parameters & LOG_REGS) { PrintRegisters(); }
3701 if (parameters & LOG_FP_REGS) { PrintFPRegisters(); } 3415 if (parameters & LOG_VREGS) {
3416 PrintVRegisters();
3417 }
3702 break; 3418 break;
3703 case TRACE_DISABLE: 3419 case TRACE_DISABLE:
3704 set_log_parameters(log_parameters() & ~parameters); 3420 set_log_parameters(log_parameters() & ~parameters);
3705 break; 3421 break;
3706 case TRACE_OVERRIDE: 3422 case TRACE_OVERRIDE:
3707 set_log_parameters(parameters); 3423 set_log_parameters(parameters);
3708 break; 3424 break;
3709 default: 3425 default:
3710 // We don't support a one-shot LOG_DISASM. 3426 // We don't support a one-shot LOG_DISASM.
3711 DCHECK((parameters & LOG_DISASM) == 0); 3427 DCHECK((parameters & LOG_DISASM) == 0);
3712 // Don't print information that is already being traced. 3428 // Don't print information that is already being traced.
3713 parameters &= ~log_parameters(); 3429 parameters &= ~log_parameters();
3714 // Print the requested information. 3430 // Print the requested information.
3715 if (parameters & LOG_SYS_REGS) PrintSystemRegisters(); 3431 if (parameters & LOG_SYS_REGS) PrintSystemRegisters();
3716 if (parameters & LOG_REGS) PrintRegisters(); 3432 if (parameters & LOG_REGS) PrintRegisters();
3717 if (parameters & LOG_FP_REGS) PrintFPRegisters(); 3433 if (parameters & LOG_VREGS) PrintVRegisters();
3718 } 3434 }
3719 3435
3720 // The stop parameters are inlined in the code. Skip them: 3436 // The stop parameters are inlined in the code. Skip them:
3721 // - Skip to the end of the message string. 3437 // - Skip to the end of the message string.
3722 size_t size = kDebugMessageOffset + strlen(message) + 1; 3438 size_t size = kDebugMessageOffset + strlen(message) + 1;
3723 pc_ = pc_->InstructionAtOffset(RoundUp(size, kInstructionSize)); 3439 pc_ = pc_->InstructionAtOffset(RoundUp(size, kInstructionSize));
3724 // - Verify that the unreachable marker is present. 3440 // - Verify that the unreachable marker is present.
3725 DCHECK(pc_->Mask(ExceptionMask) == HLT); 3441 DCHECK(pc_->Mask(ExceptionMask) == HLT);
3726 DCHECK(pc_->ImmException() == kImmExceptionIsUnreachable); 3442 DCHECK(pc_->ImmException() == kImmExceptionIsUnreachable);
3727 // - Skip past the unreachable marker. 3443 // - Skip past the unreachable marker.
(...skipping 16 matching lines...) Expand all
3744 base::OS::DebugBreak(); 3460 base::OS::DebugBreak();
3745 } 3461 }
3746 break; 3462 break;
3747 } 3463 }
3748 3464
3749 default: 3465 default:
3750 UNIMPLEMENTED(); 3466 UNIMPLEMENTED();
3751 } 3467 }
3752 } 3468 }
3753 3469
3470 void Simulator::VisitNEON2RegMisc(Instruction* instr) {
3471 NEONFormatDecoder nfd(instr);
3472 VectorFormat vf = nfd.GetVectorFormat();
3473
3474 // Format mapping for "long pair" instructions, [su]addlp, [su]adalp.
3475 static const NEONFormatMap map_lp = {
3476 {23, 22, 30}, {NF_4H, NF_8H, NF_2S, NF_4S, NF_1D, NF_2D}};
3477 VectorFormat vf_lp = nfd.GetVectorFormat(&map_lp);
3478
3479 static const NEONFormatMap map_fcvtl = {{22}, {NF_4S, NF_2D}};
3480 VectorFormat vf_fcvtl = nfd.GetVectorFormat(&map_fcvtl);
3481
3482 static const NEONFormatMap map_fcvtn = {{22, 30},
3483 {NF_4H, NF_8H, NF_2S, NF_4S}};
3484 VectorFormat vf_fcvtn = nfd.GetVectorFormat(&map_fcvtn);
3485
3486 SimVRegister& rd = vreg(instr->Rd());
3487 SimVRegister& rn = vreg(instr->Rn());
3488
3489 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_opcode) {
3490 // These instructions all use a two bit size field, except NOT and RBIT,
3491 // which use the field to encode the operation.
3492 switch (instr->Mask(NEON2RegMiscMask)) {
3493 case NEON_REV64:
3494 rev64(vf, rd, rn);
3495 break;
3496 case NEON_REV32:
3497 rev32(vf, rd, rn);
3498 break;
3499 case NEON_REV16:
3500 rev16(vf, rd, rn);
3501 break;
3502 case NEON_SUQADD:
3503 suqadd(vf, rd, rn);
3504 break;
3505 case NEON_USQADD:
3506 usqadd(vf, rd, rn);
3507 break;
3508 case NEON_CLS:
3509 cls(vf, rd, rn);
3510 break;
3511 case NEON_CLZ:
3512 clz(vf, rd, rn);
3513 break;
3514 case NEON_CNT:
3515 cnt(vf, rd, rn);
3516 break;
3517 case NEON_SQABS:
3518 abs(vf, rd, rn).SignedSaturate(vf);
3519 break;
3520 case NEON_SQNEG:
3521 neg(vf, rd, rn).SignedSaturate(vf);
3522 break;
3523 case NEON_CMGT_zero:
3524 cmp(vf, rd, rn, 0, gt);
3525 break;
3526 case NEON_CMGE_zero:
3527 cmp(vf, rd, rn, 0, ge);
3528 break;
3529 case NEON_CMEQ_zero:
3530 cmp(vf, rd, rn, 0, eq);
3531 break;
3532 case NEON_CMLE_zero:
3533 cmp(vf, rd, rn, 0, le);
3534 break;
3535 case NEON_CMLT_zero:
3536 cmp(vf, rd, rn, 0, lt);
3537 break;
3538 case NEON_ABS:
3539 abs(vf, rd, rn);
3540 break;
3541 case NEON_NEG:
3542 neg(vf, rd, rn);
3543 break;
3544 case NEON_SADDLP:
3545 saddlp(vf_lp, rd, rn);
3546 break;
3547 case NEON_UADDLP:
3548 uaddlp(vf_lp, rd, rn);
3549 break;
3550 case NEON_SADALP:
3551 sadalp(vf_lp, rd, rn);
3552 break;
3553 case NEON_UADALP:
3554 uadalp(vf_lp, rd, rn);
3555 break;
3556 case NEON_RBIT_NOT:
3557 vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
3558 switch (instr->FPType()) {
3559 case 0:
3560 not_(vf, rd, rn);
3561 break;
3562 case 1:
3563 rbit(vf, rd, rn);
3564 break;
3565 default:
3566 UNIMPLEMENTED();
3567 }
3568 break;
3569 }
3570 } else {
3571 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPFormatMap());
3572 FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
3573 bool inexact_exception = false;
3574
3575 // These instructions all use a one bit size field, except XTN, SQXTUN,
3576 // SHLL, SQXTN and UQXTN, which use a two bit size field.
3577 switch (instr->Mask(NEON2RegMiscFPMask)) {
3578 case NEON_FABS:
3579 fabs_(fpf, rd, rn);
3580 return;
3581 case NEON_FNEG:
3582 fneg(fpf, rd, rn);
3583 return;
3584 case NEON_FSQRT:
3585 fsqrt(fpf, rd, rn);
3586 return;
3587 case NEON_FCVTL:
3588 if (instr->Mask(NEON_Q)) {
3589 fcvtl2(vf_fcvtl, rd, rn);
3590 } else {
3591 fcvtl(vf_fcvtl, rd, rn);
3592 }
3593 return;
3594 case NEON_FCVTN:
3595 if (instr->Mask(NEON_Q)) {
3596 fcvtn2(vf_fcvtn, rd, rn);
3597 } else {
3598 fcvtn(vf_fcvtn, rd, rn);
3599 }
3600 return;
3601 case NEON_FCVTXN:
3602 if (instr->Mask(NEON_Q)) {
3603 fcvtxn2(vf_fcvtn, rd, rn);
3604 } else {
3605 fcvtxn(vf_fcvtn, rd, rn);
3606 }
3607 return;
3608
3609 // The following instructions break from the switch statement, rather
3610 // than return.
3611 case NEON_FRINTI:
3612 break; // Use FPCR rounding mode.
3613 case NEON_FRINTX:
3614 inexact_exception = true;
3615 break;
3616 case NEON_FRINTA:
3617 fpcr_rounding = FPTieAway;
3618 break;
3619 case NEON_FRINTM:
3620 fpcr_rounding = FPNegativeInfinity;
3621 break;
3622 case NEON_FRINTN:
3623 fpcr_rounding = FPTieEven;
3624 break;
3625 case NEON_FRINTP:
3626 fpcr_rounding = FPPositiveInfinity;
3627 break;
3628 case NEON_FRINTZ:
3629 fpcr_rounding = FPZero;
3630 break;
3631
3632 // The remaining cases return to the caller.
3633 case NEON_FCVTNS:
3634 fcvts(fpf, rd, rn, FPTieEven);
3635 return;
3636 case NEON_FCVTNU:
3637 fcvtu(fpf, rd, rn, FPTieEven);
3638 return;
3639 case NEON_FCVTPS:
3640 fcvts(fpf, rd, rn, FPPositiveInfinity);
3641 return;
3642 case NEON_FCVTPU:
3643 fcvtu(fpf, rd, rn, FPPositiveInfinity);
3644 return;
3645 case NEON_FCVTMS:
3646 fcvts(fpf, rd, rn, FPNegativeInfinity);
3647 return;
3648 case NEON_FCVTMU:
3649 fcvtu(fpf, rd, rn, FPNegativeInfinity);
3650 return;
3651 case NEON_FCVTZS:
3652 fcvts(fpf, rd, rn, FPZero);
3653 return;
3654 case NEON_FCVTZU:
3655 fcvtu(fpf, rd, rn, FPZero);
3656 return;
3657 case NEON_FCVTAS:
3658 fcvts(fpf, rd, rn, FPTieAway);
3659 return;
3660 case NEON_FCVTAU:
3661 fcvtu(fpf, rd, rn, FPTieAway);
3662 return;
3663 case NEON_SCVTF:
3664 scvtf(fpf, rd, rn, 0, fpcr_rounding);
3665 return;
3666 case NEON_UCVTF:
3667 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
3668 return;
3669 case NEON_URSQRTE:
3670 ursqrte(fpf, rd, rn);
3671 return;
3672 case NEON_URECPE:
3673 urecpe(fpf, rd, rn);
3674 return;
3675 case NEON_FRSQRTE:
3676 frsqrte(fpf, rd, rn);
3677 return;
3678 case NEON_FRECPE:
3679 frecpe(fpf, rd, rn, fpcr_rounding);
3680 return;
3681 case NEON_FCMGT_zero:
3682 fcmp_zero(fpf, rd, rn, gt);
3683 return;
3684 case NEON_FCMGE_zero:
3685 fcmp_zero(fpf, rd, rn, ge);
3686 return;
3687 case NEON_FCMEQ_zero:
3688 fcmp_zero(fpf, rd, rn, eq);
3689 return;
3690 case NEON_FCMLE_zero:
3691 fcmp_zero(fpf, rd, rn, le);
3692 return;
3693 case NEON_FCMLT_zero:
3694 fcmp_zero(fpf, rd, rn, lt);
3695 return;
3696 default:
3697 if ((NEON_XTN_opcode <= instr->Mask(NEON2RegMiscOpcode)) &&
3698 (instr->Mask(NEON2RegMiscOpcode) <= NEON_UQXTN_opcode)) {
3699 switch (instr->Mask(NEON2RegMiscMask)) {
3700 case NEON_XTN:
3701 xtn(vf, rd, rn);
3702 return;
3703 case NEON_SQXTN:
3704 sqxtn(vf, rd, rn);
3705 return;
3706 case NEON_UQXTN:
3707 uqxtn(vf, rd, rn);
3708 return;
3709 case NEON_SQXTUN:
3710 sqxtun(vf, rd, rn);
3711 return;
3712 case NEON_SHLL:
3713 vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
3714 if (instr->Mask(NEON_Q)) {
3715 shll2(vf, rd, rn);
3716 } else {
3717 shll(vf, rd, rn);
3718 }
3719 return;
3720 default:
3721 UNIMPLEMENTED();
3722 }
3723 } else {
3724 UNIMPLEMENTED();
3725 }
3726 }
3727
3728 // Only FRINT* instructions fall through the switch above.
3729 frint(fpf, rd, rn, fpcr_rounding, inexact_exception);
3730 }
3731 }
3732
3733 void Simulator::VisitNEON3Same(Instruction* instr) {
3734 NEONFormatDecoder nfd(instr);
3735 SimVRegister& rd = vreg(instr->Rd());
3736 SimVRegister& rn = vreg(instr->Rn());
3737 SimVRegister& rm = vreg(instr->Rm());
3738
3739 if (instr->Mask(NEON3SameLogicalFMask) == NEON3SameLogicalFixed) {
3740 VectorFormat vf = nfd.GetVectorFormat(nfd.LogicalFormatMap());
3741 switch (instr->Mask(NEON3SameLogicalMask)) {
3742 case NEON_AND:
3743 and_(vf, rd, rn, rm);
3744 break;
3745 case NEON_ORR:
3746 orr(vf, rd, rn, rm);
3747 break;
3748 case NEON_ORN:
3749 orn(vf, rd, rn, rm);
3750 break;
3751 case NEON_EOR:
3752 eor(vf, rd, rn, rm);
3753 break;
3754 case NEON_BIC:
3755 bic(vf, rd, rn, rm);
3756 break;
3757 case NEON_BIF:
3758 bif(vf, rd, rn, rm);
3759 break;
3760 case NEON_BIT:
3761 bit(vf, rd, rn, rm);
3762 break;
3763 case NEON_BSL:
3764 bsl(vf, rd, rn, rm);
3765 break;
3766 default:
3767 UNIMPLEMENTED();
3768 }
3769 } else if (instr->Mask(NEON3SameFPFMask) == NEON3SameFPFixed) {
3770 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
3771 switch (instr->Mask(NEON3SameFPMask)) {
3772 case NEON_FADD:
3773 fadd(vf, rd, rn, rm);
3774 break;
3775 case NEON_FSUB:
3776 fsub(vf, rd, rn, rm);
3777 break;
3778 case NEON_FMUL:
3779 fmul(vf, rd, rn, rm);
3780 break;
3781 case NEON_FDIV:
3782 fdiv(vf, rd, rn, rm);
3783 break;
3784 case NEON_FMAX:
3785 fmax(vf, rd, rn, rm);
3786 break;
3787 case NEON_FMIN:
3788 fmin(vf, rd, rn, rm);
3789 break;
3790 case NEON_FMAXNM:
3791 fmaxnm(vf, rd, rn, rm);
3792 break;
3793 case NEON_FMINNM:
3794 fminnm(vf, rd, rn, rm);
3795 break;
3796 case NEON_FMLA:
3797 fmla(vf, rd, rn, rm);
3798 break;
3799 case NEON_FMLS:
3800 fmls(vf, rd, rn, rm);
3801 break;
3802 case NEON_FMULX:
3803 fmulx(vf, rd, rn, rm);
3804 break;
3805 case NEON_FACGE:
3806 fabscmp(vf, rd, rn, rm, ge);
3807 break;
3808 case NEON_FACGT:
3809 fabscmp(vf, rd, rn, rm, gt);
3810 break;
3811 case NEON_FCMEQ:
3812 fcmp(vf, rd, rn, rm, eq);
3813 break;
3814 case NEON_FCMGE:
3815 fcmp(vf, rd, rn, rm, ge);
3816 break;
3817 case NEON_FCMGT:
3818 fcmp(vf, rd, rn, rm, gt);
3819 break;
3820 case NEON_FRECPS:
3821 frecps(vf, rd, rn, rm);
3822 break;
3823 case NEON_FRSQRTS:
3824 frsqrts(vf, rd, rn, rm);
3825 break;
3826 case NEON_FABD:
3827 fabd(vf, rd, rn, rm);
3828 break;
3829 case NEON_FADDP:
3830 faddp(vf, rd, rn, rm);
3831 break;
3832 case NEON_FMAXP:
3833 fmaxp(vf, rd, rn, rm);
3834 break;
3835 case NEON_FMAXNMP:
3836 fmaxnmp(vf, rd, rn, rm);
3837 break;
3838 case NEON_FMINP:
3839 fminp(vf, rd, rn, rm);
3840 break;
3841 case NEON_FMINNMP:
3842 fminnmp(vf, rd, rn, rm);
3843 break;
3844 default:
3845 UNIMPLEMENTED();
3846 }
3847 } else {
3848 VectorFormat vf = nfd.GetVectorFormat();
3849 switch (instr->Mask(NEON3SameMask)) {
3850 case NEON_ADD:
3851 add(vf, rd, rn, rm);
3852 break;
3853 case NEON_ADDP:
3854 addp(vf, rd, rn, rm);
3855 break;
3856 case NEON_CMEQ:
3857 cmp(vf, rd, rn, rm, eq);
3858 break;
3859 case NEON_CMGE:
3860 cmp(vf, rd, rn, rm, ge);
3861 break;
3862 case NEON_CMGT:
3863 cmp(vf, rd, rn, rm, gt);
3864 break;
3865 case NEON_CMHI:
3866 cmp(vf, rd, rn, rm, hi);
3867 break;
3868 case NEON_CMHS:
3869 cmp(vf, rd, rn, rm, hs);
3870 break;
3871 case NEON_CMTST:
3872 cmptst(vf, rd, rn, rm);
3873 break;
3874 case NEON_MLS:
3875 mls(vf, rd, rn, rm);
3876 break;
3877 case NEON_MLA:
3878 mla(vf, rd, rn, rm);
3879 break;
3880 case NEON_MUL:
3881 mul(vf, rd, rn, rm);
3882 break;
3883 case NEON_PMUL:
3884 pmul(vf, rd, rn, rm);
3885 break;
3886 case NEON_SMAX:
3887 smax(vf, rd, rn, rm);
3888 break;
3889 case NEON_SMAXP:
3890 smaxp(vf, rd, rn, rm);
3891 break;
3892 case NEON_SMIN:
3893 smin(vf, rd, rn, rm);
3894 break;
3895 case NEON_SMINP:
3896 sminp(vf, rd, rn, rm);
3897 break;
3898 case NEON_SUB:
3899 sub(vf, rd, rn, rm);
3900 break;
3901 case NEON_UMAX:
3902 umax(vf, rd, rn, rm);
3903 break;
3904 case NEON_UMAXP:
3905 umaxp(vf, rd, rn, rm);
3906 break;
3907 case NEON_UMIN:
3908 umin(vf, rd, rn, rm);
3909 break;
3910 case NEON_UMINP:
3911 uminp(vf, rd, rn, rm);
3912 break;
3913 case NEON_SSHL:
3914 sshl(vf, rd, rn, rm);
3915 break;
3916 case NEON_USHL:
3917 ushl(vf, rd, rn, rm);
3918 break;
3919 case NEON_SABD:
3920 AbsDiff(vf, rd, rn, rm, true);
3921 break;
3922 case NEON_UABD:
3923 AbsDiff(vf, rd, rn, rm, false);
3924 break;
3925 case NEON_SABA:
3926 saba(vf, rd, rn, rm);
3927 break;
3928 case NEON_UABA:
3929 uaba(vf, rd, rn, rm);
3930 break;
3931 case NEON_UQADD:
3932 add(vf, rd, rn, rm).UnsignedSaturate(vf);
3933 break;
3934 case NEON_SQADD:
3935 add(vf, rd, rn, rm).SignedSaturate(vf);
3936 break;
3937 case NEON_UQSUB:
3938 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
3939 break;
3940 case NEON_SQSUB:
3941 sub(vf, rd, rn, rm).SignedSaturate(vf);
3942 break;
3943 case NEON_SQDMULH:
3944 sqdmulh(vf, rd, rn, rm);
3945 break;
3946 case NEON_SQRDMULH:
3947 sqrdmulh(vf, rd, rn, rm);
3948 break;
3949 case NEON_UQSHL:
3950 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
3951 break;
3952 case NEON_SQSHL:
3953 sshl(vf, rd, rn, rm).SignedSaturate(vf);
3954 break;
3955 case NEON_URSHL:
3956 ushl(vf, rd, rn, rm).Round(vf);
3957 break;
3958 case NEON_SRSHL:
3959 sshl(vf, rd, rn, rm).Round(vf);
3960 break;
3961 case NEON_UQRSHL:
3962 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
3963 break;
3964 case NEON_SQRSHL:
3965 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
3966 break;
3967 case NEON_UHADD:
3968 add(vf, rd, rn, rm).Uhalve(vf);
3969 break;
3970 case NEON_URHADD:
3971 add(vf, rd, rn, rm).Uhalve(vf).Round(vf);
3972 break;
3973 case NEON_SHADD:
3974 add(vf, rd, rn, rm).Halve(vf);
3975 break;
3976 case NEON_SRHADD:
3977 add(vf, rd, rn, rm).Halve(vf).Round(vf);
3978 break;
3979 case NEON_UHSUB:
3980 sub(vf, rd, rn, rm).Uhalve(vf);
3981 break;
3982 case NEON_SHSUB:
3983 sub(vf, rd, rn, rm).Halve(vf);
3984 break;
3985 default:
3986 UNIMPLEMENTED();
3987 }
3988 }
3989 }
3990
3991 void Simulator::VisitNEON3Different(Instruction* instr) {
3992 NEONFormatDecoder nfd(instr);
3993 VectorFormat vf = nfd.GetVectorFormat();
3994 VectorFormat vf_l = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
3995
3996 SimVRegister& rd = vreg(instr->Rd());
3997 SimVRegister& rn = vreg(instr->Rn());
3998 SimVRegister& rm = vreg(instr->Rm());
3999
4000 switch (instr->Mask(NEON3DifferentMask)) {
4001 case NEON_PMULL:
4002 pmull(vf_l, rd, rn, rm);
4003 break;
4004 case NEON_PMULL2:
4005 pmull2(vf_l, rd, rn, rm);
4006 break;
4007 case NEON_UADDL:
4008 uaddl(vf_l, rd, rn, rm);
4009 break;
4010 case NEON_UADDL2:
4011 uaddl2(vf_l, rd, rn, rm);
4012 break;
4013 case NEON_SADDL:
4014 saddl(vf_l, rd, rn, rm);
4015 break;
4016 case NEON_SADDL2:
4017 saddl2(vf_l, rd, rn, rm);
4018 break;
4019 case NEON_USUBL:
4020 usubl(vf_l, rd, rn, rm);
4021 break;
4022 case NEON_USUBL2:
4023 usubl2(vf_l, rd, rn, rm);
4024 break;
4025 case NEON_SSUBL:
4026 ssubl(vf_l, rd, rn, rm);
4027 break;
4028 case NEON_SSUBL2:
4029 ssubl2(vf_l, rd, rn, rm);
4030 break;
4031 case NEON_SABAL:
4032 sabal(vf_l, rd, rn, rm);
4033 break;
4034 case NEON_SABAL2:
4035 sabal2(vf_l, rd, rn, rm);
4036 break;
4037 case NEON_UABAL:
4038 uabal(vf_l, rd, rn, rm);
4039 break;
4040 case NEON_UABAL2:
4041 uabal2(vf_l, rd, rn, rm);
4042 break;
4043 case NEON_SABDL:
4044 sabdl(vf_l, rd, rn, rm);
4045 break;
4046 case NEON_SABDL2:
4047 sabdl2(vf_l, rd, rn, rm);
4048 break;
4049 case NEON_UABDL:
4050 uabdl(vf_l, rd, rn, rm);
4051 break;
4052 case NEON_UABDL2:
4053 uabdl2(vf_l, rd, rn, rm);
4054 break;
4055 case NEON_SMLAL:
4056 smlal(vf_l, rd, rn, rm);
4057 break;
4058 case NEON_SMLAL2:
4059 smlal2(vf_l, rd, rn, rm);
4060 break;
4061 case NEON_UMLAL:
4062 umlal(vf_l, rd, rn, rm);
4063 break;
4064 case NEON_UMLAL2:
4065 umlal2(vf_l, rd, rn, rm);
4066 break;
4067 case NEON_SMLSL:
4068 smlsl(vf_l, rd, rn, rm);
4069 break;
4070 case NEON_SMLSL2:
4071 smlsl2(vf_l, rd, rn, rm);
4072 break;
4073 case NEON_UMLSL:
4074 umlsl(vf_l, rd, rn, rm);
4075 break;
4076 case NEON_UMLSL2:
4077 umlsl2(vf_l, rd, rn, rm);
4078 break;
4079 case NEON_SMULL:
4080 smull(vf_l, rd, rn, rm);
4081 break;
4082 case NEON_SMULL2:
4083 smull2(vf_l, rd, rn, rm);
4084 break;
4085 case NEON_UMULL:
4086 umull(vf_l, rd, rn, rm);
4087 break;
4088 case NEON_UMULL2:
4089 umull2(vf_l, rd, rn, rm);
4090 break;
4091 case NEON_SQDMLAL:
4092 sqdmlal(vf_l, rd, rn, rm);
4093 break;
4094 case NEON_SQDMLAL2:
4095 sqdmlal2(vf_l, rd, rn, rm);
4096 break;
4097 case NEON_SQDMLSL:
4098 sqdmlsl(vf_l, rd, rn, rm);
4099 break;
4100 case NEON_SQDMLSL2:
4101 sqdmlsl2(vf_l, rd, rn, rm);
4102 break;
4103 case NEON_SQDMULL:
4104 sqdmull(vf_l, rd, rn, rm);
4105 break;
4106 case NEON_SQDMULL2:
4107 sqdmull2(vf_l, rd, rn, rm);
4108 break;
4109 case NEON_UADDW:
4110 uaddw(vf_l, rd, rn, rm);
4111 break;
4112 case NEON_UADDW2:
4113 uaddw2(vf_l, rd, rn, rm);
4114 break;
4115 case NEON_SADDW:
4116 saddw(vf_l, rd, rn, rm);
4117 break;
4118 case NEON_SADDW2:
4119 saddw2(vf_l, rd, rn, rm);
4120 break;
4121 case NEON_USUBW:
4122 usubw(vf_l, rd, rn, rm);
4123 break;
4124 case NEON_USUBW2:
4125 usubw2(vf_l, rd, rn, rm);
4126 break;
4127 case NEON_SSUBW:
4128 ssubw(vf_l, rd, rn, rm);
4129 break;
4130 case NEON_SSUBW2:
4131 ssubw2(vf_l, rd, rn, rm);
4132 break;
4133 case NEON_ADDHN:
4134 addhn(vf, rd, rn, rm);
4135 break;
4136 case NEON_ADDHN2:
4137 addhn2(vf, rd, rn, rm);
4138 break;
4139 case NEON_RADDHN:
4140 raddhn(vf, rd, rn, rm);
4141 break;
4142 case NEON_RADDHN2:
4143 raddhn2(vf, rd, rn, rm);
4144 break;
4145 case NEON_SUBHN:
4146 subhn(vf, rd, rn, rm);
4147 break;
4148 case NEON_SUBHN2:
4149 subhn2(vf, rd, rn, rm);
4150 break;
4151 case NEON_RSUBHN:
4152 rsubhn(vf, rd, rn, rm);
4153 break;
4154 case NEON_RSUBHN2:
4155 rsubhn2(vf, rd, rn, rm);
4156 break;
4157 default:
4158 UNIMPLEMENTED();
4159 }
4160 }
4161
4162 void Simulator::VisitNEONAcrossLanes(Instruction* instr) {
4163 NEONFormatDecoder nfd(instr);
4164
4165 SimVRegister& rd = vreg(instr->Rd());
4166 SimVRegister& rn = vreg(instr->Rn());
4167
4168 // The input operand's VectorFormat is passed for these instructions.
4169 if (instr->Mask(NEONAcrossLanesFPFMask) == NEONAcrossLanesFPFixed) {
4170 VectorFormat vf = nfd.GetVectorFormat(nfd.FPFormatMap());
4171
4172 switch (instr->Mask(NEONAcrossLanesFPMask)) {
4173 case NEON_FMAXV:
4174 fmaxv(vf, rd, rn);
4175 break;
4176 case NEON_FMINV:
4177 fminv(vf, rd, rn);
4178 break;
4179 case NEON_FMAXNMV:
4180 fmaxnmv(vf, rd, rn);
4181 break;
4182 case NEON_FMINNMV:
4183 fminnmv(vf, rd, rn);
4184 break;
4185 default:
4186 UNIMPLEMENTED();
4187 }
4188 } else {
4189 VectorFormat vf = nfd.GetVectorFormat();
4190
4191 switch (instr->Mask(NEONAcrossLanesMask)) {
4192 case NEON_ADDV:
4193 addv(vf, rd, rn);
4194 break;
4195 case NEON_SMAXV:
4196 smaxv(vf, rd, rn);
4197 break;
4198 case NEON_SMINV:
4199 sminv(vf, rd, rn);
4200 break;
4201 case NEON_UMAXV:
4202 umaxv(vf, rd, rn);
4203 break;
4204 case NEON_UMINV:
4205 uminv(vf, rd, rn);
4206 break;
4207 case NEON_SADDLV:
4208 saddlv(vf, rd, rn);
4209 break;
4210 case NEON_UADDLV:
4211 uaddlv(vf, rd, rn);
4212 break;
4213 default:
4214 UNIMPLEMENTED();
4215 }
4216 }
4217 }
4218
4219 void Simulator::VisitNEONByIndexedElement(Instruction* instr) {
4220 NEONFormatDecoder nfd(instr);
4221 VectorFormat vf_r = nfd.GetVectorFormat();
4222 VectorFormat vf = nfd.GetVectorFormat(nfd.LongIntegerFormatMap());
4223
4224 SimVRegister& rd = vreg(instr->Rd());
4225 SimVRegister& rn = vreg(instr->Rn());
4226
4227 ByElementOp Op = NULL;
4228
4229 int rm_reg = instr->Rm();
4230 int index = (instr->NEONH() << 1) | instr->NEONL();
4231 if (instr->NEONSize() == 1) {
4232 rm_reg &= 0xf;
4233 index = (index << 1) | instr->NEONM();
4234 }
4235
4236 switch (instr->Mask(NEONByIndexedElementMask)) {
4237 case NEON_MUL_byelement:
4238 Op = &Simulator::mul;
4239 vf = vf_r;
4240 break;
4241 case NEON_MLA_byelement:
4242 Op = &Simulator::mla;
4243 vf = vf_r;
4244 break;
4245 case NEON_MLS_byelement:
4246 Op = &Simulator::mls;
4247 vf = vf_r;
4248 break;
4249 case NEON_SQDMULH_byelement:
4250 Op = &Simulator::sqdmulh;
4251 vf = vf_r;
4252 break;
4253 case NEON_SQRDMULH_byelement:
4254 Op = &Simulator::sqrdmulh;
4255 vf = vf_r;
4256 break;
4257 case NEON_SMULL_byelement:
4258 if (instr->Mask(NEON_Q)) {
4259 Op = &Simulator::smull2;
4260 } else {
4261 Op = &Simulator::smull;
4262 }
4263 break;
4264 case NEON_UMULL_byelement:
4265 if (instr->Mask(NEON_Q)) {
4266 Op = &Simulator::umull2;
4267 } else {
4268 Op = &Simulator::umull;
4269 }
4270 break;
4271 case NEON_SMLAL_byelement:
4272 if (instr->Mask(NEON_Q)) {
4273 Op = &Simulator::smlal2;
4274 } else {
4275 Op = &Simulator::smlal;
4276 }
4277 break;
4278 case NEON_UMLAL_byelement:
4279 if (instr->Mask(NEON_Q)) {
4280 Op = &Simulator::umlal2;
4281 } else {
4282 Op = &Simulator::umlal;
4283 }
4284 break;
4285 case NEON_SMLSL_byelement:
4286 if (instr->Mask(NEON_Q)) {
4287 Op = &Simulator::smlsl2;
4288 } else {
4289 Op = &Simulator::smlsl;
4290 }
4291 break;
4292 case NEON_UMLSL_byelement:
4293 if (instr->Mask(NEON_Q)) {
4294 Op = &Simulator::umlsl2;
4295 } else {
4296 Op = &Simulator::umlsl;
4297 }
4298 break;
4299 case NEON_SQDMULL_byelement:
4300 if (instr->Mask(NEON_Q)) {
4301 Op = &Simulator::sqdmull2;
4302 } else {
4303 Op = &Simulator::sqdmull;
4304 }
4305 break;
4306 case NEON_SQDMLAL_byelement:
4307 if (instr->Mask(NEON_Q)) {
4308 Op = &Simulator::sqdmlal2;
4309 } else {
4310 Op = &Simulator::sqdmlal;
4311 }
4312 break;
4313 case NEON_SQDMLSL_byelement:
4314 if (instr->Mask(NEON_Q)) {
4315 Op = &Simulator::sqdmlsl2;
4316 } else {
4317 Op = &Simulator::sqdmlsl;
4318 }
4319 break;
4320 default:
4321 index = instr->NEONH();
4322 if ((instr->FPType() & 1) == 0) {
4323 index = (index << 1) | instr->NEONL();
4324 }
4325
4326 vf = nfd.GetVectorFormat(nfd.FPFormatMap());
4327
4328 switch (instr->Mask(NEONByIndexedElementFPMask)) {
4329 case NEON_FMUL_byelement:
4330 Op = &Simulator::fmul;
4331 break;
4332 case NEON_FMLA_byelement:
4333 Op = &Simulator::fmla;
4334 break;
4335 case NEON_FMLS_byelement:
4336 Op = &Simulator::fmls;
4337 break;
4338 case NEON_FMULX_byelement:
4339 Op = &Simulator::fmulx;
4340 break;
4341 default:
4342 UNIMPLEMENTED();
4343 }
4344 }
4345
4346 (this->*Op)(vf, rd, rn, vreg(rm_reg), index);
4347 }
4348
4349 void Simulator::VisitNEONCopy(Instruction* instr) {
4350 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularFormatMap());
4351 VectorFormat vf = nfd.GetVectorFormat();
4352
4353 SimVRegister& rd = vreg(instr->Rd());
4354 SimVRegister& rn = vreg(instr->Rn());
4355 int imm5 = instr->ImmNEON5();
4356 int lsb = LowestSetBitPosition(imm5);
4357 int reg_index = imm5 >> lsb;
4358
4359 if (instr->Mask(NEONCopyInsElementMask) == NEON_INS_ELEMENT) {
4360 int imm4 = instr->ImmNEON4();
4361 DCHECK_GE(lsb, 1);
4362 int rn_index = imm4 >> (lsb - 1);
4363 ins_element(vf, rd, reg_index, rn, rn_index);
4364 } else if (instr->Mask(NEONCopyInsGeneralMask) == NEON_INS_GENERAL) {
4365 ins_immediate(vf, rd, reg_index, xreg(instr->Rn()));
4366 } else if (instr->Mask(NEONCopyUmovMask) == NEON_UMOV) {
4367 uint64_t value = LogicVRegister(rn).Uint(vf, reg_index);
4368 value &= MaxUintFromFormat(vf);
4369 set_xreg(instr->Rd(), value);
4370 } else if (instr->Mask(NEONCopyUmovMask) == NEON_SMOV) {
4371 int64_t value = LogicVRegister(rn).Int(vf, reg_index);
4372 if (instr->NEONQ()) {
4373 set_xreg(instr->Rd(), value);
4374 } else {
4375 DCHECK(is_int32(value));
4376 set_wreg(instr->Rd(), static_cast<int32_t>(value));
4377 }
4378 } else if (instr->Mask(NEONCopyDupElementMask) == NEON_DUP_ELEMENT) {
4379 dup_element(vf, rd, rn, reg_index);
4380 } else if (instr->Mask(NEONCopyDupGeneralMask) == NEON_DUP_GENERAL) {
4381 dup_immediate(vf, rd, xreg(instr->Rn()));
4382 } else {
4383 UNIMPLEMENTED();
4384 }
4385 }
4386
4387 void Simulator::VisitNEONExtract(Instruction* instr) {
4388 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
4389 VectorFormat vf = nfd.GetVectorFormat();
4390 SimVRegister& rd = vreg(instr->Rd());
4391 SimVRegister& rn = vreg(instr->Rn());
4392 SimVRegister& rm = vreg(instr->Rm());
4393 if (instr->Mask(NEONExtractMask) == NEON_EXT) {
4394 int index = instr->ImmNEONExt();
4395 ext(vf, rd, rn, rm, index);
4396 } else {
4397 UNIMPLEMENTED();
4398 }
4399 }
4400
4401 void Simulator::NEONLoadStoreMultiStructHelper(const Instruction* instr,
4402 AddrMode addr_mode) {
4403 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
4404 VectorFormat vf = nfd.GetVectorFormat();
4405
4406 uint64_t addr_base = xreg(instr->Rn(), Reg31IsStackPointer);
4407 int reg_size = RegisterSizeInBytesFromFormat(vf);
4408
4409 int reg[4];
4410 uint64_t addr[4];
4411 for (int i = 0; i < 4; i++) {
4412 reg[i] = (instr->Rt() + i) % kNumberOfVRegisters;
4413 addr[i] = addr_base + (i * reg_size);
4414 }
4415 int count = 1;
4416 bool log_read = true;
4417
4418 // Bit 23 determines whether this is an offset or post-index addressing mode.
4419 // In offset mode, bits 20 to 16 should be zero; these bits encode the
4420 // register of immediate in post-index mode.
4421 if ((instr->Bit(23) == 0) && (instr->Bits(20, 16) != 0)) {
4422 UNREACHABLE();
4423 }
4424
4425 // We use the PostIndex mask here, as it works in this case for both Offset
4426 // and PostIndex addressing.
4427 switch (instr->Mask(NEONLoadStoreMultiStructPostIndexMask)) {
4428 case NEON_LD1_4v:
4429 case NEON_LD1_4v_post:
4430 ld1(vf, vreg(reg[3]), addr[3]);
4431 count++; // Fall through.
4432 case NEON_LD1_3v:
4433 case NEON_LD1_3v_post:
4434 ld1(vf, vreg(reg[2]), addr[2]);
4435 count++; // Fall through.
4436 case NEON_LD1_2v:
4437 case NEON_LD1_2v_post:
4438 ld1(vf, vreg(reg[1]), addr[1]);
4439 count++; // Fall through.
4440 case NEON_LD1_1v:
4441 case NEON_LD1_1v_post:
4442 ld1(vf, vreg(reg[0]), addr[0]);
4443 break;
4444 case NEON_ST1_4v:
4445 case NEON_ST1_4v_post:
4446 st1(vf, vreg(reg[3]), addr[3]);
4447 count++; // Fall through.
4448 case NEON_ST1_3v:
4449 case NEON_ST1_3v_post:
4450 st1(vf, vreg(reg[2]), addr[2]);
4451 count++; // Fall through.
4452 case NEON_ST1_2v:
4453 case NEON_ST1_2v_post:
4454 st1(vf, vreg(reg[1]), addr[1]);
4455 count++; // Fall through.
4456 case NEON_ST1_1v:
4457 case NEON_ST1_1v_post:
4458 st1(vf, vreg(reg[0]), addr[0]);
4459 log_read = false;
4460 break;
4461 case NEON_LD2_post:
4462 case NEON_LD2:
4463 ld2(vf, vreg(reg[0]), vreg(reg[1]), addr[0]);
4464 count = 2;
4465 break;
4466 case NEON_ST2:
4467 case NEON_ST2_post:
4468 st2(vf, vreg(reg[0]), vreg(reg[1]), addr[0]);
4469 count = 2;
4470 log_read = false;
4471 break;
4472 case NEON_LD3_post:
4473 case NEON_LD3:
4474 ld3(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), addr[0]);
4475 count = 3;
4476 break;
4477 case NEON_ST3:
4478 case NEON_ST3_post:
4479 st3(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), addr[0]);
4480 count = 3;
4481 log_read = false;
4482 break;
4483 case NEON_LD4_post:
4484 case NEON_LD4:
4485 ld4(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), vreg(reg[3]), addr[0]);
4486 count = 4;
4487 break;
4488 case NEON_ST4:
4489 case NEON_ST4_post:
4490 st4(vf, vreg(reg[0]), vreg(reg[1]), vreg(reg[2]), vreg(reg[3]), addr[0]);
4491 count = 4;
4492 log_read = false;
4493 break;
4494 default:
4495 UNIMPLEMENTED();
4496 }
4497
4498 // Explicitly log the register update whilst we have type information.
4499 for (int i = 0; i < count; i++) {
4500 // For de-interleaving loads, only print the base address.
4501 int lane_size = LaneSizeInBytesFromFormat(vf);
4502 PrintRegisterFormat format = GetPrintRegisterFormatTryFP(
4503 GetPrintRegisterFormatForSize(reg_size, lane_size));
4504 if (log_read) {
4505 LogVRead(addr_base, reg[i], format);
4506 } else {
4507 LogVWrite(addr_base, reg[i], format);
4508 }
4509 }
4510
4511 if (addr_mode == PostIndex) {
4512 int rm = instr->Rm();
4513 // The immediate post index addressing mode is indicated by rm = 31.
4514 // The immediate is implied by the number of vector registers used.
4515 addr_base +=
4516 (rm == 31) ? RegisterSizeInBytesFromFormat(vf) * count : xreg(rm);
4517 set_xreg(instr->Rn(), addr_base);
4518 } else {
4519 DCHECK_EQ(addr_mode, Offset);
4520 }
4521 }
4522
4523 void Simulator::VisitNEONLoadStoreMultiStruct(Instruction* instr) {
4524 NEONLoadStoreMultiStructHelper(instr, Offset);
4525 }
4526
4527 void Simulator::VisitNEONLoadStoreMultiStructPostIndex(Instruction* instr) {
4528 NEONLoadStoreMultiStructHelper(instr, PostIndex);
4529 }
4530
4531 void Simulator::NEONLoadStoreSingleStructHelper(const Instruction* instr,
4532 AddrMode addr_mode) {
4533 uint64_t addr = xreg(instr->Rn(), Reg31IsStackPointer);
4534 int rt = instr->Rt();
4535
4536 // Bit 23 determines whether this is an offset or post-index addressing mode.
4537 // In offset mode, bits 20 to 16 should be zero; these bits encode the
4538 // register of immediate in post-index mode.
4539 if ((instr->Bit(23) == 0) && (instr->Bits(20, 16) != 0)) {
bbudge 2017/01/31 01:41:31 DCHECK_IMPLIES ?
martyn.capewell 2017/02/03 11:01:31 Done.
4540 UNREACHABLE();
4541 }
4542
4543 bool do_load = false;
4544
4545 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LoadStoreFormatMap());
4546 VectorFormat vf_t = nfd.GetVectorFormat();
4547
4548 VectorFormat vf = kFormat16B;
4549 // We use the PostIndex mask here, as it works in this case for both Offset
4550 // and PostIndex addressing.
4551 switch (instr->Mask(NEONLoadStoreSingleStructPostIndexMask)) {
4552 case NEON_LD1_b:
4553 case NEON_LD1_b_post:
4554 case NEON_LD2_b:
4555 case NEON_LD2_b_post:
4556 case NEON_LD3_b:
4557 case NEON_LD3_b_post:
4558 case NEON_LD4_b:
4559 case NEON_LD4_b_post:
4560 do_load = true; // Fall through.
4561 case NEON_ST1_b:
4562 case NEON_ST1_b_post:
4563 case NEON_ST2_b:
4564 case NEON_ST2_b_post:
4565 case NEON_ST3_b:
4566 case NEON_ST3_b_post:
4567 case NEON_ST4_b:
4568 case NEON_ST4_b_post:
4569 break;
4570
4571 case NEON_LD1_h:
4572 case NEON_LD1_h_post:
4573 case NEON_LD2_h:
4574 case NEON_LD2_h_post:
4575 case NEON_LD3_h:
4576 case NEON_LD3_h_post:
4577 case NEON_LD4_h:
4578 case NEON_LD4_h_post:
4579 do_load = true; // Fall through.
4580 case NEON_ST1_h:
4581 case NEON_ST1_h_post:
4582 case NEON_ST2_h:
4583 case NEON_ST2_h_post:
4584 case NEON_ST3_h:
4585 case NEON_ST3_h_post:
4586 case NEON_ST4_h:
4587 case NEON_ST4_h_post:
4588 vf = kFormat8H;
4589 break;
4590
4591 case NEON_LD1_s:
4592 case NEON_LD1_s_post:
4593 case NEON_LD2_s:
4594 case NEON_LD2_s_post:
4595 case NEON_LD3_s:
4596 case NEON_LD3_s_post:
4597 case NEON_LD4_s:
4598 case NEON_LD4_s_post:
4599 do_load = true; // Fall through.
4600 case NEON_ST1_s:
4601 case NEON_ST1_s_post:
4602 case NEON_ST2_s:
4603 case NEON_ST2_s_post:
4604 case NEON_ST3_s:
4605 case NEON_ST3_s_post:
4606 case NEON_ST4_s:
4607 case NEON_ST4_s_post: {
4608 static_assert((NEON_LD1_s | (1 << NEONLSSize_offset)) == NEON_LD1_d,
4609 "LSB of size distinguishes S and D registers.");
4610 static_assert(
4611 (NEON_LD1_s_post | (1 << NEONLSSize_offset)) == NEON_LD1_d_post,
4612 "LSB of size distinguishes S and D registers.");
4613 static_assert((NEON_ST1_s | (1 << NEONLSSize_offset)) == NEON_ST1_d,
4614 "LSB of size distinguishes S and D registers.");
4615 static_assert(
4616 (NEON_ST1_s_post | (1 << NEONLSSize_offset)) == NEON_ST1_d_post,
4617 "LSB of size distinguishes S and D registers.");
4618 vf = ((instr->NEONLSSize() & 1) == 0) ? kFormat4S : kFormat2D;
4619 break;
4620 }
4621
4622 case NEON_LD1R:
4623 case NEON_LD1R_post: {
4624 vf = vf_t;
4625 ld1r(vf, vreg(rt), addr);
4626 do_load = true;
4627 break;
4628 }
4629
4630 case NEON_LD2R:
4631 case NEON_LD2R_post: {
4632 vf = vf_t;
4633 int rt2 = (rt + 1) % kNumberOfVRegisters;
4634 ld2r(vf, vreg(rt), vreg(rt2), addr);
4635 do_load = true;
4636 break;
4637 }
4638
4639 case NEON_LD3R:
4640 case NEON_LD3R_post: {
4641 vf = vf_t;
4642 int rt2 = (rt + 1) % kNumberOfVRegisters;
4643 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
4644 ld3r(vf, vreg(rt), vreg(rt2), vreg(rt3), addr);
4645 do_load = true;
4646 break;
4647 }
4648
4649 case NEON_LD4R:
4650 case NEON_LD4R_post: {
4651 vf = vf_t;
4652 int rt2 = (rt + 1) % kNumberOfVRegisters;
4653 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
4654 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
4655 ld4r(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), addr);
4656 do_load = true;
4657 break;
4658 }
4659 default:
4660 UNIMPLEMENTED();
4661 }
4662
4663 PrintRegisterFormat print_format =
4664 GetPrintRegisterFormatTryFP(GetPrintRegisterFormat(vf));
4665 // Make sure that the print_format only includes a single lane.
4666 print_format =
4667 static_cast<PrintRegisterFormat>(print_format & ~kPrintRegAsVectorMask);
4668
4669 int esize = LaneSizeInBytesFromFormat(vf);
4670 int index_shift = LaneSizeInBytesLog2FromFormat(vf);
4671 int lane = instr->NEONLSIndex(index_shift);
4672 int scale = 0;
4673 int rt2 = (rt + 1) % kNumberOfVRegisters;
4674 int rt3 = (rt2 + 1) % kNumberOfVRegisters;
4675 int rt4 = (rt3 + 1) % kNumberOfVRegisters;
4676 switch (instr->Mask(NEONLoadStoreSingleLenMask)) {
4677 case NEONLoadStoreSingle1:
4678 scale = 1;
4679 if (do_load) {
4680 ld1(vf, vreg(rt), lane, addr);
4681 LogVRead(addr, rt, print_format, lane);
4682 } else {
4683 st1(vf, vreg(rt), lane, addr);
4684 LogVWrite(addr, rt, print_format, lane);
4685 }
4686 break;
4687 case NEONLoadStoreSingle2:
4688 scale = 2;
4689 if (do_load) {
4690 ld2(vf, vreg(rt), vreg(rt2), lane, addr);
4691 LogVRead(addr, rt, print_format, lane);
4692 LogVRead(addr + esize, rt2, print_format, lane);
4693 } else {
4694 st2(vf, vreg(rt), vreg(rt2), lane, addr);
4695 LogVWrite(addr, rt, print_format, lane);
4696 LogVWrite(addr + esize, rt2, print_format, lane);
4697 }
4698 break;
4699 case NEONLoadStoreSingle3:
4700 scale = 3;
4701 if (do_load) {
4702 ld3(vf, vreg(rt), vreg(rt2), vreg(rt3), lane, addr);
4703 LogVRead(addr, rt, print_format, lane);
4704 LogVRead(addr + esize, rt2, print_format, lane);
4705 LogVRead(addr + (2 * esize), rt3, print_format, lane);
4706 } else {
4707 st3(vf, vreg(rt), vreg(rt2), vreg(rt3), lane, addr);
4708 LogVWrite(addr, rt, print_format, lane);
4709 LogVWrite(addr + esize, rt2, print_format, lane);
4710 LogVWrite(addr + (2 * esize), rt3, print_format, lane);
4711 }
4712 break;
4713 case NEONLoadStoreSingle4:
4714 scale = 4;
4715 if (do_load) {
4716 ld4(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), lane, addr);
4717 LogVRead(addr, rt, print_format, lane);
4718 LogVRead(addr + esize, rt2, print_format, lane);
4719 LogVRead(addr + (2 * esize), rt3, print_format, lane);
4720 LogVRead(addr + (3 * esize), rt4, print_format, lane);
4721 } else {
4722 st4(vf, vreg(rt), vreg(rt2), vreg(rt3), vreg(rt4), lane, addr);
4723 LogVWrite(addr, rt, print_format, lane);
4724 LogVWrite(addr + esize, rt2, print_format, lane);
4725 LogVWrite(addr + (2 * esize), rt3, print_format, lane);
4726 LogVWrite(addr + (3 * esize), rt4, print_format, lane);
4727 }
4728 break;
4729 default:
4730 UNIMPLEMENTED();
4731 }
4732
4733 if (addr_mode == PostIndex) {
4734 int rm = instr->Rm();
4735 int lane_size = LaneSizeInBytesFromFormat(vf);
4736 set_xreg(instr->Rn(), addr + ((rm == 31) ? (scale * lane_size) : xreg(rm)));
4737 }
4738 }
4739
4740 void Simulator::VisitNEONLoadStoreSingleStruct(Instruction* instr) {
4741 NEONLoadStoreSingleStructHelper(instr, Offset);
4742 }
4743
4744 void Simulator::VisitNEONLoadStoreSingleStructPostIndex(Instruction* instr) {
4745 NEONLoadStoreSingleStructHelper(instr, PostIndex);
4746 }
4747
4748 void Simulator::VisitNEONModifiedImmediate(Instruction* instr) {
4749 SimVRegister& rd = vreg(instr->Rd());
4750 int cmode = instr->NEONCmode();
4751 int cmode_3_1 = (cmode >> 1) & 7;
4752 int cmode_3 = (cmode >> 3) & 1;
4753 int cmode_2 = (cmode >> 2) & 1;
4754 int cmode_1 = (cmode >> 1) & 1;
4755 int cmode_0 = cmode & 1;
4756 int q = instr->NEONQ();
4757 int op_bit = instr->NEONModImmOp();
4758 uint64_t imm8 = instr->ImmNEONabcdefgh();
4759
4760 // Find the format and immediate value
4761 uint64_t imm = 0;
4762 VectorFormat vform = kFormatUndefined;
4763 switch (cmode_3_1) {
4764 case 0x0:
4765 case 0x1:
4766 case 0x2:
4767 case 0x3:
4768 vform = (q == 1) ? kFormat4S : kFormat2S;
4769 imm = imm8 << (8 * cmode_3_1);
4770 break;
4771 case 0x4:
4772 case 0x5:
4773 vform = (q == 1) ? kFormat8H : kFormat4H;
4774 imm = imm8 << (8 * cmode_1);
4775 break;
4776 case 0x6:
4777 vform = (q == 1) ? kFormat4S : kFormat2S;
4778 if (cmode_0 == 0) {
4779 imm = imm8 << 8 | 0x000000ff;
4780 } else {
4781 imm = imm8 << 16 | 0x0000ffff;
4782 }
4783 break;
4784 case 0x7:
4785 if (cmode_0 == 0 && op_bit == 0) {
4786 vform = q ? kFormat16B : kFormat8B;
4787 imm = imm8;
4788 } else if (cmode_0 == 0 && op_bit == 1) {
4789 vform = q ? kFormat2D : kFormat1D;
4790 imm = 0;
4791 for (int i = 0; i < 8; ++i) {
4792 if (imm8 & (1 << i)) {
4793 imm |= (UINT64_C(0xff) << (8 * i));
4794 }
4795 }
4796 } else { // cmode_0 == 1, cmode == 0xf.
4797 if (op_bit == 0) {
4798 vform = q ? kFormat4S : kFormat2S;
4799 imm = bit_cast<uint32_t>(instr->ImmNEONFP32());
4800 } else if (q == 1) {
4801 vform = kFormat2D;
4802 imm = bit_cast<uint64_t>(instr->ImmNEONFP64());
4803 } else {
4804 DCHECK((q == 0) && (op_bit == 1) && (cmode == 0xf));
4805 VisitUnallocated(instr);
4806 }
4807 }
4808 break;
4809 default:
4810 UNREACHABLE();
4811 break;
4812 }
4813
4814 // Find the operation.
4815 NEONModifiedImmediateOp op;
4816 if (cmode_3 == 0) {
4817 if (cmode_0 == 0) {
4818 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
4819 } else { // cmode<0> == '1'
4820 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
4821 }
4822 } else { // cmode<3> == '1'
4823 if (cmode_2 == 0) {
4824 if (cmode_0 == 0) {
4825 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
4826 } else { // cmode<0> == '1'
4827 op = op_bit ? NEONModifiedImmediate_BIC : NEONModifiedImmediate_ORR;
4828 }
4829 } else { // cmode<2> == '1'
4830 if (cmode_1 == 0) {
4831 op = op_bit ? NEONModifiedImmediate_MVNI : NEONModifiedImmediate_MOVI;
4832 } else { // cmode<1> == '1'
4833 if (cmode_0 == 0) {
4834 op = NEONModifiedImmediate_MOVI;
4835 } else { // cmode<0> == '1'
4836 op = NEONModifiedImmediate_MOVI;
4837 }
4838 }
4839 }
4840 }
4841
4842 // Call the logic function.
4843 switch (op) {
4844 case NEONModifiedImmediate_ORR:
4845 orr(vform, rd, rd, imm);
4846 break;
4847 case NEONModifiedImmediate_BIC:
4848 bic(vform, rd, rd, imm);
4849 break;
4850 case NEONModifiedImmediate_MOVI:
4851 movi(vform, rd, imm);
4852 break;
4853 case NEONModifiedImmediate_MVNI:
4854 mvni(vform, rd, imm);
4855 break;
4856 default:
4857 VisitUnimplemented(instr);
4858 }
4859 }
4860
4861 void Simulator::VisitNEONScalar2RegMisc(Instruction* instr) {
4862 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
4863 VectorFormat vf = nfd.GetVectorFormat();
4864
4865 SimVRegister& rd = vreg(instr->Rd());
4866 SimVRegister& rn = vreg(instr->Rn());
4867
4868 if (instr->Mask(NEON2RegMiscOpcode) <= NEON_NEG_scalar_opcode) {
4869 // These instructions all use a two bit size field, except NOT and RBIT,
4870 // which use the field to encode the operation.
4871 switch (instr->Mask(NEONScalar2RegMiscMask)) {
4872 case NEON_CMEQ_zero_scalar:
4873 cmp(vf, rd, rn, 0, eq);
4874 break;
4875 case NEON_CMGE_zero_scalar:
4876 cmp(vf, rd, rn, 0, ge);
4877 break;
4878 case NEON_CMGT_zero_scalar:
4879 cmp(vf, rd, rn, 0, gt);
4880 break;
4881 case NEON_CMLT_zero_scalar:
4882 cmp(vf, rd, rn, 0, lt);
4883 break;
4884 case NEON_CMLE_zero_scalar:
4885 cmp(vf, rd, rn, 0, le);
4886 break;
4887 case NEON_ABS_scalar:
4888 abs(vf, rd, rn);
4889 break;
4890 case NEON_SQABS_scalar:
4891 abs(vf, rd, rn).SignedSaturate(vf);
4892 break;
4893 case NEON_NEG_scalar:
4894 neg(vf, rd, rn);
4895 break;
4896 case NEON_SQNEG_scalar:
4897 neg(vf, rd, rn).SignedSaturate(vf);
4898 break;
4899 case NEON_SUQADD_scalar:
4900 suqadd(vf, rd, rn);
4901 break;
4902 case NEON_USQADD_scalar:
4903 usqadd(vf, rd, rn);
4904 break;
4905 default:
4906 UNIMPLEMENTED();
4907 break;
4908 }
4909 } else {
4910 VectorFormat fpf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
4911 FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
4912
4913 // These instructions all use a one bit size field, except SQXTUN, SQXTN
4914 // and UQXTN, which use a two bit size field.
4915 switch (instr->Mask(NEONScalar2RegMiscFPMask)) {
4916 case NEON_FRECPE_scalar:
4917 frecpe(fpf, rd, rn, fpcr_rounding);
4918 break;
4919 case NEON_FRECPX_scalar:
4920 frecpx(fpf, rd, rn);
4921 break;
4922 case NEON_FRSQRTE_scalar:
4923 frsqrte(fpf, rd, rn);
4924 break;
4925 case NEON_FCMGT_zero_scalar:
4926 fcmp_zero(fpf, rd, rn, gt);
4927 break;
4928 case NEON_FCMGE_zero_scalar:
4929 fcmp_zero(fpf, rd, rn, ge);
4930 break;
4931 case NEON_FCMEQ_zero_scalar:
4932 fcmp_zero(fpf, rd, rn, eq);
4933 break;
4934 case NEON_FCMLE_zero_scalar:
4935 fcmp_zero(fpf, rd, rn, le);
4936 break;
4937 case NEON_FCMLT_zero_scalar:
4938 fcmp_zero(fpf, rd, rn, lt);
4939 break;
4940 case NEON_SCVTF_scalar:
4941 scvtf(fpf, rd, rn, 0, fpcr_rounding);
4942 break;
4943 case NEON_UCVTF_scalar:
4944 ucvtf(fpf, rd, rn, 0, fpcr_rounding);
4945 break;
4946 case NEON_FCVTNS_scalar:
4947 fcvts(fpf, rd, rn, FPTieEven);
4948 break;
4949 case NEON_FCVTNU_scalar:
4950 fcvtu(fpf, rd, rn, FPTieEven);
4951 break;
4952 case NEON_FCVTPS_scalar:
4953 fcvts(fpf, rd, rn, FPPositiveInfinity);
4954 break;
4955 case NEON_FCVTPU_scalar:
4956 fcvtu(fpf, rd, rn, FPPositiveInfinity);
4957 break;
4958 case NEON_FCVTMS_scalar:
4959 fcvts(fpf, rd, rn, FPNegativeInfinity);
4960 break;
4961 case NEON_FCVTMU_scalar:
4962 fcvtu(fpf, rd, rn, FPNegativeInfinity);
4963 break;
4964 case NEON_FCVTZS_scalar:
4965 fcvts(fpf, rd, rn, FPZero);
4966 break;
4967 case NEON_FCVTZU_scalar:
4968 fcvtu(fpf, rd, rn, FPZero);
4969 break;
4970 case NEON_FCVTAS_scalar:
4971 fcvts(fpf, rd, rn, FPTieAway);
4972 break;
4973 case NEON_FCVTAU_scalar:
4974 fcvtu(fpf, rd, rn, FPTieAway);
4975 break;
4976 case NEON_FCVTXN_scalar:
4977 // Unlike all of the other FP instructions above, fcvtxn encodes dest
4978 // size S as size<0>=1. There's only one case, so we ignore the form.
4979 DCHECK_EQ(instr->Bit(22), 1);
4980 fcvtxn(kFormatS, rd, rn);
4981 break;
4982 default:
4983 switch (instr->Mask(NEONScalar2RegMiscMask)) {
4984 case NEON_SQXTN_scalar:
4985 sqxtn(vf, rd, rn);
4986 break;
4987 case NEON_UQXTN_scalar:
4988 uqxtn(vf, rd, rn);
4989 break;
4990 case NEON_SQXTUN_scalar:
4991 sqxtun(vf, rd, rn);
4992 break;
4993 default:
4994 UNIMPLEMENTED();
4995 }
4996 }
4997 }
4998 }
4999
5000 void Simulator::VisitNEONScalar3Diff(Instruction* instr) {
5001 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
5002 VectorFormat vf = nfd.GetVectorFormat();
5003
5004 SimVRegister& rd = vreg(instr->Rd());
5005 SimVRegister& rn = vreg(instr->Rn());
5006 SimVRegister& rm = vreg(instr->Rm());
5007 switch (instr->Mask(NEONScalar3DiffMask)) {
5008 case NEON_SQDMLAL_scalar:
5009 sqdmlal(vf, rd, rn, rm);
5010 break;
5011 case NEON_SQDMLSL_scalar:
5012 sqdmlsl(vf, rd, rn, rm);
5013 break;
5014 case NEON_SQDMULL_scalar:
5015 sqdmull(vf, rd, rn, rm);
5016 break;
5017 default:
5018 UNIMPLEMENTED();
5019 }
5020 }
5021
5022 void Simulator::VisitNEONScalar3Same(Instruction* instr) {
5023 NEONFormatDecoder nfd(instr, NEONFormatDecoder::ScalarFormatMap());
5024 VectorFormat vf = nfd.GetVectorFormat();
5025
5026 SimVRegister& rd = vreg(instr->Rd());
5027 SimVRegister& rn = vreg(instr->Rn());
5028 SimVRegister& rm = vreg(instr->Rm());
5029
5030 if (instr->Mask(NEONScalar3SameFPFMask) == NEONScalar3SameFPFixed) {
5031 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
5032 switch (instr->Mask(NEONScalar3SameFPMask)) {
5033 case NEON_FMULX_scalar:
5034 fmulx(vf, rd, rn, rm);
5035 break;
5036 case NEON_FACGE_scalar:
5037 fabscmp(vf, rd, rn, rm, ge);
5038 break;
5039 case NEON_FACGT_scalar:
5040 fabscmp(vf, rd, rn, rm, gt);
5041 break;
5042 case NEON_FCMEQ_scalar:
5043 fcmp(vf, rd, rn, rm, eq);
5044 break;
5045 case NEON_FCMGE_scalar:
5046 fcmp(vf, rd, rn, rm, ge);
5047 break;
5048 case NEON_FCMGT_scalar:
5049 fcmp(vf, rd, rn, rm, gt);
5050 break;
5051 case NEON_FRECPS_scalar:
5052 frecps(vf, rd, rn, rm);
5053 break;
5054 case NEON_FRSQRTS_scalar:
5055 frsqrts(vf, rd, rn, rm);
5056 break;
5057 case NEON_FABD_scalar:
5058 fabd(vf, rd, rn, rm);
5059 break;
5060 default:
5061 UNIMPLEMENTED();
5062 }
5063 } else {
5064 switch (instr->Mask(NEONScalar3SameMask)) {
5065 case NEON_ADD_scalar:
5066 add(vf, rd, rn, rm);
5067 break;
5068 case NEON_SUB_scalar:
5069 sub(vf, rd, rn, rm);
5070 break;
5071 case NEON_CMEQ_scalar:
5072 cmp(vf, rd, rn, rm, eq);
5073 break;
5074 case NEON_CMGE_scalar:
5075 cmp(vf, rd, rn, rm, ge);
5076 break;
5077 case NEON_CMGT_scalar:
5078 cmp(vf, rd, rn, rm, gt);
5079 break;
5080 case NEON_CMHI_scalar:
5081 cmp(vf, rd, rn, rm, hi);
5082 break;
5083 case NEON_CMHS_scalar:
5084 cmp(vf, rd, rn, rm, hs);
5085 break;
5086 case NEON_CMTST_scalar:
5087 cmptst(vf, rd, rn, rm);
5088 break;
5089 case NEON_USHL_scalar:
5090 ushl(vf, rd, rn, rm);
5091 break;
5092 case NEON_SSHL_scalar:
5093 sshl(vf, rd, rn, rm);
5094 break;
5095 case NEON_SQDMULH_scalar:
5096 sqdmulh(vf, rd, rn, rm);
5097 break;
5098 case NEON_SQRDMULH_scalar:
5099 sqrdmulh(vf, rd, rn, rm);
5100 break;
5101 case NEON_UQADD_scalar:
5102 add(vf, rd, rn, rm).UnsignedSaturate(vf);
5103 break;
5104 case NEON_SQADD_scalar:
5105 add(vf, rd, rn, rm).SignedSaturate(vf);
5106 break;
5107 case NEON_UQSUB_scalar:
5108 sub(vf, rd, rn, rm).UnsignedSaturate(vf);
5109 break;
5110 case NEON_SQSUB_scalar:
5111 sub(vf, rd, rn, rm).SignedSaturate(vf);
5112 break;
5113 case NEON_UQSHL_scalar:
5114 ushl(vf, rd, rn, rm).UnsignedSaturate(vf);
5115 break;
5116 case NEON_SQSHL_scalar:
5117 sshl(vf, rd, rn, rm).SignedSaturate(vf);
5118 break;
5119 case NEON_URSHL_scalar:
5120 ushl(vf, rd, rn, rm).Round(vf);
5121 break;
5122 case NEON_SRSHL_scalar:
5123 sshl(vf, rd, rn, rm).Round(vf);
5124 break;
5125 case NEON_UQRSHL_scalar:
5126 ushl(vf, rd, rn, rm).Round(vf).UnsignedSaturate(vf);
5127 break;
5128 case NEON_SQRSHL_scalar:
5129 sshl(vf, rd, rn, rm).Round(vf).SignedSaturate(vf);
5130 break;
5131 default:
5132 UNIMPLEMENTED();
5133 }
5134 }
5135 }
5136
5137 void Simulator::VisitNEONScalarByIndexedElement(Instruction* instr) {
5138 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LongScalarFormatMap());
5139 VectorFormat vf = nfd.GetVectorFormat();
5140 VectorFormat vf_r = nfd.GetVectorFormat(nfd.ScalarFormatMap());
5141
5142 SimVRegister& rd = vreg(instr->Rd());
5143 SimVRegister& rn = vreg(instr->Rn());
5144 ByElementOp Op = NULL;
5145
5146 int rm_reg = instr->Rm();
5147 int index = (instr->NEONH() << 1) | instr->NEONL();
5148 if (instr->NEONSize() == 1) {
5149 rm_reg &= 0xf;
5150 index = (index << 1) | instr->NEONM();
5151 }
5152
5153 switch (instr->Mask(NEONScalarByIndexedElementMask)) {
5154 case NEON_SQDMULL_byelement_scalar:
5155 Op = &Simulator::sqdmull;
5156 break;
5157 case NEON_SQDMLAL_byelement_scalar:
5158 Op = &Simulator::sqdmlal;
5159 break;
5160 case NEON_SQDMLSL_byelement_scalar:
5161 Op = &Simulator::sqdmlsl;
5162 break;
5163 case NEON_SQDMULH_byelement_scalar:
5164 Op = &Simulator::sqdmulh;
5165 vf = vf_r;
5166 break;
5167 case NEON_SQRDMULH_byelement_scalar:
5168 Op = &Simulator::sqrdmulh;
5169 vf = vf_r;
5170 break;
5171 default:
5172 vf = nfd.GetVectorFormat(nfd.FPScalarFormatMap());
5173 index = instr->NEONH();
5174 if ((instr->FPType() & 1) == 0) {
5175 index = (index << 1) | instr->NEONL();
5176 }
5177 switch (instr->Mask(NEONScalarByIndexedElementFPMask)) {
5178 case NEON_FMUL_byelement_scalar:
5179 Op = &Simulator::fmul;
5180 break;
5181 case NEON_FMLA_byelement_scalar:
5182 Op = &Simulator::fmla;
5183 break;
5184 case NEON_FMLS_byelement_scalar:
5185 Op = &Simulator::fmls;
5186 break;
5187 case NEON_FMULX_byelement_scalar:
5188 Op = &Simulator::fmulx;
5189 break;
5190 default:
5191 UNIMPLEMENTED();
5192 }
5193 }
5194
5195 (this->*Op)(vf, rd, rn, vreg(rm_reg), index);
5196 }
5197
5198 void Simulator::VisitNEONScalarCopy(Instruction* instr) {
5199 NEONFormatDecoder nfd(instr, NEONFormatDecoder::TriangularScalarFormatMap());
5200 VectorFormat vf = nfd.GetVectorFormat();
5201
5202 SimVRegister& rd = vreg(instr->Rd());
5203 SimVRegister& rn = vreg(instr->Rn());
5204
5205 if (instr->Mask(NEONScalarCopyMask) == NEON_DUP_ELEMENT_scalar) {
5206 int imm5 = instr->ImmNEON5();
5207 int lsb = LowestSetBitPosition(imm5);
5208 int rn_index = imm5 >> lsb;
5209 dup_element(vf, rd, rn, rn_index);
5210 } else {
5211 UNIMPLEMENTED();
5212 }
5213 }
5214
5215 void Simulator::VisitNEONScalarPairwise(Instruction* instr) {
5216 NEONFormatDecoder nfd(instr, NEONFormatDecoder::FPScalarFormatMap());
5217 VectorFormat vf = nfd.GetVectorFormat();
5218
5219 SimVRegister& rd = vreg(instr->Rd());
5220 SimVRegister& rn = vreg(instr->Rn());
5221 switch (instr->Mask(NEONScalarPairwiseMask)) {
5222 case NEON_ADDP_scalar:
5223 addp(vf, rd, rn);
5224 break;
5225 case NEON_FADDP_scalar:
5226 faddp(vf, rd, rn);
5227 break;
5228 case NEON_FMAXP_scalar:
5229 fmaxp(vf, rd, rn);
5230 break;
5231 case NEON_FMAXNMP_scalar:
5232 fmaxnmp(vf, rd, rn);
5233 break;
5234 case NEON_FMINP_scalar:
5235 fminp(vf, rd, rn);
5236 break;
5237 case NEON_FMINNMP_scalar:
5238 fminnmp(vf, rd, rn);
5239 break;
5240 default:
5241 UNIMPLEMENTED();
5242 }
5243 }
5244
5245 void Simulator::VisitNEONScalarShiftImmediate(Instruction* instr) {
5246 SimVRegister& rd = vreg(instr->Rd());
5247 SimVRegister& rn = vreg(instr->Rn());
5248 FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
5249
5250 static const NEONFormatMap map = {
5251 {22, 21, 20, 19},
5252 {NF_UNDEF, NF_B, NF_H, NF_H, NF_S, NF_S, NF_S, NF_S, NF_D, NF_D, NF_D,
5253 NF_D, NF_D, NF_D, NF_D, NF_D}};
5254 NEONFormatDecoder nfd(instr, &map);
5255 VectorFormat vf = nfd.GetVectorFormat();
5256
5257 int highestSetBit = HighestSetBitPosition(instr->ImmNEONImmh());
5258 int immhimmb = instr->ImmNEONImmhImmb();
5259 int right_shift = (16 << highestSetBit) - immhimmb;
5260 int left_shift = immhimmb - (8 << highestSetBit);
5261 switch (instr->Mask(NEONScalarShiftImmediateMask)) {
5262 case NEON_SHL_scalar:
5263 shl(vf, rd, rn, left_shift);
5264 break;
5265 case NEON_SLI_scalar:
5266 sli(vf, rd, rn, left_shift);
5267 break;
5268 case NEON_SQSHL_imm_scalar:
5269 sqshl(vf, rd, rn, left_shift);
5270 break;
5271 case NEON_UQSHL_imm_scalar:
5272 uqshl(vf, rd, rn, left_shift);
5273 break;
5274 case NEON_SQSHLU_scalar:
5275 sqshlu(vf, rd, rn, left_shift);
5276 break;
5277 case NEON_SRI_scalar:
5278 sri(vf, rd, rn, right_shift);
5279 break;
5280 case NEON_SSHR_scalar:
5281 sshr(vf, rd, rn, right_shift);
5282 break;
5283 case NEON_USHR_scalar:
5284 ushr(vf, rd, rn, right_shift);
5285 break;
5286 case NEON_SRSHR_scalar:
5287 sshr(vf, rd, rn, right_shift).Round(vf);
5288 break;
5289 case NEON_URSHR_scalar:
5290 ushr(vf, rd, rn, right_shift).Round(vf);
5291 break;
5292 case NEON_SSRA_scalar:
5293 ssra(vf, rd, rn, right_shift);
5294 break;
5295 case NEON_USRA_scalar:
5296 usra(vf, rd, rn, right_shift);
5297 break;
5298 case NEON_SRSRA_scalar:
5299 srsra(vf, rd, rn, right_shift);
5300 break;
5301 case NEON_URSRA_scalar:
5302 ursra(vf, rd, rn, right_shift);
5303 break;
5304 case NEON_UQSHRN_scalar:
5305 uqshrn(vf, rd, rn, right_shift);
5306 break;
5307 case NEON_UQRSHRN_scalar:
5308 uqrshrn(vf, rd, rn, right_shift);
5309 break;
5310 case NEON_SQSHRN_scalar:
5311 sqshrn(vf, rd, rn, right_shift);
5312 break;
5313 case NEON_SQRSHRN_scalar:
5314 sqrshrn(vf, rd, rn, right_shift);
5315 break;
5316 case NEON_SQSHRUN_scalar:
5317 sqshrun(vf, rd, rn, right_shift);
5318 break;
5319 case NEON_SQRSHRUN_scalar:
5320 sqrshrun(vf, rd, rn, right_shift);
5321 break;
5322 case NEON_FCVTZS_imm_scalar:
5323 fcvts(vf, rd, rn, FPZero, right_shift);
5324 break;
5325 case NEON_FCVTZU_imm_scalar:
5326 fcvtu(vf, rd, rn, FPZero, right_shift);
5327 break;
5328 case NEON_SCVTF_imm_scalar:
5329 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
5330 break;
5331 case NEON_UCVTF_imm_scalar:
5332 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
5333 break;
5334 default:
5335 UNIMPLEMENTED();
5336 }
5337 }
5338
5339 void Simulator::VisitNEONShiftImmediate(Instruction* instr) {
5340 SimVRegister& rd = vreg(instr->Rd());
5341 SimVRegister& rn = vreg(instr->Rn());
5342 FPRounding fpcr_rounding = static_cast<FPRounding>(fpcr().RMode());
5343
5344 // 00010->8B, 00011->16B, 001x0->4H, 001x1->8H,
5345 // 01xx0->2S, 01xx1->4S, 1xxx1->2D, all others undefined.
5346 static const NEONFormatMap map = {
5347 {22, 21, 20, 19, 30},
5348 {NF_UNDEF, NF_UNDEF, NF_8B, NF_16B, NF_4H, NF_8H, NF_4H, NF_8H,
5349 NF_2S, NF_4S, NF_2S, NF_4S, NF_2S, NF_4S, NF_2S, NF_4S,
5350 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D,
5351 NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D, NF_UNDEF, NF_2D}};
5352 NEONFormatDecoder nfd(instr, &map);
5353 VectorFormat vf = nfd.GetVectorFormat();
5354
5355 // 0001->8H, 001x->4S, 01xx->2D, all others undefined.
5356 static const NEONFormatMap map_l = {
5357 {22, 21, 20, 19},
5358 {NF_UNDEF, NF_8H, NF_4S, NF_4S, NF_2D, NF_2D, NF_2D, NF_2D}};
5359 VectorFormat vf_l = nfd.GetVectorFormat(&map_l);
5360
5361 int highestSetBit = HighestSetBitPosition(instr->ImmNEONImmh());
5362 int immhimmb = instr->ImmNEONImmhImmb();
5363 int right_shift = (16 << highestSetBit) - immhimmb;
5364 int left_shift = immhimmb - (8 << highestSetBit);
5365
5366 switch (instr->Mask(NEONShiftImmediateMask)) {
5367 case NEON_SHL:
5368 shl(vf, rd, rn, left_shift);
5369 break;
5370 case NEON_SLI:
5371 sli(vf, rd, rn, left_shift);
5372 break;
5373 case NEON_SQSHLU:
5374 sqshlu(vf, rd, rn, left_shift);
5375 break;
5376 case NEON_SRI:
5377 sri(vf, rd, rn, right_shift);
5378 break;
5379 case NEON_SSHR:
5380 sshr(vf, rd, rn, right_shift);
5381 break;
5382 case NEON_USHR:
5383 ushr(vf, rd, rn, right_shift);
5384 break;
5385 case NEON_SRSHR:
5386 sshr(vf, rd, rn, right_shift).Round(vf);
5387 break;
5388 case NEON_URSHR:
5389 ushr(vf, rd, rn, right_shift).Round(vf);
5390 break;
5391 case NEON_SSRA:
5392 ssra(vf, rd, rn, right_shift);
5393 break;
5394 case NEON_USRA:
5395 usra(vf, rd, rn, right_shift);
5396 break;
5397 case NEON_SRSRA:
5398 srsra(vf, rd, rn, right_shift);
5399 break;
5400 case NEON_URSRA:
5401 ursra(vf, rd, rn, right_shift);
5402 break;
5403 case NEON_SQSHL_imm:
5404 sqshl(vf, rd, rn, left_shift);
5405 break;
5406 case NEON_UQSHL_imm:
5407 uqshl(vf, rd, rn, left_shift);
5408 break;
5409 case NEON_SCVTF_imm:
5410 scvtf(vf, rd, rn, right_shift, fpcr_rounding);
5411 break;
5412 case NEON_UCVTF_imm:
5413 ucvtf(vf, rd, rn, right_shift, fpcr_rounding);
5414 break;
5415 case NEON_FCVTZS_imm:
5416 fcvts(vf, rd, rn, FPZero, right_shift);
5417 break;
5418 case NEON_FCVTZU_imm:
5419 fcvtu(vf, rd, rn, FPZero, right_shift);
5420 break;
5421 case NEON_SSHLL:
5422 vf = vf_l;
5423 if (instr->Mask(NEON_Q)) {
5424 sshll2(vf, rd, rn, left_shift);
5425 } else {
5426 sshll(vf, rd, rn, left_shift);
5427 }
5428 break;
5429 case NEON_USHLL:
5430 vf = vf_l;
5431 if (instr->Mask(NEON_Q)) {
5432 ushll2(vf, rd, rn, left_shift);
5433 } else {
5434 ushll(vf, rd, rn, left_shift);
5435 }
5436 break;
5437 case NEON_SHRN:
5438 if (instr->Mask(NEON_Q)) {
5439 shrn2(vf, rd, rn, right_shift);
5440 } else {
5441 shrn(vf, rd, rn, right_shift);
5442 }
5443 break;
5444 case NEON_RSHRN:
5445 if (instr->Mask(NEON_Q)) {
5446 rshrn2(vf, rd, rn, right_shift);
5447 } else {
5448 rshrn(vf, rd, rn, right_shift);
5449 }
5450 break;
5451 case NEON_UQSHRN:
5452 if (instr->Mask(NEON_Q)) {
5453 uqshrn2(vf, rd, rn, right_shift);
5454 } else {
5455 uqshrn(vf, rd, rn, right_shift);
5456 }
5457 break;
5458 case NEON_UQRSHRN:
5459 if (instr->Mask(NEON_Q)) {
5460 uqrshrn2(vf, rd, rn, right_shift);
5461 } else {
5462 uqrshrn(vf, rd, rn, right_shift);
5463 }
5464 break;
5465 case NEON_SQSHRN:
5466 if (instr->Mask(NEON_Q)) {
5467 sqshrn2(vf, rd, rn, right_shift);
5468 } else {
5469 sqshrn(vf, rd, rn, right_shift);
5470 }
5471 break;
5472 case NEON_SQRSHRN:
5473 if (instr->Mask(NEON_Q)) {
5474 sqrshrn2(vf, rd, rn, right_shift);
5475 } else {
5476 sqrshrn(vf, rd, rn, right_shift);
5477 }
5478 break;
5479 case NEON_SQSHRUN:
5480 if (instr->Mask(NEON_Q)) {
5481 sqshrun2(vf, rd, rn, right_shift);
5482 } else {
5483 sqshrun(vf, rd, rn, right_shift);
5484 }
5485 break;
5486 case NEON_SQRSHRUN:
5487 if (instr->Mask(NEON_Q)) {
5488 sqrshrun2(vf, rd, rn, right_shift);
5489 } else {
5490 sqrshrun(vf, rd, rn, right_shift);
5491 }
5492 break;
5493 default:
5494 UNIMPLEMENTED();
5495 }
5496 }
5497
5498 void Simulator::VisitNEONTable(Instruction* instr) {
5499 NEONFormatDecoder nfd(instr, NEONFormatDecoder::LogicalFormatMap());
5500 VectorFormat vf = nfd.GetVectorFormat();
5501
5502 SimVRegister& rd = vreg(instr->Rd());
5503 SimVRegister& rn = vreg(instr->Rn());
5504 SimVRegister& rn2 = vreg((instr->Rn() + 1) % kNumberOfVRegisters);
5505 SimVRegister& rn3 = vreg((instr->Rn() + 2) % kNumberOfVRegisters);
5506 SimVRegister& rn4 = vreg((instr->Rn() + 3) % kNumberOfVRegisters);
5507 SimVRegister& rm = vreg(instr->Rm());
5508
5509 switch (instr->Mask(NEONTableMask)) {
5510 case NEON_TBL_1v:
5511 tbl(vf, rd, rn, rm);
5512 break;
5513 case NEON_TBL_2v:
5514 tbl(vf, rd, rn, rn2, rm);
5515 break;
5516 case NEON_TBL_3v:
5517 tbl(vf, rd, rn, rn2, rn3, rm);
5518 break;
5519 case NEON_TBL_4v:
5520 tbl(vf, rd, rn, rn2, rn3, rn4, rm);
5521 break;
5522 case NEON_TBX_1v:
5523 tbx(vf, rd, rn, rm);
5524 break;
5525 case NEON_TBX_2v:
5526 tbx(vf, rd, rn, rn2, rm);
5527 break;
5528 case NEON_TBX_3v:
5529 tbx(vf, rd, rn, rn2, rn3, rm);
5530 break;
5531 case NEON_TBX_4v:
5532 tbx(vf, rd, rn, rn2, rn3, rn4, rm);
5533 break;
5534 default:
5535 UNIMPLEMENTED();
5536 }
5537 }
5538
5539 void Simulator::VisitNEONPerm(Instruction* instr) {
5540 NEONFormatDecoder nfd(instr);
5541 VectorFormat vf = nfd.GetVectorFormat();
5542
5543 SimVRegister& rd = vreg(instr->Rd());
5544 SimVRegister& rn = vreg(instr->Rn());
5545 SimVRegister& rm = vreg(instr->Rm());
5546
5547 switch (instr->Mask(NEONPermMask)) {
5548 case NEON_TRN1:
5549 trn1(vf, rd, rn, rm);
5550 break;
5551 case NEON_TRN2:
5552 trn2(vf, rd, rn, rm);
5553 break;
5554 case NEON_UZP1:
5555 uzp1(vf, rd, rn, rm);
5556 break;
5557 case NEON_UZP2:
5558 uzp2(vf, rd, rn, rm);
5559 break;
5560 case NEON_ZIP1:
5561 zip1(vf, rd, rn, rm);
5562 break;
5563 case NEON_ZIP2:
5564 zip2(vf, rd, rn, rm);
5565 break;
5566 default:
5567 UNIMPLEMENTED();
5568 }
5569 }
3754 5570
3755 void Simulator::DoPrintf(Instruction* instr) { 5571 void Simulator::DoPrintf(Instruction* instr) {
3756 DCHECK((instr->Mask(ExceptionMask) == HLT) && 5572 DCHECK((instr->Mask(ExceptionMask) == HLT) &&
3757 (instr->ImmException() == kImmExceptionIsPrintf)); 5573 (instr->ImmException() == kImmExceptionIsPrintf));
3758 5574
3759 // Read the arguments encoded inline in the instruction stream. 5575 // Read the arguments encoded inline in the instruction stream.
3760 uint32_t arg_count; 5576 uint32_t arg_count;
3761 uint32_t arg_pattern_list; 5577 uint32_t arg_pattern_list;
3762 STATIC_ASSERT(sizeof(*instr) == 1); 5578 STATIC_ASSERT(sizeof(*instr) == 1);
3763 memcpy(&arg_count, 5579 memcpy(&arg_count,
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
3877 delete[] format; 5693 delete[] format;
3878 } 5694 }
3879 5695
3880 5696
3881 #endif // USE_SIMULATOR 5697 #endif // USE_SIMULATOR
3882 5698
3883 } // namespace internal 5699 } // namespace internal
3884 } // namespace v8 5700 } // namespace v8
3885 5701
3886 #endif // V8_TARGET_ARCH_ARM64 5702 #endif // V8_TARGET_ARCH_ARM64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698