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

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

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

Powered by Google App Engine
This is Rietveld 408576698