root / target-alpha / op_helper.c @ 283c7c63
History | View | Annotate | Download (24.8 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 | void helper_tb_flush (void) |
26 | 4c9649a9 | j_mayer | { |
27 | 75fc9c0c | aurel32 | tb_flush(env); |
28 | 4c9649a9 | j_mayer | } |
29 | 4c9649a9 | j_mayer | |
30 | 4c9649a9 | j_mayer | /*****************************************************************************/
|
31 | 4c9649a9 | j_mayer | /* Exceptions processing helpers */
|
32 | 6ad02592 | aurel32 | void helper_excp (int excp, int error) |
33 | 4c9649a9 | j_mayer | { |
34 | 4c9649a9 | j_mayer | env->exception_index = excp; |
35 | 4c9649a9 | j_mayer | env->error_code = error; |
36 | 4c9649a9 | j_mayer | cpu_loop_exit(); |
37 | 4c9649a9 | j_mayer | } |
38 | 4c9649a9 | j_mayer | |
39 | 6ad02592 | aurel32 | uint64_t helper_load_pcc (void)
|
40 | 4c9649a9 | j_mayer | { |
41 | 4c9649a9 | j_mayer | /* XXX: TODO */
|
42 | 6ad02592 | aurel32 | return 0; |
43 | 4c9649a9 | j_mayer | } |
44 | 4c9649a9 | j_mayer | |
45 | f18cd223 | aurel32 | uint64_t helper_load_fpcr (void)
|
46 | 4c9649a9 | j_mayer | { |
47 | f18cd223 | aurel32 | uint64_t ret = 0;
|
48 | 4c9649a9 | j_mayer | #ifdef CONFIG_SOFTFLOAT
|
49 | f18cd223 | aurel32 | ret |= env->fp_status.float_exception_flags << 52;
|
50 | 4c9649a9 | j_mayer | if (env->fp_status.float_exception_flags)
|
51 | f18cd223 | aurel32 | ret |= 1ULL << 63; |
52 | 4c9649a9 | j_mayer | env->ipr[IPR_EXC_SUM] &= ~0x3E:
|
53 | 4c9649a9 | j_mayer | env->ipr[IPR_EXC_SUM] |= env->fp_status.float_exception_flags << 1;
|
54 | 4c9649a9 | j_mayer | #endif
|
55 | 4c9649a9 | j_mayer | switch (env->fp_status.float_rounding_mode) {
|
56 | 4c9649a9 | j_mayer | case float_round_nearest_even:
|
57 | f18cd223 | aurel32 | ret |= 2ULL << 58; |
58 | 4c9649a9 | j_mayer | break;
|
59 | 4c9649a9 | j_mayer | case float_round_down:
|
60 | f18cd223 | aurel32 | ret |= 1ULL << 58; |
61 | 4c9649a9 | j_mayer | break;
|
62 | 4c9649a9 | j_mayer | case float_round_up:
|
63 | f18cd223 | aurel32 | ret |= 3ULL << 58; |
64 | 4c9649a9 | j_mayer | break;
|
65 | 4c9649a9 | j_mayer | case float_round_to_zero:
|
66 | 4c9649a9 | j_mayer | break;
|
67 | 4c9649a9 | j_mayer | } |
68 | f18cd223 | aurel32 | return ret;
|
69 | 4c9649a9 | j_mayer | } |
70 | 4c9649a9 | j_mayer | |
71 | f18cd223 | aurel32 | void helper_store_fpcr (uint64_t val)
|
72 | 4c9649a9 | j_mayer | { |
73 | 4c9649a9 | j_mayer | #ifdef CONFIG_SOFTFLOAT
|
74 | f18cd223 | aurel32 | set_float_exception_flags((val >> 52) & 0x3F, &FP_STATUS); |
75 | 4c9649a9 | j_mayer | #endif
|
76 | f18cd223 | aurel32 | switch ((val >> 58) & 3) { |
77 | 4c9649a9 | j_mayer | case 0: |
78 | 4c9649a9 | j_mayer | set_float_rounding_mode(float_round_to_zero, &FP_STATUS); |
79 | 4c9649a9 | j_mayer | break;
|
80 | 4c9649a9 | j_mayer | case 1: |
81 | 4c9649a9 | j_mayer | set_float_rounding_mode(float_round_down, &FP_STATUS); |
82 | 4c9649a9 | j_mayer | break;
|
83 | 4c9649a9 | j_mayer | case 2: |
84 | 4c9649a9 | j_mayer | set_float_rounding_mode(float_round_nearest_even, &FP_STATUS); |
85 | 4c9649a9 | j_mayer | break;
|
86 | 4c9649a9 | j_mayer | case 3: |
87 | 4c9649a9 | j_mayer | set_float_rounding_mode(float_round_up, &FP_STATUS); |
88 | 4c9649a9 | j_mayer | break;
|
89 | 4c9649a9 | j_mayer | } |
90 | 4c9649a9 | j_mayer | } |
91 | 4c9649a9 | j_mayer | |
92 | c227f099 | Anthony Liguori | static spinlock_t intr_cpu_lock = SPIN_LOCK_UNLOCKED;
|
93 | 4c9649a9 | j_mayer | |
94 | 6ad02592 | aurel32 | uint64_t helper_rs(void)
|
95 | 4c9649a9 | j_mayer | { |
96 | 6ad02592 | aurel32 | uint64_t tmp; |
97 | 6ad02592 | aurel32 | |
98 | 6ad02592 | aurel32 | spin_lock(&intr_cpu_lock); |
99 | 6ad02592 | aurel32 | tmp = env->intr_flag; |
100 | 6ad02592 | aurel32 | env->intr_flag = 1;
|
101 | 6ad02592 | aurel32 | spin_unlock(&intr_cpu_lock); |
102 | 6ad02592 | aurel32 | |
103 | 6ad02592 | aurel32 | return tmp;
|
104 | 4c9649a9 | j_mayer | } |
105 | 4c9649a9 | j_mayer | |
106 | 6ad02592 | aurel32 | uint64_t helper_rc(void)
|
107 | 4c9649a9 | j_mayer | { |
108 | 6ad02592 | aurel32 | uint64_t tmp; |
109 | 6ad02592 | aurel32 | |
110 | 6ad02592 | aurel32 | spin_lock(&intr_cpu_lock); |
111 | 6ad02592 | aurel32 | tmp = env->intr_flag; |
112 | 6ad02592 | aurel32 | env->intr_flag = 0;
|
113 | 6ad02592 | aurel32 | spin_unlock(&intr_cpu_lock); |
114 | 6ad02592 | aurel32 | |
115 | 6ad02592 | aurel32 | return tmp;
|
116 | 4c9649a9 | j_mayer | } |
117 | 4c9649a9 | j_mayer | |
118 | 04acd307 | aurel32 | uint64_t helper_addqv (uint64_t op1, uint64_t op2) |
119 | 4c9649a9 | j_mayer | { |
120 | 04acd307 | aurel32 | uint64_t tmp = op1; |
121 | 04acd307 | aurel32 | op1 += op2; |
122 | 04acd307 | aurel32 | if (unlikely((tmp ^ op2 ^ (-1ULL)) & (tmp ^ op1) & (1ULL << 63))) { |
123 | 4c9649a9 | j_mayer | helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW); |
124 | 4c9649a9 | j_mayer | } |
125 | 04acd307 | aurel32 | return op1;
|
126 | 4c9649a9 | j_mayer | } |
127 | 4c9649a9 | j_mayer | |
128 | 04acd307 | aurel32 | uint64_t helper_addlv (uint64_t op1, uint64_t op2) |
129 | 4c9649a9 | j_mayer | { |
130 | 04acd307 | aurel32 | uint64_t tmp = op1; |
131 | 04acd307 | aurel32 | op1 = (uint32_t)(op1 + op2); |
132 | 04acd307 | aurel32 | if (unlikely((tmp ^ op2 ^ (-1UL)) & (tmp ^ op1) & (1UL << 31))) { |
133 | 4c9649a9 | j_mayer | helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW); |
134 | 4c9649a9 | j_mayer | } |
135 | 04acd307 | aurel32 | return op1;
|
136 | 4c9649a9 | j_mayer | } |
137 | 4c9649a9 | j_mayer | |
138 | 04acd307 | aurel32 | uint64_t helper_subqv (uint64_t op1, uint64_t op2) |
139 | 4c9649a9 | j_mayer | { |
140 | ecbb5ea1 | aurel32 | uint64_t res; |
141 | ecbb5ea1 | aurel32 | res = op1 - op2; |
142 | ecbb5ea1 | aurel32 | if (unlikely((op1 ^ op2) & (res ^ op1) & (1ULL << 63))) { |
143 | 4c9649a9 | j_mayer | helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW); |
144 | 4c9649a9 | j_mayer | } |
145 | ecbb5ea1 | aurel32 | return res;
|
146 | 4c9649a9 | j_mayer | } |
147 | 4c9649a9 | j_mayer | |
148 | 04acd307 | aurel32 | uint64_t helper_sublv (uint64_t op1, uint64_t op2) |
149 | 4c9649a9 | j_mayer | { |
150 | ecbb5ea1 | aurel32 | uint32_t res; |
151 | ecbb5ea1 | aurel32 | res = op1 - op2; |
152 | ecbb5ea1 | aurel32 | if (unlikely((op1 ^ op2) & (res ^ op1) & (1UL << 31))) { |
153 | 4c9649a9 | j_mayer | helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW); |
154 | 4c9649a9 | j_mayer | } |
155 | ecbb5ea1 | aurel32 | return res;
|
156 | 4c9649a9 | j_mayer | } |
157 | 4c9649a9 | j_mayer | |
158 | 04acd307 | aurel32 | uint64_t helper_mullv (uint64_t op1, uint64_t op2) |
159 | 4c9649a9 | j_mayer | { |
160 | 04acd307 | aurel32 | int64_t res = (int64_t)op1 * (int64_t)op2; |
161 | 4c9649a9 | j_mayer | |
162 | 4c9649a9 | j_mayer | if (unlikely((int32_t)res != res)) {
|
163 | 4c9649a9 | j_mayer | helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW); |
164 | 4c9649a9 | j_mayer | } |
165 | 04acd307 | aurel32 | return (int64_t)((int32_t)res);
|
166 | 4c9649a9 | j_mayer | } |
167 | 4c9649a9 | j_mayer | |
168 | 04acd307 | aurel32 | uint64_t helper_mulqv (uint64_t op1, uint64_t op2) |
169 | 4c9649a9 | j_mayer | { |
170 | e14fe0a9 | j_mayer | uint64_t tl, th; |
171 | e14fe0a9 | j_mayer | |
172 | 04acd307 | aurel32 | muls64(&tl, &th, op1, op2); |
173 | e14fe0a9 | j_mayer | /* If th != 0 && th != -1, then we had an overflow */
|
174 | e14fe0a9 | j_mayer | if (unlikely((th + 1) > 1)) { |
175 | 4c9649a9 | j_mayer | helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW); |
176 | 4c9649a9 | j_mayer | } |
177 | 04acd307 | aurel32 | return tl;
|
178 | 04acd307 | aurel32 | } |
179 | 04acd307 | aurel32 | |
180 | 04acd307 | aurel32 | uint64_t helper_umulh (uint64_t op1, uint64_t op2) |
181 | 04acd307 | aurel32 | { |
182 | 04acd307 | aurel32 | uint64_t tl, th; |
183 | 04acd307 | aurel32 | |
184 | 04acd307 | aurel32 | mulu64(&tl, &th, op1, op2); |
185 | 04acd307 | aurel32 | return th;
|
186 | 4c9649a9 | j_mayer | } |
187 | 4c9649a9 | j_mayer | |
188 | ae8ecd42 | aurel32 | uint64_t helper_ctpop (uint64_t arg) |
189 | 4c9649a9 | j_mayer | { |
190 | ae8ecd42 | aurel32 | return ctpop64(arg);
|
191 | 4c9649a9 | j_mayer | } |
192 | 4c9649a9 | j_mayer | |
193 | ae8ecd42 | aurel32 | uint64_t helper_ctlz (uint64_t arg) |
194 | 4c9649a9 | j_mayer | { |
195 | ae8ecd42 | aurel32 | return clz64(arg);
|
196 | 4c9649a9 | j_mayer | } |
197 | 4c9649a9 | j_mayer | |
198 | ae8ecd42 | aurel32 | uint64_t helper_cttz (uint64_t arg) |
199 | 4c9649a9 | j_mayer | { |
200 | ae8ecd42 | aurel32 | return ctz64(arg);
|
201 | 4c9649a9 | j_mayer | } |
202 | 4c9649a9 | j_mayer | |
203 | 636aa200 | Blue Swirl | static inline uint64_t byte_zap(uint64_t op, uint8_t mskb) |
204 | 4c9649a9 | j_mayer | { |
205 | 4c9649a9 | j_mayer | uint64_t mask; |
206 | 4c9649a9 | j_mayer | |
207 | 4c9649a9 | j_mayer | mask = 0;
|
208 | 4c9649a9 | j_mayer | mask |= ((mskb >> 0) & 1) * 0x00000000000000FFULL; |
209 | 4c9649a9 | j_mayer | mask |= ((mskb >> 1) & 1) * 0x000000000000FF00ULL; |
210 | 4c9649a9 | j_mayer | mask |= ((mskb >> 2) & 1) * 0x0000000000FF0000ULL; |
211 | 4c9649a9 | j_mayer | mask |= ((mskb >> 3) & 1) * 0x00000000FF000000ULL; |
212 | 4c9649a9 | j_mayer | mask |= ((mskb >> 4) & 1) * 0x000000FF00000000ULL; |
213 | 4c9649a9 | j_mayer | mask |= ((mskb >> 5) & 1) * 0x0000FF0000000000ULL; |
214 | 4c9649a9 | j_mayer | mask |= ((mskb >> 6) & 1) * 0x00FF000000000000ULL; |
215 | 4c9649a9 | j_mayer | mask |= ((mskb >> 7) & 1) * 0xFF00000000000000ULL; |
216 | 4c9649a9 | j_mayer | |
217 | 4c9649a9 | j_mayer | return op & ~mask;
|
218 | 4c9649a9 | j_mayer | } |
219 | 4c9649a9 | j_mayer | |
220 | b3249f63 | aurel32 | uint64_t helper_mskbl(uint64_t val, uint64_t mask) |
221 | 4c9649a9 | j_mayer | { |
222 | b3249f63 | aurel32 | return byte_zap(val, 0x01 << (mask & 7)); |
223 | 4c9649a9 | j_mayer | } |
224 | 4c9649a9 | j_mayer | |
225 | b3249f63 | aurel32 | uint64_t helper_insbl(uint64_t val, uint64_t mask) |
226 | 4c9649a9 | j_mayer | { |
227 | b3249f63 | aurel32 | val <<= (mask & 7) * 8; |
228 | b3249f63 | aurel32 | return byte_zap(val, ~(0x01 << (mask & 7))); |
229 | 4c9649a9 | j_mayer | } |
230 | 4c9649a9 | j_mayer | |
231 | b3249f63 | aurel32 | uint64_t helper_mskwl(uint64_t val, uint64_t mask) |
232 | 4c9649a9 | j_mayer | { |
233 | b3249f63 | aurel32 | return byte_zap(val, 0x03 << (mask & 7)); |
234 | 4c9649a9 | j_mayer | } |
235 | 4c9649a9 | j_mayer | |
236 | b3249f63 | aurel32 | uint64_t helper_inswl(uint64_t val, uint64_t mask) |
237 | 4c9649a9 | j_mayer | { |
238 | b3249f63 | aurel32 | val <<= (mask & 7) * 8; |
239 | b3249f63 | aurel32 | return byte_zap(val, ~(0x03 << (mask & 7))); |
240 | 4c9649a9 | j_mayer | } |
241 | 4c9649a9 | j_mayer | |
242 | b3249f63 | aurel32 | uint64_t helper_mskll(uint64_t val, uint64_t mask) |
243 | 4c9649a9 | j_mayer | { |
244 | b3249f63 | aurel32 | return byte_zap(val, 0x0F << (mask & 7)); |
245 | 4c9649a9 | j_mayer | } |
246 | 4c9649a9 | j_mayer | |
247 | b3249f63 | aurel32 | uint64_t helper_insll(uint64_t val, uint64_t mask) |
248 | 4c9649a9 | j_mayer | { |
249 | b3249f63 | aurel32 | val <<= (mask & 7) * 8; |
250 | b3249f63 | aurel32 | return byte_zap(val, ~(0x0F << (mask & 7))); |
251 | 4c9649a9 | j_mayer | } |
252 | 4c9649a9 | j_mayer | |
253 | b3249f63 | aurel32 | uint64_t helper_zap(uint64_t val, uint64_t mask) |
254 | 4c9649a9 | j_mayer | { |
255 | b3249f63 | aurel32 | return byte_zap(val, mask);
|
256 | 4c9649a9 | j_mayer | } |
257 | 4c9649a9 | j_mayer | |
258 | b3249f63 | aurel32 | uint64_t helper_zapnot(uint64_t val, uint64_t mask) |
259 | 4c9649a9 | j_mayer | { |
260 | b3249f63 | aurel32 | return byte_zap(val, ~mask);
|
261 | 4c9649a9 | j_mayer | } |
262 | 4c9649a9 | j_mayer | |
263 | b3249f63 | aurel32 | uint64_t helper_mskql(uint64_t val, uint64_t mask) |
264 | 4c9649a9 | j_mayer | { |
265 | b3249f63 | aurel32 | return byte_zap(val, 0xFF << (mask & 7)); |
266 | 4c9649a9 | j_mayer | } |
267 | 4c9649a9 | j_mayer | |
268 | b3249f63 | aurel32 | uint64_t helper_insql(uint64_t val, uint64_t mask) |
269 | 4c9649a9 | j_mayer | { |
270 | b3249f63 | aurel32 | val <<= (mask & 7) * 8; |
271 | b3249f63 | aurel32 | return byte_zap(val, ~(0xFF << (mask & 7))); |
272 | 4c9649a9 | j_mayer | } |
273 | 4c9649a9 | j_mayer | |
274 | b3249f63 | aurel32 | uint64_t helper_mskwh(uint64_t val, uint64_t mask) |
275 | 4c9649a9 | j_mayer | { |
276 | b3249f63 | aurel32 | return byte_zap(val, (0x03 << (mask & 7)) >> 8); |
277 | 4c9649a9 | j_mayer | } |
278 | 4c9649a9 | j_mayer | |
279 | b3249f63 | aurel32 | uint64_t helper_inswh(uint64_t val, uint64_t mask) |
280 | 4c9649a9 | j_mayer | { |
281 | b3249f63 | aurel32 | val >>= 64 - ((mask & 7) * 8); |
282 | b3249f63 | aurel32 | return byte_zap(val, ~((0x03 << (mask & 7)) >> 8)); |
283 | 4c9649a9 | j_mayer | } |
284 | 4c9649a9 | j_mayer | |
285 | b3249f63 | aurel32 | uint64_t helper_msklh(uint64_t val, uint64_t mask) |
286 | 4c9649a9 | j_mayer | { |
287 | b3249f63 | aurel32 | return byte_zap(val, (0x0F << (mask & 7)) >> 8); |
288 | 4c9649a9 | j_mayer | } |
289 | 4c9649a9 | j_mayer | |
290 | b3249f63 | aurel32 | uint64_t helper_inslh(uint64_t val, uint64_t mask) |
291 | 4c9649a9 | j_mayer | { |
292 | b3249f63 | aurel32 | val >>= 64 - ((mask & 7) * 8); |
293 | b3249f63 | aurel32 | return byte_zap(val, ~((0x0F << (mask & 7)) >> 8)); |
294 | 4c9649a9 | j_mayer | } |
295 | 4c9649a9 | j_mayer | |
296 | b3249f63 | aurel32 | uint64_t helper_mskqh(uint64_t val, uint64_t mask) |
297 | 4c9649a9 | j_mayer | { |
298 | b3249f63 | aurel32 | return byte_zap(val, (0xFF << (mask & 7)) >> 8); |
299 | 4c9649a9 | j_mayer | } |
300 | 4c9649a9 | j_mayer | |
301 | b3249f63 | aurel32 | uint64_t helper_insqh(uint64_t val, uint64_t mask) |
302 | 4c9649a9 | j_mayer | { |
303 | b3249f63 | aurel32 | val >>= 64 - ((mask & 7) * 8); |
304 | b3249f63 | aurel32 | return byte_zap(val, ~((0xFF << (mask & 7)) >> 8)); |
305 | 4c9649a9 | j_mayer | } |
306 | 4c9649a9 | j_mayer | |
307 | 04acd307 | aurel32 | uint64_t helper_cmpbge (uint64_t op1, uint64_t op2) |
308 | 4c9649a9 | j_mayer | { |
309 | 4c9649a9 | j_mayer | uint8_t opa, opb, res; |
310 | 4c9649a9 | j_mayer | int i;
|
311 | 4c9649a9 | j_mayer | |
312 | 4c9649a9 | j_mayer | res = 0;
|
313 | 970d622e | aurel32 | for (i = 0; i < 8; i++) { |
314 | 04acd307 | aurel32 | opa = op1 >> (i * 8);
|
315 | 04acd307 | aurel32 | opb = op2 >> (i * 8);
|
316 | 4c9649a9 | j_mayer | if (opa >= opb)
|
317 | 4c9649a9 | j_mayer | res |= 1 << i;
|
318 | 4c9649a9 | j_mayer | } |
319 | 04acd307 | aurel32 | return res;
|
320 | 4c9649a9 | j_mayer | } |
321 | 4c9649a9 | j_mayer | |
322 | f18cd223 | aurel32 | /* Floating point helpers */
|
323 | f18cd223 | aurel32 | |
324 | f18cd223 | aurel32 | /* F floating (VAX) */
|
325 | 636aa200 | Blue Swirl | static inline uint64_t float32_to_f(float32 fa) |
326 | 4c9649a9 | j_mayer | { |
327 | f18cd223 | aurel32 | uint64_t r, exp, mant, sig; |
328 | e2eb2798 | aurel32 | CPU_FloatU a; |
329 | f18cd223 | aurel32 | |
330 | e2eb2798 | aurel32 | a.f = fa; |
331 | e2eb2798 | aurel32 | sig = ((uint64_t)a.l & 0x80000000) << 32; |
332 | e2eb2798 | aurel32 | exp = (a.l >> 23) & 0xff; |
333 | e2eb2798 | aurel32 | mant = ((uint64_t)a.l & 0x007fffff) << 29; |
334 | f18cd223 | aurel32 | |
335 | f18cd223 | aurel32 | if (exp == 255) { |
336 | f18cd223 | aurel32 | /* NaN or infinity */
|
337 | f18cd223 | aurel32 | r = 1; /* VAX dirty zero */ |
338 | f18cd223 | aurel32 | } else if (exp == 0) { |
339 | f18cd223 | aurel32 | if (mant == 0) { |
340 | f18cd223 | aurel32 | /* Zero */
|
341 | f18cd223 | aurel32 | r = 0;
|
342 | f18cd223 | aurel32 | } else {
|
343 | f18cd223 | aurel32 | /* Denormalized */
|
344 | f18cd223 | aurel32 | r = sig | ((exp + 1) << 52) | mant; |
345 | f18cd223 | aurel32 | } |
346 | f18cd223 | aurel32 | } else {
|
347 | f18cd223 | aurel32 | if (exp >= 253) { |
348 | f18cd223 | aurel32 | /* Overflow */
|
349 | f18cd223 | aurel32 | r = 1; /* VAX dirty zero */ |
350 | f18cd223 | aurel32 | } else {
|
351 | f18cd223 | aurel32 | r = sig | ((exp + 2) << 52); |
352 | f18cd223 | aurel32 | } |
353 | f18cd223 | aurel32 | } |
354 | f18cd223 | aurel32 | |
355 | f18cd223 | aurel32 | return r;
|
356 | 4c9649a9 | j_mayer | } |
357 | 4c9649a9 | j_mayer | |
358 | 636aa200 | Blue Swirl | static inline float32 f_to_float32(uint64_t a) |
359 | 4c9649a9 | j_mayer | { |
360 | e2eb2798 | aurel32 | uint32_t exp, mant_sig; |
361 | e2eb2798 | aurel32 | CPU_FloatU r; |
362 | f18cd223 | aurel32 | |
363 | f18cd223 | aurel32 | exp = ((a >> 55) & 0x80) | ((a >> 52) & 0x7f); |
364 | f18cd223 | aurel32 | mant_sig = ((a >> 32) & 0x80000000) | ((a >> 29) & 0x007fffff); |
365 | f18cd223 | aurel32 | |
366 | f18cd223 | aurel32 | if (unlikely(!exp && mant_sig)) {
|
367 | f18cd223 | aurel32 | /* Reserved operands / Dirty zero */
|
368 | f18cd223 | aurel32 | helper_excp(EXCP_OPCDEC, 0);
|
369 | f18cd223 | aurel32 | } |
370 | f18cd223 | aurel32 | |
371 | f18cd223 | aurel32 | if (exp < 3) { |
372 | f18cd223 | aurel32 | /* Underflow */
|
373 | e2eb2798 | aurel32 | r.l = 0;
|
374 | f18cd223 | aurel32 | } else {
|
375 | e2eb2798 | aurel32 | r.l = ((exp - 2) << 23) | mant_sig; |
376 | f18cd223 | aurel32 | } |
377 | f18cd223 | aurel32 | |
378 | e2eb2798 | aurel32 | return r.f;
|
379 | 4c9649a9 | j_mayer | } |
380 | 4c9649a9 | j_mayer | |
381 | f18cd223 | aurel32 | uint32_t helper_f_to_memory (uint64_t a) |
382 | 4c9649a9 | j_mayer | { |
383 | f18cd223 | aurel32 | uint32_t r; |
384 | f18cd223 | aurel32 | r = (a & 0x00001fffe0000000ull) >> 13; |
385 | f18cd223 | aurel32 | r |= (a & 0x07ffe00000000000ull) >> 45; |
386 | f18cd223 | aurel32 | r |= (a & 0xc000000000000000ull) >> 48; |
387 | f18cd223 | aurel32 | return r;
|
388 | f18cd223 | aurel32 | } |
389 | 4c9649a9 | j_mayer | |
390 | f18cd223 | aurel32 | uint64_t helper_memory_to_f (uint32_t a) |
391 | f18cd223 | aurel32 | { |
392 | f18cd223 | aurel32 | uint64_t r; |
393 | f18cd223 | aurel32 | r = ((uint64_t)(a & 0x0000c000)) << 48; |
394 | f18cd223 | aurel32 | r |= ((uint64_t)(a & 0x003fffff)) << 45; |
395 | f18cd223 | aurel32 | r |= ((uint64_t)(a & 0xffff0000)) << 13; |
396 | f18cd223 | aurel32 | if (!(a & 0x00004000)) |
397 | f18cd223 | aurel32 | r |= 0x7ll << 59; |
398 | f18cd223 | aurel32 | return r;
|
399 | 4c9649a9 | j_mayer | } |
400 | 4c9649a9 | j_mayer | |
401 | f18cd223 | aurel32 | uint64_t helper_addf (uint64_t a, uint64_t b) |
402 | 4c9649a9 | j_mayer | { |
403 | f18cd223 | aurel32 | float32 fa, fb, fr; |
404 | 4c9649a9 | j_mayer | |
405 | f18cd223 | aurel32 | fa = f_to_float32(a); |
406 | f18cd223 | aurel32 | fb = f_to_float32(b); |
407 | f18cd223 | aurel32 | fr = float32_add(fa, fb, &FP_STATUS); |
408 | f18cd223 | aurel32 | return float32_to_f(fr);
|
409 | 4c9649a9 | j_mayer | } |
410 | 4c9649a9 | j_mayer | |
411 | f18cd223 | aurel32 | uint64_t helper_subf (uint64_t a, uint64_t b) |
412 | 4c9649a9 | j_mayer | { |
413 | f18cd223 | aurel32 | float32 fa, fb, fr; |
414 | 4c9649a9 | j_mayer | |
415 | f18cd223 | aurel32 | fa = f_to_float32(a); |
416 | f18cd223 | aurel32 | fb = f_to_float32(b); |
417 | f18cd223 | aurel32 | fr = float32_sub(fa, fb, &FP_STATUS); |
418 | f18cd223 | aurel32 | return float32_to_f(fr);
|
419 | 4c9649a9 | j_mayer | } |
420 | 4c9649a9 | j_mayer | |
421 | f18cd223 | aurel32 | uint64_t helper_mulf (uint64_t a, uint64_t b) |
422 | 4c9649a9 | j_mayer | { |
423 | f18cd223 | aurel32 | float32 fa, fb, fr; |
424 | 4c9649a9 | j_mayer | |
425 | f18cd223 | aurel32 | fa = f_to_float32(a); |
426 | f18cd223 | aurel32 | fb = f_to_float32(b); |
427 | f18cd223 | aurel32 | fr = float32_mul(fa, fb, &FP_STATUS); |
428 | f18cd223 | aurel32 | return float32_to_f(fr);
|
429 | 4c9649a9 | j_mayer | } |
430 | 4c9649a9 | j_mayer | |
431 | f18cd223 | aurel32 | uint64_t helper_divf (uint64_t a, uint64_t b) |
432 | 4c9649a9 | j_mayer | { |
433 | f18cd223 | aurel32 | float32 fa, fb, fr; |
434 | 4c9649a9 | j_mayer | |
435 | f18cd223 | aurel32 | fa = f_to_float32(a); |
436 | f18cd223 | aurel32 | fb = f_to_float32(b); |
437 | f18cd223 | aurel32 | fr = float32_div(fa, fb, &FP_STATUS); |
438 | f18cd223 | aurel32 | return float32_to_f(fr);
|
439 | 4c9649a9 | j_mayer | } |
440 | 4c9649a9 | j_mayer | |
441 | f18cd223 | aurel32 | uint64_t helper_sqrtf (uint64_t t) |
442 | 4c9649a9 | j_mayer | { |
443 | f18cd223 | aurel32 | float32 ft, fr; |
444 | f18cd223 | aurel32 | |
445 | f18cd223 | aurel32 | ft = f_to_float32(t); |
446 | f18cd223 | aurel32 | fr = float32_sqrt(ft, &FP_STATUS); |
447 | f18cd223 | aurel32 | return float32_to_f(fr);
|
448 | 4c9649a9 | j_mayer | } |
449 | 4c9649a9 | j_mayer | |
450 | f18cd223 | aurel32 | |
451 | f18cd223 | aurel32 | /* G floating (VAX) */
|
452 | 636aa200 | Blue Swirl | static inline uint64_t float64_to_g(float64 fa) |
453 | 4c9649a9 | j_mayer | { |
454 | e2eb2798 | aurel32 | uint64_t r, exp, mant, sig; |
455 | e2eb2798 | aurel32 | CPU_DoubleU a; |
456 | 4c9649a9 | j_mayer | |
457 | e2eb2798 | aurel32 | a.d = fa; |
458 | e2eb2798 | aurel32 | sig = a.ll & 0x8000000000000000ull;
|
459 | e2eb2798 | aurel32 | exp = (a.ll >> 52) & 0x7ff; |
460 | e2eb2798 | aurel32 | mant = a.ll & 0x000fffffffffffffull;
|
461 | f18cd223 | aurel32 | |
462 | f18cd223 | aurel32 | if (exp == 2047) { |
463 | f18cd223 | aurel32 | /* NaN or infinity */
|
464 | f18cd223 | aurel32 | r = 1; /* VAX dirty zero */ |
465 | f18cd223 | aurel32 | } else if (exp == 0) { |
466 | f18cd223 | aurel32 | if (mant == 0) { |
467 | f18cd223 | aurel32 | /* Zero */
|
468 | f18cd223 | aurel32 | r = 0;
|
469 | f18cd223 | aurel32 | } else {
|
470 | f18cd223 | aurel32 | /* Denormalized */
|
471 | f18cd223 | aurel32 | r = sig | ((exp + 1) << 52) | mant; |
472 | f18cd223 | aurel32 | } |
473 | f18cd223 | aurel32 | } else {
|
474 | f18cd223 | aurel32 | if (exp >= 2045) { |
475 | f18cd223 | aurel32 | /* Overflow */
|
476 | f18cd223 | aurel32 | r = 1; /* VAX dirty zero */ |
477 | f18cd223 | aurel32 | } else {
|
478 | f18cd223 | aurel32 | r = sig | ((exp + 2) << 52); |
479 | f18cd223 | aurel32 | } |
480 | f18cd223 | aurel32 | } |
481 | f18cd223 | aurel32 | |
482 | f18cd223 | aurel32 | return r;
|
483 | 4c9649a9 | j_mayer | } |
484 | 4c9649a9 | j_mayer | |
485 | 636aa200 | Blue Swirl | static inline float64 g_to_float64(uint64_t a) |
486 | 4c9649a9 | j_mayer | { |
487 | e2eb2798 | aurel32 | uint64_t exp, mant_sig; |
488 | e2eb2798 | aurel32 | CPU_DoubleU r; |
489 | f18cd223 | aurel32 | |
490 | f18cd223 | aurel32 | exp = (a >> 52) & 0x7ff; |
491 | f18cd223 | aurel32 | mant_sig = a & 0x800fffffffffffffull;
|
492 | f18cd223 | aurel32 | |
493 | f18cd223 | aurel32 | if (!exp && mant_sig) {
|
494 | f18cd223 | aurel32 | /* Reserved operands / Dirty zero */
|
495 | f18cd223 | aurel32 | helper_excp(EXCP_OPCDEC, 0);
|
496 | f18cd223 | aurel32 | } |
497 | 4c9649a9 | j_mayer | |
498 | f18cd223 | aurel32 | if (exp < 3) { |
499 | f18cd223 | aurel32 | /* Underflow */
|
500 | e2eb2798 | aurel32 | r.ll = 0;
|
501 | f18cd223 | aurel32 | } else {
|
502 | e2eb2798 | aurel32 | r.ll = ((exp - 2) << 52) | mant_sig; |
503 | f18cd223 | aurel32 | } |
504 | f18cd223 | aurel32 | |
505 | e2eb2798 | aurel32 | return r.d;
|
506 | 4c9649a9 | j_mayer | } |
507 | 4c9649a9 | j_mayer | |
508 | f18cd223 | aurel32 | uint64_t helper_g_to_memory (uint64_t a) |
509 | 4c9649a9 | j_mayer | { |
510 | f18cd223 | aurel32 | uint64_t r; |
511 | f18cd223 | aurel32 | r = (a & 0x000000000000ffffull) << 48; |
512 | f18cd223 | aurel32 | r |= (a & 0x00000000ffff0000ull) << 16; |
513 | f18cd223 | aurel32 | r |= (a & 0x0000ffff00000000ull) >> 16; |
514 | f18cd223 | aurel32 | r |= (a & 0xffff000000000000ull) >> 48; |
515 | f18cd223 | aurel32 | return r;
|
516 | f18cd223 | aurel32 | } |
517 | 4c9649a9 | j_mayer | |
518 | f18cd223 | aurel32 | uint64_t helper_memory_to_g (uint64_t a) |
519 | f18cd223 | aurel32 | { |
520 | f18cd223 | aurel32 | uint64_t r; |
521 | f18cd223 | aurel32 | r = (a & 0x000000000000ffffull) << 48; |
522 | f18cd223 | aurel32 | r |= (a & 0x00000000ffff0000ull) << 16; |
523 | f18cd223 | aurel32 | r |= (a & 0x0000ffff00000000ull) >> 16; |
524 | f18cd223 | aurel32 | r |= (a & 0xffff000000000000ull) >> 48; |
525 | f18cd223 | aurel32 | return r;
|
526 | 4c9649a9 | j_mayer | } |
527 | 4c9649a9 | j_mayer | |
528 | f18cd223 | aurel32 | uint64_t helper_addg (uint64_t a, uint64_t b) |
529 | 4c9649a9 | j_mayer | { |
530 | f18cd223 | aurel32 | float64 fa, fb, fr; |
531 | 4c9649a9 | j_mayer | |
532 | f18cd223 | aurel32 | fa = g_to_float64(a); |
533 | f18cd223 | aurel32 | fb = g_to_float64(b); |
534 | f18cd223 | aurel32 | fr = float64_add(fa, fb, &FP_STATUS); |
535 | f18cd223 | aurel32 | return float64_to_g(fr);
|
536 | 4c9649a9 | j_mayer | } |
537 | 4c9649a9 | j_mayer | |
538 | f18cd223 | aurel32 | uint64_t helper_subg (uint64_t a, uint64_t b) |
539 | 4c9649a9 | j_mayer | { |
540 | f18cd223 | aurel32 | float64 fa, fb, fr; |
541 | 4c9649a9 | j_mayer | |
542 | f18cd223 | aurel32 | fa = g_to_float64(a); |
543 | f18cd223 | aurel32 | fb = g_to_float64(b); |
544 | f18cd223 | aurel32 | fr = float64_sub(fa, fb, &FP_STATUS); |
545 | f18cd223 | aurel32 | return float64_to_g(fr);
|
546 | 4c9649a9 | j_mayer | } |
547 | 4c9649a9 | j_mayer | |
548 | f18cd223 | aurel32 | uint64_t helper_mulg (uint64_t a, uint64_t b) |
549 | 4c9649a9 | j_mayer | { |
550 | f18cd223 | aurel32 | float64 fa, fb, fr; |
551 | 4c9649a9 | j_mayer | |
552 | f18cd223 | aurel32 | fa = g_to_float64(a); |
553 | f18cd223 | aurel32 | fb = g_to_float64(b); |
554 | f18cd223 | aurel32 | fr = float64_mul(fa, fb, &FP_STATUS); |
555 | f18cd223 | aurel32 | return float64_to_g(fr);
|
556 | 4c9649a9 | j_mayer | } |
557 | 4c9649a9 | j_mayer | |
558 | f18cd223 | aurel32 | uint64_t helper_divg (uint64_t a, uint64_t b) |
559 | 4c9649a9 | j_mayer | { |
560 | f18cd223 | aurel32 | float64 fa, fb, fr; |
561 | 4c9649a9 | j_mayer | |
562 | f18cd223 | aurel32 | fa = g_to_float64(a); |
563 | f18cd223 | aurel32 | fb = g_to_float64(b); |
564 | f18cd223 | aurel32 | fr = float64_div(fa, fb, &FP_STATUS); |
565 | f18cd223 | aurel32 | return float64_to_g(fr);
|
566 | f18cd223 | aurel32 | } |
567 | f18cd223 | aurel32 | |
568 | f18cd223 | aurel32 | uint64_t helper_sqrtg (uint64_t a) |
569 | f18cd223 | aurel32 | { |
570 | f18cd223 | aurel32 | float64 fa, fr; |
571 | 4c9649a9 | j_mayer | |
572 | f18cd223 | aurel32 | fa = g_to_float64(a); |
573 | f18cd223 | aurel32 | fr = float64_sqrt(fa, &FP_STATUS); |
574 | f18cd223 | aurel32 | return float64_to_g(fr);
|
575 | 4c9649a9 | j_mayer | } |
576 | 4c9649a9 | j_mayer | |
577 | f18cd223 | aurel32 | |
578 | f18cd223 | aurel32 | /* S floating (single) */
|
579 | 636aa200 | Blue Swirl | static inline uint64_t float32_to_s(float32 fa) |
580 | 4c9649a9 | j_mayer | { |
581 | e2eb2798 | aurel32 | CPU_FloatU a; |
582 | f18cd223 | aurel32 | uint64_t r; |
583 | 4c9649a9 | j_mayer | |
584 | e2eb2798 | aurel32 | a.f = fa; |
585 | 4c9649a9 | j_mayer | |
586 | e2eb2798 | aurel32 | r = (((uint64_t)(a.l & 0xc0000000)) << 32) | (((uint64_t)(a.l & 0x3fffffff)) << 29); |
587 | e2eb2798 | aurel32 | if (((a.l & 0x7f800000) != 0x7f800000) && (!(a.l & 0x40000000))) |
588 | f18cd223 | aurel32 | r |= 0x7ll << 59; |
589 | f18cd223 | aurel32 | return r;
|
590 | 4c9649a9 | j_mayer | } |
591 | 4c9649a9 | j_mayer | |
592 | 636aa200 | Blue Swirl | static inline float32 s_to_float32(uint64_t a) |
593 | 4c9649a9 | j_mayer | { |
594 | e2eb2798 | aurel32 | CPU_FloatU r; |
595 | e2eb2798 | aurel32 | r.l = ((a >> 32) & 0xc0000000) | ((a >> 29) & 0x3fffffff); |
596 | e2eb2798 | aurel32 | return r.f;
|
597 | f18cd223 | aurel32 | } |
598 | 4c9649a9 | j_mayer | |
599 | f18cd223 | aurel32 | uint32_t helper_s_to_memory (uint64_t a) |
600 | f18cd223 | aurel32 | { |
601 | f18cd223 | aurel32 | /* Memory format is the same as float32 */
|
602 | f18cd223 | aurel32 | float32 fa = s_to_float32(a); |
603 | f18cd223 | aurel32 | return *(uint32_t*)(&fa);
|
604 | f18cd223 | aurel32 | } |
605 | 4c9649a9 | j_mayer | |
606 | f18cd223 | aurel32 | uint64_t helper_memory_to_s (uint32_t a) |
607 | f18cd223 | aurel32 | { |
608 | f18cd223 | aurel32 | /* Memory format is the same as float32 */
|
609 | f18cd223 | aurel32 | return float32_to_s(*(float32*)(&a));
|
610 | 4c9649a9 | j_mayer | } |
611 | 4c9649a9 | j_mayer | |
612 | f18cd223 | aurel32 | uint64_t helper_adds (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 = s_to_float32(a); |
617 | f18cd223 | aurel32 | fb = s_to_float32(b); |
618 | f18cd223 | aurel32 | fr = float32_add(fa, fb, &FP_STATUS); |
619 | f18cd223 | aurel32 | return float32_to_s(fr);
|
620 | 4c9649a9 | j_mayer | } |
621 | 4c9649a9 | j_mayer | |
622 | f18cd223 | aurel32 | uint64_t helper_subs (uint64_t a, uint64_t b) |
623 | 4c9649a9 | j_mayer | { |
624 | f18cd223 | aurel32 | float32 fa, fb, fr; |
625 | 4c9649a9 | j_mayer | |
626 | f18cd223 | aurel32 | fa = s_to_float32(a); |
627 | f18cd223 | aurel32 | fb = s_to_float32(b); |
628 | f18cd223 | aurel32 | fr = float32_sub(fa, fb, &FP_STATUS); |
629 | f18cd223 | aurel32 | return float32_to_s(fr);
|
630 | 4c9649a9 | j_mayer | } |
631 | 4c9649a9 | j_mayer | |
632 | f18cd223 | aurel32 | uint64_t helper_muls (uint64_t a, uint64_t b) |
633 | 4c9649a9 | j_mayer | { |
634 | f18cd223 | aurel32 | float32 fa, fb, fr; |
635 | 4c9649a9 | j_mayer | |
636 | f18cd223 | aurel32 | fa = s_to_float32(a); |
637 | f18cd223 | aurel32 | fb = s_to_float32(b); |
638 | f18cd223 | aurel32 | fr = float32_mul(fa, fb, &FP_STATUS); |
639 | f18cd223 | aurel32 | return float32_to_s(fr);
|
640 | 4c9649a9 | j_mayer | } |
641 | 4c9649a9 | j_mayer | |
642 | f18cd223 | aurel32 | uint64_t helper_divs (uint64_t a, uint64_t b) |
643 | 4c9649a9 | j_mayer | { |
644 | f18cd223 | aurel32 | float32 fa, fb, fr; |
645 | 4c9649a9 | j_mayer | |
646 | f18cd223 | aurel32 | fa = s_to_float32(a); |
647 | f18cd223 | aurel32 | fb = s_to_float32(b); |
648 | f18cd223 | aurel32 | fr = float32_div(fa, fb, &FP_STATUS); |
649 | f18cd223 | aurel32 | return float32_to_s(fr);
|
650 | 4c9649a9 | j_mayer | } |
651 | 4c9649a9 | j_mayer | |
652 | f18cd223 | aurel32 | uint64_t helper_sqrts (uint64_t a) |
653 | 4c9649a9 | j_mayer | { |
654 | f18cd223 | aurel32 | float32 fa, fr; |
655 | 4c9649a9 | j_mayer | |
656 | f18cd223 | aurel32 | fa = s_to_float32(a); |
657 | f18cd223 | aurel32 | fr = float32_sqrt(fa, &FP_STATUS); |
658 | f18cd223 | aurel32 | return float32_to_s(fr);
|
659 | 4c9649a9 | j_mayer | } |
660 | 4c9649a9 | j_mayer | |
661 | f18cd223 | aurel32 | |
662 | f18cd223 | aurel32 | /* T floating (double) */
|
663 | 636aa200 | Blue Swirl | static inline float64 t_to_float64(uint64_t a) |
664 | 4c9649a9 | j_mayer | { |
665 | f18cd223 | aurel32 | /* Memory format is the same as float64 */
|
666 | e2eb2798 | aurel32 | CPU_DoubleU r; |
667 | e2eb2798 | aurel32 | r.ll = a; |
668 | e2eb2798 | aurel32 | return r.d;
|
669 | 4c9649a9 | j_mayer | } |
670 | 4c9649a9 | j_mayer | |
671 | 636aa200 | Blue Swirl | static inline uint64_t float64_to_t(float64 fa) |
672 | 4c9649a9 | j_mayer | { |
673 | f18cd223 | aurel32 | /* Memory format is the same as float64 */
|
674 | e2eb2798 | aurel32 | CPU_DoubleU r; |
675 | e2eb2798 | aurel32 | r.d = fa; |
676 | e2eb2798 | aurel32 | return r.ll;
|
677 | f18cd223 | aurel32 | } |
678 | 4c9649a9 | j_mayer | |
679 | f18cd223 | aurel32 | uint64_t helper_addt (uint64_t a, uint64_t b) |
680 | f18cd223 | aurel32 | { |
681 | f18cd223 | aurel32 | float64 fa, fb, fr; |
682 | 4c9649a9 | j_mayer | |
683 | f18cd223 | aurel32 | fa = t_to_float64(a); |
684 | f18cd223 | aurel32 | fb = t_to_float64(b); |
685 | f18cd223 | aurel32 | fr = float64_add(fa, fb, &FP_STATUS); |
686 | f18cd223 | aurel32 | return float64_to_t(fr);
|
687 | 4c9649a9 | j_mayer | } |
688 | 4c9649a9 | j_mayer | |
689 | f18cd223 | aurel32 | uint64_t helper_subt (uint64_t a, uint64_t b) |
690 | 4c9649a9 | j_mayer | { |
691 | f18cd223 | aurel32 | float64 fa, fb, fr; |
692 | 4c9649a9 | j_mayer | |
693 | f18cd223 | aurel32 | fa = t_to_float64(a); |
694 | f18cd223 | aurel32 | fb = t_to_float64(b); |
695 | f18cd223 | aurel32 | fr = float64_sub(fa, fb, &FP_STATUS); |
696 | f18cd223 | aurel32 | return float64_to_t(fr);
|
697 | 4c9649a9 | j_mayer | } |
698 | 4c9649a9 | j_mayer | |
699 | f18cd223 | aurel32 | uint64_t helper_mult (uint64_t a, uint64_t b) |
700 | 4c9649a9 | j_mayer | { |
701 | f18cd223 | aurel32 | float64 fa, fb, fr; |
702 | 4c9649a9 | j_mayer | |
703 | f18cd223 | aurel32 | fa = t_to_float64(a); |
704 | f18cd223 | aurel32 | fb = t_to_float64(b); |
705 | f18cd223 | aurel32 | fr = float64_mul(fa, fb, &FP_STATUS); |
706 | f18cd223 | aurel32 | return float64_to_t(fr);
|
707 | 4c9649a9 | j_mayer | } |
708 | 4c9649a9 | j_mayer | |
709 | f18cd223 | aurel32 | uint64_t helper_divt (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 = t_to_float64(a); |
714 | f18cd223 | aurel32 | fb = t_to_float64(b); |
715 | f18cd223 | aurel32 | fr = float64_div(fa, fb, &FP_STATUS); |
716 | f18cd223 | aurel32 | return float64_to_t(fr);
|
717 | 4c9649a9 | j_mayer | } |
718 | 4c9649a9 | j_mayer | |
719 | f18cd223 | aurel32 | uint64_t helper_sqrtt (uint64_t a) |
720 | 4c9649a9 | j_mayer | { |
721 | f18cd223 | aurel32 | float64 fa, fr; |
722 | 4c9649a9 | j_mayer | |
723 | f18cd223 | aurel32 | fa = t_to_float64(a); |
724 | f18cd223 | aurel32 | fr = float64_sqrt(fa, &FP_STATUS); |
725 | f18cd223 | aurel32 | return float64_to_t(fr);
|
726 | 4c9649a9 | j_mayer | } |
727 | 4c9649a9 | j_mayer | |
728 | 4c9649a9 | j_mayer | |
729 | f18cd223 | aurel32 | /* Sign copy */
|
730 | f18cd223 | aurel32 | uint64_t helper_cpys(uint64_t a, uint64_t b) |
731 | f18cd223 | aurel32 | { |
732 | f18cd223 | aurel32 | return (a & 0x8000000000000000ULL) | (b & ~0x8000000000000000ULL); |
733 | 4c9649a9 | j_mayer | } |
734 | 4c9649a9 | j_mayer | |
735 | f18cd223 | aurel32 | uint64_t helper_cpysn(uint64_t a, uint64_t b) |
736 | 4c9649a9 | j_mayer | { |
737 | f18cd223 | aurel32 | return ((~a) & 0x8000000000000000ULL) | (b & ~0x8000000000000000ULL); |
738 | f18cd223 | aurel32 | } |
739 | 4c9649a9 | j_mayer | |
740 | f18cd223 | aurel32 | uint64_t helper_cpyse(uint64_t a, uint64_t b) |
741 | f18cd223 | aurel32 | { |
742 | f18cd223 | aurel32 | return (a & 0xFFF0000000000000ULL) | (b & ~0xFFF0000000000000ULL); |
743 | 4c9649a9 | j_mayer | } |
744 | 4c9649a9 | j_mayer | |
745 | f18cd223 | aurel32 | |
746 | f18cd223 | aurel32 | /* Comparisons */
|
747 | f18cd223 | aurel32 | uint64_t helper_cmptun (uint64_t a, uint64_t b) |
748 | 4c9649a9 | j_mayer | { |
749 | f18cd223 | aurel32 | float64 fa, fb; |
750 | 4c9649a9 | j_mayer | |
751 | f18cd223 | aurel32 | fa = t_to_float64(a); |
752 | f18cd223 | aurel32 | fb = t_to_float64(b); |
753 | f18cd223 | aurel32 | |
754 | f18cd223 | aurel32 | if (float64_is_nan(fa) || float64_is_nan(fb))
|
755 | f18cd223 | aurel32 | return 0x4000000000000000ULL; |
756 | f18cd223 | aurel32 | else
|
757 | f18cd223 | aurel32 | return 0; |
758 | 4c9649a9 | j_mayer | } |
759 | 4c9649a9 | j_mayer | |
760 | f18cd223 | aurel32 | uint64_t helper_cmpteq(uint64_t a, uint64_t b) |
761 | 4c9649a9 | j_mayer | { |
762 | f18cd223 | aurel32 | float64 fa, fb; |
763 | 4c9649a9 | j_mayer | |
764 | f18cd223 | aurel32 | fa = t_to_float64(a); |
765 | f18cd223 | aurel32 | fb = t_to_float64(b); |
766 | f18cd223 | aurel32 | |
767 | f18cd223 | aurel32 | if (float64_eq(fa, fb, &FP_STATUS))
|
768 | f18cd223 | aurel32 | return 0x4000000000000000ULL; |
769 | f18cd223 | aurel32 | else
|
770 | f18cd223 | aurel32 | return 0; |
771 | 4c9649a9 | j_mayer | } |
772 | 4c9649a9 | j_mayer | |
773 | f18cd223 | aurel32 | uint64_t helper_cmptle(uint64_t a, uint64_t b) |
774 | 4c9649a9 | j_mayer | { |
775 | f18cd223 | aurel32 | float64 fa, fb; |
776 | 4c9649a9 | j_mayer | |
777 | f18cd223 | aurel32 | fa = t_to_float64(a); |
778 | f18cd223 | aurel32 | fb = t_to_float64(b); |
779 | f18cd223 | aurel32 | |
780 | f18cd223 | aurel32 | if (float64_le(fa, fb, &FP_STATUS))
|
781 | f18cd223 | aurel32 | return 0x4000000000000000ULL; |
782 | f18cd223 | aurel32 | else
|
783 | f18cd223 | aurel32 | return 0; |
784 | 4c9649a9 | j_mayer | } |
785 | 4c9649a9 | j_mayer | |
786 | f18cd223 | aurel32 | uint64_t helper_cmptlt(uint64_t a, uint64_t b) |
787 | 4c9649a9 | j_mayer | { |
788 | f18cd223 | aurel32 | float64 fa, fb; |
789 | 4c9649a9 | j_mayer | |
790 | f18cd223 | aurel32 | fa = t_to_float64(a); |
791 | f18cd223 | aurel32 | fb = t_to_float64(b); |
792 | f18cd223 | aurel32 | |
793 | f18cd223 | aurel32 | if (float64_lt(fa, fb, &FP_STATUS))
|
794 | f18cd223 | aurel32 | return 0x4000000000000000ULL; |
795 | f18cd223 | aurel32 | else
|
796 | f18cd223 | aurel32 | return 0; |
797 | 4c9649a9 | j_mayer | } |
798 | 4c9649a9 | j_mayer | |
799 | f18cd223 | aurel32 | uint64_t helper_cmpgeq(uint64_t a, uint64_t b) |
800 | 4c9649a9 | j_mayer | { |
801 | f18cd223 | aurel32 | float64 fa, fb; |
802 | 4c9649a9 | j_mayer | |
803 | f18cd223 | aurel32 | fa = g_to_float64(a); |
804 | f18cd223 | aurel32 | fb = g_to_float64(b); |
805 | f18cd223 | aurel32 | |
806 | f18cd223 | aurel32 | if (float64_eq(fa, fb, &FP_STATUS))
|
807 | f18cd223 | aurel32 | return 0x4000000000000000ULL; |
808 | f18cd223 | aurel32 | else
|
809 | f18cd223 | aurel32 | return 0; |
810 | 4c9649a9 | j_mayer | } |
811 | 4c9649a9 | j_mayer | |
812 | f18cd223 | aurel32 | uint64_t helper_cmpgle(uint64_t a, uint64_t b) |
813 | 4c9649a9 | j_mayer | { |
814 | f18cd223 | aurel32 | float64 fa, fb; |
815 | f18cd223 | aurel32 | |
816 | f18cd223 | aurel32 | fa = g_to_float64(a); |
817 | f18cd223 | aurel32 | fb = g_to_float64(b); |
818 | 4c9649a9 | j_mayer | |
819 | f18cd223 | aurel32 | if (float64_le(fa, fb, &FP_STATUS))
|
820 | f18cd223 | aurel32 | return 0x4000000000000000ULL; |
821 | f18cd223 | aurel32 | else
|
822 | f18cd223 | aurel32 | return 0; |
823 | 4c9649a9 | j_mayer | } |
824 | 4c9649a9 | j_mayer | |
825 | f18cd223 | aurel32 | uint64_t helper_cmpglt(uint64_t a, uint64_t b) |
826 | 4c9649a9 | j_mayer | { |
827 | f18cd223 | aurel32 | float64 fa, fb; |
828 | f18cd223 | aurel32 | |
829 | f18cd223 | aurel32 | fa = g_to_float64(a); |
830 | f18cd223 | aurel32 | fb = g_to_float64(b); |
831 | 4c9649a9 | j_mayer | |
832 | f18cd223 | aurel32 | if (float64_lt(fa, fb, &FP_STATUS))
|
833 | f18cd223 | aurel32 | return 0x4000000000000000ULL; |
834 | f18cd223 | aurel32 | else
|
835 | f18cd223 | aurel32 | return 0; |
836 | 4c9649a9 | j_mayer | } |
837 | 4c9649a9 | j_mayer | |
838 | f18cd223 | aurel32 | uint64_t helper_cmpfeq (uint64_t a) |
839 | 4c9649a9 | j_mayer | { |
840 | f18cd223 | aurel32 | return !(a & 0x7FFFFFFFFFFFFFFFULL); |
841 | 4c9649a9 | j_mayer | } |
842 | 4c9649a9 | j_mayer | |
843 | f18cd223 | aurel32 | uint64_t helper_cmpfne (uint64_t a) |
844 | 4c9649a9 | j_mayer | { |
845 | f18cd223 | aurel32 | return (a & 0x7FFFFFFFFFFFFFFFULL); |
846 | f18cd223 | aurel32 | } |
847 | 4c9649a9 | j_mayer | |
848 | f18cd223 | aurel32 | uint64_t helper_cmpflt (uint64_t a) |
849 | f18cd223 | aurel32 | { |
850 | f18cd223 | aurel32 | return (a & 0x8000000000000000ULL) && (a & 0x7FFFFFFFFFFFFFFFULL); |
851 | 4c9649a9 | j_mayer | } |
852 | 4c9649a9 | j_mayer | |
853 | f18cd223 | aurel32 | uint64_t helper_cmpfle (uint64_t a) |
854 | 4c9649a9 | j_mayer | { |
855 | f18cd223 | aurel32 | return (a & 0x8000000000000000ULL) || !(a & 0x7FFFFFFFFFFFFFFFULL); |
856 | 4c9649a9 | j_mayer | } |
857 | 4c9649a9 | j_mayer | |
858 | f18cd223 | aurel32 | uint64_t helper_cmpfgt (uint64_t a) |
859 | 4c9649a9 | j_mayer | { |
860 | f18cd223 | aurel32 | return !(a & 0x8000000000000000ULL) && (a & 0x7FFFFFFFFFFFFFFFULL); |
861 | f18cd223 | aurel32 | } |
862 | 4c9649a9 | j_mayer | |
863 | f18cd223 | aurel32 | uint64_t helper_cmpfge (uint64_t a) |
864 | f18cd223 | aurel32 | { |
865 | f18cd223 | aurel32 | return !(a & 0x8000000000000000ULL) || !(a & 0x7FFFFFFFFFFFFFFFULL); |
866 | 4c9649a9 | j_mayer | } |
867 | 4c9649a9 | j_mayer | |
868 | f18cd223 | aurel32 | |
869 | f18cd223 | aurel32 | /* Floating point format conversion */
|
870 | f18cd223 | aurel32 | uint64_t helper_cvtts (uint64_t a) |
871 | 4c9649a9 | j_mayer | { |
872 | f18cd223 | aurel32 | float64 fa; |
873 | f18cd223 | aurel32 | float32 fr; |
874 | 4c9649a9 | j_mayer | |
875 | f18cd223 | aurel32 | fa = t_to_float64(a); |
876 | f18cd223 | aurel32 | fr = float64_to_float32(fa, &FP_STATUS); |
877 | f18cd223 | aurel32 | return float32_to_s(fr);
|
878 | 4c9649a9 | j_mayer | } |
879 | 4c9649a9 | j_mayer | |
880 | f18cd223 | aurel32 | uint64_t helper_cvtst (uint64_t a) |
881 | 4c9649a9 | j_mayer | { |
882 | f18cd223 | aurel32 | float32 fa; |
883 | f18cd223 | aurel32 | float64 fr; |
884 | f18cd223 | aurel32 | |
885 | f18cd223 | aurel32 | fa = s_to_float32(a); |
886 | f18cd223 | aurel32 | fr = float32_to_float64(fa, &FP_STATUS); |
887 | f18cd223 | aurel32 | return float64_to_t(fr);
|
888 | 4c9649a9 | j_mayer | } |
889 | 4c9649a9 | j_mayer | |
890 | f18cd223 | aurel32 | uint64_t helper_cvtqs (uint64_t a) |
891 | 4c9649a9 | j_mayer | { |
892 | f18cd223 | aurel32 | float32 fr = int64_to_float32(a, &FP_STATUS); |
893 | f18cd223 | aurel32 | return float32_to_s(fr);
|
894 | 4c9649a9 | j_mayer | } |
895 | 4c9649a9 | j_mayer | |
896 | f18cd223 | aurel32 | uint64_t helper_cvttq (uint64_t a) |
897 | 4c9649a9 | j_mayer | { |
898 | f18cd223 | aurel32 | float64 fa = t_to_float64(a); |
899 | f18cd223 | aurel32 | return float64_to_int64_round_to_zero(fa, &FP_STATUS);
|
900 | f18cd223 | aurel32 | } |
901 | 4c9649a9 | j_mayer | |
902 | f18cd223 | aurel32 | uint64_t helper_cvtqt (uint64_t a) |
903 | f18cd223 | aurel32 | { |
904 | f18cd223 | aurel32 | float64 fr = int64_to_float64(a, &FP_STATUS); |
905 | f18cd223 | aurel32 | return float64_to_t(fr);
|
906 | 4c9649a9 | j_mayer | } |
907 | 4c9649a9 | j_mayer | |
908 | f18cd223 | aurel32 | uint64_t helper_cvtqf (uint64_t a) |
909 | 4c9649a9 | j_mayer | { |
910 | f18cd223 | aurel32 | float32 fr = int64_to_float32(a, &FP_STATUS); |
911 | f18cd223 | aurel32 | return float32_to_f(fr);
|
912 | 4c9649a9 | j_mayer | } |
913 | 4c9649a9 | j_mayer | |
914 | f18cd223 | aurel32 | uint64_t helper_cvtgf (uint64_t a) |
915 | 4c9649a9 | j_mayer | { |
916 | f18cd223 | aurel32 | float64 fa; |
917 | f18cd223 | aurel32 | float32 fr; |
918 | f18cd223 | aurel32 | |
919 | f18cd223 | aurel32 | fa = g_to_float64(a); |
920 | f18cd223 | aurel32 | fr = float64_to_float32(fa, &FP_STATUS); |
921 | f18cd223 | aurel32 | return float32_to_f(fr);
|
922 | 4c9649a9 | j_mayer | } |
923 | 4c9649a9 | j_mayer | |
924 | f18cd223 | aurel32 | uint64_t helper_cvtgq (uint64_t a) |
925 | 4c9649a9 | j_mayer | { |
926 | f18cd223 | aurel32 | float64 fa = g_to_float64(a); |
927 | f18cd223 | aurel32 | return float64_to_int64_round_to_zero(fa, &FP_STATUS);
|
928 | 4c9649a9 | j_mayer | } |
929 | 4c9649a9 | j_mayer | |
930 | f18cd223 | aurel32 | uint64_t helper_cvtqg (uint64_t a) |
931 | 4c9649a9 | j_mayer | { |
932 | f18cd223 | aurel32 | float64 fr; |
933 | f18cd223 | aurel32 | fr = int64_to_float64(a, &FP_STATUS); |
934 | f18cd223 | aurel32 | return float64_to_g(fr);
|
935 | 4c9649a9 | j_mayer | } |
936 | 4c9649a9 | j_mayer | |
937 | f18cd223 | aurel32 | uint64_t helper_cvtlq (uint64_t a) |
938 | 4c9649a9 | j_mayer | { |
939 | f18cd223 | aurel32 | return (int64_t)((int32_t)((a >> 32) | ((a >> 29) & 0x3FFFFFFF))); |
940 | 4c9649a9 | j_mayer | } |
941 | 4c9649a9 | j_mayer | |
942 | 636aa200 | Blue Swirl | static inline uint64_t __helper_cvtql(uint64_t a, int s, int v) |
943 | 4c9649a9 | j_mayer | { |
944 | f18cd223 | aurel32 | uint64_t r; |
945 | f18cd223 | aurel32 | |
946 | f18cd223 | aurel32 | r = ((uint64_t)(a & 0xC0000000)) << 32; |
947 | f18cd223 | aurel32 | r |= ((uint64_t)(a & 0x7FFFFFFF)) << 29; |
948 | f18cd223 | aurel32 | |
949 | f18cd223 | aurel32 | if (v && (int64_t)((int32_t)r) != (int64_t)r) {
|
950 | f18cd223 | aurel32 | helper_excp(EXCP_ARITH, EXCP_ARITH_OVERFLOW); |
951 | f18cd223 | aurel32 | } |
952 | f18cd223 | aurel32 | if (s) {
|
953 | f18cd223 | aurel32 | /* TODO */
|
954 | f18cd223 | aurel32 | } |
955 | f18cd223 | aurel32 | return r;
|
956 | 4c9649a9 | j_mayer | } |
957 | 4c9649a9 | j_mayer | |
958 | f18cd223 | aurel32 | uint64_t helper_cvtql (uint64_t a) |
959 | 4c9649a9 | j_mayer | { |
960 | f18cd223 | aurel32 | return __helper_cvtql(a, 0, 0); |
961 | 4c9649a9 | j_mayer | } |
962 | 4c9649a9 | j_mayer | |
963 | f18cd223 | aurel32 | uint64_t helper_cvtqlv (uint64_t a) |
964 | 4c9649a9 | j_mayer | { |
965 | f18cd223 | aurel32 | return __helper_cvtql(a, 0, 1); |
966 | 4c9649a9 | j_mayer | } |
967 | 4c9649a9 | j_mayer | |
968 | f18cd223 | aurel32 | uint64_t helper_cvtqlsv (uint64_t a) |
969 | 4c9649a9 | j_mayer | { |
970 | f18cd223 | aurel32 | return __helper_cvtql(a, 1, 1); |
971 | 4c9649a9 | j_mayer | } |
972 | 4c9649a9 | j_mayer | |
973 | 8bb6e981 | aurel32 | /* PALcode support special instructions */
|
974 | 4c9649a9 | j_mayer | #if !defined (CONFIG_USER_ONLY)
|
975 | 8bb6e981 | aurel32 | void helper_hw_rei (void) |
976 | 8bb6e981 | aurel32 | { |
977 | 8bb6e981 | aurel32 | env->pc = env->ipr[IPR_EXC_ADDR] & ~3;
|
978 | 8bb6e981 | aurel32 | env->ipr[IPR_EXC_ADDR] = env->ipr[IPR_EXC_ADDR] & 1;
|
979 | 8bb6e981 | aurel32 | /* XXX: re-enable interrupts and memory mapping */
|
980 | 8bb6e981 | aurel32 | } |
981 | 8bb6e981 | aurel32 | |
982 | 8bb6e981 | aurel32 | void helper_hw_ret (uint64_t a)
|
983 | 8bb6e981 | aurel32 | { |
984 | 8bb6e981 | aurel32 | env->pc = a & ~3;
|
985 | 8bb6e981 | aurel32 | env->ipr[IPR_EXC_ADDR] = a & 1;
|
986 | 8bb6e981 | aurel32 | /* XXX: re-enable interrupts and memory mapping */
|
987 | 8bb6e981 | aurel32 | } |
988 | 8bb6e981 | aurel32 | |
989 | 8bb6e981 | aurel32 | uint64_t helper_mfpr (int iprn, uint64_t val)
|
990 | 8bb6e981 | aurel32 | { |
991 | 8bb6e981 | aurel32 | uint64_t tmp; |
992 | 8bb6e981 | aurel32 | |
993 | 8bb6e981 | aurel32 | if (cpu_alpha_mfpr(env, iprn, &tmp) == 0) |
994 | 8bb6e981 | aurel32 | val = tmp; |
995 | 8bb6e981 | aurel32 | |
996 | 8bb6e981 | aurel32 | return val;
|
997 | 8bb6e981 | aurel32 | } |
998 | 8bb6e981 | aurel32 | |
999 | 8bb6e981 | aurel32 | void helper_mtpr (int iprn, uint64_t val) |
1000 | 4c9649a9 | j_mayer | { |
1001 | 8bb6e981 | aurel32 | cpu_alpha_mtpr(env, iprn, val, NULL);
|
1002 | 8bb6e981 | aurel32 | } |
1003 | 4c9649a9 | j_mayer | |
1004 | 8bb6e981 | aurel32 | void helper_set_alt_mode (void) |
1005 | 8bb6e981 | aurel32 | { |
1006 | 8bb6e981 | aurel32 | env->saved_mode = env->ps & 0xC;
|
1007 | 8bb6e981 | aurel32 | env->ps = (env->ps & ~0xC) | (env->ipr[IPR_ALT_MODE] & 0xC); |
1008 | 4c9649a9 | j_mayer | } |
1009 | 4c9649a9 | j_mayer | |
1010 | 8bb6e981 | aurel32 | void helper_restore_mode (void) |
1011 | 4c9649a9 | j_mayer | { |
1012 | 8bb6e981 | aurel32 | env->ps = (env->ps & ~0xC) | env->saved_mode;
|
1013 | 4c9649a9 | j_mayer | } |
1014 | 8bb6e981 | aurel32 | |
1015 | 4c9649a9 | j_mayer | #endif
|
1016 | 4c9649a9 | j_mayer | |
1017 | 4c9649a9 | j_mayer | /*****************************************************************************/
|
1018 | 4c9649a9 | j_mayer | /* Softmmu support */
|
1019 | 4c9649a9 | j_mayer | #if !defined (CONFIG_USER_ONLY)
|
1020 | 4c9649a9 | j_mayer | |
1021 | 4c9649a9 | j_mayer | /* XXX: the two following helpers are pure hacks.
|
1022 | 4c9649a9 | j_mayer | * Hopefully, we emulate the PALcode, then we should never see
|
1023 | 4c9649a9 | j_mayer | * HW_LD / HW_ST instructions.
|
1024 | 4c9649a9 | j_mayer | */
|
1025 | 8bb6e981 | aurel32 | uint64_t helper_ld_virt_to_phys (uint64_t virtaddr) |
1026 | 4c9649a9 | j_mayer | { |
1027 | 4c9649a9 | j_mayer | uint64_t tlb_addr, physaddr; |
1028 | 6ebbf390 | j_mayer | int index, mmu_idx;
|
1029 | 4c9649a9 | j_mayer | void *retaddr;
|
1030 | 4c9649a9 | j_mayer | |
1031 | 6ebbf390 | j_mayer | mmu_idx = cpu_mmu_index(env); |
1032 | 8bb6e981 | aurel32 | index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
1033 | 4c9649a9 | j_mayer | redo:
|
1034 | 6ebbf390 | j_mayer | tlb_addr = env->tlb_table[mmu_idx][index].addr_read; |
1035 | 8bb6e981 | aurel32 | if ((virtaddr & TARGET_PAGE_MASK) ==
|
1036 | 4c9649a9 | j_mayer | (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { |
1037 | 8bb6e981 | aurel32 | physaddr = virtaddr + env->tlb_table[mmu_idx][index].addend; |
1038 | 4c9649a9 | j_mayer | } else {
|
1039 | 4c9649a9 | j_mayer | /* the page is not in the TLB : fill it */
|
1040 | 4c9649a9 | j_mayer | retaddr = GETPC(); |
1041 | 8bb6e981 | aurel32 | tlb_fill(virtaddr, 0, mmu_idx, retaddr);
|
1042 | 4c9649a9 | j_mayer | goto redo;
|
1043 | 4c9649a9 | j_mayer | } |
1044 | 8bb6e981 | aurel32 | return physaddr;
|
1045 | 4c9649a9 | j_mayer | } |
1046 | 4c9649a9 | j_mayer | |
1047 | 8bb6e981 | aurel32 | uint64_t helper_st_virt_to_phys (uint64_t virtaddr) |
1048 | 4c9649a9 | j_mayer | { |
1049 | 4c9649a9 | j_mayer | uint64_t tlb_addr, physaddr; |
1050 | 6ebbf390 | j_mayer | int index, mmu_idx;
|
1051 | 4c9649a9 | j_mayer | void *retaddr;
|
1052 | 4c9649a9 | j_mayer | |
1053 | 6ebbf390 | j_mayer | mmu_idx = cpu_mmu_index(env); |
1054 | 8bb6e981 | aurel32 | index = (virtaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
1055 | 4c9649a9 | j_mayer | redo:
|
1056 | 6ebbf390 | j_mayer | tlb_addr = env->tlb_table[mmu_idx][index].addr_write; |
1057 | 8bb6e981 | aurel32 | if ((virtaddr & TARGET_PAGE_MASK) ==
|
1058 | 4c9649a9 | j_mayer | (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) { |
1059 | 8bb6e981 | aurel32 | physaddr = virtaddr + env->tlb_table[mmu_idx][index].addend; |
1060 | 4c9649a9 | j_mayer | } else {
|
1061 | 4c9649a9 | j_mayer | /* the page is not in the TLB : fill it */
|
1062 | 4c9649a9 | j_mayer | retaddr = GETPC(); |
1063 | 8bb6e981 | aurel32 | tlb_fill(virtaddr, 1, mmu_idx, retaddr);
|
1064 | 4c9649a9 | j_mayer | goto redo;
|
1065 | 4c9649a9 | j_mayer | } |
1066 | 8bb6e981 | aurel32 | return physaddr;
|
1067 | 8bb6e981 | aurel32 | } |
1068 | 8bb6e981 | aurel32 | |
1069 | 8bb6e981 | aurel32 | void helper_ldl_raw(uint64_t t0, uint64_t t1)
|
1070 | 8bb6e981 | aurel32 | { |
1071 | 8bb6e981 | aurel32 | ldl_raw(t1, t0); |
1072 | 8bb6e981 | aurel32 | } |
1073 | 8bb6e981 | aurel32 | |
1074 | 8bb6e981 | aurel32 | void helper_ldq_raw(uint64_t t0, uint64_t t1)
|
1075 | 8bb6e981 | aurel32 | { |
1076 | 8bb6e981 | aurel32 | ldq_raw(t1, t0); |
1077 | 8bb6e981 | aurel32 | } |
1078 | 8bb6e981 | aurel32 | |
1079 | 8bb6e981 | aurel32 | void helper_ldl_l_raw(uint64_t t0, uint64_t t1)
|
1080 | 8bb6e981 | aurel32 | { |
1081 | 8bb6e981 | aurel32 | env->lock = t1; |
1082 | 8bb6e981 | aurel32 | ldl_raw(t1, t0); |
1083 | 8bb6e981 | aurel32 | } |
1084 | 8bb6e981 | aurel32 | |
1085 | 8bb6e981 | aurel32 | void helper_ldq_l_raw(uint64_t t0, uint64_t t1)
|
1086 | 8bb6e981 | aurel32 | { |
1087 | 8bb6e981 | aurel32 | env->lock = t1; |
1088 | 8bb6e981 | aurel32 | ldl_raw(t1, t0); |
1089 | 8bb6e981 | aurel32 | } |
1090 | 8bb6e981 | aurel32 | |
1091 | 8bb6e981 | aurel32 | void helper_ldl_kernel(uint64_t t0, uint64_t t1)
|
1092 | 8bb6e981 | aurel32 | { |
1093 | 8bb6e981 | aurel32 | ldl_kernel(t1, t0); |
1094 | 8bb6e981 | aurel32 | } |
1095 | 8bb6e981 | aurel32 | |
1096 | 8bb6e981 | aurel32 | void helper_ldq_kernel(uint64_t t0, uint64_t t1)
|
1097 | 8bb6e981 | aurel32 | { |
1098 | 8bb6e981 | aurel32 | ldq_kernel(t1, t0); |
1099 | 8bb6e981 | aurel32 | } |
1100 | 8bb6e981 | aurel32 | |
1101 | 8bb6e981 | aurel32 | void helper_ldl_data(uint64_t t0, uint64_t t1)
|
1102 | 8bb6e981 | aurel32 | { |
1103 | 8bb6e981 | aurel32 | ldl_data(t1, t0); |
1104 | 8bb6e981 | aurel32 | } |
1105 | 8bb6e981 | aurel32 | |
1106 | 8bb6e981 | aurel32 | void helper_ldq_data(uint64_t t0, uint64_t t1)
|
1107 | 8bb6e981 | aurel32 | { |
1108 | 8bb6e981 | aurel32 | ldq_data(t1, t0); |
1109 | 8bb6e981 | aurel32 | } |
1110 | 8bb6e981 | aurel32 | |
1111 | 8bb6e981 | aurel32 | void helper_stl_raw(uint64_t t0, uint64_t t1)
|
1112 | 8bb6e981 | aurel32 | { |
1113 | 8bb6e981 | aurel32 | stl_raw(t1, t0); |
1114 | 8bb6e981 | aurel32 | } |
1115 | 8bb6e981 | aurel32 | |
1116 | 8bb6e981 | aurel32 | void helper_stq_raw(uint64_t t0, uint64_t t1)
|
1117 | 8bb6e981 | aurel32 | { |
1118 | 8bb6e981 | aurel32 | stq_raw(t1, t0); |
1119 | 8bb6e981 | aurel32 | } |
1120 | 8bb6e981 | aurel32 | |
1121 | 8bb6e981 | aurel32 | uint64_t helper_stl_c_raw(uint64_t t0, uint64_t t1) |
1122 | 8bb6e981 | aurel32 | { |
1123 | 8bb6e981 | aurel32 | uint64_t ret; |
1124 | 8bb6e981 | aurel32 | |
1125 | 8bb6e981 | aurel32 | if (t1 == env->lock) {
|
1126 | 8bb6e981 | aurel32 | stl_raw(t1, t0); |
1127 | 8bb6e981 | aurel32 | ret = 0;
|
1128 | 8bb6e981 | aurel32 | } else
|
1129 | 8bb6e981 | aurel32 | ret = 1;
|
1130 | 8bb6e981 | aurel32 | |
1131 | 8bb6e981 | aurel32 | env->lock = 1;
|
1132 | 8bb6e981 | aurel32 | |
1133 | 8bb6e981 | aurel32 | return ret;
|
1134 | 8bb6e981 | aurel32 | } |
1135 | 8bb6e981 | aurel32 | |
1136 | 8bb6e981 | aurel32 | uint64_t helper_stq_c_raw(uint64_t t0, uint64_t t1) |
1137 | 8bb6e981 | aurel32 | { |
1138 | 8bb6e981 | aurel32 | uint64_t ret; |
1139 | 8bb6e981 | aurel32 | |
1140 | 8bb6e981 | aurel32 | if (t1 == env->lock) {
|
1141 | 8bb6e981 | aurel32 | stq_raw(t1, t0); |
1142 | 8bb6e981 | aurel32 | ret = 0;
|
1143 | 8bb6e981 | aurel32 | } else
|
1144 | 8bb6e981 | aurel32 | ret = 1;
|
1145 | 8bb6e981 | aurel32 | |
1146 | 8bb6e981 | aurel32 | env->lock = 1;
|
1147 | 8bb6e981 | aurel32 | |
1148 | 8bb6e981 | aurel32 | return ret;
|
1149 | 4c9649a9 | j_mayer | } |
1150 | 4c9649a9 | j_mayer | |
1151 | 4c9649a9 | j_mayer | #define MMUSUFFIX _mmu
|
1152 | 4c9649a9 | j_mayer | |
1153 | 4c9649a9 | j_mayer | #define SHIFT 0 |
1154 | 4c9649a9 | j_mayer | #include "softmmu_template.h" |
1155 | 4c9649a9 | j_mayer | |
1156 | 4c9649a9 | j_mayer | #define SHIFT 1 |
1157 | 4c9649a9 | j_mayer | #include "softmmu_template.h" |
1158 | 4c9649a9 | j_mayer | |
1159 | 4c9649a9 | j_mayer | #define SHIFT 2 |
1160 | 4c9649a9 | j_mayer | #include "softmmu_template.h" |
1161 | 4c9649a9 | j_mayer | |
1162 | 4c9649a9 | j_mayer | #define SHIFT 3 |
1163 | 4c9649a9 | j_mayer | #include "softmmu_template.h" |
1164 | 4c9649a9 | j_mayer | |
1165 | 4c9649a9 | j_mayer | /* try to fill the TLB and return an exception if error. If retaddr is
|
1166 | 4c9649a9 | j_mayer | NULL, it means that the function was called in C code (i.e. not
|
1167 | 4c9649a9 | j_mayer | from generated code or from helper.c) */
|
1168 | 4c9649a9 | j_mayer | /* XXX: fix it to restore all registers */
|
1169 | 6ebbf390 | j_mayer | void tlb_fill (target_ulong addr, int is_write, int mmu_idx, void *retaddr) |
1170 | 4c9649a9 | j_mayer | { |
1171 | 4c9649a9 | j_mayer | TranslationBlock *tb; |
1172 | 4c9649a9 | j_mayer | CPUState *saved_env; |
1173 | 44f8625d | bellard | unsigned long pc; |
1174 | 4c9649a9 | j_mayer | int ret;
|
1175 | 4c9649a9 | j_mayer | |
1176 | 4c9649a9 | j_mayer | /* XXX: hack to restore env in all cases, even if not called from
|
1177 | 4c9649a9 | j_mayer | generated code */
|
1178 | 4c9649a9 | j_mayer | saved_env = env; |
1179 | 4c9649a9 | j_mayer | env = cpu_single_env; |
1180 | 6ebbf390 | j_mayer | ret = cpu_alpha_handle_mmu_fault(env, addr, is_write, mmu_idx, 1);
|
1181 | 4c9649a9 | j_mayer | if (!likely(ret == 0)) { |
1182 | 4c9649a9 | j_mayer | if (likely(retaddr)) {
|
1183 | 4c9649a9 | j_mayer | /* now we have a real cpu fault */
|
1184 | 44f8625d | bellard | pc = (unsigned long)retaddr; |
1185 | 4c9649a9 | j_mayer | tb = tb_find_pc(pc); |
1186 | 4c9649a9 | j_mayer | if (likely(tb)) {
|
1187 | 4c9649a9 | j_mayer | /* the PC is inside the translated code. It means that we have
|
1188 | 4c9649a9 | j_mayer | a virtual CPU fault */
|
1189 | 4c9649a9 | j_mayer | cpu_restore_state(tb, env, pc, NULL);
|
1190 | 4c9649a9 | j_mayer | } |
1191 | 4c9649a9 | j_mayer | } |
1192 | 4c9649a9 | j_mayer | /* Exception index and error code are already set */
|
1193 | 4c9649a9 | j_mayer | cpu_loop_exit(); |
1194 | 4c9649a9 | j_mayer | } |
1195 | 4c9649a9 | j_mayer | env = saved_env; |
1196 | 4c9649a9 | j_mayer | } |
1197 | 4c9649a9 | j_mayer | |
1198 | 4c9649a9 | j_mayer | #endif |