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