| OLD | NEW |
| 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 "vm/globals.h" | 5 #include "vm/globals.h" |
| 6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
| 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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", | 66 "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", |
| 67 "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", | 67 "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", |
| 68 }; | 68 }; |
| 69 | 69 |
| 70 | 70 |
| 71 const char* Assembler::FpuRegisterName(FpuRegister reg) { | 71 const char* Assembler::FpuRegisterName(FpuRegister reg) { |
| 72 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); | 72 ASSERT((0 <= reg) && (reg < kNumberOfFpuRegisters)); |
| 73 return fpu_reg_names[reg]; | 73 return fpu_reg_names[reg]; |
| 74 } | 74 } |
| 75 | 75 |
| 76 |
| 77 static int CountLeadingZeros(uint64_t value, int width) { |
| 78 ASSERT((width == 32) || (width == 64)); |
| 79 if (value == 0) { |
| 80 return width; |
| 81 } |
| 82 int count = 0; |
| 83 do { |
| 84 count++; |
| 85 } while (value >>= 1); |
| 86 return width - count; |
| 87 } |
| 88 |
| 89 |
| 90 static int CountOneBits(uint64_t value, int width) { |
| 91 // Mask out unused bits to ensure that they are not counted. |
| 92 value &= (0xffffffffffffffffUL >> (64-width)); |
| 93 |
| 94 value = ((value >> 1) & 0x5555555555555555) + (value & 0x5555555555555555); |
| 95 value = ((value >> 2) & 0x3333333333333333) + (value & 0x3333333333333333); |
| 96 value = ((value >> 4) & 0x0f0f0f0f0f0f0f0f) + (value & 0x0f0f0f0f0f0f0f0f); |
| 97 value = ((value >> 8) & 0x00ff00ff00ff00ff) + (value & 0x00ff00ff00ff00ff); |
| 98 value = ((value >> 16) & 0x0000ffff0000ffff) + (value & 0x0000ffff0000ffff); |
| 99 value = ((value >> 32) & 0x00000000ffffffff) + (value & 0x00000000ffffffff); |
| 100 |
| 101 return value; |
| 102 } |
| 103 |
| 104 |
| 105 // Test if a given value can be encoded in the immediate field of a logical |
| 106 // instruction. |
| 107 // If it can be encoded, the function returns true, and values pointed to by n, |
| 108 // imm_s and imm_r are updated with immediates encoded in the format required |
| 109 // by the corresponding fields in the logical instruction. |
| 110 // If it can't be encoded, the function returns false, and the operand is |
| 111 // undefined. |
| 112 bool Assembler::IsImmLogical(uint64_t value, uint8_t width, Operand* imm_op) { |
| 113 ASSERT(imm_op != NULL); |
| 114 ASSERT((width == kWRegSizeInBits) || (width == kXRegSizeInBits)); |
| 115 ASSERT((width == kXRegSizeInBits) || (value <= 0xffffffffUL)); |
| 116 uint8_t n = 0; |
| 117 uint8_t imm_s = 0; |
| 118 uint8_t imm_r = 0; |
| 119 |
| 120 // Logical immediates are encoded using parameters n, imm_s and imm_r using |
| 121 // the following table: |
| 122 // |
| 123 // N imms immr size S R |
| 124 // 1 ssssss rrrrrr 64 UInt(ssssss) UInt(rrrrrr) |
| 125 // 0 0sssss xrrrrr 32 UInt(sssss) UInt(rrrrr) |
| 126 // 0 10ssss xxrrrr 16 UInt(ssss) UInt(rrrr) |
| 127 // 0 110sss xxxrrr 8 UInt(sss) UInt(rrr) |
| 128 // 0 1110ss xxxxrr 4 UInt(ss) UInt(rr) |
| 129 // 0 11110s xxxxxr 2 UInt(s) UInt(r) |
| 130 // (s bits must not be all set) |
| 131 // |
| 132 // A pattern is constructed of size bits, where the least significant S+1 |
| 133 // bits are set. The pattern is rotated right by R, and repeated across a |
| 134 // 32 or 64-bit value, depending on destination register width. |
| 135 // |
| 136 // To test if an arbitrary immediate can be encoded using this scheme, an |
| 137 // iterative algorithm is used. |
| 138 |
| 139 // 1. If the value has all set or all clear bits, it can't be encoded. |
| 140 if ((value == 0) || (value == 0xffffffffffffffffULL) || |
| 141 ((width == kWRegSizeInBits) && (value == 0xffffffff))) { |
| 142 return false; |
| 143 } |
| 144 |
| 145 int lead_zero = CountLeadingZeros(value, width); |
| 146 int lead_one = CountLeadingZeros(~value, width); |
| 147 int trail_zero = Utils::CountTrailingZeros(value); |
| 148 int trail_one = Utils::CountTrailingZeros(~value); |
| 149 int set_bits = CountOneBits(value, width); |
| 150 |
| 151 // The fixed bits in the immediate s field. |
| 152 // If width == 64 (X reg), start at 0xFFFFFF80. |
| 153 // If width == 32 (W reg), start at 0xFFFFFFC0, as the iteration for 64-bit |
| 154 // widths won't be executed. |
| 155 int imm_s_fixed = (width == kXRegSizeInBits) ? -128 : -64; |
| 156 int imm_s_mask = 0x3F; |
| 157 |
| 158 for (;;) { |
| 159 // 2. If the value is two bits wide, it can be encoded. |
| 160 if (width == 2) { |
| 161 n = 0; |
| 162 imm_s = 0x3C; |
| 163 imm_r = (value & 3) - 1; |
| 164 *imm_op = Operand(n, imm_s, imm_r); |
| 165 return true; |
| 166 } |
| 167 |
| 168 n = (width == 64) ? 1 : 0; |
| 169 imm_s = ((imm_s_fixed | (set_bits - 1)) & imm_s_mask); |
| 170 if ((lead_zero + set_bits) == width) { |
| 171 imm_r = 0; |
| 172 } else { |
| 173 imm_r = (lead_zero > 0) ? (width - trail_zero) : lead_one; |
| 174 } |
| 175 |
| 176 // 3. If the sum of leading zeros, trailing zeros and set bits is equal to |
| 177 // the bit width of the value, it can be encoded. |
| 178 if (lead_zero + trail_zero + set_bits == width) { |
| 179 *imm_op = Operand(n, imm_s, imm_r); |
| 180 return true; |
| 181 } |
| 182 |
| 183 // 4. If the sum of leading ones, trailing ones and unset bits in the |
| 184 // value is equal to the bit width of the value, it can be encoded. |
| 185 if (lead_one + trail_one + (width - set_bits) == width) { |
| 186 *imm_op = Operand(n, imm_s, imm_r); |
| 187 return true; |
| 188 } |
| 189 |
| 190 // 5. If the most-significant half of the bitwise value is equal to the |
| 191 // least-significant half, return to step 2 using the least-significant |
| 192 // half of the value. |
| 193 uint64_t mask = (1UL << (width >> 1)) - 1; |
| 194 if ((value & mask) == ((value >> (width >> 1)) & mask)) { |
| 195 width >>= 1; |
| 196 set_bits >>= 1; |
| 197 imm_s_fixed >>= 1; |
| 198 continue; |
| 199 } |
| 200 |
| 201 // 6. Otherwise, the value can't be encoded. |
| 202 return false; |
| 203 } |
| 204 } |
| 205 |
| 76 } // namespace dart | 206 } // namespace dart |
| 77 | 207 |
| 78 #endif // defined TARGET_ARCH_ARM64 | 208 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |