root / target-alpha / op_helper.c @ b5f1aa64
History | View | Annotate | Download (28.1 kB)
1 | 4c9649a9 | j_mayer | /*
|
---|---|---|---|
2 | 4c9649a9 | j_mayer | * Alpha emulation cpu micro-operations helpers for qemu.
|
3 | 5fafdf24 | ths | *
|
4 | 4c9649a9 | j_mayer | * Copyright (c) 2007 Jocelyn Mayer
|
5 | 4c9649a9 | j_mayer | *
|
6 | 4c9649a9 | j_mayer | * This library is free software; you can redistribute it and/or
|
7 | 4c9649a9 | j_mayer | * modify it under the terms of the GNU Lesser General Public
|
8 | 4c9649a9 | j_mayer | * License as published by the Free Software Foundation; either
|
9 | 4c9649a9 | j_mayer | * version 2 of the License, or (at your option) any later version.
|
10 | 4c9649a9 | j_mayer | *
|
11 | 4c9649a9 | j_mayer | * This library is distributed in the hope that it will be useful,
|
12 | 4c9649a9 | j_mayer | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 | 4c9649a9 | j_mayer | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 | 4c9649a9 | j_mayer | * Lesser General Public License for more details.
|
15 | 4c9649a9 | j_mayer | *
|
16 | 4c9649a9 | j_mayer | * You should have received a copy of the GNU Lesser General Public
|
17 | 8167ee88 | Blue Swirl | * License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
18 | 4c9649a9 | j_mayer | */
|
19 | 4c9649a9 | j_mayer | |
20 | 4c9649a9 | j_mayer | #include "exec.h" |
21 | 603fccce | j_mayer | #include "host-utils.h" |
22 | 4c9649a9 | j_mayer | #include "softfloat.h" |
23 | a7812ae4 | pbrook | #include "helper.h" |
24 | 18f8e2c0 | Richard Henderson | #include "qemu-timer.h" |
25 | 4c9649a9 | j_mayer | |
26 | 4c9649a9 | j_mayer | /*****************************************************************************/
|
27 | 4c9649a9 | j_mayer | /* Exceptions processing helpers */
|
28 | c2c789cf | Richard Henderson | void QEMU_NORETURN helper_excp (int excp, int error) |
29 | 4c9649a9 | j_mayer | { |
30 | 4c9649a9 | j_mayer | env->exception_index = excp; |
31 | 4c9649a9 | j_mayer | env->error_code = error; |
32 | 4c9649a9 | j_mayer | cpu_loop_exit(); |
33 | 4c9649a9 | j_mayer | } |
34 | 4c9649a9 | j_mayer | |
35 | b5f1aa64 | Richard Henderson | static void QEMU_NORETURN arith_excp(int exc, uint64_t mask) |
36 | b5f1aa64 | Richard Henderson | { |
37 | b5f1aa64 | Richard Henderson | env->exception_index = EXCP_ARITH; |
38 | b5f1aa64 | Richard Henderson | env->error_code = 0;
|
39 | b5f1aa64 | Richard Henderson | env->trap_arg0 = exc; |
40 | b5f1aa64 | Richard Henderson | env->trap_arg1 = mask; |
41 | b5f1aa64 | Richard Henderson | cpu_loop_exit(); |
42 | b5f1aa64 | Richard Henderson | } |
43 | b5f1aa64 | Richard Henderson | |
44 | 6ad02592 | aurel32 | uint64_t helper_load_pcc (void)
|
45 | 4c9649a9 | j_mayer | { |
46 | 18f8e2c0 | Richard Henderson | /* ??? This isn't a timer for which we have any rate info. */
|
47 | 18f8e2c0 | Richard Henderson | return (uint32_t)cpu_get_real_ticks();
|
48 | 4c9649a9 | j_mayer | } |
49 | 4c9649a9 | j_mayer | |
50 | f18cd223 | aurel32 | uint64_t helper_load_fpcr (void)
|
51 | 4c9649a9 | j_mayer | { |
52 | ba0e276d | Richard Henderson | return cpu_alpha_load_fpcr (env);
|
53 | 4c9649a9 | j_mayer | } |
54 | 4c9649a9 | j_mayer | |
55 | f18cd223 | aurel32 | void helper_store_fpcr (uint64_t val)
|
56 | 4c9649a9 | j_mayer | { |
57 | ba0e276d | Richard Henderson | cpu_alpha_store_fpcr (env, val); |
58 | 4c9649a9 | j_mayer | } |
59 | 4c9649a9 | j_mayer | |
60 | 04acd307 | aurel32 | uint64_t helper_addqv (uint64_t op1, uint64_t op2) |
61 | 4c9649a9 | j_mayer | { |
62 | 04acd307 | aurel32 | uint64_t tmp = op1; |
63 | 04acd307 | aurel32 | op1 += op2; |
64 | 04acd307 | aurel32 | if (unlikely((tmp ^ op2 ^ (-1ULL)) & (tmp ^ op1) & (1ULL << 63))) { |
65 | b5f1aa64 | Richard Henderson | arith_excp(EXC_M_IOV, 0);
|
66 | 4c9649a9 | j_mayer | } |
67 | 04acd307 | aurel32 | return op1;
|
68 | 4c9649a9 | j_mayer | } |
69 | 4c9649a9 | j_mayer | |
70 | 04acd307 | aurel32 | uint64_t helper_addlv (uint64_t op1, uint64_t op2) |
71 | 4c9649a9 | j_mayer | { |
72 | 04acd307 | aurel32 | uint64_t tmp = op1; |
73 | 04acd307 | aurel32 | op1 = (uint32_t)(op1 + op2); |
74 | 04acd307 | aurel32 | if (unlikely((tmp ^ op2 ^ (-1UL)) & (tmp ^ op1) & (1UL << 31))) { |
75 | b5f1aa64 | Richard Henderson | arith_excp(EXC_M_IOV, 0);
|
76 | 4c9649a9 | j_mayer | } |
77 | 04acd307 | aurel32 | return op1;
|
78 | 4c9649a9 | j_mayer | } |
79 | 4c9649a9 | j_mayer | |
80 | 04acd307 | aurel32 | uint64_t helper_subqv (uint64_t op1, uint64_t op2) |
81 | 4c9649a9 | j_mayer | { |
82 | ecbb5ea1 | aurel32 | uint64_t res; |
83 | ecbb5ea1 | aurel32 | res = op1 - op2; |
84 | ecbb5ea1 | aurel32 | if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) { |
85 | b5f1aa64 | Richard Henderson | arith_excp(EXC_M_IOV, 0);
|
86 | 4c9649a9 | j_mayer | } |
87 | ecbb5ea1 | aurel32 | return res;
|
88 | 4c9649a9 | j_mayer | } |
89 | 4c9649a9 | j_mayer | |
90 | 04acd307 | aurel32 | uint64_t helper_sublv (uint64_t op1, uint64_t op2) |
91 | 4c9649a9 | j_mayer | { |
92 | ecbb5ea1 | aurel32 | uint32_t res; |
93 | ecbb5ea1 | aurel32 | res = op1 - op2; |
94 | ecbb5ea1 | aurel32 | if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) { |
95 | b5f1aa64 | Richard Henderson | arith_excp(EXC_M_IOV, 0);
|
96 | 4c9649a9 | j_mayer | } |
97 | ecbb5ea1 | aurel32 | return res;
|
98 | 4c9649a9 | j_mayer | } |
99 | 4c9649a9 | j_mayer | |
100 | 04acd307 | aurel32 | uint64_t helper_mullv (uint64_t op1, uint64_t op2) |
101 | 4c9649a9 | j_mayer | { |
102 | 04acd307 | aurel32 | int64_t res = (int64_t)op1 * (int64_t)op2; |
103 | 4c9649a9 | j_mayer | |
104 | 4c9649a9 | j_mayer | if (unlikely((int32_t)res != res)) {
|
105 | b5f1aa64 | Richard Henderson | arith_excp(EXC_M_IOV, 0);
|
106 | 4c9649a9 | j_mayer | } |
107 | 04acd307 | aurel32 | return (int64_t)((int32_t)res);
|
108 | 4c9649a9 | j_mayer | } |
109 | 4c9649a9 | j_mayer | |
110 | 04acd307 | aurel32 | uint64_t helper_mulqv (uint64_t op1, uint64_t op2) |
111 | 4c9649a9 | j_mayer | { |
112 | e14fe0a9 | j_mayer | uint64_t tl, th; |
113 | e14fe0a9 | j_mayer | |
114 | 04acd307 | aurel32 | muls64(&tl, &th, op1, op2); |
115 | e14fe0a9 | j_mayer | /* If th != 0 && th != -1, then we had an overflow */
|
116 | e14fe0a9 | j_mayer | if (unlikely((th + 1) > 1)) { |
117 | b5f1aa64 | Richard Henderson | arith_excp(EXC_M_IOV, 0);
|
118 | 4c9649a9 | j_mayer | } |
119 | 04acd307 | aurel32 | return tl;
|
120 | 04acd307 | aurel32 | } |
121 | 04acd307 | aurel32 | |
122 | 04acd307 | aurel32 | uint64_t helper_umulh (uint64_t op1, uint64_t op2) |
123 | 04acd307 | aurel32 | { |
124 | 04acd307 | aurel32 | uint64_t tl, th; |
125 | 04acd307 | aurel32 | |
126 | 04acd307 | aurel32 | mulu64(&tl, &th, op1, op2); |
127 | 04acd307 | aurel32 | return th;
|
128 | 4c9649a9 | j_mayer | } |
129 | 4c9649a9 | j_mayer | |
130 | ae8ecd42 | aurel32 | uint64_t helper_ctpop (uint64_t arg) |
131 | 4c9649a9 | j_mayer | { |
132 | ae8ecd42 | aurel32 | return ctpop64(arg);
|
133 | 4c9649a9 | j_mayer | } |
134 | 4c9649a9 | j_mayer | |
135 | ae8ecd42 | aurel32 | uint64_t helper_ctlz (uint64_t arg) |
136 | 4c9649a9 | j_mayer | { |
137 | ae8ecd42 | aurel32 | return clz64(arg);
|
138 | 4c9649a9 | j_mayer | } |
139 | 4c9649a9 | j_mayer | |
140 | ae8ecd42 | aurel32 | uint64_t helper_cttz (uint64_t arg) |
141 | 4c9649a9 | j_mayer | { |
142 | ae8ecd42 | aurel32 | return ctz64(arg);
|
143 | 4c9649a9 | j_mayer | } |
144 | 4c9649a9 | j_mayer | |
145 | 636aa200 | Blue Swirl | static inline uint64_t byte_zap(uint64_t op, uint8_t mskb) |
146 | 4c9649a9 | j_mayer | { |
147 | 4c9649a9 | j_mayer | uint64_t mask; |
148 | 4c9649a9 | j_mayer | |
149 | 4c9649a9 | j_mayer | mask = 0;
|
150 | 4c9649a9 | j_mayer | mask |= ((mskb >> 0) & 1) * 0x00000000000000FFULL; |
151 | 4c9649a9 | j_mayer | mask |= ((mskb >> 1) & 1) * 0x000000000000FF00ULL; |
152 | 4c9649a9 | j_mayer | mask |= ((mskb >> 2) & 1) * 0x0000000000FF0000ULL; |
153 | 4c9649a9 | j_mayer | mask |= ((mskb >> 3) & 1) * 0x00000000FF000000ULL; |
154 | 4c9649a9 | j_mayer | mask |= ((mskb >> 4) & 1) * 0x000000FF00000000ULL; |
155 | 4c9649a9 | j_mayer | mask |= ((mskb >> 5) & 1) * 0x0000FF0000000000ULL; |
156 | 4c9649a9 | j_mayer | mask |= ((mskb >> 6) & 1) * 0x00FF000000000000ULL; |
157 | 4c9649a9 | j_mayer | mask |= ((mskb >> 7) & 1) * 0xFF00000000000000ULL; |
158 | 4c9649a9 | j_mayer | |
159 | 4c9649a9 | j_mayer | return op & ~mask;
|
160 | 4c9649a9 | j_mayer | } |
161 | 4c9649a9 | j_mayer | |
162 | b3249f63 | aurel32 | uint64_t helper_zap(uint64_t val, uint64_t mask) |
163 | 4c9649a9 | j_mayer | { |
164 | b3249f63 | aurel32 | return byte_zap(val, mask);
|
165 | 4c9649a9 | j_mayer | } |
166 | 4c9649a9 | j_mayer | |
167 | b3249f63 | aurel32 | uint64_t helper_zapnot(uint64_t val, uint64_t mask) |
168 | 4c9649a9 | j_mayer | { |
169 | b3249f63 | aurel32 | return byte_zap(val, ~mask);
|
170 | 4c9649a9 | j_mayer | } |
171 | 4c9649a9 | j_mayer | |
172 | 04acd307 | aurel32 | uint64_t helper_cmpbge (uint64_t op1, uint64_t op2) |
173 | 4c9649a9 | j_mayer | { |
174 | 4c9649a9 | j_mayer | uint8_t opa, opb, res; |
175 | 4c9649a9 | j_mayer | int i;
|
176 | 4c9649a9 | j_mayer | |
177 | 4c9649a9 | j_mayer | res = 0;
|
178 | 970d622e | aurel32 | for (i = 0; i < 8; i++) { |
179 | 04acd307 | aurel32 | opa = op1 >> (i * 8);
|
180 | 04acd307 | aurel32 | opb = op2 >> (i * 8);
|
181 | 4c9649a9 | j_mayer | if (opa >= opb)
|
182 | 4c9649a9 | j_mayer | res |= 1 << i;
|
183 | 4c9649a9 | j_mayer | } |
184 | 04acd307 | aurel32 | return res;
|
185 | 4c9649a9 | j_mayer | } |
186 | 4c9649a9 | j_mayer | |
187 | 13e4df99 | Richard Henderson | uint64_t helper_minub8 (uint64_t op1, uint64_t op2) |
188 | 13e4df99 | Richard Henderson | { |
189 | 13e4df99 | Richard Henderson | uint64_t res = 0;
|
190 | 13e4df99 | Richard Henderson | uint8_t opa, opb, opr; |
191 | 13e4df99 | Richard Henderson | int i;
|
192 | 13e4df99 | Richard Henderson | |
193 | 13e4df99 | Richard Henderson | for (i = 0; i < 8; ++i) { |
194 | 13e4df99 | Richard Henderson | opa = op1 >> (i * 8);
|
195 | 13e4df99 | Richard Henderson | opb = op2 >> (i * 8);
|
196 | 13e4df99 | Richard Henderson | opr = opa < opb ? opa : opb; |
197 | 13e4df99 | Richard Henderson | res |= (uint64_t)opr << (i * 8);
|
198 | 13e4df99 | Richard Henderson | } |
199 | 13e4df99 | Richard Henderson | return res;
|
200 | 13e4df99 | Richard Henderson | } |
201 | 13e4df99 | Richard Henderson | |
202 | 13e4df99 | Richard Henderson | uint64_t helper_minsb8 (uint64_t op1, uint64_t op2) |
203 | 13e4df99 | Richard Henderson | { |
204 | 13e4df99 | Richard Henderson | uint64_t res = 0;
|
205 | 13e4df99 | Richard Henderson | int8_t opa, opb; |
206 | 13e4df99 | Richard Henderson | uint8_t opr; |
207 | 13e4df99 | Richard Henderson | int i;
|
208 | 13e4df99 | Richard Henderson | |
209 | 13e4df99 | Richard Henderson | for (i = 0; i < 8; ++i) { |
210 | 13e4df99 | Richard Henderson | opa = op1 >> (i * 8);
|
211 | 13e4df99 | Richard Henderson | opb = op2 >> (i * 8);
|
212 | 13e4df99 | Richard Henderson | opr = opa < opb ? opa : opb; |
213 | 13e4df99 | Richard Henderson | res |= (uint64_t)opr << (i * 8);
|
214 | 13e4df99 | Richard Henderson | } |
215 | 13e4df99 | Richard Henderson | return res;
|
216 | 13e4df99 | Richard Henderson | } |
217 | 13e4df99 | Richard Henderson | |
218 | 13e4df99 | Richard Henderson | uint64_t helper_minuw4 (uint64_t op1, uint64_t op2) |
219 | 13e4df99 | Richard Henderson | { |
220 | 13e4df99 | Richard Henderson | uint64_t res = 0;
|
221 | 13e4df99 | Richard Henderson | uint16_t opa, opb, opr; |
222 | 13e4df99 | Richard Henderson | int i;
|
223 | 13e4df99 | Richard Henderson | |
224 | 13e4df99 | Richard Henderson | for (i = 0; i < 4; ++i) { |
225 | 13e4df99 | Richard Henderson | opa = op1 >> (i * 16);
|
226 | 13e4df99 | Richard Henderson | opb = op2 >> (i * 16);
|
227 | 13e4df99 | Richard Henderson | opr = opa < opb ? opa : opb; |
228 | 13e4df99 | Richard Henderson | res |= (uint64_t)opr << (i * 16);
|
229 | 13e4df99 | Richard Henderson | } |
230 | 13e4df99 | Richard Henderson | return res;
|
231 | 13e4df99 | Richard Henderson | } |
232 | 13e4df99 | Richard Henderson | |
233 | 13e4df99 | Richard Henderson | uint64_t helper_minsw4 (uint64_t op1, uint64_t op2) |
234 | 13e4df99 | Richard Henderson | { |
235 | 13e4df99 | Richard Henderson | uint64_t res = 0;
|
236 | 13e4df99 | Richard Henderson | int16_t opa, opb; |
237 | 13e4df99 | Richard Henderson | uint16_t opr; |
238 | 13e4df99 | Richard Henderson | int i;
|
239 | 13e4df99 | Richard Henderson | |
240 | 13e4df99 | Richard Henderson | for (i = 0; i < 4; ++i) { |
241 | 13e4df99 | Richard Henderson | opa = op1 >> (i * 16);
|
242 | 13e4df99 | Richard Henderson | opb = op2 >> (i * 16);
|
243 | 13e4df99 | Richard Henderson | opr = opa < opb ? opa : opb; |
244 | 13e4df99 | Richard Henderson | res |= (uint64_t)opr << (i * 16);
|
245 | 13e4df99 | Richard Henderson | } |
246 | 13e4df99 | Richard Henderson | return res;
|
247 | 13e4df99 | Richard Henderson | } |
248 | 13e4df99 | Richard Henderson | |
249 | 13e4df99 | Richard Henderson | uint64_t helper_maxub8 (uint64_t op1, uint64_t op2) |
250 | 13e4df99 | Richard Henderson | { |
251 | 13e4df99 | Richard Henderson | uint64_t res = 0;
|
252 | 13e4df99 | Richard Henderson | uint8_t opa, opb, opr; |
253 | 13e4df99 | Richard Henderson | int i;
|
254 | 13e4df99 | Richard Henderson | |
255 | 13e4df99 | Richard Henderson | for (i = 0; i < 8; ++i) { |
256 | 13e4df99 | Richard Henderson | opa = op1 >> (i * 8);
|
257 | 13e4df99 | Richard Henderson | opb = op2 >> (i * 8);
|
258 | 13e4df99 | Richard Henderson | opr = opa > opb ? opa : opb; |
259 | 13e4df99 | Richard Henderson | res |= (uint64_t)opr << (i * 8);
|
260 | 13e4df99 | Richard Henderson | } |
261 | 13e4df99 | Richard Henderson | return res;
|
262 | 13e4df99 | Richard Henderson | } |
263 | 13e4df99 | Richard Henderson | |
264 | 13e4df99 | Richard Henderson | uint64_t helper_maxsb8 (uint64_t op1, uint64_t op2) |
265 | 13e4df99 | Richard Henderson | { |
266 | 13e4df99 | Richard Henderson | uint64_t res = 0;
|
267 | 13e4df99 | Richard Henderson | int8_t opa, opb; |
268 | 13e4df99 | Richard Henderson | uint8_t opr; |
269 | 13e4df99 | Richard Henderson | int i;
|
270 | 13e4df99 | Richard Henderson | |
271 | 13e4df99 | Richard Henderson | for (i = 0; i < 8; ++i) { |
272 | 13e4df99 | Richard Henderson | opa = op1 >> (i * 8);
|
273 | 13e4df99 | Richard Henderson | opb = op2 >> (i * 8);
|
274 | 13e4df99 | Richard Henderson | opr = opa > opb ? opa : opb; |
275 | 13e4df99 | Richard Henderson | res |= (uint64_t)opr << (i * 8);
|
276 | 13e4df99 | Richard Henderson | } |
277 | 13e4df99 | Richard Henderson | return res;
|
278 | 13e4df99 | Richard Henderson | } |
279 | 13e4df99 | Richard Henderson | |
280 | 13e4df99 | Richard Henderson | uint64_t helper_maxuw4 (uint64_t op1, uint64_t op2) |
281 | 13e4df99 | Richard Henderson | { |
282 | 13e4df99 | Richard Henderson | uint64_t res = 0;
|
283 | 13e4df99 | Richard Henderson | uint16_t opa, opb, opr; |
284 | 13e4df99 | Richard Henderson | int i;
|
285 | 13e4df99 | Richard Henderson | |
286 | 13e4df99 | Richard Henderson | for (i = 0; i < 4; ++i) { |
287 | 13e4df99 | Richard Henderson | opa = op1 >> (i * 16);
|
288 | 13e4df99 | Richard Henderson | opb = op2 >> (i * 16);
|
289 | 13e4df99 | Richard Henderson | opr = opa > opb ? opa : opb; |
290 | 13e4df99 | Richard Henderson | res |= (uint64_t)opr << (i * 16);
|
291 | 13e4df99 | Richard Henderson | } |
292 | 13e4df99 | Richard Henderson | return res;
|
293 | 13e4df99 | Richard Henderson | } |
294 | 13e4df99 | Richard Henderson | |
295 | 13e4df99 | Richard Henderson | uint64_t helper_maxsw4 (uint64_t op1, uint64_t op2) |
296 | 13e4df99 | Richard Henderson | { |
297 | 13e4df99 | Richard Henderson | uint64_t res = 0;
|
298 | 13e4df99 | Richard Henderson | int16_t opa, opb; |
299 | 13e4df99 | Richard Henderson | uint16_t opr; |
300 | 13e4df99 | Richard Henderson | int i;
|
301 | 13e4df99 | Richard Henderson | |
302 | 13e4df99 | Richard Henderson | for (i = 0; i < 4; ++i) { |
303 | 13e4df99 | Richard Henderson | opa = op1 >> (i * 16);
|
304 | 13e4df99 | Richard Henderson | opb = op2 >> (i * 16);
|
305 | 13e4df99 | Richard Henderson | opr = opa > opb ? opa : opb; |
306 | 13e4df99 | Richard Henderson | res |= (uint64_t)opr << (i * 16);
|
307 | 13e4df99 | Richard Henderson | } |
308 | 13e4df99 | Richard Henderson | return res;
|
309 | 13e4df99 | Richard Henderson | } |
310 | 13e4df99 | Richard Henderson | |
311 | 13e4df99 | Richard Henderson | uint64_t helper_perr (uint64_t op1, uint64_t op2) |
312 | 13e4df99 | Richard Henderson | { |
313 | 13e4df99 | Richard Henderson | uint64_t res = 0;
|
314 | 13e4df99 | Richard Henderson | uint8_t opa, opb, opr; |
315 | 13e4df99 | Richard Henderson | int i;
|
316 | 13e4df99 | Richard Henderson | |
317 | 13e4df99 | Richard Henderson | for (i = 0; i < 8; ++i) { |
318 | 13e4df99 | Richard Henderson | opa = op1 >> (i * 8);
|
319 | 13e4df99 | Richard Henderson | opb = op2 >> (i * 8);
|
320 | 13e4df99 | Richard Henderson | if (opa >= opb)
|
321 | 13e4df99 | Richard Henderson | opr = opa - opb; |
322 | 13e4df99 | Richard Henderson | else
|
323 | 13e4df99 | Richard Henderson | opr = opb - opa; |
324 | 13e4df99 | Richard Henderson | res += opr; |
325 | 13e4df99 | Richard Henderson | } |
326 | 13e4df99 | Richard Henderson | return res;
|
327 | 13e4df99 | Richard Henderson | } |
328 | 13e4df99 | Richard Henderson | |
329 | 13e4df99 | Richard Henderson | uint64_t helper_pklb (uint64_t op1) |
330 | 13e4df99 | Richard Henderson | { |
331 | 13e4df99 | Richard Henderson | return (op1 & 0xff) | ((op1 >> 24) & 0xff00); |
332 | 13e4df99 | Richard Henderson | } |
333 | 13e4df99 | Richard Henderson | |
334 | 13e4df99 | Richard Henderson | uint64_t helper_pkwb (uint64_t op1) |
335 | 13e4df99 | Richard Henderson | { |
336 | 13e4df99 | Richard Henderson | return ((op1 & 0xff) |
337 | 13e4df99 | Richard Henderson | | ((op1 >> 8) & 0xff00) |
338 | 13e4df99 | Richard Henderson | | ((op1 >> 16) & 0xff0000) |
339 | 13e4df99 | Richard Henderson | | ((op1 >> 24) & 0xff000000)); |
340 | 13e4df99 | Richard Henderson | } |
341 | 13e4df99 | Richard Henderson | |
342 | 13e4df99 | Richard Henderson | uint64_t helper_unpkbl (uint64_t op1) |
343 | 13e4df99 | Richard Henderson | { |
344 | 13e4df99 | Richard Henderson | return (op1 & 0xff) | ((op1 & 0xff00) << 24); |
345 | 13e4df99 | Richard Henderson | } |
346 | 13e4df99 | Richard Henderson | |
347 | 13e4df99 | Richard Henderson | uint64_t helper_unpkbw (uint64_t op1) |
348 | 13e4df99 | Richard Henderson | { |
349 | 13e4df99 | Richard Henderson | return ((op1 & 0xff) |
350 | 13e4df99 | Richard Henderson | | ((op1 & 0xff00) << 8) |
351 | 13e4df99 | Richard Henderson | | ((op1 & 0xff0000) << 16) |
352 | 13e4df99 | Richard Henderson | | ((op1 & 0xff000000) << 24)); |
353 | 13e4df99 | Richard Henderson | } |
354 | 13e4df99 | Richard Henderson | |
355 | f18cd223 | aurel32 | /* Floating point helpers */
|
356 | f18cd223 | aurel32 | |
357 | f24518b5 | Richard Henderson | void helper_setroundmode (uint32_t val)
|
358 | f24518b5 | Richard Henderson | { |
359 | f24518b5 | Richard Henderson | set_float_rounding_mode(val, &FP_STATUS); |
360 | f24518b5 | Richard Henderson | } |
361 | f24518b5 | Richard Henderson | |
362 | f24518b5 | Richard Henderson | void helper_setflushzero (uint32_t val)
|
363 | f24518b5 | Richard Henderson | { |
364 | f24518b5 | Richard Henderson | set_flush_to_zero(val, &FP_STATUS); |
365 | f24518b5 | Richard Henderson | } |
366 | f24518b5 | Richard Henderson | |
367 | f24518b5 | Richard Henderson | void helper_fp_exc_clear (void) |
368 | f24518b5 | Richard Henderson | { |
369 | f24518b5 | Richard Henderson | set_float_exception_flags(0, &FP_STATUS);
|
370 | f24518b5 | Richard Henderson | } |
371 | f24518b5 | Richard Henderson | |
372 | f24518b5 | Richard Henderson | uint32_t helper_fp_exc_get (void)
|
373 | f24518b5 | Richard Henderson | { |
374 | f24518b5 | Richard Henderson | return get_float_exception_flags(&FP_STATUS);
|
375 | f24518b5 | Richard Henderson | } |
376 | f24518b5 | Richard Henderson | |
377 | f24518b5 | Richard Henderson | /* Raise exceptions for ieee fp insns without software completion.
|
378 | f24518b5 | Richard Henderson | In that case there are no exceptions that don't trap; the mask
|
379 | f24518b5 | Richard Henderson | doesn't apply. */
|
380 | f24518b5 | Richard Henderson | void helper_fp_exc_raise(uint32_t exc, uint32_t regno)
|
381 | f24518b5 | Richard Henderson | { |
382 | f24518b5 | Richard Henderson | if (exc) {
|
383 | f24518b5 | Richard Henderson | uint32_t hw_exc = 0;
|
384 | f24518b5 | Richard Henderson | |
385 | f24518b5 | Richard Henderson | if (exc & float_flag_invalid) {
|
386 | f24518b5 | Richard Henderson | hw_exc |= EXC_M_INV; |
387 | f24518b5 | Richard Henderson | } |
388 | f24518b5 | Richard Henderson | if (exc & float_flag_divbyzero) {
|
389 | f24518b5 | Richard Henderson | hw_exc |= EXC_M_DZE; |
390 | f24518b5 | Richard Henderson | } |
391 | f24518b5 | Richard Henderson | if (exc & float_flag_overflow) {
|
392 | f24518b5 | Richard Henderson | hw_exc |= EXC_M_FOV; |
393 | f24518b5 | Richard Henderson | } |
394 | f24518b5 | Richard Henderson | if (exc & float_flag_underflow) {
|
395 | f24518b5 | Richard Henderson | hw_exc |= EXC_M_UNF; |
396 | f24518b5 | Richard Henderson | } |
397 | f24518b5 | Richard Henderson | if (exc & float_flag_inexact) {
|
398 | f24518b5 | Richard Henderson | hw_exc |= EXC_M_INE; |
399 | f24518b5 | Richard Henderson | } |
400 | b5f1aa64 | Richard Henderson | |
401 | b5f1aa64 | Richard Henderson | arith_excp(hw_exc, 1ull << regno);
|
402 | f24518b5 | Richard Henderson | } |
403 | f24518b5 | Richard Henderson | } |
404 | f24518b5 | Richard Henderson | |
405 | f24518b5 | Richard Henderson | /* Raise exceptions for ieee fp insns with software completion. */
|
406 | f24518b5 | Richard Henderson | void helper_fp_exc_raise_s(uint32_t exc, uint32_t regno)
|
407 | f24518b5 | Richard Henderson | { |
408 | f24518b5 | Richard Henderson | if (exc) {
|
409 | f24518b5 | Richard Henderson | env->fpcr_exc_status |= exc; |
410 | f24518b5 | Richard Henderson | |
411 | f24518b5 | Richard Henderson | exc &= ~env->fpcr_exc_mask; |
412 | f24518b5 | Richard Henderson | if (exc) {
|
413 | f24518b5 | Richard Henderson | helper_fp_exc_raise(exc, regno); |
414 | f24518b5 | Richard Henderson | } |
415 | f24518b5 | Richard Henderson | } |
416 | f24518b5 | Richard Henderson | } |
417 | f24518b5 | Richard Henderson | |
418 | f24518b5 | Richard Henderson | /* Input remapping without software completion. Handle denormal-map-to-zero
|
419 | f24518b5 | Richard Henderson | and trap for all other non-finite numbers. */
|
420 | f24518b5 | Richard Henderson | uint64_t helper_ieee_input(uint64_t val) |
421 | f24518b5 | Richard Henderson | { |
422 | f24518b5 | Richard Henderson | uint32_t exp = (uint32_t)(val >> 52) & 0x7ff; |
423 | f24518b5 | Richard Henderson | uint64_t frac = val & 0xfffffffffffffull;
|
424 | f24518b5 | Richard Henderson | |
425 | f24518b5 | Richard Henderson | if (exp == 0) { |
426 | f24518b5 | Richard Henderson | if (frac != 0) { |
427 | f24518b5 | Richard Henderson | /* If DNZ is set flush denormals to zero on input. */
|
428 | f24518b5 | Richard Henderson | if (env->fpcr_dnz) {
|
429 | f24518b5 | Richard Henderson | val &= 1ull << 63; |
430 | f24518b5 | Richard Henderson | } else {
|
431 | b5f1aa64 | Richard Henderson | arith_excp(EXC_M_UNF, 0);
|
432 | f24518b5 | Richard Henderson | } |
433 | f24518b5 | Richard Henderson | } |
434 | f24518b5 | Richard Henderson | } else if (exp == 0x7ff) { |
435 | f24518b5 | Richard Henderson | /* Infinity or NaN. */
|
436 | f24518b5 | Richard Henderson | /* ??? I'm not sure these exception bit flags are correct. I do
|
437 | f24518b5 | Richard Henderson | know that the Linux kernel, at least, doesn't rely on them and
|
438 | f24518b5 | Richard Henderson | just emulates the insn to figure out what exception to use. */
|
439 | b5f1aa64 | Richard Henderson | arith_excp(frac ? EXC_M_INV : EXC_M_FOV, 0);
|
440 | f24518b5 | Richard Henderson | } |
441 | f24518b5 | Richard Henderson | return val;
|
442 | f24518b5 | Richard Henderson | } |
443 | f24518b5 | Richard Henderson | |
444 | f24518b5 | Richard Henderson | /* Similar, but does not trap for infinities. Used for comparisons. */
|
445 | f24518b5 | Richard Henderson | uint64_t helper_ieee_input_cmp(uint64_t val) |
446 | f24518b5 | Richard Henderson | { |
447 | f24518b5 | Richard Henderson | uint32_t exp = (uint32_t)(val >> 52) & 0x7ff; |
448 | f24518b5 | Richard Henderson | uint64_t frac = val & 0xfffffffffffffull;
|
449 | f24518b5 | Richard Henderson | |
450 | f24518b5 | Richard Henderson | if (exp == 0) { |
451 | f24518b5 | Richard Henderson | if (frac != 0) { |
452 | f24518b5 | Richard Henderson | /* If DNZ is set flush denormals to zero on input. */
|
453 | f24518b5 | Richard Henderson | if (env->fpcr_dnz) {
|
454 | f24518b5 | Richard Henderson | val &= 1ull << 63; |
455 | f24518b5 | Richard Henderson | } else {
|
456 | b5f1aa64 | Richard Henderson | arith_excp(EXC_M_UNF, 0);
|
457 | f24518b5 | Richard Henderson | } |
458 | f24518b5 | Richard Henderson | } |
459 | f24518b5 | Richard Henderson | } else if (exp == 0x7ff && frac) { |
460 | f24518b5 | Richard Henderson | /* NaN. */
|
461 | b5f1aa64 | Richard Henderson | arith_excp(EXC_M_INV, 0);
|
462 | f24518b5 | Richard Henderson | } |
463 | f24518b5 | Richard Henderson | return val;
|
464 | f24518b5 | Richard Henderson | } |
465 | f24518b5 | Richard Henderson | |
466 | f24518b5 | Richard Henderson | /* Input remapping with software completion enabled. All we have to do
|
467 | f24518b5 | Richard Henderson | is handle denormal-map-to-zero; all other inputs get exceptions as
|
468 | f24518b5 | Richard Henderson | needed from the actual operation. */
|
469 | f24518b5 | Richard Henderson | uint64_t helper_ieee_input_s(uint64_t val) |
470 | f24518b5 | Richard Henderson | { |
471 | f24518b5 | Richard Henderson | if (env->fpcr_dnz) {
|
472 | f24518b5 | Richard Henderson | uint32_t exp = (uint32_t)(val >> 52) & 0x7ff; |
473 | f24518b5 | Richard Henderson | if (exp == 0) { |
474 | f24518b5 | Richard Henderson | val &= 1ull << 63; |
475 | f24518b5 | Richard Henderson | } |
476 | f24518b5 | Richard Henderson | } |
477 | f24518b5 | Richard Henderson | return val;
|
478 | f24518b5 | Richard Henderson | } |
479 | f24518b5 | Richard Henderson | |
480 | f18cd223 | aurel32 | /* F floating (VAX) */
|
481 | 636aa200 | Blue Swirl | static inline uint64_t float32_to_f(float32 fa) |
482 | 4c9649a9 | j_mayer | { |
483 | f18cd223 | aurel32 | uint64_t r, exp, mant, sig; |
484 | e2eb2798 | aurel32 | CPU_FloatU a; |
485 | f18cd223 | aurel32 | |
486 | e2eb2798 | aurel32 | a.f = fa; |
487 | e2eb2798 | aurel32 | sig = ((uint64_t)a.l & 0x80000000) << 32; |
488 | e2eb2798 | aurel32 | exp = (a.l >> 23) & 0xff; |
489 | e2eb2798 | aurel32 | mant = ((uint64_t)a.l & 0x007fffff) << 29; |
490 | f18cd223 | aurel32 | |
491 | f18cd223 | aurel32 | if (exp == 255) { |
492 | f18cd223 | aurel32 | /* NaN or infinity */
|
493 | f18cd223 | aurel32 | r = 1; /* VAX dirty zero */ |
494 | f18cd223 | aurel32 | } else if (exp == 0) { |
495 | f18cd223 | aurel32 | if (mant == 0) { |
496 | f18cd223 | aurel32 | /* Zero */
|
497 | f18cd223 | aurel32 | r = 0;
|
498 | f18cd223 | aurel32 | } else {
|
499 | f18cd223 | aurel32 | /* Denormalized */
|
500 | f18cd223 | aurel32 | r = sig | ((exp + 1) << 52) | mant; |
501 | f18cd223 | aurel32 | } |
502 | f18cd223 | aurel32 | } else {
|
503 | f18cd223 | aurel32 | if (exp >= 253) { |
504 | f18cd223 | aurel32 | /* Overflow */
|
505 | f18cd223 | aurel32 | r = 1; /* VAX dirty zero */ |
506 | f18cd223 | aurel32 | } else {
|
507 | f18cd223 | aurel32 | r = sig | ((exp + 2) << 52); |
508 | f18cd223 | aurel32 | } |
509 | f18cd223 | aurel32 | } |
510 | f18cd223 | aurel32 | |
511 | f18cd223 | aurel32 | return r;
|
512 | 4c9649a9 | j_mayer | } |
513 | 4c9649a9 | j_mayer | |
514 | 636aa200 | Blue Swirl | static inline float32 f_to_float32(uint64_t a) |
515 | 4c9649a9 | j_mayer | { |
516 | e2eb2798 | aurel32 | uint32_t exp, mant_sig; |
517 | e2eb2798 | aurel32 | CPU_FloatU r; |
518 | f18cd223 | aurel32 | |
519 | f18cd223 | aurel32 | exp = ((a >> 55) & 0x80) | ((a >> 52) & 0x7f); |
520 | f18cd223 | aurel32 | mant_sig = ((a >> 32) & 0x80000000) | ((a >> 29) & 0x007fffff); |
521 | f18cd223 | aurel32 | |
522 | f18cd223 | aurel32 | if (unlikely(!exp && mant_sig)) {
|
523 | f18cd223 | aurel32 | /* Reserved operands / Dirty zero */
|
524 | f18cd223 | aurel32 | helper_excp(EXCP_OPCDEC, 0);
|
525 | f18cd223 | aurel32 | } |
526 | f18cd223 | aurel32 | |
527 | f18cd223 | aurel32 | if (exp < 3) { |
528 | f18cd223 | aurel32 | /* Underflow */
|
529 | e2eb2798 | aurel32 | r.l = 0;
|
530 | f18cd223 | aurel32 | } else {
|
531 | e2eb2798 | aurel32 | r.l = ((exp - 2) << 23) | mant_sig; |
532 | f18cd223 | aurel32 | } |
533 | f18cd223 | aurel32 | |
534 | e2eb2798 | aurel32 | return r.f;
|
535 | 4c9649a9 | j_mayer | } |
536 | 4c9649a9 | j_mayer | |
537 | f18cd223 | aurel32 | uint32_t helper_f_to_memory (uint64_t a) |
538 | 4c9649a9 | j_mayer | { |
539 | f18cd223 | aurel32 | uint32_t r; |
540 | f18cd223 | aurel32 | r = (a & 0x00001fffe0000000ull) >> 13; |
541 | f18cd223 | aurel32 | r |= (a & 0x07ffe00000000000ull) >> 45; |
542 | f18cd223 | aurel32 | r |= (a & 0xc000000000000000ull) >> 48; |
543 | f18cd223 | aurel32 | return r;
|
544 | f18cd223 | aurel32 | } |
545 | 4c9649a9 | j_mayer | |
546 | f18cd223 | aurel32 | uint64_t helper_memory_to_f (uint32_t a) |
547 | f18cd223 | aurel32 | { |
548 | f18cd223 | aurel32 | uint64_t r; |
549 | f18cd223 | aurel32 | r = ((uint64_t)(a & 0x0000c000)) << 48; |
550 | f18cd223 | aurel32 | r |= ((uint64_t)(a & 0x003fffff)) << 45; |
551 | f18cd223 | aurel32 | r |= ((uint64_t)(a & 0xffff0000)) << 13; |
552 | f18cd223 | aurel32 | if (!(a & 0x00004000)) |
553 | f18cd223 | aurel32 | r |= 0x7ll << 59; |
554 | f18cd223 | aurel32 | return r;
|
555 | 4c9649a9 | j_mayer | } |
556 | 4c9649a9 | j_mayer | |
557 | f24518b5 | Richard Henderson | /* ??? Emulating VAX arithmetic with IEEE arithmetic is wrong. We should
|
558 | f24518b5 | Richard Henderson | either implement VAX arithmetic properly or just signal invalid opcode. */
|
559 | f24518b5 | Richard Henderson | |
560 | f18cd223 | aurel32 | uint64_t helper_addf (uint64_t a, uint64_t b) |
561 | 4c9649a9 | j_mayer | { |
562 | f18cd223 | aurel32 | float32 fa, fb, fr; |
563 | 4c9649a9 | j_mayer | |
564 | f18cd223 | aurel32 | fa = f_to_float32(a); |
565 | f18cd223 | aurel32 | fb = f_to_float32(b); |
566 | f18cd223 | aurel32 | fr = float32_add(fa, fb, &FP_STATUS); |
567 | f18cd223 | aurel32 | return float32_to_f(fr);
|
568 | 4c9649a9 | j_mayer | } |
569 | 4c9649a9 | j_mayer | |
570 | f18cd223 | aurel32 | uint64_t helper_subf (uint64_t a, uint64_t b) |
571 | 4c9649a9 | j_mayer | { |
572 | f18cd223 | aurel32 | float32 fa, fb, fr; |
573 | 4c9649a9 | j_mayer | |
574 | f18cd223 | aurel32 | fa = f_to_float32(a); |
575 | f18cd223 | aurel32 | fb = f_to_float32(b); |
576 | f18cd223 | aurel32 | fr = float32_sub(fa, fb, &FP_STATUS); |
577 | f18cd223 | aurel32 | return float32_to_f(fr);
|
578 | 4c9649a9 | j_mayer | } |
579 | 4c9649a9 | j_mayer | |
580 | f18cd223 | aurel32 | uint64_t helper_mulf (uint64_t a, uint64_t b) |
581 | 4c9649a9 | j_mayer | { |
582 | f18cd223 | aurel32 | float32 fa, fb, fr; |
583 | 4c9649a9 | j_mayer | |
584 | f18cd223 | aurel32 | fa = f_to_float32(a); |
585 | f18cd223 | aurel32 | fb = f_to_float32(b); |
586 | f18cd223 | aurel32 | fr = float32_mul(fa, fb, &FP_STATUS); |
587 | f18cd223 | aurel32 | return float32_to_f(fr);
|
588 | 4c9649a9 | j_mayer | } |
589 | 4c9649a9 | j_mayer | |
590 | f18cd223 | aurel32 | uint64_t helper_divf (uint64_t a, uint64_t b) |
591 | 4c9649a9 | j_mayer | { |
592 | f18cd223 | aurel32 | float32 fa, fb, fr; |
593 | 4c9649a9 | j_mayer | |
594 | f18cd223 | aurel32 | fa = f_to_float32(a); |
595 | f18cd223 | aurel32 | fb = f_to_float32(b); |
596 | f18cd223 | aurel32 | fr = float32_div(fa, fb, &FP_STATUS); |
597 | f18cd223 | aurel32 | return float32_to_f(fr);
|
598 | 4c9649a9 | j_mayer | } |
599 | 4c9649a9 | j_mayer | |
600 | f18cd223 | aurel32 | uint64_t helper_sqrtf (uint64_t t) |
601 | 4c9649a9 | j_mayer | { |
602 | f18cd223 | aurel32 | float32 ft, fr; |
603 | f18cd223 | aurel32 | |
604 | f18cd223 | aurel32 | ft = f_to_float32(t); |
605 | f18cd223 | aurel32 | fr = float32_sqrt(ft, &FP_STATUS); |
606 | f18cd223 | aurel32 | return float32_to_f(fr);
|
607 | 4c9649a9 | j_mayer | } |
608 | 4c9649a9 | j_mayer | |
609 | f18cd223 | aurel32 | |
610 | f18cd223 | aurel32 | /* G floating (VAX) */
|
611 | 636aa200 | Blue Swirl | static inline uint64_t float64_to_g(float64 fa) |
612 | 4c9649a9 | j_mayer | { |
613 | e2eb2798 | aurel32 | uint64_t r, exp, mant, sig; |
614 | e2eb2798 | aurel32 | CPU_DoubleU a; |
615 | 4c9649a9 | j_mayer | |
616 | e2eb2798 | aurel32 | a.d = fa; |
617 | e2eb2798 | aurel32 | sig = a.ll & 0x8000000000000000ull;
|
618 | e2eb2798 | aurel32 | exp = (a.ll >> 52) & 0x7ff; |
619 | e2eb2798 | aurel32 | mant = a.ll & 0x000fffffffffffffull;
|
620 | f18cd223 | aurel32 | |
621 | f18cd223 | aurel32 | if (exp == 2047) { |
622 | f18cd223 | aurel32 | /* NaN or infinity */
|
623 | f18cd223 | aurel32 | r = 1; /* VAX dirty zero */ |
624 | f18cd223 | aurel32 | } else if (exp == 0) { |
625 | f18cd223 | aurel32 | if (mant == 0) { |
626 | f18cd223 | aurel32 | /* Zero */
|
627 | f18cd223 | aurel32 | r = 0;
|
628 | f18cd223 | aurel32 | } else {
|
629 | f18cd223 | aurel32 | /* Denormalized */
|
630 | f18cd223 | aurel32 | r = sig | ((exp + 1) << 52) | mant; |
631 | f18cd223 | aurel32 | } |
632 | f18cd223 | aurel32 | } else {
|
633 | f18cd223 | aurel32 | if (exp >= 2045) { |
634 | f18cd223 | aurel32 | /* Overflow */
|
635 | f18cd223 | aurel32 | r = 1; /* VAX dirty zero */ |
636 | f18cd223 | aurel32 | } else {
|
637 | f18cd223 | aurel32 | r = sig | ((exp + 2) << 52); |
638 | f18cd223 | aurel32 | } |
639 | f18cd223 | aurel32 | } |
640 | f18cd223 | aurel32 | |
641 | f18cd223 | aurel32 | return r;
|
642 | 4c9649a9 | j_mayer | } |
643 | 4c9649a9 | j_mayer | |
644 | 636aa200 | Blue Swirl | static inline float64 g_to_float64(uint64_t a) |
645 | 4c9649a9 | j_mayer | { |
646 | e2eb2798 | aurel32 | uint64_t exp, mant_sig; |
647 | e2eb2798 | aurel32 | CPU_DoubleU r; |
648 | f18cd223 | aurel32 | |
649 | f18cd223 | aurel32 | exp = (a >> 52) & 0x7ff; |
650 | f18cd223 | aurel32 | mant_sig = a & 0x800fffffffffffffull;
|
651 | f18cd223 | aurel32 | |
652 | f18cd223 | aurel32 | if (!exp && mant_sig) {
|
653 | f18cd223 | aurel32 | /* Reserved operands / Dirty zero */
|
654 | f18cd223 | aurel32 | helper_excp(EXCP_OPCDEC, 0);
|
655 | f18cd223 | aurel32 | } |
656 | 4c9649a9 | j_mayer | |
657 | f18cd223 | aurel32 | if (exp < 3) { |
658 | f18cd223 | aurel32 | /* Underflow */
|
659 | e2eb2798 | aurel32 | r.ll = 0;
|
660 | f18cd223 | aurel32 | } else {
|
661 | e2eb2798 | aurel32 | r.ll = ((exp - 2) << 52) | mant_sig; |
662 | f18cd223 | aurel32 | } |
663 | f18cd223 | aurel32 | |
664 | e2eb2798 | aurel32 | return r.d;
|
665 | 4c9649a9 | j_mayer | } |
666 | 4c9649a9 | j_mayer | |
667 | f18cd223 | aurel32 | uint64_t helper_g_to_memory (uint64_t a) |
668 | 4c9649a9 | j_mayer | { |
669 | f18cd223 | aurel32 | uint64_t r; |
670 | f18cd223 | aurel32 | r = (a & 0x000000000000ffffull) << 48; |
671 | f18cd223 | aurel32 | r |= (a & 0x00000000ffff0000ull) << 16; |
672 | f18cd223 | aurel32 | r |= (a & 0x0000ffff00000000ull) >> 16; |
673 | f18cd223 | aurel32 | r |= (a & 0xffff000000000000ull) >> 48; |
674 | f18cd223 | aurel32 | return r;
|
675 | f18cd223 | aurel32 | } |
676 | 4c9649a9 | j_mayer | |
677 | f18cd223 | aurel32 | uint64_t helper_memory_to_g (uint64_t a) |
678 | f18cd223 | aurel32 | { |
679 | f18cd223 | aurel32 | uint64_t r; |
680 | f18cd223 | aurel32 | r = (a & 0x000000000000ffffull) << 48; |
681 | f18cd223 | aurel32 | r |= (a & 0x00000000ffff0000ull) << 16; |
682 | f18cd223 | aurel32 | r |= (a & 0x0000ffff00000000ull) >> 16; |
683 | f18cd223 | aurel32 | r |= (a & 0xffff000000000000ull) >> 48; |
684 | f18cd223 | aurel32 | return r;
|
685 | 4c9649a9 | j_mayer | } |
686 | 4c9649a9 | j_mayer | |
687 | f18cd223 | aurel32 | uint64_t helper_addg (uint64_t a, uint64_t b) |
688 | 4c9649a9 | j_mayer | { |
689 | f18cd223 | aurel32 | float64 fa, fb, fr; |
690 | 4c9649a9 | j_mayer | |
691 | f18cd223 | aurel32 | fa = g_to_float64(a); |
692 | f18cd223 | aurel32 | fb = g_to_float64(b); |
693 | f18cd223 | aurel32 | fr = float64_add(fa, fb, &FP_STATUS); |
694 | f18cd223 | aurel32 | return float64_to_g(fr);
|
695 | 4c9649a9 | j_mayer | } |
696 | 4c9649a9 | j_mayer | |
697 | f18cd223 | aurel32 | uint64_t helper_subg (uint64_t a, uint64_t b) |
698 | 4c9649a9 | j_mayer | { |
699 | f18cd223 | aurel32 | float64 fa, fb, fr; |
700 | 4c9649a9 | j_mayer | |
701 | f18cd223 | aurel32 | fa = g_to_float64(a); |
702 | f18cd223 | aurel32 | fb = g_to_float64(b); |
703 | f18cd223 | aurel32 | fr = float64_sub(fa, fb, &FP_STATUS); |
704 | f18cd223 | aurel32 | return float64_to_g(fr);
|
705 | 4c9649a9 | j_mayer | } |
706 | 4c9649a9 | j_mayer | |
707 | f18cd223 | aurel32 | uint64_t helper_mulg (uint64_t a, uint64_t b) |
708 | 4c9649a9 | j_mayer | { |
709 | f18cd223 | aurel32 | float64 fa, fb, fr; |
710 | 4c9649a9 | j_mayer | |
711 | f18cd223 | aurel32 | fa = g_to_float64(a); |
712 | f18cd223 | aurel32 | fb = g_to_float64(b); |
713 | f18cd223 | aurel32 | fr = float64_mul(fa, fb, &FP_STATUS); |
714 | f18cd223 | aurel32 | return float64_to_g(fr);
|
715 | 4c9649a9 | j_mayer | } |
716 | 4c9649a9 | j_mayer | |
717 | f18cd223 | aurel32 | uint64_t helper_divg (uint64_t a, uint64_t b) |
718 | 4c9649a9 | j_mayer | { |
719 | f18cd223 | aurel32 | float64 fa, fb, fr; |
720 | 4c9649a9 | j_mayer | |
721 | f18cd223 | aurel32 | fa = g_to_float64(a); |
722 | f18cd223 | aurel32 | fb = g_to_float64(b); |
723 | f18cd223 | aurel32 | fr = float64_div(fa, fb, &FP_STATUS); |
724 | f18cd223 | aurel32 | return float64_to_g(fr);
|
725 | f18cd223 | aurel32 | } |
726 | f18cd223 | aurel32 | |
727 | f18cd223 | aurel32 | uint64_t helper_sqrtg (uint64_t a) |
728 | f18cd223 | aurel32 | { |
729 | f18cd223 | aurel32 | float64 fa, fr; |
730 | 4c9649a9 | j_mayer | |
731 | f18cd223 | aurel32 | fa = g_to_float64(a); |
732 | f18cd223 | aurel32 | fr = float64_sqrt(fa, &FP_STATUS); |
733 | f18cd223 | aurel32 | return float64_to_g(fr);
|
734 | 4c9649a9 | j_mayer | } |
735 | 4c9649a9 | j_mayer | |
736 | f18cd223 | aurel32 | |
737 | f18cd223 | aurel32 | /* S floating (single) */
|
738 | d0af5445 | Richard Henderson | |
739 | d0af5445 | Richard Henderson | /* Taken from linux/arch/alpha/kernel/traps.c, s_mem_to_reg. */
|
740 | d0af5445 | Richard Henderson | static inline uint64_t float32_to_s_int(uint32_t fi) |
741 | d0af5445 | Richard Henderson | { |
742 | d0af5445 | Richard Henderson | uint32_t frac = fi & 0x7fffff;
|
743 | d0af5445 | Richard Henderson | uint32_t sign = fi >> 31;
|
744 | d0af5445 | Richard Henderson | uint32_t exp_msb = (fi >> 30) & 1; |
745 | d0af5445 | Richard Henderson | uint32_t exp_low = (fi >> 23) & 0x7f; |
746 | d0af5445 | Richard Henderson | uint32_t exp; |
747 | d0af5445 | Richard Henderson | |
748 | d0af5445 | Richard Henderson | exp = (exp_msb << 10) | exp_low;
|
749 | d0af5445 | Richard Henderson | if (exp_msb) {
|
750 | d0af5445 | Richard Henderson | if (exp_low == 0x7f) |
751 | d0af5445 | Richard Henderson | exp = 0x7ff;
|
752 | d0af5445 | Richard Henderson | } else {
|
753 | d0af5445 | Richard Henderson | if (exp_low != 0x00) |
754 | d0af5445 | Richard Henderson | exp |= 0x380;
|
755 | d0af5445 | Richard Henderson | } |
756 | d0af5445 | Richard Henderson | |
757 | d0af5445 | Richard Henderson | return (((uint64_t)sign << 63) |
758 | d0af5445 | Richard Henderson | | ((uint64_t)exp << 52)
|
759 | d0af5445 | Richard Henderson | | ((uint64_t)frac << 29));
|
760 | d0af5445 | Richard Henderson | } |
761 | d0af5445 | Richard Henderson | |
762 | 636aa200 | Blue Swirl | static inline uint64_t float32_to_s(float32 fa) |
763 | 4c9649a9 | j_mayer | { |
764 | e2eb2798 | aurel32 | CPU_FloatU a; |
765 | e2eb2798 | aurel32 | a.f = fa; |
766 | d0af5445 | Richard Henderson | return float32_to_s_int(a.l);
|
767 | d0af5445 | Richard Henderson | } |
768 | 4c9649a9 | j_mayer | |
769 | d0af5445 | Richard Henderson | static inline uint32_t s_to_float32_int(uint64_t a) |
770 | d0af5445 | Richard Henderson | { |
771 | d0af5445 | Richard Henderson | return ((a >> 32) & 0xc0000000) | ((a >> 29) & 0x3fffffff); |
772 | 4c9649a9 | j_mayer | } |
773 | 4c9649a9 | j_mayer | |
774 | 636aa200 | Blue Swirl | static inline float32 s_to_float32(uint64_t a) |
775 | 4c9649a9 | j_mayer | { |
776 | e2eb2798 | aurel32 | CPU_FloatU r; |
777 | d0af5445 | Richard Henderson | r.l = s_to_float32_int(a); |
778 | e2eb2798 | aurel32 | return r.f;
|
779 | f18cd223 | aurel32 | } |
780 | 4c9649a9 | j_mayer | |
781 | f18cd223 | aurel32 | uint32_t helper_s_to_memory (uint64_t a) |
782 | f18cd223 | aurel32 | { |
783 | d0af5445 | Richard Henderson | return s_to_float32_int(a);
|
784 | f18cd223 | aurel32 | } |
785 | 4c9649a9 | j_mayer | |
786 | f18cd223 | aurel32 | uint64_t helper_memory_to_s (uint32_t a) |
787 | f18cd223 | aurel32 | { |
788 | d0af5445 | Richard Henderson | return float32_to_s_int(a);
|
789 | 4c9649a9 | j_mayer | } |
790 | 4c9649a9 | j_mayer | |
791 | f18cd223 | aurel32 | uint64_t helper_adds (uint64_t a, uint64_t b) |
792 | 4c9649a9 | j_mayer | { |
793 | f18cd223 | aurel32 | float32 fa, fb, fr; |
794 | 4c9649a9 | j_mayer | |
795 | f18cd223 | aurel32 | fa = s_to_float32(a); |
796 | f18cd223 | aurel32 | fb = s_to_float32(b); |
797 | f18cd223 | aurel32 | fr = float32_add(fa, fb, &FP_STATUS); |
798 | f18cd223 | aurel32 | return float32_to_s(fr);
|
799 | 4c9649a9 | j_mayer | } |
800 | 4c9649a9 | j_mayer | |
801 | f18cd223 | aurel32 | uint64_t helper_subs (uint64_t a, uint64_t b) |
802 | 4c9649a9 | j_mayer | { |
803 | f18cd223 | aurel32 | float32 fa, fb, fr; |
804 | 4c9649a9 | j_mayer | |
805 | f18cd223 | aurel32 | fa = s_to_float32(a); |
806 | f18cd223 | aurel32 | fb = s_to_float32(b); |
807 | f18cd223 | aurel32 | fr = float32_sub(fa, fb, &FP_STATUS); |
808 | f18cd223 | aurel32 | return float32_to_s(fr);
|
809 | 4c9649a9 | j_mayer | } |
810 | 4c9649a9 | j_mayer | |
811 | f18cd223 | aurel32 | uint64_t helper_muls (uint64_t a, uint64_t b) |
812 | 4c9649a9 | j_mayer | { |
813 | f18cd223 | aurel32 | float32 fa, fb, fr; |
814 | 4c9649a9 | j_mayer | |
815 | f18cd223 | aurel32 | fa = s_to_float32(a); |
816 | f18cd223 | aurel32 | fb = s_to_float32(b); |
817 | f18cd223 | aurel32 | fr = float32_mul(fa, fb, &FP_STATUS); |
818 | f18cd223 | aurel32 | return float32_to_s(fr);
|
819 | 4c9649a9 | j_mayer | } |
820 | 4c9649a9 | j_mayer | |
821 | f18cd223 | aurel32 | uint64_t helper_divs (uint64_t a, uint64_t b) |
822 | 4c9649a9 | j_mayer | { |
823 | f18cd223 | aurel32 | float32 fa, fb, fr; |
824 | 4c9649a9 | j_mayer | |
825 | f18cd223 | aurel32 | fa = s_to_float32(a); |
826 | f18cd223 | aurel32 | fb = s_to_float32(b); |
827 | f18cd223 | aurel32 | fr = float32_div(fa, fb, &FP_STATUS); |
828 | f18cd223 | aurel32 | return float32_to_s(fr);
|
829 | 4c9649a9 | j_mayer | } |
830 | 4c9649a9 | j_mayer | |
831 | f18cd223 | aurel32 | uint64_t helper_sqrts (uint64_t a) |
832 | 4c9649a9 | j_mayer | { |
833 | f18cd223 | aurel32 | float32 fa, fr; |
834 | 4c9649a9 | j_mayer | |
835 | f18cd223 | aurel32 | fa = s_to_float32(a); |
836 | f18cd223 | aurel32 | fr = float32_sqrt(fa, &FP_STATUS); |
837 | f18cd223 | aurel32 | return float32_to_s(fr);
|
838 | 4c9649a9 | j_mayer | } |
839 | 4c9649a9 | j_mayer | |
840 | f18cd223 | aurel32 | |
841 | f18cd223 | aurel32 | /* T floating (double) */
|
842 | 636aa200 | Blue Swirl | static inline float64 t_to_float64(uint64_t a) |
843 | 4c9649a9 | j_mayer | { |
844 | f18cd223 | aurel32 | /* Memory format is the same as float64 */
|
845 | e2eb2798 | aurel32 | CPU_DoubleU r; |
846 | e2eb2798 | aurel32 | r.ll = a; |
847 | e2eb2798 | aurel32 | return r.d;
|
848 | 4c9649a9 | j_mayer | } |
849 | 4c9649a9 | j_mayer | |
850 | 636aa200 | Blue Swirl | static inline uint64_t float64_to_t(float64 fa) |
851 | 4c9649a9 | j_mayer | { |
852 | f18cd223 | aurel32 | /* Memory format is the same as float64 */
|
853 | e2eb2798 | aurel32 | CPU_DoubleU r; |
854 | e2eb2798 | aurel32 | r.d = fa; |
855 | e2eb2798 | aurel32 | return r.ll;
|
856 | f18cd223 | aurel32 | } |
857 | 4c9649a9 | j_mayer | |
858 | f18cd223 | aurel32 | uint64_t helper_addt (uint64_t a, uint64_t b) |
859 | f18cd223 | aurel32 | { |
860 | f18cd223 | aurel32 | float64 fa, fb, fr; |
861 | 4c9649a9 | j_mayer | |
862 | f18cd223 | aurel32 | fa = t_to_float64(a); |
863 | f18cd223 | aurel32 | fb = t_to_float64(b); |
864 | f18cd223 | aurel32 | fr = float64_add(fa, fb, &FP_STATUS); |
865 | f18cd223 | aurel32 | return float64_to_t(fr);
|
866 | 4c9649a9 | j_mayer | } |
867 | 4c9649a9 | j_mayer | |
868 | f18cd223 | aurel32 | uint64_t helper_subt (uint64_t a, uint64_t b) |
869 | 4c9649a9 | j_mayer | { |
870 | f18cd223 | aurel32 | float64 fa, fb, fr; |
871 | 4c9649a9 | j_mayer | |
872 | f18cd223 | aurel32 | fa = t_to_float64(a); |
873 | f18cd223 | aurel32 | fb = t_to_float64(b); |
874 | f18cd223 | aurel32 | fr = float64_sub(fa, fb, &FP_STATUS); |
875 | f18cd223 | aurel32 | return float64_to_t(fr);
|
876 | 4c9649a9 | j_mayer | } |
877 | 4c9649a9 | j_mayer | |
878 | f18cd223 | aurel32 | uint64_t helper_mult (uint64_t a, uint64_t b) |
879 | 4c9649a9 | j_mayer | { |
880 | f18cd223 | aurel32 | float64 fa, fb, fr; |
881 | 4c9649a9 | j_mayer | |
882 | f18cd223 | aurel32 | fa = t_to_float64(a); |
883 | f18cd223 | aurel32 | fb = t_to_float64(b); |
884 | f18cd223 | aurel32 | fr = float64_mul(fa, fb, &FP_STATUS); |
885 | f18cd223 | aurel32 | return float64_to_t(fr);
|
886 | 4c9649a9 | j_mayer | } |
887 | 4c9649a9 | j_mayer | |
888 | f18cd223 | aurel32 | uint64_t helper_divt (uint64_t a, uint64_t b) |
889 | 4c9649a9 | j_mayer | { |
890 | f18cd223 | aurel32 | float64 fa, fb, fr; |
891 | 4c9649a9 | j_mayer | |
892 | f18cd223 | aurel32 | fa = t_to_float64(a); |
893 | f18cd223 | aurel32 | fb = t_to_float64(b); |
894 | f18cd223 | aurel32 | fr = float64_div(fa, fb, &FP_STATUS); |
895 | f18cd223 | aurel32 | return float64_to_t(fr);
|
896 | 4c9649a9 | j_mayer | } |
897 | 4c9649a9 | j_mayer | |
898 | f18cd223 | aurel32 | uint64_t helper_sqrtt (uint64_t a) |
899 | 4c9649a9 | j_mayer | { |
900 | f18cd223 | aurel32 | float64 fa, fr; |
901 | 4c9649a9 | j_mayer | |
902 | f18cd223 | aurel32 | fa = t_to_float64(a); |
903 | f18cd223 | aurel32 | fr = float64_sqrt(fa, &FP_STATUS); |
904 | f18cd223 | aurel32 | return float64_to_t(fr);
|
905 | 4c9649a9 | j_mayer | } |
906 | 4c9649a9 | j_mayer | |
907 | f18cd223 | aurel32 | /* Comparisons */
|
908 | f18cd223 | aurel32 | uint64_t helper_cmptun (uint64_t a, uint64_t b) |
909 | 4c9649a9 | j_mayer | { |
910 | f18cd223 | aurel32 | float64 fa, fb; |
911 | 4c9649a9 | j_mayer | |
912 | f18cd223 | aurel32 | fa = t_to_float64(a); |
913 | f18cd223 | aurel32 | fb = t_to_float64(b); |
914 | f18cd223 | aurel32 | |
915 | a4d2d1a0 | Aurelien Jarno | if (float64_unordered_quiet(fa, fb, &FP_STATUS)) {
|
916 | f18cd223 | aurel32 | return 0x4000000000000000ULL; |
917 | a4d2d1a0 | Aurelien Jarno | } else {
|
918 | f18cd223 | aurel32 | return 0; |
919 | a4d2d1a0 | Aurelien Jarno | } |
920 | 4c9649a9 | j_mayer | } |
921 | 4c9649a9 | j_mayer | |
922 | f18cd223 | aurel32 | uint64_t helper_cmpteq(uint64_t a, uint64_t b) |
923 | 4c9649a9 | j_mayer | { |
924 | f18cd223 | aurel32 | float64 fa, fb; |
925 | 4c9649a9 | j_mayer | |
926 | f18cd223 | aurel32 | fa = t_to_float64(a); |
927 | f18cd223 | aurel32 | fb = t_to_float64(b); |
928 | f18cd223 | aurel32 | |
929 | 211315fb | Aurelien Jarno | if (float64_eq_quiet(fa, fb, &FP_STATUS))
|
930 | f18cd223 | aurel32 | return 0x4000000000000000ULL; |
931 | f18cd223 | aurel32 | else
|
932 | f18cd223 | aurel32 | return 0; |
933 | 4c9649a9 | j_mayer | } |
934 | 4c9649a9 | j_mayer | |
935 | f18cd223 | aurel32 | uint64_t helper_cmptle(uint64_t a, uint64_t b) |
936 | 4c9649a9 | j_mayer | { |
937 | f18cd223 | aurel32 | float64 fa, fb; |
938 | 4c9649a9 | j_mayer | |
939 | f18cd223 | aurel32 | fa = t_to_float64(a); |
940 | f18cd223 | aurel32 | fb = t_to_float64(b); |
941 | f18cd223 | aurel32 | |
942 | f18cd223 | aurel32 | if (float64_le(fa, fb, &FP_STATUS))
|
943 | f18cd223 | aurel32 | return 0x4000000000000000ULL; |
944 | f18cd223 | aurel32 | else
|
945 | f18cd223 | aurel32 | return 0; |
946 | 4c9649a9 | j_mayer | } |
947 | 4c9649a9 | j_mayer | |
948 | f18cd223 | aurel32 | uint64_t helper_cmptlt(uint64_t a, uint64_t b) |
949 | 4c9649a9 | j_mayer | { |
950 | f18cd223 | aurel32 | float64 fa, fb; |
951 | 4c9649a9 | j_mayer | |
952 | f18cd223 | aurel32 | fa = t_to_float64(a); |
953 | f18cd223 | aurel32 | fb = t_to_float64(b); |
954 | f18cd223 | aurel32 | |
955 | f18cd223 | aurel32 | if (float64_lt(fa, fb, &FP_STATUS))
|
956 | f18cd223 | aurel32 | return 0x4000000000000000ULL; |
957 | f18cd223 | aurel32 | else
|
958 | f18cd223 | aurel32 | return 0; |
959 | 4c9649a9 | j_mayer | } |
960 | 4c9649a9 | j_mayer | |
961 | f18cd223 | aurel32 | uint64_t helper_cmpgeq(uint64_t a, uint64_t b) |
962 | 4c9649a9 | j_mayer | { |
963 | f18cd223 | aurel32 | float64 fa, fb; |
964 | 4c9649a9 | j_mayer | |
965 | f18cd223 | aurel32 | fa = g_to_float64(a); |
966 | f18cd223 | aurel32 | fb = g_to_float64(b); |
967 | f18cd223 | aurel32 | |
968 | 211315fb | Aurelien Jarno | if (float64_eq_quiet(fa, fb, &FP_STATUS))
|
969 | f18cd223 | aurel32 | return 0x4000000000000000ULL; |
970 | f18cd223 | aurel32 | else
|
971 | f18cd223 | aurel32 | return 0; |
972 | 4c9649a9 | j_mayer | } |
973 | 4c9649a9 | j_mayer | |
974 | f18cd223 | aurel32 | uint64_t helper_cmpgle(uint64_t a, uint64_t b) |
975 | 4c9649a9 | j_mayer | { |
976 | f18cd223 | aurel32 | float64 fa, fb; |
977 | f18cd223 | aurel32 | |
978 | f18cd223 | aurel32 | fa = g_to_float64(a); |
979 | f18cd223 | aurel32 | fb = g_to_float64(b); |
980 | 4c9649a9 | j_mayer | |
981 | f18cd223 | aurel32 | if (float64_le(fa, fb, &FP_STATUS))
|
982 | f18cd223 | aurel32 | return 0x4000000000000000ULL; |
983 | f18cd223 | aurel32 | else
|
984 | f18cd223 | aurel32 | return 0; |
985 | 4c9649a9 | j_mayer | } |
986 | 4c9649a9 | j_mayer | |
987 | f18cd223 | aurel32 | uint64_t helper_cmpglt(uint64_t a, uint64_t b) |
988 | 4c9649a9 | j_mayer | { |
989 | f18cd223 | aurel32 | float64 fa, fb; |
990 | f18cd223 | aurel32 | |
991 | f18cd223 | aurel32 | fa = g_to_float64(a); |
992 | f18cd223 | aurel32 | fb = g_to_float64(b); |
993 | 4c9649a9 | j_mayer | |
994 | f18cd223 | aurel32 | if (float64_lt(fa, fb, &FP_STATUS))
|
995 | f18cd223 | aurel32 | return 0x4000000000000000ULL; |
996 | f18cd223 | aurel32 | else
|
997 | f18cd223 | aurel32 | return 0; |
998 | 4c9649a9 | j_mayer | } |
999 | 4c9649a9 | j_mayer | |
1000 | f18cd223 | aurel32 | /* Floating point format conversion */
|
1001 | f18cd223 | aurel32 | uint64_t helper_cvtts (uint64_t a) |
1002 | 4c9649a9 | j_mayer | { |
1003 | f18cd223 | aurel32 | float64 fa; |
1004 | f18cd223 | aurel32 | float32 fr; |
1005 | 4c9649a9 | j_mayer | |
1006 | f18cd223 | aurel32 | fa = t_to_float64(a); |
1007 | f18cd223 | aurel32 | fr = float64_to_float32(fa, &FP_STATUS); |
1008 | f18cd223 | aurel32 | return float32_to_s(fr);
|
1009 | 4c9649a9 | j_mayer | } |
1010 | 4c9649a9 | j_mayer | |
1011 | f18cd223 | aurel32 | uint64_t helper_cvtst (uint64_t a) |
1012 | 4c9649a9 | j_mayer | { |
1013 | f18cd223 | aurel32 | float32 fa; |
1014 | f18cd223 | aurel32 | float64 fr; |
1015 | f18cd223 | aurel32 | |
1016 | f18cd223 | aurel32 | fa = s_to_float32(a); |
1017 | f18cd223 | aurel32 | fr = float32_to_float64(fa, &FP_STATUS); |
1018 | f18cd223 | aurel32 | return float64_to_t(fr);
|
1019 | 4c9649a9 | j_mayer | } |
1020 | 4c9649a9 | j_mayer | |
1021 | f18cd223 | aurel32 | uint64_t helper_cvtqs (uint64_t a) |
1022 | 4c9649a9 | j_mayer | { |
1023 | f18cd223 | aurel32 | float32 fr = int64_to_float32(a, &FP_STATUS); |
1024 | f18cd223 | aurel32 | return float32_to_s(fr);
|
1025 | 4c9649a9 | j_mayer | } |
1026 | 4c9649a9 | j_mayer | |
1027 | f24518b5 | Richard Henderson | /* Implement float64 to uint64 conversion without saturation -- we must
|
1028 | f24518b5 | Richard Henderson | supply the truncated result. This behaviour is used by the compiler
|
1029 | f24518b5 | Richard Henderson | to get unsigned conversion for free with the same instruction.
|
1030 | f24518b5 | Richard Henderson | |
1031 | f24518b5 | Richard Henderson | The VI flag is set when overflow or inexact exceptions should be raised. */
|
1032 | f24518b5 | Richard Henderson | |
1033 | f24518b5 | Richard Henderson | static inline uint64_t helper_cvttq_internal(uint64_t a, int roundmode, int VI) |
1034 | 4c9649a9 | j_mayer | { |
1035 | f24518b5 | Richard Henderson | uint64_t frac, ret = 0;
|
1036 | f24518b5 | Richard Henderson | uint32_t exp, sign, exc = 0;
|
1037 | f24518b5 | Richard Henderson | int shift;
|
1038 | f24518b5 | Richard Henderson | |
1039 | f24518b5 | Richard Henderson | sign = (a >> 63);
|
1040 | f24518b5 | Richard Henderson | exp = (uint32_t)(a >> 52) & 0x7ff; |
1041 | f24518b5 | Richard Henderson | frac = a & 0xfffffffffffffull;
|
1042 | f24518b5 | Richard Henderson | |
1043 | f24518b5 | Richard Henderson | if (exp == 0) { |
1044 | f24518b5 | Richard Henderson | if (unlikely(frac != 0)) { |
1045 | f24518b5 | Richard Henderson | goto do_underflow;
|
1046 | f24518b5 | Richard Henderson | } |
1047 | f24518b5 | Richard Henderson | } else if (exp == 0x7ff) { |
1048 | f24518b5 | Richard Henderson | exc = (frac ? float_flag_invalid : VI ? float_flag_overflow : 0);
|
1049 | f24518b5 | Richard Henderson | } else {
|
1050 | f24518b5 | Richard Henderson | /* Restore implicit bit. */
|
1051 | f24518b5 | Richard Henderson | frac |= 0x10000000000000ull;
|
1052 | f24518b5 | Richard Henderson | |
1053 | f24518b5 | Richard Henderson | shift = exp - 1023 - 52; |
1054 | f24518b5 | Richard Henderson | if (shift >= 0) { |
1055 | f24518b5 | Richard Henderson | /* In this case the number is so large that we must shift
|
1056 | f24518b5 | Richard Henderson | the fraction left. There is no rounding to do. */
|
1057 | f24518b5 | Richard Henderson | if (shift < 63) { |
1058 | f24518b5 | Richard Henderson | ret = frac << shift; |
1059 | f24518b5 | Richard Henderson | if (VI && (ret >> shift) != frac) {
|
1060 | f24518b5 | Richard Henderson | exc = float_flag_overflow; |
1061 | f24518b5 | Richard Henderson | } |
1062 | f24518b5 | Richard Henderson | } |
1063 | f24518b5 | Richard Henderson | } else {
|
1064 | f24518b5 | Richard Henderson | uint64_t round; |
1065 | f24518b5 | Richard Henderson | |
1066 | f24518b5 | Richard Henderson | /* In this case the number is smaller than the fraction as
|
1067 | f24518b5 | Richard Henderson | represented by the 52 bit number. Here we must think
|
1068 | f24518b5 | Richard Henderson | about rounding the result. Handle this by shifting the
|
1069 | f24518b5 | Richard Henderson | fractional part of the number into the high bits of ROUND.
|
1070 | f24518b5 | Richard Henderson | This will let us efficiently handle round-to-nearest. */
|
1071 | f24518b5 | Richard Henderson | shift = -shift; |
1072 | f24518b5 | Richard Henderson | if (shift < 63) { |
1073 | f24518b5 | Richard Henderson | ret = frac >> shift; |
1074 | f24518b5 | Richard Henderson | round = frac << (64 - shift);
|
1075 | f24518b5 | Richard Henderson | } else {
|
1076 | f24518b5 | Richard Henderson | /* The exponent is so small we shift out everything.
|
1077 | f24518b5 | Richard Henderson | Leave a sticky bit for proper rounding below. */
|
1078 | f24518b5 | Richard Henderson | do_underflow:
|
1079 | f24518b5 | Richard Henderson | round = 1;
|
1080 | f24518b5 | Richard Henderson | } |
1081 | f24518b5 | Richard Henderson | |
1082 | f24518b5 | Richard Henderson | if (round) {
|
1083 | f24518b5 | Richard Henderson | exc = (VI ? float_flag_inexact : 0);
|
1084 | f24518b5 | Richard Henderson | switch (roundmode) {
|
1085 | f24518b5 | Richard Henderson | case float_round_nearest_even:
|
1086 | f24518b5 | Richard Henderson | if (round == (1ull << 63)) { |
1087 | f24518b5 | Richard Henderson | /* Fraction is exactly 0.5; round to even. */
|
1088 | f24518b5 | Richard Henderson | ret += (ret & 1);
|
1089 | f24518b5 | Richard Henderson | } else if (round > (1ull << 63)) { |
1090 | f24518b5 | Richard Henderson | ret += 1;
|
1091 | f24518b5 | Richard Henderson | } |
1092 | f24518b5 | Richard Henderson | break;
|
1093 | f24518b5 | Richard Henderson | case float_round_to_zero:
|
1094 | f24518b5 | Richard Henderson | break;
|
1095 | f24518b5 | Richard Henderson | case float_round_up:
|
1096 | f24518b5 | Richard Henderson | ret += 1 - sign;
|
1097 | f24518b5 | Richard Henderson | break;
|
1098 | f24518b5 | Richard Henderson | case float_round_down:
|
1099 | f24518b5 | Richard Henderson | ret += sign; |
1100 | f24518b5 | Richard Henderson | break;
|
1101 | f24518b5 | Richard Henderson | } |
1102 | f24518b5 | Richard Henderson | } |
1103 | f24518b5 | Richard Henderson | } |
1104 | f24518b5 | Richard Henderson | if (sign) {
|
1105 | f24518b5 | Richard Henderson | ret = -ret; |
1106 | f24518b5 | Richard Henderson | } |
1107 | f24518b5 | Richard Henderson | } |
1108 | f24518b5 | Richard Henderson | if (unlikely(exc)) {
|
1109 | f24518b5 | Richard Henderson | float_raise(exc, &FP_STATUS); |
1110 | f24518b5 | Richard Henderson | } |
1111 | f24518b5 | Richard Henderson | |
1112 | f24518b5 | Richard Henderson | return ret;
|
1113 | f24518b5 | Richard Henderson | } |
1114 | f24518b5 | Richard Henderson | |
1115 | f24518b5 | Richard Henderson | uint64_t helper_cvttq(uint64_t a) |
1116 | f24518b5 | Richard Henderson | { |
1117 | f24518b5 | Richard Henderson | return helper_cvttq_internal(a, FP_STATUS.float_rounding_mode, 1); |
1118 | f24518b5 | Richard Henderson | } |
1119 | f24518b5 | Richard Henderson | |
1120 | f24518b5 | Richard Henderson | uint64_t helper_cvttq_c(uint64_t a) |
1121 | f24518b5 | Richard Henderson | { |
1122 | f24518b5 | Richard Henderson | return helper_cvttq_internal(a, float_round_to_zero, 0); |
1123 | f24518b5 | Richard Henderson | } |
1124 | f24518b5 | Richard Henderson | |
1125 | f24518b5 | Richard Henderson | uint64_t helper_cvttq_svic(uint64_t a) |
1126 | f24518b5 | Richard Henderson | { |
1127 | f24518b5 | Richard Henderson | return helper_cvttq_internal(a, float_round_to_zero, 1); |
1128 | f18cd223 | aurel32 | } |
1129 | 4c9649a9 | j_mayer | |
1130 | f18cd223 | aurel32 | uint64_t helper_cvtqt (uint64_t a) |
1131 | f18cd223 | aurel32 | { |
1132 | f18cd223 | aurel32 | float64 fr = int64_to_float64(a, &FP_STATUS); |
1133 | f18cd223 | aurel32 | return float64_to_t(fr);
|
1134 | 4c9649a9 | j_mayer | } |
1135 | 4c9649a9 | j_mayer | |
1136 | f18cd223 | aurel32 | uint64_t helper_cvtqf (uint64_t a) |
1137 | 4c9649a9 | j_mayer | { |
1138 | f18cd223 | aurel32 | float32 fr = int64_to_float32(a, &FP_STATUS); |
1139 | f18cd223 | aurel32 | return float32_to_f(fr);
|
1140 | 4c9649a9 | j_mayer | } |
1141 | 4c9649a9 | j_mayer | |
1142 | f18cd223 | aurel32 | uint64_t helper_cvtgf (uint64_t a) |
1143 | 4c9649a9 | j_mayer | { |
1144 | f18cd223 | aurel32 | float64 fa; |
1145 | f18cd223 | aurel32 | float32 fr; |
1146 | f18cd223 | aurel32 | |
1147 | f18cd223 | aurel32 | fa = g_to_float64(a); |
1148 | f18cd223 | aurel32 | fr = float64_to_float32(fa, &FP_STATUS); |
1149 | f18cd223 | aurel32 | return float32_to_f(fr);
|
1150 | 4c9649a9 | j_mayer | } |
1151 | 4c9649a9 | j_mayer | |
1152 | f18cd223 | aurel32 | uint64_t helper_cvtgq (uint64_t a) |
1153 | 4c9649a9 | j_mayer | { |
1154 | f18cd223 | aurel32 | float64 fa = g_to_float64(a); |
1155 | f18cd223 | aurel32 | return float64_to_int64_round_to_zero(fa, &FP_STATUS);
|
1156 | 4c9649a9 | j_mayer | } |
1157 | 4c9649a9 | j_mayer | |
1158 | f18cd223 | aurel32 | uint64_t helper_cvtqg (uint64_t a) |
1159 | 4c9649a9 | j_mayer | { |
1160 | f18cd223 | aurel32 | float64 fr; |
1161 | f18cd223 | aurel32 | fr = int64_to_float64(a, &FP_STATUS); |
1162 | f18cd223 | aurel32 | return float64_to_g(fr);
|
1163 | 4c9649a9 | j_mayer | } |
1164 | 4c9649a9 | j_mayer | |
1165 | 8bb6e981 | aurel32 | /* PALcode support special instructions */
|
1166 | 4c9649a9 | j_mayer | #if !defined (CONFIG_USER_ONLY)
|
1167 | 8bb6e981 | aurel32 | void helper_hw_ret (uint64_t a)
|
1168 | 8bb6e981 | aurel32 | { |
1169 | 8bb6e981 | aurel32 | env->pc = a & ~3;
|
1170 | 129d8aa5 | Richard Henderson | env->pal_mode = a & 1;
|
1171 | ac316ca4 | Richard Henderson | env->intr_flag = 0;
|
1172 | 6910b8f6 | Richard Henderson | env->lock_addr = -1;
|
1173 | 8bb6e981 | aurel32 | } |
1174 | 4c9649a9 | j_mayer | #endif
|
1175 | 4c9649a9 | j_mayer | |
1176 | 4c9649a9 | j_mayer | /*****************************************************************************/
|
1177 | 4c9649a9 | j_mayer | /* Softmmu support */
|
1178 | 4c9649a9 | j_mayer | #if !defined (CONFIG_USER_ONLY)
|
1179 | 2374e73e | Richard Henderson | uint64_t helper_ldl_phys(uint64_t p) |
1180 | 8bb6e981 | aurel32 | { |
1181 | 2374e73e | Richard Henderson | return (int32_t)ldl_phys(p);
|
1182 | 8bb6e981 | aurel32 | } |
1183 | 8bb6e981 | aurel32 | |
1184 | 2374e73e | Richard Henderson | uint64_t helper_ldq_phys(uint64_t p) |
1185 | 8bb6e981 | aurel32 | { |
1186 | 2374e73e | Richard Henderson | return ldq_phys(p);
|
1187 | 8bb6e981 | aurel32 | } |
1188 | 8bb6e981 | aurel32 | |
1189 | 2374e73e | Richard Henderson | uint64_t helper_ldl_l_phys(uint64_t p) |
1190 | 8bb6e981 | aurel32 | { |
1191 | 2374e73e | Richard Henderson | env->lock_addr = p; |
1192 | 2374e73e | Richard Henderson | return env->lock_value = (int32_t)ldl_phys(p);
|
1193 | 8bb6e981 | aurel32 | } |
1194 | 8bb6e981 | aurel32 | |
1195 | 2374e73e | Richard Henderson | uint64_t helper_ldq_l_phys(uint64_t p) |
1196 | 8bb6e981 | aurel32 | { |
1197 | 2374e73e | Richard Henderson | env->lock_addr = p; |
1198 | 2374e73e | Richard Henderson | return env->lock_value = ldl_phys(p);
|
1199 | 8bb6e981 | aurel32 | } |
1200 | 8bb6e981 | aurel32 | |
1201 | 2374e73e | Richard Henderson | void helper_stl_phys(uint64_t p, uint64_t v)
|
1202 | 8bb6e981 | aurel32 | { |
1203 | 2374e73e | Richard Henderson | stl_phys(p, v); |
1204 | 8bb6e981 | aurel32 | } |
1205 | 8bb6e981 | aurel32 | |
1206 | 2374e73e | Richard Henderson | void helper_stq_phys(uint64_t p, uint64_t v)
|
1207 | 8bb6e981 | aurel32 | { |
1208 | 2374e73e | Richard Henderson | stq_phys(p, v); |
1209 | 8bb6e981 | aurel32 | } |
1210 | 8bb6e981 | aurel32 | |
1211 | 2374e73e | Richard Henderson | uint64_t helper_stl_c_phys(uint64_t p, uint64_t v) |
1212 | 8bb6e981 | aurel32 | { |
1213 | 2374e73e | Richard Henderson | uint64_t ret = 0;
|
1214 | 8bb6e981 | aurel32 | |
1215 | 2374e73e | Richard Henderson | if (p == env->lock_addr) {
|
1216 | 2374e73e | Richard Henderson | int32_t old = ldl_phys(p); |
1217 | 2374e73e | Richard Henderson | if (old == (int32_t)env->lock_value) {
|
1218 | 2374e73e | Richard Henderson | stl_phys(p, v); |
1219 | 2374e73e | Richard Henderson | ret = 1;
|
1220 | 2374e73e | Richard Henderson | } |
1221 | 2374e73e | Richard Henderson | } |
1222 | 2374e73e | Richard Henderson | env->lock_addr = -1;
|
1223 | 8bb6e981 | aurel32 | |
1224 | 8bb6e981 | aurel32 | return ret;
|
1225 | 8bb6e981 | aurel32 | } |
1226 | 8bb6e981 | aurel32 | |
1227 | 2374e73e | Richard Henderson | uint64_t helper_stq_c_phys(uint64_t p, uint64_t v) |
1228 | 8bb6e981 | aurel32 | { |
1229 | 2374e73e | Richard Henderson | uint64_t ret = 0;
|
1230 | 8bb6e981 | aurel32 | |
1231 | 2374e73e | Richard Henderson | if (p == env->lock_addr) {
|
1232 | 2374e73e | Richard Henderson | uint64_t old = ldq_phys(p); |
1233 | 2374e73e | Richard Henderson | if (old == env->lock_value) {
|
1234 | 2374e73e | Richard Henderson | stq_phys(p, v); |
1235 | 2374e73e | Richard Henderson | ret = 1;
|
1236 | 2374e73e | Richard Henderson | } |
1237 | 2374e73e | Richard Henderson | } |
1238 | 2374e73e | Richard Henderson | env->lock_addr = -1;
|
1239 | 8bb6e981 | aurel32 | |
1240 | 8bb6e981 | aurel32 | return ret;
|
1241 | 4c9649a9 | j_mayer | } |
1242 | 4c9649a9 | j_mayer | |
1243 | 4c9649a9 | j_mayer | #define MMUSUFFIX _mmu
|
1244 | 4c9649a9 | j_mayer | |
1245 | 4c9649a9 | j_mayer | #define SHIFT 0 |
1246 | 4c9649a9 | j_mayer | #include "softmmu_template.h" |
1247 | 4c9649a9 | j_mayer | |
1248 | 4c9649a9 | j_mayer | #define SHIFT 1 |
1249 | 4c9649a9 | j_mayer | #include "softmmu_template.h" |
1250 | 4c9649a9 | j_mayer | |
1251 | 4c9649a9 | j_mayer | #define SHIFT 2 |
1252 | 4c9649a9 | j_mayer | #include "softmmu_template.h" |
1253 | 4c9649a9 | j_mayer | |
1254 | 4c9649a9 | j_mayer | #define SHIFT 3 |
1255 | 4c9649a9 | j_mayer | #include "softmmu_template.h" |
1256 | 4c9649a9 | j_mayer | |
1257 | 4c9649a9 | j_mayer | /* try to fill the TLB and return an exception if error. If retaddr is
|
1258 | 4c9649a9 | j_mayer | NULL, it means that the function was called in C code (i.e. not
|
1259 | 4c9649a9 | j_mayer | from generated code or from helper.c) */
|
1260 | 4c9649a9 | j_mayer | /* XXX: fix it to restore all registers */
|
1261 | 6ebbf390 | j_mayer | void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) |
1262 | 4c9649a9 | j_mayer | { |
1263 | 4c9649a9 | j_mayer | TranslationBlock *tb; |
1264 | 4c9649a9 | j_mayer | CPUState *saved_env; |
1265 | 44f8625d | bellard | unsigned long pc; |
1266 | 4c9649a9 | j_mayer | int ret;
|
1267 | 4c9649a9 | j_mayer | |
1268 | 4c9649a9 | j_mayer | /* XXX: hack to restore env in all cases, even if not called from
|
1269 | 4c9649a9 | j_mayer | generated code */
|
1270 | 4c9649a9 | j_mayer | saved_env = env; |
1271 | 4c9649a9 | j_mayer | env = cpu_single_env; |
1272 | 6ebbf390 | j_mayer | ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
|
1273 | 4c9649a9 | j_mayer | if (!likely(ret == 0)) { |
1274 | 4c9649a9 | j_mayer | if (likely(retaddr)) {
|
1275 | 4c9649a9 | j_mayer | /* now we have a real cpu fault */
|
1276 | 44f8625d | bellard | pc = (unsigned long)retaddr; |
1277 | 4c9649a9 | j_mayer | tb = tb_find_pc(pc); |
1278 | 4c9649a9 | j_mayer | if (likely(tb)) {
|
1279 | 4c9649a9 | j_mayer | /* the PC is inside the translated code. It means that we have
|
1280 | 4c9649a9 | j_mayer | a virtual CPU fault */
|
1281 | 618ba8e6 | Stefan Weil | cpu_restore_state(tb, env, pc); |
1282 | 4c9649a9 | j_mayer | } |
1283 | 4c9649a9 | j_mayer | } |
1284 | 4c9649a9 | j_mayer | /* Exception index and error code are already set */
|
1285 | 4c9649a9 | j_mayer | cpu_loop_exit(); |
1286 | 4c9649a9 | j_mayer | } |
1287 | 4c9649a9 | j_mayer | env = saved_env; |
1288 | 4c9649a9 | j_mayer | } |
1289 | 4c9649a9 | j_mayer | |
1290 | 4c9649a9 | j_mayer | #endif |