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