2 * Alpha emulation cpu helpers for qemu.
4 * Copyright (c) 2007 Jocelyn Mayer
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.
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.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
26 #include "softfloat.h"
28 uint64_t cpu_alpha_load_fpcr (CPUState
*env
)
33 flags
= env
->fp_status
.float_exception_flags
;
34 ret
|= (uint64_t) flags
<< 52;
37 env
->ipr
[IPR_EXC_SUM
] &= ~0x3E;
38 env
->ipr
[IPR_EXC_SUM
] |= flags
<< 1;
40 mask
= env
->fp_status
.float_exception_mask
;
41 if (mask
& float_flag_invalid
)
43 if (mask
& float_flag_divbyzero
)
45 if (mask
& float_flag_overflow
)
47 if (mask
& float_flag_underflow
)
49 if (mask
& float_flag_inexact
)
52 switch (env
->fp_status
.float_rounding_mode
) {
53 case float_round_nearest_even
:
54 ret
|= 2ULL << FPCR_DYN_SHIFT
;
56 case float_round_down
:
57 ret
|= 1ULL << FPCR_DYN_SHIFT
;
60 ret
|= 3ULL << FPCR_DYN_SHIFT
;
62 case float_round_to_zero
:
68 void cpu_alpha_store_fpcr (CPUState
*env
, uint64_t val
)
72 set_float_exception_flags((val
>> 52) & 0x3F, &env
->fp_status
);
76 mask
|= float_flag_invalid
;
78 mask
|= float_flag_divbyzero
;
80 mask
|= float_flag_overflow
;
82 mask
|= float_flag_underflow
;
84 mask
|= float_flag_inexact
;
85 env
->fp_status
.float_exception_mask
= mask
;
87 switch ((val
>> FPCR_DYN_SHIFT
) & 3) {
89 round_mode
= float_round_to_zero
;
92 round_mode
= float_round_down
;
95 round_mode
= float_round_nearest_even
;
98 default: /* this avoids a gcc (< 4.4) warning */
99 round_mode
= float_round_up
;
102 set_float_rounding_mode(round_mode
, &env
->fp_status
);
105 #if defined(CONFIG_USER_ONLY)
107 int cpu_alpha_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
108 int mmu_idx
, int is_softmmu
)
111 env
->exception_index
= EXCP_ITB_MISS
;
113 env
->exception_index
= EXCP_DFAULT
;
114 env
->ipr
[IPR_EXC_ADDR
] = address
;
119 target_phys_addr_t
cpu_get_phys_page_debug (CPUState
*env
, target_ulong addr
)
124 void do_interrupt (CPUState
*env
)
126 env
->exception_index
= -1;
131 target_phys_addr_t
cpu_get_phys_page_debug (CPUState
*env
, target_ulong addr
)
136 int cpu_alpha_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
137 int mmu_idx
, int is_softmmu
)
142 /* Instruction translation buffer miss */
143 env
->exception_index
= EXCP_ITB_MISS
;
145 if (env
->ipr
[IPR_EXC_ADDR
] & 1)
146 env
->exception_index
= EXCP_DTB_MISS_PAL
;
148 env
->exception_index
= EXCP_DTB_MISS_NATIVE
;
149 opc
= (ldl_code(env
->pc
) >> 21) << 4;
155 env
->ipr
[IPR_MM_STAT
] = opc
;
161 int cpu_alpha_mfpr (CPUState
*env
, int iprn
, uint64_t *valp
)
166 hwpcb
= env
->ipr
[IPR_PCBB
];
169 if (env
->features
& FEATURE_ASN
)
170 *valp
= env
->ipr
[IPR_ASN
];
175 *valp
= ((int64_t)(env
->ipr
[IPR_ASTEN
] << 60)) >> 60;
178 *valp
= ((int64_t)(env
->ipr
[IPR_ASTSR
] << 60)) >> 60;
185 if (env
->features
& FEATURE_SPS
)
186 *valp
= env
->ipr
[IPR_ESP
];
188 *valp
= ldq_raw(hwpcb
+ 8);
191 *valp
= ((int64_t)(env
->ipr
[IPR_FEN
] << 63)) >> 63;
198 *valp
= ((int64_t)(env
->ipr
[IPR_IPL
] << 59)) >> 59;
201 if (!(env
->ipr
[IPR_EXC_ADDR
] & 1)) {
204 if (env
->features
& FEATURE_SPS
)
205 *valp
= env
->ipr
[IPR_KSP
];
207 *valp
= ldq_raw(hwpcb
+ 0);
211 *valp
= ((int64_t)(env
->ipr
[IPR_MCES
] << 59)) >> 59;
214 /* Implementation specific */
218 *valp
= ((int64_t)env
->ipr
[IPR_PCBB
] << 16) >> 16;
221 *valp
= env
->ipr
[IPR_PRBR
];
224 *valp
= env
->ipr
[IPR_PTBR
];
227 *valp
= (int64_t)((int32_t)env
->ipr
[IPR_SCBB
]);
234 *valp
= (int64_t)((int16_t)env
->ipr
[IPR_SISR
]);
236 if (env
->features
& FEATURE_SPS
)
237 *valp
= env
->ipr
[IPR_SSP
];
239 *valp
= ldq_raw(hwpcb
+ 16);
242 if (env
->features
& FEATURE_VIRBND
)
243 *valp
= env
->ipr
[IPR_SYSPTBR
];
248 if ((env
->features
& FEATURE_TBCHK
)) {
277 if (env
->features
& FEATURE_SPS
)
278 *valp
= env
->ipr
[IPR_USP
];
280 *valp
= ldq_raw(hwpcb
+ 24);
283 if (env
->features
& FEATURE_VIRBND
)
284 *valp
= env
->ipr
[IPR_VIRBND
];
289 *valp
= env
->ipr
[IPR_VPTB
];
292 *valp
= env
->ipr
[IPR_WHAMI
];
303 int cpu_alpha_mtpr (CPUState
*env
, int iprn
, uint64_t val
, uint64_t *oldvalp
)
305 uint64_t hwpcb
, tmp64
;
309 hwpcb
= env
->ipr
[IPR_PCBB
];
316 tmp8
= ((int8_t)(env
->ipr
[IPR_ASTEN
] << 4)) >> 4;
319 tmp8
|= (val
>> 4) & 0xF;
320 env
->ipr
[IPR_ASTEN
] &= ~0xF;
321 env
->ipr
[IPR_ASTEN
] |= tmp8
;
325 tmp8
= ((int8_t)(env
->ipr
[IPR_ASTSR
] << 4)) >> 4;
328 tmp8
|= (val
>> 4) & 0xF;
329 env
->ipr
[IPR_ASTSR
] &= ~0xF;
330 env
->ipr
[IPR_ASTSR
] |= tmp8
;
333 env
->ipr
[IPR_DATFX
] &= ~0x1;
334 env
->ipr
[IPR_DATFX
] |= val
& 1;
335 tmp64
= ldq_raw(hwpcb
+ 56);
336 tmp64
&= ~0x8000000000000000ULL
;
337 tmp64
|= (val
& 1) << 63;
338 stq_raw(hwpcb
+ 56, tmp64
);
341 if (env
->features
& FEATURE_SPS
)
342 env
->ipr
[IPR_ESP
] = val
;
344 stq_raw(hwpcb
+ 8, val
);
347 env
->ipr
[IPR_FEN
] = val
& 1;
348 tmp64
= ldq_raw(hwpcb
+ 56);
351 stq_raw(hwpcb
+ 56, tmp64
);
354 /* XXX: TODO: Send IRQ to CPU #ir[16] */
357 *oldvalp
= ((int64_t)(env
->ipr
[IPR_IPL
] << 59)) >> 59;
358 env
->ipr
[IPR_IPL
] &= ~0x1F;
359 env
->ipr
[IPR_IPL
] |= val
& 0x1F;
360 /* XXX: may issue an interrupt or ASR _now_ */
364 if (!(env
->ipr
[IPR_EXC_ADDR
] & 1)) {
367 if (env
->features
& FEATURE_SPS
)
368 env
->ipr
[IPR_KSP
] = val
;
370 stq_raw(hwpcb
+ 0, val
);
374 env
->ipr
[IPR_MCES
] &= ~((val
& 0x7) | 0x18);
375 env
->ipr
[IPR_MCES
] |= val
& 0x18;
378 /* Implementation specific */
387 env
->ipr
[IPR_PRBR
] = val
;
394 env
->ipr
[IPR_SCBB
] = (uint32_t)val
;
398 env
->ipr
[IPR_SISR
] |= 1 << (val
& 0xF);
399 /* XXX: request a software interrupt _now_ */
407 if (env
->features
& FEATURE_SPS
)
408 env
->ipr
[IPR_SSP
] = val
;
410 stq_raw(hwpcb
+ 16, val
);
413 if (env
->features
& FEATURE_VIRBND
)
414 env
->ipr
[IPR_SYSPTBR
] = val
;
428 tlb_flush_page(env
, val
);
431 tlb_flush_page(env
, val
);
434 tlb_flush_page(env
, val
);
437 if (env
->features
& FEATURE_SPS
)
438 env
->ipr
[IPR_USP
] = val
;
440 stq_raw(hwpcb
+ 24, val
);
443 if (env
->features
& FEATURE_VIRBND
)
444 env
->ipr
[IPR_VIRBND
] = val
;
449 env
->ipr
[IPR_VPTB
] = val
;
464 void do_interrupt (CPUState
*env
)
468 env
->ipr
[IPR_EXC_ADDR
] = env
->pc
| 1;
469 excp
= env
->exception_index
;
470 env
->exception_index
= 0;
472 /* XXX: disable interrupts and memory mapping */
473 if (env
->ipr
[IPR_PAL_BASE
] != -1ULL) {
474 /* We use native PALcode */
475 env
->pc
= env
->ipr
[IPR_PAL_BASE
] + excp
;
477 /* We use emulated PALcode */
480 env
->pc
= env
->ipr
[IPR_EXC_ADDR
] & ~7;
481 env
->ipr
[IPR_EXC_ADDR
] = env
->ipr
[IPR_EXC_ADDR
] & 1;
482 /* XXX: re-enable interrupts and memory mapping */
487 void cpu_dump_state (CPUState
*env
, FILE *f
,
488 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
491 static const char *linux_reg_names
[] = {
492 "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ",
493 "t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ",
494 "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ",
495 "t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero",
499 cpu_fprintf(f
, " PC " TARGET_FMT_lx
" PS " TARGET_FMT_lx
"\n",
501 for (i
= 0; i
< 31; i
++) {
502 cpu_fprintf(f
, "IR%02d %s " TARGET_FMT_lx
" ", i
,
503 linux_reg_names
[i
], env
->ir
[i
]);
505 cpu_fprintf(f
, "\n");
507 cpu_fprintf(f
, "\n");
508 for (i
= 0; i
< 31; i
++) {
509 cpu_fprintf(f
, "FIR%02d " TARGET_FMT_lx
" ", i
,
510 *((uint64_t *)(&env
->fir
[i
])));
512 cpu_fprintf(f
, "\n");
514 cpu_fprintf(f
, "\nlock " TARGET_FMT_lx
"\n", env
->lock
);