OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
6 #if defined(TARGET_ARCH_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
(...skipping 2015 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2026 const ARMVersion version = TargetCPUFeatures::arm_version(); | 2026 const ARMVersion version = TargetCPUFeatures::arm_version(); |
2027 if ((version == ARMv5TE) || (version == ARMv6)) { | 2027 if ((version == ARMv5TE) || (version == ARMv6)) { |
2028 BindARMv6(label); | 2028 BindARMv6(label); |
2029 } else { | 2029 } else { |
2030 ASSERT(version == ARMv7); | 2030 ASSERT(version == ARMv7); |
2031 BindARMv7(label); | 2031 BindARMv7(label); |
2032 } | 2032 } |
2033 } | 2033 } |
2034 | 2034 |
2035 | 2035 |
2036 bool Address::CanHoldLoadOffset(OperandSize type, | 2036 OperandSize Address::OperandSizeFor(intptr_t cid) { |
| 2037 switch (cid) { |
| 2038 case kArrayCid: |
| 2039 case kImmutableArrayCid: |
| 2040 return kWord; |
| 2041 case kOneByteStringCid: |
| 2042 return kByte; |
| 2043 case kTwoByteStringCid: |
| 2044 return kHalfword; |
| 2045 case kTypedDataInt8ArrayCid: |
| 2046 return kByte; |
| 2047 case kTypedDataUint8ArrayCid: |
| 2048 case kTypedDataUint8ClampedArrayCid: |
| 2049 case kExternalTypedDataUint8ArrayCid: |
| 2050 case kExternalTypedDataUint8ClampedArrayCid: |
| 2051 return kUnsignedByte; |
| 2052 case kTypedDataInt16ArrayCid: |
| 2053 return kHalfword; |
| 2054 case kTypedDataUint16ArrayCid: |
| 2055 return kUnsignedHalfword; |
| 2056 case kTypedDataInt32ArrayCid: |
| 2057 return kWord; |
| 2058 case kTypedDataUint32ArrayCid: |
| 2059 return kUnsignedWord; |
| 2060 case kTypedDataInt64ArrayCid: |
| 2061 case kTypedDataUint64ArrayCid: |
| 2062 UNREACHABLE(); |
| 2063 return kByte; |
| 2064 case kTypedDataFloat32ArrayCid: |
| 2065 return kSWord; |
| 2066 case kTypedDataFloat64ArrayCid: |
| 2067 return kDWord; |
| 2068 case kTypedDataFloat32x4ArrayCid: |
| 2069 case kTypedDataInt32x4ArrayCid: |
| 2070 case kTypedDataFloat64x2ArrayCid: |
| 2071 return kRegList; |
| 2072 case kTypedDataInt8ArrayViewCid: |
| 2073 UNREACHABLE(); |
| 2074 return kByte; |
| 2075 default: |
| 2076 UNREACHABLE(); |
| 2077 return kByte; |
| 2078 } |
| 2079 } |
| 2080 |
| 2081 |
| 2082 bool Address::CanHoldLoadOffset(OperandSize size, |
2037 int32_t offset, | 2083 int32_t offset, |
2038 int32_t* offset_mask) { | 2084 int32_t* offset_mask) { |
2039 switch (type) { | 2085 switch (size) { |
2040 case kByte: | 2086 case kByte: |
2041 case kHalfword: | 2087 case kHalfword: |
2042 case kUnsignedHalfword: | 2088 case kUnsignedHalfword: |
2043 case kWordPair: { | 2089 case kWordPair: { |
2044 *offset_mask = 0xff; | 2090 *offset_mask = 0xff; |
2045 return Utils::IsAbsoluteUint(8, offset); // Addressing mode 3. | 2091 return Utils::IsAbsoluteUint(8, offset); // Addressing mode 3. |
2046 } | 2092 } |
2047 case kUnsignedByte: | 2093 case kUnsignedByte: |
2048 case kWord: { | 2094 case kWord: |
| 2095 case kUnsignedWord: { |
2049 *offset_mask = 0xfff; | 2096 *offset_mask = 0xfff; |
2050 return Utils::IsAbsoluteUint(12, offset); // Addressing mode 2. | 2097 return Utils::IsAbsoluteUint(12, offset); // Addressing mode 2. |
2051 } | 2098 } |
2052 case kSWord: | 2099 case kSWord: |
2053 case kDWord: { | 2100 case kDWord: { |
2054 *offset_mask = 0x3fc; // Multiple of 4. | 2101 *offset_mask = 0x3fc; // Multiple of 4. |
2055 // VFP addressing mode. | 2102 // VFP addressing mode. |
2056 return (Utils::IsAbsoluteUint(10, offset) && Utils::IsAligned(offset, 4)); | 2103 return (Utils::IsAbsoluteUint(10, offset) && Utils::IsAligned(offset, 4)); |
2057 } | 2104 } |
| 2105 case kRegList: { |
| 2106 *offset_mask = 0x0; |
| 2107 return offset == 0; |
| 2108 } |
2058 default: { | 2109 default: { |
2059 UNREACHABLE(); | 2110 UNREACHABLE(); |
2060 return false; | 2111 return false; |
2061 } | 2112 } |
2062 } | 2113 } |
2063 } | 2114 } |
2064 | 2115 |
2065 | 2116 |
2066 bool Address::CanHoldStoreOffset(OperandSize type, | 2117 bool Address::CanHoldStoreOffset(OperandSize size, |
2067 int32_t offset, | 2118 int32_t offset, |
2068 int32_t* offset_mask) { | 2119 int32_t* offset_mask) { |
2069 switch (type) { | 2120 switch (size) { |
2070 case kHalfword: | 2121 case kHalfword: |
| 2122 case kUnsignedHalfword: |
2071 case kWordPair: { | 2123 case kWordPair: { |
2072 *offset_mask = 0xff; | 2124 *offset_mask = 0xff; |
2073 return Utils::IsAbsoluteUint(8, offset); // Addressing mode 3. | 2125 return Utils::IsAbsoluteUint(8, offset); // Addressing mode 3. |
2074 } | 2126 } |
2075 case kByte: | 2127 case kByte: |
2076 case kWord: { | 2128 case kUnsignedByte: |
| 2129 case kWord: |
| 2130 case kUnsignedWord: { |
2077 *offset_mask = 0xfff; | 2131 *offset_mask = 0xfff; |
2078 return Utils::IsAbsoluteUint(12, offset); // Addressing mode 2. | 2132 return Utils::IsAbsoluteUint(12, offset); // Addressing mode 2. |
2079 } | 2133 } |
2080 case kSWord: | 2134 case kSWord: |
2081 case kDWord: { | 2135 case kDWord: { |
2082 *offset_mask = 0x3fc; // Multiple of 4. | 2136 *offset_mask = 0x3fc; // Multiple of 4. |
2083 // VFP addressing mode. | 2137 // VFP addressing mode. |
2084 return (Utils::IsAbsoluteUint(10, offset) && Utils::IsAligned(offset, 4)); | 2138 return (Utils::IsAbsoluteUint(10, offset) && Utils::IsAligned(offset, 4)); |
2085 } | 2139 } |
| 2140 case kRegList: { |
| 2141 *offset_mask = 0x0; |
| 2142 return offset == 0; |
| 2143 } |
2086 default: { | 2144 default: { |
2087 UNREACHABLE(); | 2145 UNREACHABLE(); |
2088 return false; | 2146 return false; |
2089 } | 2147 } |
2090 } | 2148 } |
2091 } | 2149 } |
2092 | 2150 |
2093 | 2151 |
2094 void Assembler::Push(Register rd, Condition cond) { | 2152 void Assembler::Push(Register rd, Condition cond) { |
2095 str(rd, Address(SP, -kWordSize, Address::PreIndex), cond); | 2153 str(rd, Address(SP, -kWordSize, Address::PreIndex), cond); |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2347 // A scratch register and IP are needed to load an arbitrary double. | 2405 // A scratch register and IP are needed to load an arbitrary double. |
2348 ASSERT(scratch != kNoRegister); | 2406 ASSERT(scratch != kNoRegister); |
2349 int64_t imm64 = bit_cast<int64_t, double>(value); | 2407 int64_t imm64 = bit_cast<int64_t, double>(value); |
2350 LoadImmediate(IP, Utils::Low32Bits(imm64), cond); | 2408 LoadImmediate(IP, Utils::Low32Bits(imm64), cond); |
2351 LoadImmediate(scratch, Utils::High32Bits(imm64), cond); | 2409 LoadImmediate(scratch, Utils::High32Bits(imm64), cond); |
2352 vmovdrr(dd, IP, scratch, cond); | 2410 vmovdrr(dd, IP, scratch, cond); |
2353 } | 2411 } |
2354 } | 2412 } |
2355 | 2413 |
2356 | 2414 |
2357 void Assembler::LoadFromOffset(OperandSize type, | 2415 void Assembler::LoadFromOffset(OperandSize size, |
2358 Register reg, | 2416 Register reg, |
2359 Register base, | 2417 Register base, |
2360 int32_t offset, | 2418 int32_t offset, |
2361 Condition cond) { | 2419 Condition cond) { |
2362 int32_t offset_mask = 0; | 2420 int32_t offset_mask = 0; |
2363 if (!Address::CanHoldLoadOffset(type, offset, &offset_mask)) { | 2421 if (!Address::CanHoldLoadOffset(size, offset, &offset_mask)) { |
2364 ASSERT(base != IP); | 2422 ASSERT(base != IP); |
2365 AddImmediate(IP, base, offset & ~offset_mask, cond); | 2423 AddImmediate(IP, base, offset & ~offset_mask, cond); |
2366 base = IP; | 2424 base = IP; |
2367 offset = offset & offset_mask; | 2425 offset = offset & offset_mask; |
2368 } | 2426 } |
2369 switch (type) { | 2427 switch (size) { |
2370 case kByte: | 2428 case kByte: |
2371 ldrsb(reg, Address(base, offset), cond); | 2429 ldrsb(reg, Address(base, offset), cond); |
2372 break; | 2430 break; |
2373 case kUnsignedByte: | 2431 case kUnsignedByte: |
2374 ldrb(reg, Address(base, offset), cond); | 2432 ldrb(reg, Address(base, offset), cond); |
2375 break; | 2433 break; |
2376 case kHalfword: | 2434 case kHalfword: |
2377 ldrsh(reg, Address(base, offset), cond); | 2435 ldrsh(reg, Address(base, offset), cond); |
2378 break; | 2436 break; |
2379 case kUnsignedHalfword: | 2437 case kUnsignedHalfword: |
2380 ldrh(reg, Address(base, offset), cond); | 2438 ldrh(reg, Address(base, offset), cond); |
2381 break; | 2439 break; |
2382 case kWord: | 2440 case kWord: |
2383 ldr(reg, Address(base, offset), cond); | 2441 ldr(reg, Address(base, offset), cond); |
2384 break; | 2442 break; |
2385 case kWordPair: | 2443 case kWordPair: |
2386 ldrd(reg, Address(base, offset), cond); | 2444 ldrd(reg, Address(base, offset), cond); |
2387 break; | 2445 break; |
2388 default: | 2446 default: |
2389 UNREACHABLE(); | 2447 UNREACHABLE(); |
2390 } | 2448 } |
2391 } | 2449 } |
2392 | 2450 |
2393 | 2451 |
2394 void Assembler::StoreToOffset(OperandSize type, | 2452 void Assembler::StoreToOffset(OperandSize size, |
2395 Register reg, | 2453 Register reg, |
2396 Register base, | 2454 Register base, |
2397 int32_t offset, | 2455 int32_t offset, |
2398 Condition cond) { | 2456 Condition cond) { |
2399 int32_t offset_mask = 0; | 2457 int32_t offset_mask = 0; |
2400 if (!Address::CanHoldStoreOffset(type, offset, &offset_mask)) { | 2458 if (!Address::CanHoldStoreOffset(size, offset, &offset_mask)) { |
2401 ASSERT(reg != IP); | 2459 ASSERT(reg != IP); |
2402 ASSERT(base != IP); | 2460 ASSERT(base != IP); |
2403 AddImmediate(IP, base, offset & ~offset_mask, cond); | 2461 AddImmediate(IP, base, offset & ~offset_mask, cond); |
2404 base = IP; | 2462 base = IP; |
2405 offset = offset & offset_mask; | 2463 offset = offset & offset_mask; |
2406 } | 2464 } |
2407 switch (type) { | 2465 switch (size) { |
2408 case kByte: | 2466 case kByte: |
2409 strb(reg, Address(base, offset), cond); | 2467 strb(reg, Address(base, offset), cond); |
2410 break; | 2468 break; |
2411 case kHalfword: | 2469 case kHalfword: |
2412 strh(reg, Address(base, offset), cond); | 2470 strh(reg, Address(base, offset), cond); |
2413 break; | 2471 break; |
2414 case kWord: | 2472 case kWord: |
2415 str(reg, Address(base, offset), cond); | 2473 str(reg, Address(base, offset), cond); |
2416 break; | 2474 break; |
2417 case kWordPair: | 2475 case kWordPair: |
(...skipping 734 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3152 | 3210 |
3153 | 3211 |
3154 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 3212 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
3155 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); | 3213 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); |
3156 return fpu_reg_names[reg]; | 3214 return fpu_reg_names[reg]; |
3157 } | 3215 } |
3158 | 3216 |
3159 } // namespace dart | 3217 } // namespace dart |
3160 | 3218 |
3161 #endif // defined TARGET_ARCH_ARM | 3219 #endif // defined TARGET_ARCH_ARM |
OLD | NEW |