]>
git.proxmox.com Git - qemu.git/blob - target-alpha/helper.c
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 round_mode
= float_round_up
;
101 set_float_rounding_mode(round_mode
, &env
->fp_status
);
104 #if defined(CONFIG_USER_ONLY)
106 int cpu_alpha_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
107 int mmu_idx
, int is_softmmu
)
110 env
->exception_index
= EXCP_ITB_MISS
;
112 env
->exception_index
= EXCP_DFAULT
;
113 env
->ipr
[IPR_EXC_ADDR
] = address
;
118 target_phys_addr_t
cpu_get_phys_page_debug (CPUState
*env
, target_ulong addr
)
123 void do_interrupt (CPUState
*env
)
125 env
->exception_index
= -1;
130 target_phys_addr_t
cpu_get_phys_page_debug (CPUState
*env
, target_ulong addr
)
135 int cpu_alpha_handle_mmu_fault (CPUState
*env
, target_ulong address
, int rw
,
136 int mmu_idx
, int is_softmmu
)
141 /* Instruction translation buffer miss */
142 env
->exception_index
= EXCP_ITB_MISS
;
144 if (env
->ipr
[IPR_EXC_ADDR
] & 1)
145 env
->exception_index
= EXCP_DTB_MISS_PAL
;
147 env
->exception_index
= EXCP_DTB_MISS_NATIVE
;
148 opc
= (ldl_code(env
->pc
) >> 21) << 4;
154 env
->ipr
[IPR_MM_STAT
] = opc
;
160 int cpu_alpha_mfpr (CPUState
*env
, int iprn
, uint64_t *valp
)
165 hwpcb
= env
->ipr
[IPR_PCBB
];
168 if (env
->features
& FEATURE_ASN
)
169 *valp
= env
->ipr
[IPR_ASN
];
174 *valp
= ((int64_t)(env
->ipr
[IPR_ASTEN
] << 60)) >> 60;
177 *valp
= ((int64_t)(env
->ipr
[IPR_ASTSR
] << 60)) >> 60;
184 if (env
->features
& FEATURE_SPS
)
185 *valp
= env
->ipr
[IPR_ESP
];
187 *valp
= ldq_raw(hwpcb
+ 8);
190 *valp
= ((int64_t)(env
->ipr
[IPR_FEN
] << 63)) >> 63;
197 *valp
= ((int64_t)(env
->ipr
[IPR_IPL
] << 59)) >> 59;
200 if (!(env
->ipr
[IPR_EXC_ADDR
] & 1)) {
203 if (env
->features
& FEATURE_SPS
)
204 *valp
= env
->ipr
[IPR_KSP
];
206 *valp
= ldq_raw(hwpcb
+ 0);
210 *valp
= ((int64_t)(env
->ipr
[IPR_MCES
] << 59)) >> 59;
213 /* Implementation specific */
217 *valp
= ((int64_t)env
->ipr
[IPR_PCBB
] << 16) >> 16;
220 *valp
= env
->ipr
[IPR_PRBR
];
223 *valp
= env
->ipr
[IPR_PTBR
];
226 *valp
= (int64_t)((int32_t)env
->ipr
[IPR_SCBB
]);
233 *valp
= (int64_t)((int16_t)env
->ipr
[IPR_SISR
]);
235 if (env
->features
& FEATURE_SPS
)
236 *valp
= env
->ipr
[IPR_SSP
];
238 *valp
= ldq_raw(hwpcb
+ 16);
241 if (env
->features
& FEATURE_VIRBND
)
242 *valp
= env
->ipr
[IPR_SYSPTBR
];
247 if ((env
->features
& FEATURE_TBCHK
)) {
276 if (env
->features
& FEATURE_SPS
)
277 *valp
= env
->ipr
[IPR_USP
];
279 *valp
= ldq_raw(hwpcb
+ 24);
282 if (env
->features
& FEATURE_VIRBND
)
283 *valp
= env
->ipr
[IPR_VIRBND
];
288 *valp
= env
->ipr
[IPR_VPTB
];
291 *valp
= env
->ipr
[IPR_WHAMI
];
302 int cpu_alpha_mtpr (CPUState
*env
, int iprn
, uint64_t val
, uint64_t *oldvalp
)
304 uint64_t hwpcb
, tmp64
;
308 hwpcb
= env
->ipr
[IPR_PCBB
];
315 tmp8
= ((int8_t)(env
->ipr
[IPR_ASTEN
] << 4)) >> 4;
318 tmp8
|= (val
>> 4) & 0xF;
319 env
->ipr
[IPR_ASTEN
] &= ~0xF;
320 env
->ipr
[IPR_ASTEN
] |= tmp8
;
324 tmp8
= ((int8_t)(env
->ipr
[IPR_ASTSR
] << 4)) >> 4;
327 tmp8
|= (val
>> 4) & 0xF;
328 env
->ipr
[IPR_ASTSR
] &= ~0xF;
329 env
->ipr
[IPR_ASTSR
] |= tmp8
;
332 env
->ipr
[IPR_DATFX
] &= ~0x1;
333 env
->ipr
[IPR_DATFX
] |= val
& 1;
334 tmp64
= ldq_raw(hwpcb
+ 56);
335 tmp64
&= ~0x8000000000000000ULL
;
336 tmp64
|= (val
& 1) << 63;
337 stq_raw(hwpcb
+ 56, tmp64
);
340 if (env
->features
& FEATURE_SPS
)
341 env
->ipr
[IPR_ESP
] = val
;
343 stq_raw(hwpcb
+ 8, val
);
346 env
->ipr
[IPR_FEN
] = val
& 1;
347 tmp64
= ldq_raw(hwpcb
+ 56);
350 stq_raw(hwpcb
+ 56, tmp64
);
353 /* XXX: TODO: Send IRQ to CPU #ir[16] */
356 *oldvalp
= ((int64_t)(env
->ipr
[IPR_IPL
] << 59)) >> 59;
357 env
->ipr
[IPR_IPL
] &= ~0x1F;
358 env
->ipr
[IPR_IPL
] |= val
& 0x1F;
359 /* XXX: may issue an interrupt or ASR _now_ */
363 if (!(env
->ipr
[IPR_EXC_ADDR
] & 1)) {
366 if (env
->features
& FEATURE_SPS
)
367 env
->ipr
[IPR_KSP
] = val
;
369 stq_raw(hwpcb
+ 0, val
);
373 env
->ipr
[IPR_MCES
] &= ~((val
& 0x7) | 0x18);
374 env
->ipr
[IPR_MCES
] |= val
& 0x18;
377 /* Implementation specific */
386 env
->ipr
[IPR_PRBR
] = val
;
393 env
->ipr
[IPR_SCBB
] = (uint32_t)val
;
397 env
->ipr
[IPR_SISR
] |= 1 << (val
& 0xF);
398 /* XXX: request a software interrupt _now_ */
406 if (env
->features
& FEATURE_SPS
)
407 env
->ipr
[IPR_SSP
] = val
;
409 stq_raw(hwpcb
+ 16, val
);
412 if (env
->features
& FEATURE_VIRBND
)
413 env
->ipr
[IPR_SYSPTBR
] = val
;
427 tlb_flush_page(env
, val
);
430 tlb_flush_page(env
, val
);
433 tlb_flush_page(env
, val
);
436 if (env
->features
& FEATURE_SPS
)
437 env
->ipr
[IPR_USP
] = val
;
439 stq_raw(hwpcb
+ 24, val
);
442 if (env
->features
& FEATURE_VIRBND
)
443 env
->ipr
[IPR_VIRBND
] = val
;
448 env
->ipr
[IPR_VPTB
] = val
;
463 void do_interrupt (CPUState
*env
)
467 env
->ipr
[IPR_EXC_ADDR
] = env
->pc
| 1;
468 excp
= env
->exception_index
;
469 env
->exception_index
= 0;
471 /* XXX: disable interrupts and memory mapping */
472 if (env
->ipr
[IPR_PAL_BASE
] != -1ULL) {
473 /* We use native PALcode */
474 env
->pc
= env
->ipr
[IPR_PAL_BASE
] + excp
;
476 /* We use emulated PALcode */
479 env
->pc
= env
->ipr
[IPR_EXC_ADDR
] & ~7;
480 env
->ipr
[IPR_EXC_ADDR
] = env
->ipr
[IPR_EXC_ADDR
] & 1;
481 /* XXX: re-enable interrupts and memory mapping */
486 void cpu_dump_state (CPUState
*env
, FILE *f
,
487 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
490 static const char *linux_reg_names
[] = {
491 "v0 ", "t0 ", "t1 ", "t2 ", "t3 ", "t4 ", "t5 ", "t6 ",
492 "t7 ", "s0 ", "s1 ", "s2 ", "s3 ", "s4 ", "s5 ", "fp ",
493 "a0 ", "a1 ", "a2 ", "a3 ", "a4 ", "a5 ", "t8 ", "t9 ",
494 "t10", "t11", "ra ", "t12", "at ", "gp ", "sp ", "zero",
498 cpu_fprintf(f
, " PC " TARGET_FMT_lx
" PS " TARGET_FMT_lx
"\n",
500 for (i
= 0; i
< 31; i
++) {
501 cpu_fprintf(f
, "IR%02d %s " TARGET_FMT_lx
" ", i
,
502 linux_reg_names
[i
], env
->ir
[i
]);
504 cpu_fprintf(f
, "\n");
506 cpu_fprintf(f
, "\n");
507 for (i
= 0; i
< 31; i
++) {
508 cpu_fprintf(f
, "FIR%02d " TARGET_FMT_lx
" ", i
,
509 *((uint64_t *)(&env
->fir
[i
])));
511 cpu_fprintf(f
, "\n");
513 cpu_fprintf(f
, "\nlock " TARGET_FMT_lx
"\n", env
->lock
);