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