5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include <stdlib.h>
26 #include "immediate_aarch64.hpp"
27
28 // there are at most 2^13 possible logical immediate encodings
29 // however, some combinations of immr and imms are invalid
30 static const unsigned LI_TABLE_SIZE = (1 << 13);
31
32 static int li_table_entry_count;
33
34 // for forward lookup we just use a direct array lookup
35 // and assume that the cient has supplied a valid encoding
36 // table[encoding] = immediate
37 static u_int64_t LITable[LI_TABLE_SIZE];
38
39 // for reverse lookup we need a sparse map so we store a table of
40 // immediate and encoding pairs sorted by immediate value
41
42 struct li_pair {
43 u_int64_t immediate;
44 u_int32_t encoding;
45 };
46
47 static struct li_pair InverseLITable[LI_TABLE_SIZE];
48
49 // comparator to sort entries in the inverse table
50 int compare_immediate_pair(const void *i1, const void *i2)
51 {
52 struct li_pair *li1 = (struct li_pair *)i1;
53 struct li_pair *li2 = (struct li_pair *)i2;
54 if (li1->immediate < li2->immediate) {
55 return -1;
56 }
57 if (li1->immediate > li2->immediate) {
58 return 1;
59 }
60 return 0;
61 }
62
63 // helper functions used by expandLogicalImmediate
64
65 // for i = 1, ... N result<i-1> = 1 other bits are zero
66 static inline u_int64_t ones(int N)
67 {
68 return (N == 64 ? (u_int64_t)-1UL : ((1UL << N) - 1));
69 }
70
71 /*
72 * bit twiddling helpers for instruction decode
73 */
74
75 // 32 bit mask with bits [hi,...,lo] set
76 static inline u_int32_t mask32(int hi = 31, int lo = 0)
77 {
78 int nbits = (hi + 1) - lo;
79 return ((1 << nbits) - 1) << lo;
80 }
81
82 static inline u_int64_t mask64(int hi = 63, int lo = 0)
83 {
84 int nbits = (hi + 1) - lo;
85 return ((1L << nbits) - 1) << lo;
86 }
87
88 // pick bits [hi,...,lo] from val
89 static inline u_int32_t pick32(u_int32_t val, int hi = 31, int lo = 0)
90 {
91 return (val & mask32(hi, lo));
92 }
93
94 // pick bits [hi,...,lo] from val
95 static inline u_int64_t pick64(u_int64_t val, int hi = 31, int lo = 0)
96 {
97 return (val & mask64(hi, lo));
98 }
99
100 // mask [hi,lo] and shift down to start at bit 0
101 static inline u_int32_t pickbits32(u_int32_t val, int hi = 31, int lo = 0)
102 {
103 return (pick32(val, hi, lo) >> lo);
104 }
105
106 // mask [hi,lo] and shift down to start at bit 0
107 static inline u_int64_t pickbits64(u_int64_t val, int hi = 63, int lo = 0)
108 {
109 return (pick64(val, hi, lo) >> lo);
110 }
111
112 // result<0> to val<N>
113 static inline u_int64_t pickbit(u_int64_t val, int N)
114 {
115 return pickbits64(val, N, N);
116 }
117
118 static inline u_int32_t uimm(u_int32_t val, int hi, int lo)
119 {
120 return pickbits32(val, hi, lo);
121 }
122
123 // SPEC bits(M*N) Replicate(bits(M) x, integer N);
124 // this is just an educated guess
125
126 u_int64_t replicate(u_int64_t bits, int nbits, int count)
127 {
128 u_int64_t result = 0;
129 // nbits may be 64 in which case we want mask to be -1
130 u_int64_t mask = ones(nbits);
131 for (int i = 0; i < count ; i++) {
132 result <<= nbits;
133 result |= (bits & mask);
134 }
135 return result;
136 }
137
138 // this function writes the supplied bimm reference and returns a
139 // boolean to indicate success (1) or fail (0) because an illegal
140 // encoding must be treated as an UNALLOC instruction
141
142 // construct a 32 bit immediate value for a logical immediate operation
143 int expandLogicalImmediate(u_int32_t immN, u_int32_t immr,
144 u_int32_t imms, u_int64_t &bimm)
145 {
146 int len; // ought to be <= 6
147 u_int32_t levels; // 6 bits
148 u_int32_t tmask_and; // 6 bits
149 u_int32_t wmask_and; // 6 bits
150 u_int32_t tmask_or; // 6 bits
151 u_int32_t wmask_or; // 6 bits
152 u_int64_t imm64; // 64 bits
153 u_int64_t tmask, wmask; // 64 bits
154 u_int32_t S, R, diff; // 6 bits?
155
156 if (immN == 1) {
157 len = 6; // looks like 7 given the spec above but this cannot be!
158 } else {
159 len = 0;
160 u_int32_t val = (~imms & 0x3f);
161 for (int i = 5; i > 0; i--) {
162 if (val & (1 << i)) {
163 len = i;
164 break;
165 }
166 }
167 if (len < 1) {
168 return 0;
169 }
170 // for valid inputs leading 1s in immr must be less than leading
171 // zeros in imms
172 int len2 = 0; // ought to be < len
173 u_int32_t val2 = (~immr & 0x3f);
174 for (int i = 5; i > 0; i--) {
175 if (!(val2 & (1 << i))) {
176 len2 = i;
177 break;
178 }
179 }
180 if (len2 >= len) {
181 return 0;
182 }
183 }
184
185 levels = (1 << len) - 1;
186
187 if ((imms & levels) == levels) {
188 return 0;
189 }
190
191 S = imms & levels;
192 R = immr & levels;
193
194 // 6 bit arithmetic!
195 diff = S - R;
196 tmask_and = (diff | ~levels) & 0x3f;
197 tmask_or = (diff & levels) & 0x3f;
198 tmask = 0xffffffffffffffffULL;
199
200 for (int i = 0; i < 6; i++) {
201 int nbits = 1 << i;
202 u_int64_t and_bit = pickbit(tmask_and, i);
203 u_int64_t or_bit = pickbit(tmask_or, i);
204 u_int64_t and_bits_sub = replicate(and_bit, 1, nbits);
205 u_int64_t or_bits_sub = replicate(or_bit, 1, nbits);
206 u_int64_t and_bits_top = (and_bits_sub << nbits) | ones(nbits);
207 u_int64_t or_bits_top = (0 << nbits) | or_bits_sub;
208
209 tmask = ((tmask
210 & (replicate(and_bits_top, 2 * nbits, 32 / nbits)))
211 | replicate(or_bits_top, 2 * nbits, 32 / nbits));
212 }
213
214 wmask_and = (immr | ~levels) & 0x3f;
215 wmask_or = (immr & levels) & 0x3f;
216
217 wmask = 0;
218
219 for (int i = 0; i < 6; i++) {
220 int nbits = 1 << i;
221 u_int64_t and_bit = pickbit(wmask_and, i);
222 u_int64_t or_bit = pickbit(wmask_or, i);
223 u_int64_t and_bits_sub = replicate(and_bit, 1, nbits);
224 u_int64_t or_bits_sub = replicate(or_bit, 1, nbits);
225 u_int64_t and_bits_top = (ones(nbits) << nbits) | and_bits_sub;
226 u_int64_t or_bits_top = (or_bits_sub << nbits) | 0;
227
228 wmask = ((wmask
229 & (replicate(and_bits_top, 2 * nbits, 32 / nbits)))
230 | replicate(or_bits_top, 2 * nbits, 32 / nbits));
231 }
232
233 if (diff & (1U << 6)) {
234 imm64 = tmask & wmask;
235 } else {
236 imm64 = tmask | wmask;
237 }
238
239
240 bimm = imm64;
241 return 1;
242 }
243
244 // constructor to initialise the lookup tables
245
246 static void initLITables() __attribute__ ((constructor));
247 static void initLITables()
248 {
249 li_table_entry_count = 0;
250 for (unsigned index = 0; index < LI_TABLE_SIZE; index++) {
251 u_int32_t N = uimm(index, 12, 12);
252 u_int32_t immr = uimm(index, 11, 6);
253 u_int32_t imms = uimm(index, 5, 0);
254 if (expandLogicalImmediate(N, immr, imms, LITable[index])) {
255 InverseLITable[li_table_entry_count].immediate = LITable[index];
256 InverseLITable[li_table_entry_count].encoding = index;
257 li_table_entry_count++;
258 }
259 }
260 // now sort the inverse table
261 qsort(InverseLITable, li_table_entry_count,
262 sizeof(InverseLITable[0]), compare_immediate_pair);
263 }
264
265 // public APIs provided for logical immediate lookup and reverse lookup
266
267 u_int64_t logical_immediate_for_encoding(u_int32_t encoding)
268 {
269 return LITable[encoding];
270 }
271
272 u_int32_t encoding_for_logical_immediate(u_int64_t immediate)
273 {
274 struct li_pair pair;
275 struct li_pair *result;
276
277 pair.immediate = immediate;
278
279 result = (struct li_pair *)
280 bsearch(&pair, InverseLITable, li_table_entry_count,
281 sizeof(InverseLITable[0]), compare_immediate_pair);
282
283 if (result) {
284 return result->encoding;
285 }
286
287 return 0xffffffff;
288 }
289
290 // floating point immediates are encoded in 8 bits
291 // fpimm[7] = sign bit
292 // fpimm[6:4] = signed exponent
293 // fpimm[3:0] = fraction (assuming leading 1)
294 // i.e. F = s * 1.f * 2^(e - b)
295
296 u_int64_t fp_immediate_for_encoding(u_int32_t imm8, int is_dp)
297 {
298 union {
299 float fpval;
300 double dpval;
301 u_int64_t val;
302 };
303
304 u_int32_t s, e, f;
305 s = (imm8 >> 7 ) & 0x1;
306 e = (imm8 >> 4) & 0x7;
307 f = imm8 & 0xf;
308 // the fp value is s * n/16 * 2r where n is 16+e
309 fpval = (16.0 + f) / 16.0;
310 // n.b. exponent is signed
311 if (e < 4) {
312 int epos = e;
313 for (int i = 0; i <= epos; i++) {
314 fpval *= 2.0;
315 }
316 } else {
317 int eneg = 7 - e;
318 for (int i = 0; i < eneg; i++) {
319 fpval /= 2.0;
320 }
321 }
322
323 if (s) {
324 fpval = -fpval;
325 }
326 if (is_dp) {
327 dpval = (double)fpval;
328 }
329 return val;
330 }
331
332 u_int32_t encoding_for_fp_immediate(float immediate)
333 {
334 // given a float which is of the form
335 //
336 // s * n/16 * 2r
337 //
338 // where n is 16+f and imm1:s, imm4:f, simm3:r
339 // return the imm8 result [s:r:f]
340 //
341
342 union {
343 float fpval;
344 u_int32_t val;
345 };
346 fpval = immediate;
347 u_int32_t s, r, f, res;
348 // sign bit is 31
349 s = (val >> 31) & 0x1;
350 // exponent is bits 30-23 but we only want the bottom 3 bits
351 // strictly we ought to check that the bits bits 30-25 are
352 // either all 1s or all 0s
353 r = (val >> 23) & 0x7;
354 // fraction is bits 22-0
355 f = (val >> 19) & 0xf;
356 res = (s << 7) | (r << 4) | f;
357 return res;
358 }
359
|
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "utilities/globalDefinitions.hpp"
26 #include "immediate_aarch64.hpp"
27
28 // there are at most 2^13 possible logical immediate encodings
29 // however, some combinations of immr and imms are invalid
30 static const unsigned LI_TABLE_SIZE = (1 << 13);
31
32 static int li_table_entry_count;
33
34 // for forward lookup we just use a direct array lookup
35 // and assume that the cient has supplied a valid encoding
36 // table[encoding] = immediate
37 static uint64_t LITable[LI_TABLE_SIZE];
38
39 // for reverse lookup we need a sparse map so we store a table of
40 // immediate and encoding pairs sorted by immediate value
41
42 struct li_pair {
43 uint64_t immediate;
44 uint32_t encoding;
45 };
46
47 static struct li_pair InverseLITable[LI_TABLE_SIZE];
48
49 // comparator to sort entries in the inverse table
50 int compare_immediate_pair(const void *i1, const void *i2)
51 {
52 struct li_pair *li1 = (struct li_pair *)i1;
53 struct li_pair *li2 = (struct li_pair *)i2;
54 if (li1->immediate < li2->immediate) {
55 return -1;
56 }
57 if (li1->immediate > li2->immediate) {
58 return 1;
59 }
60 return 0;
61 }
62
63 // helper functions used by expandLogicalImmediate
64
65 // for i = 1, ... N result<i-1> = 1 other bits are zero
66 static inline uint64_t ones(int N)
67 {
68 return (N == 64 ? (uint64_t)-1ULL : ((1ULL << N) - 1));
69 }
70
71 /*
72 * bit twiddling helpers for instruction decode
73 */
74
75 // 32 bit mask with bits [hi,...,lo] set
76 static inline uint32_t mask32(int hi = 31, int lo = 0)
77 {
78 int nbits = (hi + 1) - lo;
79 return ((1 << nbits) - 1) << lo;
80 }
81
82 static inline uint64_t mask64(int hi = 63, int lo = 0)
83 {
84 int nbits = (hi + 1) - lo;
85 return ((1L << nbits) - 1) << lo;
86 }
87
88 // pick bits [hi,...,lo] from val
89 static inline uint32_t pick32(uint32_t val, int hi = 31, int lo = 0)
90 {
91 return (val & mask32(hi, lo));
92 }
93
94 // pick bits [hi,...,lo] from val
95 static inline uint64_t pick64(uint64_t val, int hi = 31, int lo = 0)
96 {
97 return (val & mask64(hi, lo));
98 }
99
100 // mask [hi,lo] and shift down to start at bit 0
101 static inline uint32_t pickbits32(uint32_t val, int hi = 31, int lo = 0)
102 {
103 return (pick32(val, hi, lo) >> lo);
104 }
105
106 // mask [hi,lo] and shift down to start at bit 0
107 static inline uint64_t pickbits64(uint64_t val, int hi = 63, int lo = 0)
108 {
109 return (pick64(val, hi, lo) >> lo);
110 }
111
112 // result<0> to val<N>
113 static inline uint64_t pickbit(uint64_t val, int N)
114 {
115 return pickbits64(val, N, N);
116 }
117
118 static inline uint32_t uimm(uint32_t val, int hi, int lo)
119 {
120 return pickbits32(val, hi, lo);
121 }
122
123 // SPEC bits(M*N) Replicate(bits(M) x, integer N);
124 // this is just an educated guess
125
126 uint64_t replicate(uint64_t bits, int nbits, int count)
127 {
128 uint64_t result = 0;
129 // nbits may be 64 in which case we want mask to be -1
130 uint64_t mask = ones(nbits);
131 for (int i = 0; i < count ; i++) {
132 result <<= nbits;
133 result |= (bits & mask);
134 }
135 return result;
136 }
137
138 // this function writes the supplied bimm reference and returns a
139 // boolean to indicate success (1) or fail (0) because an illegal
140 // encoding must be treated as an UNALLOC instruction
141
142 // construct a 32 bit immediate value for a logical immediate operation
143 int expandLogicalImmediate(uint32_t immN, uint32_t immr,
144 uint32_t imms, uint64_t &bimm)
145 {
146 int len; // ought to be <= 6
147 uint32_t levels; // 6 bits
148 uint32_t tmask_and; // 6 bits
149 uint32_t wmask_and; // 6 bits
150 uint32_t tmask_or; // 6 bits
151 uint32_t wmask_or; // 6 bits
152 uint64_t imm64; // 64 bits
153 uint64_t tmask, wmask; // 64 bits
154 uint32_t S, R, diff; // 6 bits?
155
156 if (immN == 1) {
157 len = 6; // looks like 7 given the spec above but this cannot be!
158 } else {
159 len = 0;
160 uint32_t val = (~imms & 0x3f);
161 for (int i = 5; i > 0; i--) {
162 if (val & (1 << i)) {
163 len = i;
164 break;
165 }
166 }
167 if (len < 1) {
168 return 0;
169 }
170 // for valid inputs leading 1s in immr must be less than leading
171 // zeros in imms
172 int len2 = 0; // ought to be < len
173 uint32_t val2 = (~immr & 0x3f);
174 for (int i = 5; i > 0; i--) {
175 if (!(val2 & (1 << i))) {
176 len2 = i;
177 break;
178 }
179 }
180 if (len2 >= len) {
181 return 0;
182 }
183 }
184
185 levels = (1 << len) - 1;
186
187 if ((imms & levels) == levels) {
188 return 0;
189 }
190
191 S = imms & levels;
192 R = immr & levels;
193
194 // 6 bit arithmetic!
195 diff = S - R;
196 tmask_and = (diff | ~levels) & 0x3f;
197 tmask_or = (diff & levels) & 0x3f;
198 tmask = 0xffffffffffffffffULL;
199
200 for (int i = 0; i < 6; i++) {
201 int nbits = 1 << i;
202 uint64_t and_bit = pickbit(tmask_and, i);
203 uint64_t or_bit = pickbit(tmask_or, i);
204 uint64_t and_bits_sub = replicate(and_bit, 1, nbits);
205 uint64_t or_bits_sub = replicate(or_bit, 1, nbits);
206 uint64_t and_bits_top = (and_bits_sub << nbits) | ones(nbits);
207 uint64_t or_bits_top = (0 << nbits) | or_bits_sub;
208
209 tmask = ((tmask
210 & (replicate(and_bits_top, 2 * nbits, 32 / nbits)))
211 | replicate(or_bits_top, 2 * nbits, 32 / nbits));
212 }
213
214 wmask_and = (immr | ~levels) & 0x3f;
215 wmask_or = (immr & levels) & 0x3f;
216
217 wmask = 0;
218
219 for (int i = 0; i < 6; i++) {
220 int nbits = 1 << i;
221 uint64_t and_bit = pickbit(wmask_and, i);
222 uint64_t or_bit = pickbit(wmask_or, i);
223 uint64_t and_bits_sub = replicate(and_bit, 1, nbits);
224 uint64_t or_bits_sub = replicate(or_bit, 1, nbits);
225 uint64_t and_bits_top = (ones(nbits) << nbits) | and_bits_sub;
226 uint64_t or_bits_top = (or_bits_sub << nbits) | 0;
227
228 wmask = ((wmask
229 & (replicate(and_bits_top, 2 * nbits, 32 / nbits)))
230 | replicate(or_bits_top, 2 * nbits, 32 / nbits));
231 }
232
233 if (diff & (1U << 6)) {
234 imm64 = tmask & wmask;
235 } else {
236 imm64 = tmask | wmask;
237 }
238
239
240 bimm = imm64;
241 return 1;
242 }
243
244 // constructor to initialise the lookup tables
245
246 static void initLITables() __attribute__ ((constructor));
247 static void initLITables()
248 {
249 li_table_entry_count = 0;
250 for (unsigned index = 0; index < LI_TABLE_SIZE; index++) {
251 uint32_t N = uimm(index, 12, 12);
252 uint32_t immr = uimm(index, 11, 6);
253 uint32_t imms = uimm(index, 5, 0);
254 if (expandLogicalImmediate(N, immr, imms, LITable[index])) {
255 InverseLITable[li_table_entry_count].immediate = LITable[index];
256 InverseLITable[li_table_entry_count].encoding = index;
257 li_table_entry_count++;
258 }
259 }
260 // now sort the inverse table
261 qsort(InverseLITable, li_table_entry_count,
262 sizeof(InverseLITable[0]), compare_immediate_pair);
263 }
264
265 // public APIs provided for logical immediate lookup and reverse lookup
266
267 uint64_t logical_immediate_for_encoding(uint32_t encoding)
268 {
269 return LITable[encoding];
270 }
271
272 uint32_t encoding_for_logical_immediate(uint64_t immediate)
273 {
274 struct li_pair pair;
275 struct li_pair *result;
276
277 pair.immediate = immediate;
278
279 result = (struct li_pair *)
280 bsearch(&pair, InverseLITable, li_table_entry_count,
281 sizeof(InverseLITable[0]), compare_immediate_pair);
282
283 if (result) {
284 return result->encoding;
285 }
286
287 return 0xffffffff;
288 }
289
290 // floating point immediates are encoded in 8 bits
291 // fpimm[7] = sign bit
292 // fpimm[6:4] = signed exponent
293 // fpimm[3:0] = fraction (assuming leading 1)
294 // i.e. F = s * 1.f * 2^(e - b)
295
296 uint64_t fp_immediate_for_encoding(uint32_t imm8, int is_dp)
297 {
298 union {
299 float fpval;
300 double dpval;
301 uint64_t val;
302 };
303
304 uint32_t s, e, f;
305 s = (imm8 >> 7 ) & 0x1;
306 e = (imm8 >> 4) & 0x7;
307 f = imm8 & 0xf;
308 // the fp value is s * n/16 * 2r where n is 16+e
309 fpval = (16.0 + f) / 16.0;
310 // n.b. exponent is signed
311 if (e < 4) {
312 int epos = e;
313 for (int i = 0; i <= epos; i++) {
314 fpval *= 2.0;
315 }
316 } else {
317 int eneg = 7 - e;
318 for (int i = 0; i < eneg; i++) {
319 fpval /= 2.0;
320 }
321 }
322
323 if (s) {
324 fpval = -fpval;
325 }
326 if (is_dp) {
327 dpval = (double)fpval;
328 }
329 return val;
330 }
331
332 uint32_t encoding_for_fp_immediate(float immediate)
333 {
334 // given a float which is of the form
335 //
336 // s * n/16 * 2r
337 //
338 // where n is 16+f and imm1:s, imm4:f, simm3:r
339 // return the imm8 result [s:r:f]
340 //
341
342 union {
343 float fpval;
344 uint32_t val;
345 };
346 fpval = immediate;
347 uint32_t s, r, f, res;
348 // sign bit is 31
349 s = (val >> 31) & 0x1;
350 // exponent is bits 30-23 but we only want the bottom 3 bits
351 // strictly we ought to check that the bits bits 30-25 are
352 // either all 1s or all 0s
353 r = (val >> 23) & 0x7;
354 // fraction is bits 22-0
355 f = (val >> 19) & 0xf;
356 res = (s << 7) | (r << 4) | f;
357 return res;
358 }
359
|