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

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

Issue 231373003: Adds logical operations to arm64. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 8 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
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 "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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698