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

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
« no previous file with comments | « runtime/vm/assembler_arm64.h ('k') | runtime/vm/assembler_arm64_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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) {
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
OLDNEW
« no previous file with comments | « runtime/vm/assembler_arm64.h ('k') | runtime/vm/assembler_arm64_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698