Chromium Code Reviews| Index: src/arm/assembler-arm.cc |
| =================================================================== |
| --- src/arm/assembler-arm.cc (revision 14076) |
| +++ src/arm/assembler-arm.cc (working copy) |
| @@ -154,6 +154,11 @@ |
| } |
| #else // __arm__ |
| + if (!IsSupported(NEON) && OS::ArmCpuHasFeature(NEON)) { |
| + found_by_runtime_probing_only_ |= |
| + static_cast<uint64_t>(1) << NEON; |
| + } |
| + |
| // Probe for additional features not already known to be available. |
| if (!IsSupported(VFP3) && OS::ArmCpuHasFeature(VFP3)) { |
| // This implementation also sets the VFP flags if runtime |
| @@ -1597,7 +1602,17 @@ |
| addrmod4(cond | B27 | am, base, src); |
| } |
| +void Assembler::pld(Register base, int offset, int write) { |
|
hans
2013/04/02 12:34:29
Many of the newly added functions to the assembler
Nike
2013/04/03 15:04:06
Done.
Nike
2013/04/03 15:04:06
Done description, is it OK to make simulator+test
hans
2013/04/04 09:56:51
Thanks! This makes it much easier to verify the co
|
| + int U = (offset >= 0) ? B23 : 0; |
|
hans
2013/04/02 12:34:29
looks like indentation is too deep in this functio
Nike
2013/04/03 15:04:06
Done.
|
| + int R = (write == 0) ? B22 : 0; |
|
hans
2013/04/02 12:34:29
since write is just a flag, should it be a bool ra
Nike
2013/04/03 15:04:06
Done.
|
| + if (offset < 0) |
| + offset = -offset; |
| + ASSERT(is_uint12(offset)); |
| + emit(0xf510f000 | B16 * base.code() | U | R | offset); |
|
hans
2013/04/02 12:34:29
I think "base.code()*B16" would be more in line wi
Nike
2013/04/03 15:04:06
Done.
|
| +} |
| + |
| + |
| // Exception-generating instructions and debugging support. |
| // Stops with a non-negative code less than kNumOfWatchedStops support |
| // enabling/disabling and a counter feature. See simulator-arm.h . |
| @@ -2650,7 +2665,210 @@ |
| m*B5 | vm); |
| } |
|
hans
2013/04/02 12:34:29
v8 likes to have two empty lines between each func
Nike
2013/04/03 15:04:06
Done.
|
| +static inline int bin_log(int x) { |
| + switch (x) { |
| + case 1: |
| + return 0; |
| + case 2: |
| + return 1; |
| + case 4: |
| + return 2; |
| + case 8: |
| + return 3; |
| + case 16: |
| + return 4; |
| + case 32: |
| + return 5; |
| + case 64: |
| + return 6; |
| + default: |
| + UNREACHABLE(); |
| + return 0; |
| + } |
| +} |
| +static inline int count_to_type(int count) { |
| + switch (count) { |
| + case 1: |
| + return 7; |
| + case 2: |
| + return 10; |
| + case 3: |
| + return 6; |
| + case 4: |
| + return 2; |
| + default: |
| + UNREACHABLE(); |
| + return 0; |
| + } |
| +} |
| + |
| +enum NeonElementType { |
| + MultipleElements = 0, |
| + SingleElement = 1 |
| +}; |
| + |
| +enum NeonLoadStoreType { |
| + Store = 0, |
| + Load = 1 |
| +}; |
| + |
| +static uint32_t neon_vector_op(int size, |
| + const Register base, |
| + const DwVfpRegister first, |
| + NeonWritebackType writeback, |
| + int align_bytes, |
| + NeonLoadStoreType load, |
| + NeonElementType single, |
| + NeonElementIndex element_index, |
| + int type) { |
| + ASSERT(type >= 0); |
| + ASSERT(!base.is(pc)); |
| + ASSERT(size == 8 || size == 16 || size == 32); |
| + |
| + int d = (first.code() >> 4) & 1; |
| + int Vd = first.code() & 0xf; |
|
hans
2013/04/02 12:34:29
I think it's nicer to use DwVfpRegister::split to
Nike
2013/04/03 15:04:06
Done.
|
| + // we don't need arbitrary Rm so far |
|
hans
2013/04/02 12:34:29
nit: comments should ideally start with a capital
Nike
2013/04/03 15:04:06
Done.
|
| + int rm = (writeback == Writeback) ? 13 : 15; |
| + int size_enc = bin_log(size) - 3; |
|
hans
2013/04/02 12:34:29
Since size_enc isn't going to be used until furthe
Nike
2013/04/03 15:04:06
Done.
|
| + uint32_t result = |
| + (0xf << 28) | B26 | B22*d | B21*load | B16*base.code() | |
|
hans
2013/04/02 12:34:29
Instead of "0xf << 28", 0xf*B28 would be more in l
Nike
2013/04/03 15:04:06
B22 done.
Using 0xf*B28 gives
error: integer over
|
| + B12*Vd | rm; |
| + |
| + int index_align = 0; |
| + if (single == SingleElement) { |
| + switch (align_bytes) { |
| + case 16: |
| + ASSERT(size == 32); |
| + ASSERT(element_index < element_2); |
| + index_align = 0x3 | ((element_index & 0x1) << 3); |
| + break; |
| + case 8: |
| + ASSERT(size == 16 || size == 32); |
| + ASSERT(element_index < element_4); |
| + index_align = 0x1 | ((element_index & 0x3) << 2); |
| + break; |
| + case 4: |
| + ASSERT(size == 8); |
| + index_align = (element_index & 0x7) << 1; |
| + break; |
| + case 1: |
| + index_align = 0; |
| + break; |
| + default: |
| + UNREACHABLE(); |
| + } |
| + } |
| + |
| + if (single == SingleElement) { |
| + result |= B23 | (1<<10)*size_enc | B9 | B8 | B4*index_align; |
| + } else { |
| + int align_enc = align_bytes == 1 ? 0 : bin_log(align_bytes / 4); |
| + result |= B8*type | B6*size_enc | B4*align_enc; |
| + } |
| + return result; |
| +} |
| + |
| +void Assembler::vld1(int size, |
| + const Register base, |
| + const DwVfpRegister first, |
| + const DwVfpRegister last, |
| + NeonWritebackType writeback, |
| + int align_bytes) { |
| + ASSERT(IsEnabled(NEON)); |
| + ASSERT_LE(first.code(), last.code()); |
| + int count = last.code() - first.code() + 1; |
| + ASSERT(count <= 4); |
| + emit(neon_vector_op(size, base, first, writeback, align_bytes, |
| + Load, MultipleElements, element_0, |
| + count_to_type(count))); |
| +} |
| + |
| +void Assembler::vld1(int size, |
| + const Register base, |
| + const DwVfpRegister first, |
| + NeonElementIndex element_index, |
| + NeonWritebackType writeback, |
| + int align_bytes) { |
| + ASSERT(IsEnabled(NEON)); |
| + emit(neon_vector_op(size, base, first, writeback, align_bytes, |
| + Load, SingleElement, element_index, 0)); |
| +} |
| + |
| +void Assembler::vst1(int size, |
| + const Register base, |
| + const DwVfpRegister first, |
| + const DwVfpRegister last, |
| + NeonWritebackType writeback, |
| + int align_bytes) { |
| + ASSERT(IsEnabled(NEON)); |
| + ASSERT_LE(first.code(), last.code()); |
| + int count = last.code() - first.code() + 1; |
| + ASSERT(count <= 4); |
| + emit(neon_vector_op(size, base, first, writeback, align_bytes, |
| + Store, MultipleElements, element_0, |
| + count_to_type(count))); |
| +} |
| + |
| +void Assembler::vst1(int size, |
| + const Register base, |
| + const DwVfpRegister first, |
| + NeonElementIndex element_index, |
| + NeonWritebackType writeback, |
| + int align_bytes) { |
| + ASSERT(IsEnabled(NEON)); |
| + emit(neon_vector_op(size, base, first, writeback, align_bytes, |
| + Store, SingleElement, element_index, 0)); |
| +} |
| + |
| +void Assembler::vld4(int size, |
| + const Register base, |
| + const DwVfpRegister first, |
| + const DwVfpRegister last, |
| + NeonWritebackType writeback, |
| + int align_bytes) { |
| + ASSERT(IsEnabled(NEON)); |
| + // we don't support increment == 2, yet |
| + int type = 0; |
| + emit(neon_vector_op(size, base, first, writeback, align_bytes, |
| + Load, MultipleElements, element_0, type)); |
| +} |
| + |
| +void Assembler::vld4(int size, |
| + const Register base, |
| + const DwVfpRegister first, |
| + NeonElementIndex element_index, |
| + NeonWritebackType writeback, |
| + int align_bytes) { |
| + ASSERT(IsEnabled(NEON)); |
| + emit(neon_vector_op(size, base, first, writeback, align_bytes, |
| + Load, SingleElement, element_index, 0)); |
| +} |
| + |
| +void Assembler::vst4(int size, |
| + const Register base, |
| + const DwVfpRegister first, |
| + const DwVfpRegister last, |
| + NeonWritebackType writeback, |
| + int align_bytes) { |
| + ASSERT(IsEnabled(NEON)); |
| + // we don't support increment == 2, yet |
| + int type = 0; |
| + emit(neon_vector_op(size, base, first, writeback, align_bytes, |
| + Store, MultipleElements, element_0, type)); |
| +} |
| + |
| +void Assembler::vst4(int size, |
| + const Register base, |
| + const DwVfpRegister first, |
| + NeonElementIndex element_index, |
| + NeonWritebackType writeback, |
| + int align_bytes) { |
| + ASSERT(IsEnabled(NEON)); |
| + emit(neon_vector_op(size, base, first, writeback, align_bytes, |
| + Store, SingleElement, element_index, 0)); |
| +} |
| + |
| // Pseudo instructions. |
| void Assembler::nop(int type) { |
| // ARMv6{K/T2} and v7 have an actual NOP instruction but it serializes |