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