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

Side by Side Diff: runtime/vm/simulator_arm64.cc

Issue 269343010: Adds single-precision and SIMD load/store to arm64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/simulator_arm64.h ('k') | runtime/vm/stub_code_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 (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include <math.h> // for isnan. 5 #include <math.h> // for isnan.
6 #include <setjmp.h> 6 #include <setjmp.h>
7 #include <stdlib.h> 7 #include <stdlib.h>
8 8
9 #include "vm/globals.h" 9 #include "vm/globals.h"
10 #if defined(TARGET_ARCH_ARM64) 10 #if defined(TARGET_ARCH_ARM64)
(...skipping 598 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 int32_t Simulator::get_wregister(Register reg, R31Type r31t) const { 609 int32_t Simulator::get_wregister(Register reg, R31Type r31t) const {
610 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters)); 610 ASSERT((reg >= 0) && (reg < kNumberOfCpuRegisters));
611 if ((reg == R31) && (r31t == R31IsZR)) { 611 if ((reg == R31) && (r31t == R31IsZR)) {
612 return 0; 612 return 0;
613 } else { 613 } else {
614 return registers_[reg]; 614 return registers_[reg];
615 } 615 }
616 } 616 }
617 617
618 618
619 int64_t Simulator::get_vregisterd(VRegister reg) { 619 int64_t Simulator::get_vregisterd(VRegister reg) const {
620 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters)); 620 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters));
621 return vregisters_[reg].lo; 621 return vregisters_[reg].lo;
622 } 622 }
623 623
624 624
625 void Simulator::set_vregisterd(VRegister reg, int64_t value) { 625 void Simulator::set_vregisterd(VRegister reg, int64_t value) {
626 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters)); 626 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters));
627 vregisters_[reg].lo = value; 627 vregisters_[reg].lo = value;
628 vregisters_[reg].hi = 0; 628 vregisters_[reg].hi = 0;
629 } 629 }
630 630
631 631
632 void Simulator::get_vregister(VRegister reg, simd_value_t* value) const {
633 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters));
634 value->lo = vregisters_[reg].lo;
635 value->hi = vregisters_[reg].hi;
636 }
637
638
639 void Simulator::set_vregister(VRegister reg, const simd_value_t& value) {
640 ASSERT((reg >= 0) && (reg < kNumberOfVRegisters));
641 vregisters_[reg].lo = value.lo;
642 vregisters_[reg].hi = value.hi;
643 }
644
645
632 // Raw access to the PC register. 646 // Raw access to the PC register.
633 void Simulator::set_pc(int64_t value) { 647 void Simulator::set_pc(int64_t value) {
634 pc_modified_ = true; 648 pc_modified_ = true;
635 last_pc_ = pc_; 649 last_pc_ = pc_;
636 pc_ = value; 650 pc_ = value;
637 } 651 }
638 652
639 653
640 // Raw access to the pc. 654 // Raw access to the pc.
641 int64_t Simulator::get_pc() const { 655 int64_t Simulator::get_pc() const {
(...skipping 760 matching lines...) Expand 10 before | Expand all | Expand 10 after
1402 } 1416 }
1403 } 1417 }
1404 1418
1405 1419
1406 void Simulator::DecodeLoadStoreReg(Instr* instr) { 1420 void Simulator::DecodeLoadStoreReg(Instr* instr) {
1407 // Calculate the address. 1421 // Calculate the address.
1408 const Register rn = instr->RnField(); 1422 const Register rn = instr->RnField();
1409 const Register rt = instr->RtField(); 1423 const Register rt = instr->RtField();
1410 const VRegister vt = instr->VtField(); 1424 const VRegister vt = instr->VtField();
1411 const int64_t rn_val = get_register(rn, R31IsSP); 1425 const int64_t rn_val = get_register(rn, R31IsSP);
1412 const uint32_t size = instr->SzField(); 1426 const uint32_t size =
1427 (instr->Bit(26) == 1) ? ((instr->Bit(23) << 2) | instr->SzField())
1428 : instr->SzField();
1413 uword address = 0; 1429 uword address = 0;
1414 uword wb_address = 0; 1430 uword wb_address = 0;
1415 bool wb = false; 1431 bool wb = false;
1416 if (instr->Bit(24) == 1) { 1432 if (instr->Bit(24) == 1) {
1417 // addr = rn + scaled unsigned 12-bit immediate offset. 1433 // addr = rn + scaled unsigned 12-bit immediate offset.
1418 const uint32_t imm12 = static_cast<uint32_t>(instr->Imm12Field()); 1434 const uint32_t imm12 = static_cast<uint32_t>(instr->Imm12Field());
1419 const uint32_t offset = imm12 << size; 1435 const uint32_t offset = imm12 << size;
1420 address = rn_val + offset; 1436 address = rn_val + offset;
1421 } else if (instr->Bits(10, 2) == 0) { 1437 } else if (instr->Bits(10, 2) == 0) {
1422 // addr = rn + signed 9-bit immediate offset. 1438 // addr = rn + signed 9-bit immediate offset.
(...skipping 28 matching lines...) Expand all
1451 return; 1467 return;
1452 } 1468 }
1453 1469
1454 // Check the address. 1470 // Check the address.
1455 if (IsIllegalAddress(address)) { 1471 if (IsIllegalAddress(address)) {
1456 HandleIllegalAccess(address, instr); 1472 HandleIllegalAccess(address, instr);
1457 return; 1473 return;
1458 } 1474 }
1459 1475
1460 // Do access. 1476 // Do access.
1461 if (instr->Bits(22, 2) == 0) { 1477 if (instr->Bit(26) == 1) {
1462 if (instr->Bit(26) == 1) { 1478 if (instr->Bit(22) == 0) {
1463 // Format(instr, "vstrd 'vt, 'memop"); 1479 // Format(instr, "fstr'fsz 'vt, 'memop");
1464 if (size != 3) { 1480 const int64_t vt_val = get_vregisterd(vt);
1465 UnimplementedInstruction(instr); 1481 switch (size) {
1466 return; 1482 case 2:
1483 WriteW(address, vt_val & kWRegMask, instr);
1484 break;
1485 case 3:
1486 WriteX(address, vt_val, instr);
1487 break;
1488 case 4: {
1489 simd_value_t val;
1490 get_vregister(vt, &val);
1491 WriteX(address, val.lo, instr);
1492 WriteX(address + kWordSize, val.hi, instr);
1493 break;
1494 }
1495 default:
1496 UnimplementedInstruction(instr);
1497 return;
1467 } 1498 }
1468 const int64_t vt_val = get_vregisterd(vt);
1469 WriteX(address, vt_val, instr);
1470 } else { 1499 } else {
1500 // Format(instr, "fldr'fsz 'vt, 'memop");
1501 switch (size) {
1502 case 2:
1503 set_vregisterd(vt, static_cast<int64_t>(ReadWU(address, instr)));
1504 break;
1505 case 3:
1506 set_vregisterd(vt, ReadX(address, instr));
1507 break;
1508 case 4: {
1509 simd_value_t val;
1510 val.lo = ReadX(address, instr);
1511 val.hi = ReadX(address + kWordSize, instr);
1512 set_vregister(vt, val);
1513 break;
1514 }
1515 default:
1516 UnimplementedInstruction(instr);
1517 return;
1518 }
1519 }
1520 } else {
1521 if (instr->Bits(22, 2) == 0) {
1471 // Format(instr, "str'sz 'rt, 'memop"); 1522 // Format(instr, "str'sz 'rt, 'memop");
1472 const int32_t rt_val32 = get_wregister(rt, R31IsZR); 1523 const int32_t rt_val32 = get_wregister(rt, R31IsZR);
1473 switch (size) { 1524 switch (size) {
1474 case 0: { 1525 case 0: {
1475 const uint8_t val = static_cast<uint8_t>(rt_val32); 1526 const uint8_t val = static_cast<uint8_t>(rt_val32);
1476 WriteB(address, val); 1527 WriteB(address, val);
1477 break; 1528 break;
1478 } 1529 }
1479 case 1: { 1530 case 1: {
1480 const uint16_t val = static_cast<uint16_t>(rt_val32); 1531 const uint16_t val = static_cast<uint16_t>(rt_val32);
1481 WriteH(address, val, instr); 1532 WriteH(address, val, instr);
1482 break; 1533 break;
1483 } 1534 }
1484 case 2: { 1535 case 2: {
1485 const uint32_t val = static_cast<uint32_t>(rt_val32); 1536 const uint32_t val = static_cast<uint32_t>(rt_val32);
1486 WriteW(address, val, instr); 1537 WriteW(address, val, instr);
1487 break; 1538 break;
1488 } 1539 }
1489 case 3: { 1540 case 3: {
1490 const int64_t val = get_register(rt, R31IsZR); 1541 const int64_t val = get_register(rt, R31IsZR);
1491 WriteX(address, val, instr); 1542 WriteX(address, val, instr);
1492 break; 1543 break;
1493 } 1544 }
1494 default: 1545 default:
1495 UNREACHABLE(); 1546 UNREACHABLE();
1496 break; 1547 break;
1497 } 1548 }
1498 }
1499 } else {
1500 if (instr->Bit(26) == 1) {
1501 // Format(instr, "ldrd 'vt, 'memop");
1502 if ((size != 3) || (instr->Bit(23) != 0)) {
1503 UnimplementedInstruction(instr);
1504 return;
1505 }
1506 const int64_t val = ReadX(address, instr);
1507 set_vregisterd(vt, val);
1508 } else { 1549 } else {
1509 // Format(instr, "ldr'sz 'rt, 'memop"); 1550 // Format(instr, "ldr'sz 'rt, 'memop");
1510 // Undefined case. 1551 // Undefined case.
1511 if ((size == 3) && (instr->Bits(22, 2) == 3)) { 1552 if ((size == 3) && (instr->Bits(22, 2) == 3)) {
1512 UnimplementedInstruction(instr); 1553 UnimplementedInstruction(instr);
1513 return; 1554 return;
1514 } 1555 }
1515 1556
1516 // Read the value. 1557 // Read the value.
1517 const bool signd = instr->Bit(23) == 1; 1558 const bool signd = instr->Bit(23) == 1;
(...skipping 560 matching lines...) Expand 10 before | Expand all | Expand 10 after
2078 // Format(instr, "fcvtzds 'rd, 'vn"); 2119 // Format(instr, "fcvtzds 'rd, 'vn");
2079 const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn)); 2120 const double vn_val = bit_cast<double, int64_t>(get_vregisterd(vn));
2080 set_register(rd, static_cast<int64_t>(vn_val), instr->RdMode()); 2121 set_register(rd, static_cast<int64_t>(vn_val), instr->RdMode());
2081 } else { 2122 } else {
2082 UnimplementedInstruction(instr); 2123 UnimplementedInstruction(instr);
2083 } 2124 }
2084 } 2125 }
2085 2126
2086 2127
2087 void Simulator::DecodeFPOneSource(Instr* instr) { 2128 void Simulator::DecodeFPOneSource(Instr* instr) {
2088 const int opc = instr->Bits(15, 2); 2129 const int opc = instr->Bits(15, 6);
2089 const VRegister vd = instr->VdField(); 2130 const VRegister vd = instr->VdField();
2090 const VRegister vn = instr->VnField(); 2131 const VRegister vn = instr->VnField();
2091 const int64_t vn_val = get_vregisterd(vn); 2132 const int64_t vn_val = get_vregisterd(vn);
2133 const int32_t vn_val32 = vn_val & kWRegMask;
2092 const double vn_dbl = bit_cast<double, int64_t>(vn_val); 2134 const double vn_dbl = bit_cast<double, int64_t>(vn_val);
2135 const float vn_flt = bit_cast<float, int32_t>(vn_val32);
2136
2137 if ((opc != 5) && (instr->Bit(22) != 1)) {
2138 // Source is interpreted as single-precision only if we're doing a
2139 // conversion from single -> double.
2140 UnimplementedInstruction(instr);
2141 return;
2142 }
2093 2143
2094 int64_t res_val = 0; 2144 int64_t res_val = 0;
2095 switch (opc) { 2145 switch (opc) {
2096 case 0: 2146 case 0:
2097 // Format("fmovdd 'vd, 'vn"); 2147 // Format("fmovdd 'vd, 'vn");
2098 res_val = get_vregisterd(vn); 2148 res_val = get_vregisterd(vn);
2099 break; 2149 break;
2100 case 1: 2150 case 1:
2101 // Format("fabsd 'vd, 'vn"); 2151 // Format("fabsd 'vd, 'vn");
2102 res_val = bit_cast<int64_t, double>(fabs(vn_dbl)); 2152 res_val = bit_cast<int64_t, double>(fabs(vn_dbl));
2103 break; 2153 break;
2104 case 2: 2154 case 2:
2105 // Format("fnegd 'vd, 'vn"); 2155 // Format("fnegd 'vd, 'vn");
2106 res_val = bit_cast<int64_t, double>(-vn_dbl); 2156 res_val = bit_cast<int64_t, double>(-vn_dbl);
2107 break; 2157 break;
2108 case 3: 2158 case 3:
2109 // Format("fsqrtd 'vd, 'vn"); 2159 // Format("fsqrtd 'vd, 'vn");
2110 res_val = bit_cast<int64_t, double>(sqrt(vn_dbl)); 2160 res_val = bit_cast<int64_t, double>(sqrt(vn_dbl));
2111 break; 2161 break;
2162 case 4: {
2163 // Format(instr, "fcvtsd 'vd, 'vn");
2164 const uint32_t val =
2165 bit_cast<uint32_t, float>(static_cast<float>(vn_dbl));
2166 res_val = static_cast<int64_t>(val);
2167 break;
2168 }
2169 case 5:
2170 // Format(instr, "fcvtds 'vd, 'vn");
2171 res_val = bit_cast<int64_t, double>(static_cast<double>(vn_flt));
2172 break;
2112 default: 2173 default:
2113 UNREACHABLE(); 2174 UnimplementedInstruction(instr);
2114 break; 2175 break;
2115 } 2176 }
2116 2177
2117 set_vregisterd(vd, res_val); 2178 set_vregisterd(vd, res_val);
2118 } 2179 }
2119 2180
2120 2181
2121 void Simulator::DecodeFPTwoSource(Instr* instr) { 2182 void Simulator::DecodeFPTwoSource(Instr* instr) {
2122 if (instr->Bits(22, 2) != 1) { 2183 if (instr->Bits(22, 2) != 1) {
2123 UnimplementedInstruction(instr); 2184 UnimplementedInstruction(instr);
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after
2411 set_register(kExceptionObjectReg, bit_cast<int64_t>(raw_exception)); 2472 set_register(kExceptionObjectReg, bit_cast<int64_t>(raw_exception));
2412 set_register(kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace)); 2473 set_register(kStackTraceObjectReg, bit_cast<int64_t>(raw_stacktrace));
2413 buf->Longjmp(); 2474 buf->Longjmp();
2414 } 2475 }
2415 2476
2416 } // namespace dart 2477 } // namespace dart
2417 2478
2418 #endif // !defined(HOST_ARCH_ARM64) 2479 #endif // !defined(HOST_ARCH_ARM64)
2419 2480
2420 #endif // defined TARGET_ARCH_ARM64 2481 #endif // defined TARGET_ARCH_ARM64
OLDNEW
« no previous file with comments | « runtime/vm/simulator_arm64.h ('k') | runtime/vm/stub_code_arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698