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