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 t
= env
->fpcr_exc_status
;
36 if (t
& float_flag_invalid
) {
39 if (t
& float_flag_divbyzero
) {
42 if (t
& float_flag_overflow
) {
45 if (t
& float_flag_underflow
) {
48 if (t
& float_flag_inexact
) {
53 t
= env
->fpcr_exc_mask
;
54 if (t
& float_flag_invalid
) {
57 if (t
& float_flag_divbyzero
) {
60 if (t
& float_flag_overflow
) {
63 if (t
& float_flag_underflow
) {
66 if (t
& float_flag_inexact
) {
70 switch (env
->fpcr_dyn_round
) {
71 case float_round_nearest_even
:
74 case float_round_down
:
80 case float_round_to_zero
:
81 r
|= FPCR_DYN_CHOPPED
;
98 void cpu_alpha_store_fpcr (CPUState
*env
, uint64_t val
)
103 if (val
& FPCR_INV
) {
104 t
|= float_flag_invalid
;
106 if (val
& FPCR_DZE
) {
107 t
|= float_flag_divbyzero
;
109 if (val
& FPCR_OVF
) {
110 t
|= float_flag_overflow
;
112 if (val
& FPCR_UNF
) {
113 t
|= float_flag_underflow
;
115 if (val
& FPCR_INE
) {
116 t
|= float_flag_inexact
;
118 env
->fpcr_exc_status
= t
;
121 if (val
& FPCR_INVD
) {
122 t
|= float_flag_invalid
;
124 if (val
& FPCR_DZED
) {
125 t
|= float_flag_divbyzero
;
127 if (val
& FPCR_OVFD
) {
128 t
|= float_flag_overflow
;
130 if (val
& FPCR_UNFD
) {
131 t
|= float_flag_underflow
;
133 if (val
& FPCR_INED
) {
134 t
|= float_flag_inexact
;
136 env
->fpcr_exc_mask
= t
;
138 switch (val
& FPCR_DYN_MASK
) {
139 case FPCR_DYN_CHOPPED
:
140 t
= float_round_to_zero
;
143 t
= float_round_down
;
145 case FPCR_DYN_NORMAL
:
146 t
= float_round_nearest_even
;
152 env
->fpcr_dyn_round
= t
;
154 env
->fpcr_flush_to_zero
155 = (val
& (FPCR_UNDZ
|FPCR_UNFD
)) == (FPCR_UNDZ
|FPCR_UNFD
);
157 env
->fpcr_dnz
= (val
& FPCR_DNZ
) != 0;
158 env
->fpcr_dnod
= (val
& FPCR_DNOD
) != 0;
159 env
->fpcr_undz
= (val
& FPCR_UNDZ
) != 0;
162 #if defined(CONFIG_USER_ONLY)
163 int cpu_alpha_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
164 int mmu_idx
, int is_softmmu
)
166 env
->exception_index
= EXCP_MMFAULT
;
167 env
->trap_arg0
= address
;
171 target_phys_addr_t
cpu_get_phys_page_debug (CPUState
*env
, target_ulong addr
)
176 int cpu_alpha_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
177 int mmu_idx
, int is_softmmu
)
181 #endif /* USER_ONLY */
183 void do_interrupt (CPUState
*env
)
185 int i
= env
->exception_index
;
187 if (qemu_loglevel_mask(CPU_LOG_INT
)) {
189 const char *name
= "<unknown>";
198 case EXCP_SMP_INTERRUPT
:
199 name
= "smp_interrupt";
201 case EXCP_CLK_INTERRUPT
:
202 name
= "clk_interrupt";
204 case EXCP_DEV_INTERRUPT
:
205 name
= "dev_interrupt";
232 qemu_log("INT %6d: %s(%#x) pc=%016" PRIx64
" sp=%016" PRIx64
"\n",
233 ++count
, name
, env
->error_code
, env
->pc
, env
->ir
[IR_SP
]);
236 env
->exception_index
= -1;
238 #if !defined(CONFIG_USER_ONLY)
246 case EXCP_SMP_INTERRUPT
:
249 case EXCP_CLK_INTERRUPT
:
252 case EXCP_DEV_INTERRUPT
:
272 /* There are 64 entry points for both privileged and unprivileged,
273 with bit 0x80 indicating unprivileged. Each entry point gets
274 64 bytes to do its job. */
276 i
= 0x2000 + (i
- 0x80) * 64;
282 cpu_abort(env
, "Unhandled CPU exception");
285 /* Remember where the exception happened. Emulate real hardware in
286 that the low bit of the PC indicates PALmode. */
287 env
->exc_addr
= env
->pc
| env
->pal_mode
;
289 /* Continue execution at the PALcode entry point. */
290 env
->pc
= env
->palbr
+ i
;
292 /* Switch to PALmode. */
294 #endif /* !USER_ONLY */
297 void cpu_dump_state (CPUState
*env
, FILE *f
, fprintf_function cpu_fprintf
,
300 static const char *linux_reg_names
[] = {
301 "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ",
302 "t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ",
303 "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ",
304 "t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero",
308 cpu_fprintf(f
, " PC " TARGET_FMT_lx
" PS %02x\n",
310 for (i
= 0; i
< 31; i
++) {
311 cpu_fprintf(f
, "IR%02d %s " TARGET_FMT_lx
" ", i
,
312 linux_reg_names
[i
], env
->ir
[i
]);
314 cpu_fprintf(f
, "\n");
317 cpu_fprintf(f
, "lock_a " TARGET_FMT_lx
" lock_v " TARGET_FMT_lx
"\n",
318 env
->lock_addr
, env
->lock_value
);
320 for (i
= 0; i
< 31; i
++) {
321 cpu_fprintf(f
, "FIR%02d " TARGET_FMT_lx
" ", i
,
322 *((uint64_t *)(&env
->fir
[i
])));
324 cpu_fprintf(f
, "\n");
326 cpu_fprintf(f
, "\n");