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 void swap_shadow_regs(CPUState
*env
)
173 uint64_t i0
, i1
, i2
, i3
, i4
, i5
, i6
, i7
;
184 env
->ir
[8] = env
->shadow
[0];
185 env
->ir
[9] = env
->shadow
[1];
186 env
->ir
[10] = env
->shadow
[2];
187 env
->ir
[11] = env
->shadow
[3];
188 env
->ir
[12] = env
->shadow
[4];
189 env
->ir
[13] = env
->shadow
[5];
190 env
->ir
[14] = env
->shadow
[6];
191 env
->ir
[25] = env
->shadow
[7];
203 target_phys_addr_t
cpu_get_phys_page_debug (CPUState
*env
, target_ulong addr
)
208 int cpu_alpha_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
209 int mmu_idx
, int is_softmmu
)
213 #endif /* USER_ONLY */
215 void do_interrupt (CPUState
*env
)
217 int i
= env
->exception_index
;
219 if (qemu_loglevel_mask(CPU_LOG_INT
)) {
221 const char *name
= "<unknown>";
230 case EXCP_SMP_INTERRUPT
:
231 name
= "smp_interrupt";
233 case EXCP_CLK_INTERRUPT
:
234 name
= "clk_interrupt";
236 case EXCP_DEV_INTERRUPT
:
237 name
= "dev_interrupt";
264 qemu_log("INT %6d: %s(%#x) pc=%016" PRIx64
" sp=%016" PRIx64
"\n",
265 ++count
, name
, env
->error_code
, env
->pc
, env
->ir
[IR_SP
]);
268 env
->exception_index
= -1;
270 #if !defined(CONFIG_USER_ONLY)
278 case EXCP_SMP_INTERRUPT
:
281 case EXCP_CLK_INTERRUPT
:
284 case EXCP_DEV_INTERRUPT
:
304 /* There are 64 entry points for both privileged and unprivileged,
305 with bit 0x80 indicating unprivileged. Each entry point gets
306 64 bytes to do its job. */
308 i
= 0x2000 + (i
- 0x80) * 64;
314 cpu_abort(env
, "Unhandled CPU exception");
317 /* Remember where the exception happened. Emulate real hardware in
318 that the low bit of the PC indicates PALmode. */
319 env
->exc_addr
= env
->pc
| env
->pal_mode
;
321 /* Continue execution at the PALcode entry point. */
322 env
->pc
= env
->palbr
+ i
;
324 /* Switch to PALmode. */
325 if (!env
->pal_mode
) {
327 swap_shadow_regs(env
);
329 #endif /* !USER_ONLY */
332 void cpu_dump_state (CPUState
*env
, FILE *f
, fprintf_function cpu_fprintf
,
335 static const char *linux_reg_names
[] = {
336 "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ",
337 "t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ",
338 "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ",
339 "t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero",
343 cpu_fprintf(f
, " PC " TARGET_FMT_lx
" PS %02x\n",
345 for (i
= 0; i
< 31; i
++) {
346 cpu_fprintf(f
, "IR%02d %s " TARGET_FMT_lx
" ", i
,
347 linux_reg_names
[i
], env
->ir
[i
]);
349 cpu_fprintf(f
, "\n");
352 cpu_fprintf(f
, "lock_a " TARGET_FMT_lx
" lock_v " TARGET_FMT_lx
"\n",
353 env
->lock_addr
, env
->lock_value
);
355 for (i
= 0; i
< 31; i
++) {
356 cpu_fprintf(f
, "FIR%02d " TARGET_FMT_lx
" ", i
,
357 *((uint64_t *)(&env
->fir
[i
])));
359 cpu_fprintf(f
, "\n");
361 cpu_fprintf(f
, "\n");