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