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 void do_interrupt (CPUState
*env
)
178 env
->exception_index
= -1;
183 target_phys_addr_t
cpu_get_phys_page_debug (CPUState
*env
, target_ulong addr
)
188 int cpu_alpha_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
189 int mmu_idx
, int is_softmmu
)
194 /* Instruction translation buffer miss */
195 env
->exception_index
= EXCP_ITB_MISS
;
197 if (env
->ipr
[IPR_EXC_ADDR
] & 1)
198 env
->exception_index
= EXCP_DTB_MISS_PAL
;
200 env
->exception_index
= EXCP_DTB_MISS_NATIVE
;
201 opc
= (ldl_code(env
->pc
) >> 21) << 4;
207 env
->ipr
[IPR_MM_STAT
] = opc
;
213 int cpu_alpha_mfpr (CPUState
*env
, int iprn
, uint64_t *valp
)
218 hwpcb
= env
->ipr
[IPR_PCBB
];
221 if (env
->features
& FEATURE_ASN
)
222 *valp
= env
->ipr
[IPR_ASN
];
227 *valp
= ((int64_t)(env
->ipr
[IPR_ASTEN
] << 60)) >> 60;
230 *valp
= ((int64_t)(env
->ipr
[IPR_ASTSR
] << 60)) >> 60;
237 if (env
->features
& FEATURE_SPS
)
238 *valp
= env
->ipr
[IPR_ESP
];
240 *valp
= ldq_raw(hwpcb
+ 8);
243 *valp
= ((int64_t)(env
->ipr
[IPR_FEN
] << 63)) >> 63;
250 *valp
= ((int64_t)(env
->ipr
[IPR_IPL
] << 59)) >> 59;
253 if (!(env
->ipr
[IPR_EXC_ADDR
] & 1)) {
256 if (env
->features
& FEATURE_SPS
)
257 *valp
= env
->ipr
[IPR_KSP
];
259 *valp
= ldq_raw(hwpcb
+ 0);
263 *valp
= ((int64_t)(env
->ipr
[IPR_MCES
] << 59)) >> 59;
266 /* Implementation specific */
270 *valp
= ((int64_t)env
->ipr
[IPR_PCBB
] << 16) >> 16;
273 *valp
= env
->ipr
[IPR_PRBR
];
276 *valp
= env
->ipr
[IPR_PTBR
];
279 *valp
= (int64_t)((int32_t)env
->ipr
[IPR_SCBB
]);
286 *valp
= (int64_t)((int16_t)env
->ipr
[IPR_SISR
]);
288 if (env
->features
& FEATURE_SPS
)
289 *valp
= env
->ipr
[IPR_SSP
];
291 *valp
= ldq_raw(hwpcb
+ 16);
294 if (env
->features
& FEATURE_VIRBND
)
295 *valp
= env
->ipr
[IPR_SYSPTBR
];
300 if ((env
->features
& FEATURE_TBCHK
)) {
329 if (env
->features
& FEATURE_SPS
)
330 *valp
= env
->ipr
[IPR_USP
];
332 *valp
= ldq_raw(hwpcb
+ 24);
335 if (env
->features
& FEATURE_VIRBND
)
336 *valp
= env
->ipr
[IPR_VIRBND
];
341 *valp
= env
->ipr
[IPR_VPTB
];
344 *valp
= env
->ipr
[IPR_WHAMI
];
355 int cpu_alpha_mtpr (CPUState
*env
, int iprn
, uint64_t val
, uint64_t *oldvalp
)
357 uint64_t hwpcb
, tmp64
;
361 hwpcb
= env
->ipr
[IPR_PCBB
];
368 tmp8
= ((int8_t)(env
->ipr
[IPR_ASTEN
] << 4)) >> 4;
371 tmp8
|= (val
>> 4) & 0xF;
372 env
->ipr
[IPR_ASTEN
] &= ~0xF;
373 env
->ipr
[IPR_ASTEN
] |= tmp8
;
377 tmp8
= ((int8_t)(env
->ipr
[IPR_ASTSR
] << 4)) >> 4;
380 tmp8
|= (val
>> 4) & 0xF;
381 env
->ipr
[IPR_ASTSR
] &= ~0xF;
382 env
->ipr
[IPR_ASTSR
] |= tmp8
;
385 env
->ipr
[IPR_DATFX
] &= ~0x1;
386 env
->ipr
[IPR_DATFX
] |= val
& 1;
387 tmp64
= ldq_raw(hwpcb
+ 56);
388 tmp64
&= ~0x8000000000000000ULL
;
389 tmp64
|= (val
& 1) << 63;
390 stq_raw(hwpcb
+ 56, tmp64
);
393 if (env
->features
& FEATURE_SPS
)
394 env
->ipr
[IPR_ESP
] = val
;
396 stq_raw(hwpcb
+ 8, val
);
399 env
->ipr
[IPR_FEN
] = val
& 1;
400 tmp64
= ldq_raw(hwpcb
+ 56);
403 stq_raw(hwpcb
+ 56, tmp64
);
406 /* XXX: TODO: Send IRQ to CPU #ir[16] */
409 *oldvalp
= ((int64_t)(env
->ipr
[IPR_IPL
] << 59)) >> 59;
410 env
->ipr
[IPR_IPL
] &= ~0x1F;
411 env
->ipr
[IPR_IPL
] |= val
& 0x1F;
412 /* XXX: may issue an interrupt or ASR _now_ */
416 if (!(env
->ipr
[IPR_EXC_ADDR
] & 1)) {
419 if (env
->features
& FEATURE_SPS
)
420 env
->ipr
[IPR_KSP
] = val
;
422 stq_raw(hwpcb
+ 0, val
);
426 env
->ipr
[IPR_MCES
] &= ~((val
& 0x7) | 0x18);
427 env
->ipr
[IPR_MCES
] |= val
& 0x18;
430 /* Implementation specific */
439 env
->ipr
[IPR_PRBR
] = val
;
446 env
->ipr
[IPR_SCBB
] = (uint32_t)val
;
450 env
->ipr
[IPR_SISR
] |= 1 << (val
& 0xF);
451 /* XXX: request a software interrupt _now_ */
459 if (env
->features
& FEATURE_SPS
)
460 env
->ipr
[IPR_SSP
] = val
;
462 stq_raw(hwpcb
+ 16, val
);
465 if (env
->features
& FEATURE_VIRBND
)
466 env
->ipr
[IPR_SYSPTBR
] = val
;
480 tlb_flush_page(env
, val
);
483 tlb_flush_page(env
, val
);
486 tlb_flush_page(env
, val
);
489 if (env
->features
& FEATURE_SPS
)
490 env
->ipr
[IPR_USP
] = val
;
492 stq_raw(hwpcb
+ 24, val
);
495 if (env
->features
& FEATURE_VIRBND
)
496 env
->ipr
[IPR_VIRBND
] = val
;
501 env
->ipr
[IPR_VPTB
] = val
;
516 void do_interrupt (CPUState
*env
)
520 env
->ipr
[IPR_EXC_ADDR
] = env
->pc
| 1;
521 excp
= env
->exception_index
;
522 env
->exception_index
= -1;
524 /* XXX: disable interrupts and memory mapping */
525 if (env
->ipr
[IPR_PAL_BASE
] != -1ULL) {
526 /* We use native PALcode */
527 env
->pc
= env
->ipr
[IPR_PAL_BASE
] + excp
;
529 /* We use emulated PALcode */
532 env
->pc
= env
->ipr
[IPR_EXC_ADDR
] & ~7;
533 env
->ipr
[IPR_EXC_ADDR
] = env
->ipr
[IPR_EXC_ADDR
] & 1;
534 /* XXX: re-enable interrupts and memory mapping */
539 void cpu_dump_state (CPUState
*env
, FILE *f
,
540 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
543 static const char *linux_reg_names
[] = {
544 "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ",
545 "t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ",
546 "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ",
547 "t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero",
551 cpu_fprintf(f
, " PC " TARGET_FMT_lx
" PS " TARGET_FMT_lx
"\n",
553 for (i
= 0; i
< 31; i
++) {
554 cpu_fprintf(f
, "IR%02d %s " TARGET_FMT_lx
" ", i
,
555 linux_reg_names
[i
], env
->ir
[i
]);
557 cpu_fprintf(f
, "\n");
559 cpu_fprintf(f
, "\n");
560 for (i
= 0; i
< 31; i
++) {
561 cpu_fprintf(f
, "FIR%02d " TARGET_FMT_lx
" ", i
,
562 *((uint64_t *)(&env
->fir
[i
])));
564 cpu_fprintf(f
, "\n");
566 cpu_fprintf(f
, "\nlock " TARGET_FMT_lx
"\n", env
->lock
);