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)
164 int cpu_alpha_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
165 int mmu_idx
, int is_softmmu
)
168 env
->exception_index
= EXCP_ITB_MISS
;
170 env
->exception_index
= EXCP_DFAULT
;
171 env
->ipr
[IPR_EXC_ADDR
] = address
;
176 target_phys_addr_t
cpu_get_phys_page_debug (CPUState
*env
, target_ulong addr
)
181 void do_interrupt (CPUState
*env
)
183 env
->exception_index
= -1;
188 target_phys_addr_t
cpu_get_phys_page_debug (CPUState
*env
, target_ulong addr
)
193 int cpu_alpha_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
194 int mmu_idx
, int is_softmmu
)
199 /* Instruction translation buffer miss */
200 env
->exception_index
= EXCP_ITB_MISS
;
202 if (env
->ipr
[IPR_EXC_ADDR
] & 1)
203 env
->exception_index
= EXCP_DTB_MISS_PAL
;
205 env
->exception_index
= EXCP_DTB_MISS_NATIVE
;
206 opc
= (ldl_code(env
->pc
) >> 21) << 4;
212 env
->ipr
[IPR_MM_STAT
] = opc
;
218 int cpu_alpha_mfpr (CPUState
*env
, int iprn
, uint64_t *valp
)
223 hwpcb
= env
->ipr
[IPR_PCBB
];
226 if (env
->features
& FEATURE_ASN
)
227 *valp
= env
->ipr
[IPR_ASN
];
232 *valp
= ((int64_t)(env
->ipr
[IPR_ASTEN
] << 60)) >> 60;
235 *valp
= ((int64_t)(env
->ipr
[IPR_ASTSR
] << 60)) >> 60;
242 if (env
->features
& FEATURE_SPS
)
243 *valp
= env
->ipr
[IPR_ESP
];
245 *valp
= ldq_raw(hwpcb
+ 8);
248 *valp
= ((int64_t)(env
->ipr
[IPR_FEN
] << 63)) >> 63;
255 *valp
= ((int64_t)(env
->ipr
[IPR_IPL
] << 59)) >> 59;
258 if (!(env
->ipr
[IPR_EXC_ADDR
] & 1)) {
261 if (env
->features
& FEATURE_SPS
)
262 *valp
= env
->ipr
[IPR_KSP
];
264 *valp
= ldq_raw(hwpcb
+ 0);
268 *valp
= ((int64_t)(env
->ipr
[IPR_MCES
] << 59)) >> 59;
271 /* Implementation specific */
275 *valp
= ((int64_t)env
->ipr
[IPR_PCBB
] << 16) >> 16;
278 *valp
= env
->ipr
[IPR_PRBR
];
281 *valp
= env
->ipr
[IPR_PTBR
];
284 *valp
= (int64_t)((int32_t)env
->ipr
[IPR_SCBB
]);
291 *valp
= (int64_t)((int16_t)env
->ipr
[IPR_SISR
]);
293 if (env
->features
& FEATURE_SPS
)
294 *valp
= env
->ipr
[IPR_SSP
];
296 *valp
= ldq_raw(hwpcb
+ 16);
299 if (env
->features
& FEATURE_VIRBND
)
300 *valp
= env
->ipr
[IPR_SYSPTBR
];
305 if ((env
->features
& FEATURE_TBCHK
)) {
334 if (env
->features
& FEATURE_SPS
)
335 *valp
= env
->ipr
[IPR_USP
];
337 *valp
= ldq_raw(hwpcb
+ 24);
340 if (env
->features
& FEATURE_VIRBND
)
341 *valp
= env
->ipr
[IPR_VIRBND
];
346 *valp
= env
->ipr
[IPR_VPTB
];
349 *valp
= env
->ipr
[IPR_WHAMI
];
360 int cpu_alpha_mtpr (CPUState
*env
, int iprn
, uint64_t val
, uint64_t *oldvalp
)
362 uint64_t hwpcb
, tmp64
;
366 hwpcb
= env
->ipr
[IPR_PCBB
];
373 tmp8
= ((int8_t)(env
->ipr
[IPR_ASTEN
] << 4)) >> 4;
376 tmp8
|= (val
>> 4) & 0xF;
377 env
->ipr
[IPR_ASTEN
] &= ~0xF;
378 env
->ipr
[IPR_ASTEN
] |= tmp8
;
382 tmp8
= ((int8_t)(env
->ipr
[IPR_ASTSR
] << 4)) >> 4;
385 tmp8
|= (val
>> 4) & 0xF;
386 env
->ipr
[IPR_ASTSR
] &= ~0xF;
387 env
->ipr
[IPR_ASTSR
] |= tmp8
;
390 env
->ipr
[IPR_DATFX
] &= ~0x1;
391 env
->ipr
[IPR_DATFX
] |= val
& 1;
392 tmp64
= ldq_raw(hwpcb
+ 56);
393 tmp64
&= ~0x8000000000000000ULL
;
394 tmp64
|= (val
& 1) << 63;
395 stq_raw(hwpcb
+ 56, tmp64
);
398 if (env
->features
& FEATURE_SPS
)
399 env
->ipr
[IPR_ESP
] = val
;
401 stq_raw(hwpcb
+ 8, val
);
404 env
->ipr
[IPR_FEN
] = val
& 1;
405 tmp64
= ldq_raw(hwpcb
+ 56);
408 stq_raw(hwpcb
+ 56, tmp64
);
411 /* XXX: TODO: Send IRQ to CPU #ir[16] */
414 *oldvalp
= ((int64_t)(env
->ipr
[IPR_IPL
] << 59)) >> 59;
415 env
->ipr
[IPR_IPL
] &= ~0x1F;
416 env
->ipr
[IPR_IPL
] |= val
& 0x1F;
417 /* XXX: may issue an interrupt or ASR _now_ */
421 if (!(env
->ipr
[IPR_EXC_ADDR
] & 1)) {
424 if (env
->features
& FEATURE_SPS
)
425 env
->ipr
[IPR_KSP
] = val
;
427 stq_raw(hwpcb
+ 0, val
);
431 env
->ipr
[IPR_MCES
] &= ~((val
& 0x7) | 0x18);
432 env
->ipr
[IPR_MCES
] |= val
& 0x18;
435 /* Implementation specific */
444 env
->ipr
[IPR_PRBR
] = val
;
451 env
->ipr
[IPR_SCBB
] = (uint32_t)val
;
455 env
->ipr
[IPR_SISR
] |= 1 << (val
& 0xF);
456 /* XXX: request a software interrupt _now_ */
464 if (env
->features
& FEATURE_SPS
)
465 env
->ipr
[IPR_SSP
] = val
;
467 stq_raw(hwpcb
+ 16, val
);
470 if (env
->features
& FEATURE_VIRBND
)
471 env
->ipr
[IPR_SYSPTBR
] = val
;
485 tlb_flush_page(env
, val
);
488 tlb_flush_page(env
, val
);
491 tlb_flush_page(env
, val
);
494 if (env
->features
& FEATURE_SPS
)
495 env
->ipr
[IPR_USP
] = val
;
497 stq_raw(hwpcb
+ 24, val
);
500 if (env
->features
& FEATURE_VIRBND
)
501 env
->ipr
[IPR_VIRBND
] = val
;
506 env
->ipr
[IPR_VPTB
] = val
;
521 void do_interrupt (CPUState
*env
)
525 env
->ipr
[IPR_EXC_ADDR
] = env
->pc
| 1;
526 excp
= env
->exception_index
;
527 env
->exception_index
= -1;
529 /* XXX: disable interrupts and memory mapping */
530 if (env
->ipr
[IPR_PAL_BASE
] != -1ULL) {
531 /* We use native PALcode */
532 env
->pc
= env
->ipr
[IPR_PAL_BASE
] + excp
;
534 /* We use emulated PALcode */
537 env
->pc
= env
->ipr
[IPR_EXC_ADDR
] & ~7;
538 env
->ipr
[IPR_EXC_ADDR
] = env
->ipr
[IPR_EXC_ADDR
] & 1;
539 /* XXX: re-enable interrupts and memory mapping */
544 void cpu_dump_state (CPUState
*env
, FILE *f
,
545 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
548 static const char *linux_reg_names
[] = {
549 "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ",
550 "t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ",
551 "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ",
552 "t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero",
556 cpu_fprintf(f
, " PC " TARGET_FMT_lx
" PS " TARGET_FMT_lx
"\n",
558 for (i
= 0; i
< 31; i
++) {
559 cpu_fprintf(f
, "IR%02d %s " TARGET_FMT_lx
" ", i
,
560 linux_reg_names
[i
], env
->ir
[i
]);
562 cpu_fprintf(f
, "\n");
564 cpu_fprintf(f
, "\n");
565 for (i
= 0; i
< 31; i
++) {
566 cpu_fprintf(f
, "FIR%02d " TARGET_FMT_lx
" ", i
,
567 *((uint64_t *)(&env
->fir
[i
])));
569 cpu_fprintf(f
, "\n");
571 cpu_fprintf(f
, "\nlock " TARGET_FMT_lx
"\n", env
->lock
);