target/hppa:

- Use TCG_COND_TST where applicable.
   - Use CF_BP_PAGE instead of a local breakpoint search.
   - Clean up IAOQ handling during translation.
   - Implement CF_PCREL.
   - Implement PSW.B.
   - Implement PSW.X.
   - Log cpu state on interrupt and rfi.
 -----BEGIN PGP SIGNATURE-----
 
 iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmZEgnwdHHJpY2hhcmQu
 aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV+43gf8CakQdMSqfGV2nGP+
 7wWZOAV04IyfkJ38F/CH0ihUkblEOzXJ1shTFkrHEw257j0D10MctSSbjrqz5BwU
 obQcwoVlxzTGXqzhkZ6wagkcqjv3TtlPtznZIk6JssdlrtwIKDmE2/3t1dzHnyBD
 WTrS0SK3YvVRovq/ai51raUbiBsNq7XG3skHEsMKsFxp4EaDP5JTbputdQWdffjh
 TBmXImhHC3gm09KWIUZwfEBHlaa7YXk2orzB8kBE8S2kQj9vrGXEaC4jYnBcQLPw
 NDDkBYRqxHYQr0vIAHee+5cUgt1jDBr5rXnAnJwzK0wyEEc4Mi4OTPhNE604iu2y
 SDxS8Q==
 =A4Qf
 -----END PGP SIGNATURE-----

Merge tag 'pull-hppa-20240515' of https://gitlab.com/rth7680/qemu into staging

target/hppa:
  - Use TCG_COND_TST where applicable.
  - Use CF_BP_PAGE instead of a local breakpoint search.
  - Clean up IAOQ handling during translation.
  - Implement CF_PCREL.
  - Implement PSW.B.
  - Implement PSW.X.
  - Log cpu state on interrupt and rfi.

# -----BEGIN PGP SIGNATURE-----
#
# iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmZEgnwdHHJpY2hhcmQu
# aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV+43gf8CakQdMSqfGV2nGP+
# 7wWZOAV04IyfkJ38F/CH0ihUkblEOzXJ1shTFkrHEw257j0D10MctSSbjrqz5BwU
# obQcwoVlxzTGXqzhkZ6wagkcqjv3TtlPtznZIk6JssdlrtwIKDmE2/3t1dzHnyBD
# WTrS0SK3YvVRovq/ai51raUbiBsNq7XG3skHEsMKsFxp4EaDP5JTbputdQWdffjh
# TBmXImhHC3gm09KWIUZwfEBHlaa7YXk2orzB8kBE8S2kQj9vrGXEaC4jYnBcQLPw
# NDDkBYRqxHYQr0vIAHee+5cUgt1jDBr5rXnAnJwzK0wyEEc4Mi4OTPhNE604iu2y
# SDxS8Q==
# =A4Qf
# -----END PGP SIGNATURE-----
# gpg: Signature made Wed 15 May 2024 11:38:04 AM CEST
# gpg:                using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F
# gpg:                issuer "richard.henderson@linaro.org"
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [ultimate]

* tag 'pull-hppa-20240515' of https://gitlab.com/rth7680/qemu: (43 commits)
  target/hppa: Log cpu state on return-from-interrupt
  target/hppa: Log cpu state at interrupt
  target/hppa: Implement CF_PCREL
  target/hppa: Adjust priv for B,GATE at runtime
  target/hppa: Drop tlb_entry return from hppa_get_physical_address
  target/hppa: Implement PSW_X
  target/hppa: Implement PSW_B
  target/hppa: Manage PSW_X and PSW_B in translator
  target/hppa: Split PSW X and B into their own field
  target/hppa: Improve hppa_cpu_dump_state
  target/hppa: Do not mask in copy_iaoq_entry
  target/hppa: Store full iaoq_f and page offset of iaoq_b in TB
  linux-user/hppa: Force all code addresses to PRIV_USER
  target/hppa: Use delay_excp for conditional trap on overflow
  target/hppa: Use delay_excp for conditional traps
  target/hppa: Introduce DisasDelayException
  target/hppa: Remove cond_free
  target/hppa: Use TCG_COND_TST* in trans_ftest
  target/hppa: Use registerfields.h for FPSR
  target/hppa: Use TCG_COND_TST* in trans_bb_imm
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2024-05-15 11:46:58 +02:00
commit 922582ace2
15 changed files with 868 additions and 752 deletions

View file

@ -1887,8 +1887,8 @@ static inline void init_thread(struct target_pt_regs *regs,
static inline void init_thread(struct target_pt_regs *regs, static inline void init_thread(struct target_pt_regs *regs,
struct image_info *infop) struct image_info *infop)
{ {
regs->iaoq[0] = infop->entry; regs->iaoq[0] = infop->entry | PRIV_USER;
regs->iaoq[1] = infop->entry + 4; regs->iaoq[1] = regs->iaoq[0] + 4;
regs->gr[23] = 0; regs->gr[23] = 0;
regs->gr[24] = infop->argv; regs->gr[24] = infop->argv;
regs->gr[25] = infop->argc; regs->gr[25] = infop->argc;

View file

@ -129,8 +129,8 @@ void cpu_loop(CPUHPPAState *env)
default: default:
env->gr[28] = ret; env->gr[28] = ret;
/* We arrived here by faking the gateway page. Return. */ /* We arrived here by faking the gateway page. Return. */
env->iaoq_f = env->gr[31]; env->iaoq_f = env->gr[31] | PRIV_USER;
env->iaoq_b = env->gr[31] + 4; env->iaoq_b = env->iaoq_f + 4;
break; break;
case -QEMU_ERESTARTSYS: case -QEMU_ERESTARTSYS:
case -QEMU_ESIGRETURN: case -QEMU_ESIGRETURN:
@ -140,8 +140,8 @@ void cpu_loop(CPUHPPAState *env)
case EXCP_SYSCALL_LWS: case EXCP_SYSCALL_LWS:
env->gr[21] = hppa_lws(env); env->gr[21] = hppa_lws(env);
/* We arrived here by faking the gateway page. Return. */ /* We arrived here by faking the gateway page. Return. */
env->iaoq_f = env->gr[31]; env->iaoq_f = env->gr[31] | PRIV_USER;
env->iaoq_b = env->gr[31] + 4; env->iaoq_b = env->iaoq_f + 4;
break; break;
case EXCP_IMP: case EXCP_IMP:
force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, env->iaoq_f); force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, env->iaoq_f);
@ -152,9 +152,9 @@ void cpu_loop(CPUHPPAState *env)
case EXCP_PRIV_OPR: case EXCP_PRIV_OPR:
/* check for glibc ABORT_INSTRUCTION "iitlbp %r0,(%sr0, %r0)" */ /* check for glibc ABORT_INSTRUCTION "iitlbp %r0,(%sr0, %r0)" */
if (env->cr[CR_IIR] == 0x04000000) { if (env->cr[CR_IIR] == 0x04000000) {
force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->iaoq_f); force_sig_fault(TARGET_SIGILL, TARGET_ILL_ILLOPC, env->iaoq_f);
} else { } else {
force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->iaoq_f); force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->iaoq_f);
} }
break; break;
case EXCP_PRIV_REG: case EXCP_PRIV_REG:
@ -170,7 +170,7 @@ void cpu_loop(CPUHPPAState *env)
force_sig_fault(TARGET_SIGFPE, 0, env->iaoq_f); force_sig_fault(TARGET_SIGFPE, 0, env->iaoq_f);
break; break;
case EXCP_BREAK: case EXCP_BREAK:
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->iaoq_f & ~3); force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->iaoq_f);
break; break;
case EXCP_DEBUG: case EXCP_DEBUG:
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->iaoq_f); force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->iaoq_f);

View file

@ -101,7 +101,9 @@ static void restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc)
cpu_hppa_loaded_fr0(env); cpu_hppa_loaded_fr0(env);
__get_user(env->iaoq_f, &sc->sc_iaoq[0]); __get_user(env->iaoq_f, &sc->sc_iaoq[0]);
env->iaoq_f |= PRIV_USER;
__get_user(env->iaoq_b, &sc->sc_iaoq[1]); __get_user(env->iaoq_b, &sc->sc_iaoq[1]);
env->iaoq_b |= PRIV_USER;
__get_user(env->cr[CR_SAR], &sc->sc_sar); __get_user(env->cr[CR_SAR], &sc->sc_sar);
} }
@ -162,8 +164,8 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
unlock_user(fdesc, haddr, 0); unlock_user(fdesc, haddr, 0);
haddr = dest; haddr = dest;
} }
env->iaoq_f = haddr; env->iaoq_f = haddr | PRIV_USER;
env->iaoq_b = haddr + 4; env->iaoq_b = env->iaoq_f + 4;
env->psw_n = 0; env->psw_n = 0;
return; return;

View file

@ -28,8 +28,8 @@ static inline void cpu_clone_regs_child(CPUHPPAState *env, target_ulong newsp,
/* Indicate child in return value. */ /* Indicate child in return value. */
env->gr[28] = 0; env->gr[28] = 0;
/* Return from the syscall. */ /* Return from the syscall. */
env->iaoq_f = env->gr[31]; env->iaoq_f = env->gr[31] | PRIV_USER;
env->iaoq_b = env->gr[31] + 4; env->iaoq_b = env->iaoq_f + 4;
} }
static inline void cpu_clone_regs_parent(CPUHPPAState *env, unsigned flags) static inline void cpu_clone_regs_parent(CPUHPPAState *env, unsigned flags)

View file

@ -32,15 +32,67 @@ static void hppa_cpu_set_pc(CPUState *cs, vaddr value)
{ {
HPPACPU *cpu = HPPA_CPU(cs); HPPACPU *cpu = HPPA_CPU(cs);
#ifdef CONFIG_USER_ONLY
value |= PRIV_USER;
#endif
cpu->env.iaoq_f = value; cpu->env.iaoq_f = value;
cpu->env.iaoq_b = value + 4; cpu->env.iaoq_b = value + 4;
} }
static vaddr hppa_cpu_get_pc(CPUState *cs) static vaddr hppa_cpu_get_pc(CPUState *cs)
{ {
HPPACPU *cpu = HPPA_CPU(cs); CPUHPPAState *env = cpu_env(cs);
return cpu->env.iaoq_f; return hppa_form_gva_psw(env->psw, (env->psw & PSW_C ? env->iasq_f : 0),
env->iaoq_f & -4);
}
void cpu_get_tb_cpu_state(CPUHPPAState *env, vaddr *pc,
uint64_t *pcsbase, uint32_t *pflags)
{
uint32_t flags = 0;
uint64_t cs_base = 0;
/*
* TB lookup assumes that PC contains the complete virtual address.
* If we leave space+offset separate, we'll get ITLB misses to an
* incomplete virtual address. This also means that we must separate
* out current cpu privilege from the low bits of IAOQ_F.
*/
*pc = hppa_cpu_get_pc(env_cpu(env));
flags |= (env->iaoq_f & 3) << TB_FLAG_PRIV_SHIFT;
/*
* The only really interesting case is if IAQ_Back is on the same page
* as IAQ_Front, so that we can use goto_tb between the blocks. In all
* other cases, we'll be ending the TranslationBlock with one insn and
* not linking between them.
*/
if (env->iasq_f != env->iasq_b) {
cs_base |= CS_BASE_DIFFSPACE;
} else if ((env->iaoq_f ^ env->iaoq_b) & TARGET_PAGE_MASK) {
cs_base |= CS_BASE_DIFFPAGE;
} else {
cs_base |= env->iaoq_b & ~TARGET_PAGE_MASK;
}
/* ??? E, T, H, L bits need to be here, when implemented. */
flags |= env->psw_n * PSW_N;
flags |= env->psw_xb;
flags |= env->psw & (PSW_W | PSW_C | PSW_D | PSW_P);
#ifdef CONFIG_USER_ONLY
flags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus;
#else
if ((env->sr[4] == env->sr[5])
& (env->sr[4] == env->sr[6])
& (env->sr[4] == env->sr[7])) {
flags |= TB_FLAG_SR_SAME;
}
#endif
*pcsbase = cs_base;
*pflags = flags;
} }
static void hppa_cpu_synchronize_from_tb(CPUState *cs, static void hppa_cpu_synchronize_from_tb(CPUState *cs,
@ -48,45 +100,28 @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs,
{ {
HPPACPU *cpu = HPPA_CPU(cs); HPPACPU *cpu = HPPA_CPU(cs);
tcg_debug_assert(!tcg_cflags_has(cs, CF_PCREL)); /* IAQ is always up-to-date before goto_tb. */
#ifdef CONFIG_USER_ONLY
cpu->env.iaoq_f = tb->pc;
cpu->env.iaoq_b = tb->cs_base;
#else
/* Recover the IAOQ values from the GVA + PRIV. */
uint32_t priv = (tb->flags >> TB_FLAG_PRIV_SHIFT) & 3;
target_ulong cs_base = tb->cs_base;
target_ulong iasq_f = cs_base & ~0xffffffffull;
int32_t diff = cs_base;
cpu->env.iasq_f = iasq_f;
cpu->env.iaoq_f = (tb->pc & ~iasq_f) + priv;
if (diff) {
cpu->env.iaoq_b = cpu->env.iaoq_f + diff;
}
#endif
cpu->env.psw_n = (tb->flags & PSW_N) != 0; cpu->env.psw_n = (tb->flags & PSW_N) != 0;
cpu->env.psw_xb = tb->flags & (PSW_X | PSW_B);
} }
static void hppa_restore_state_to_opc(CPUState *cs, static void hppa_restore_state_to_opc(CPUState *cs,
const TranslationBlock *tb, const TranslationBlock *tb,
const uint64_t *data) const uint64_t *data)
{ {
HPPACPU *cpu = HPPA_CPU(cs); CPUHPPAState *env = cpu_env(cs);
cpu->env.iaoq_f = data[0]; env->iaoq_f = (env->iaoq_f & TARGET_PAGE_MASK) | data[0];
if (data[1] != (target_ulong)-1) { if (data[1] != INT32_MIN) {
cpu->env.iaoq_b = data[1]; env->iaoq_b = env->iaoq_f + data[1];
} }
cpu->env.unwind_breg = data[2]; env->unwind_breg = data[2];
/* /*
* Since we were executing the instruction at IAOQ_F, and took some * Since we were executing the instruction at IAOQ_F, and took some
* sort of action that provoked the cpu_restore_state, we can infer * sort of action that provoked the cpu_restore_state, we can infer
* that the instruction was not nullified. * that the instruction was not nullified.
*/ */
cpu->env.psw_n = 0; env->psw_n = 0;
} }
static bool hppa_cpu_has_work(CPUState *cs) static bool hppa_cpu_has_work(CPUState *cs)
@ -152,6 +187,9 @@ static void hppa_cpu_realizefn(DeviceState *dev, Error **errp)
hppa_ptlbe(&cpu->env); hppa_ptlbe(&cpu->env);
} }
#endif #endif
/* Use pc-relative instructions always to simplify the translator. */
tcg_cflags_set(cs, CF_PCREL);
} }
static void hppa_cpu_initfn(Object *obj) static void hppa_cpu_initfn(Object *obj)

View file

@ -24,6 +24,7 @@
#include "exec/cpu-defs.h" #include "exec/cpu-defs.h"
#include "qemu/cpu-float.h" #include "qemu/cpu-float.h"
#include "qemu/interval-tree.h" #include "qemu/interval-tree.h"
#include "hw/registerfields.h"
#define MMU_ABS_W_IDX 6 #define MMU_ABS_W_IDX 6
#define MMU_ABS_IDX 7 #define MMU_ABS_IDX 7
@ -41,6 +42,9 @@
#define MMU_IDX_TO_P(MIDX) (((MIDX) - MMU_KERNEL_IDX) & 1) #define MMU_IDX_TO_P(MIDX) (((MIDX) - MMU_KERNEL_IDX) & 1)
#define PRIV_P_TO_MMU_IDX(PRIV, P) ((PRIV) * 2 + !!(P) + MMU_KERNEL_IDX) #define PRIV_P_TO_MMU_IDX(PRIV, P) ((PRIV) * 2 + !!(P) + MMU_KERNEL_IDX)
#define PRIV_KERNEL 0
#define PRIV_USER 3
#define TARGET_INSN_START_EXTRA_WORDS 2 #define TARGET_INSN_START_EXTRA_WORDS 2
/* No need to flush MMU_ABS*_IDX */ /* No need to flush MMU_ABS*_IDX */
@ -152,6 +156,30 @@
#define CR_IPSW 22 #define CR_IPSW 22
#define CR_EIRR 23 #define CR_EIRR 23
FIELD(FPSR, ENA_I, 0, 1)
FIELD(FPSR, ENA_U, 1, 1)
FIELD(FPSR, ENA_O, 2, 1)
FIELD(FPSR, ENA_Z, 3, 1)
FIELD(FPSR, ENA_V, 4, 1)
FIELD(FPSR, ENABLES, 0, 5)
FIELD(FPSR, D, 5, 1)
FIELD(FPSR, T, 6, 1)
FIELD(FPSR, RM, 9, 2)
FIELD(FPSR, CQ, 11, 11)
FIELD(FPSR, CQ0_6, 15, 7)
FIELD(FPSR, CQ0_4, 17, 5)
FIELD(FPSR, CQ0_2, 19, 3)
FIELD(FPSR, CQ0, 21, 1)
FIELD(FPSR, CA, 15, 7)
FIELD(FPSR, CA0, 21, 1)
FIELD(FPSR, C, 26, 1)
FIELD(FPSR, FLG_I, 27, 1)
FIELD(FPSR, FLG_U, 28, 1)
FIELD(FPSR, FLG_O, 29, 1)
FIELD(FPSR, FLG_Z, 30, 1)
FIELD(FPSR, FLG_V, 31, 1)
FIELD(FPSR, FLAGS, 27, 5)
typedef struct HPPATLBEntry { typedef struct HPPATLBEntry {
union { union {
IntervalTreeNode itree; IntervalTreeNode itree;
@ -180,7 +208,8 @@ typedef struct CPUArchState {
uint64_t fr[32]; uint64_t fr[32];
uint64_t sr[8]; /* stored shifted into place for gva */ uint64_t sr[8]; /* stored shifted into place for gva */
target_ulong psw; /* All psw bits except the following: */ uint32_t psw; /* All psw bits except the following: */
uint32_t psw_xb; /* X and B, in their normal positions */
target_ulong psw_n; /* boolean */ target_ulong psw_n; /* boolean */
target_long psw_v; /* in most significant bit */ target_long psw_v; /* in most significant bit */
@ -313,48 +342,11 @@ hwaddr hppa_abs_to_phys_pa2_w1(vaddr addr);
#define TB_FLAG_SR_SAME PSW_I #define TB_FLAG_SR_SAME PSW_I
#define TB_FLAG_PRIV_SHIFT 8 #define TB_FLAG_PRIV_SHIFT 8
#define TB_FLAG_UNALIGN 0x400 #define TB_FLAG_UNALIGN 0x400
#define CS_BASE_DIFFPAGE (1 << 12)
#define CS_BASE_DIFFSPACE (1 << 13)
static inline void cpu_get_tb_cpu_state(CPUHPPAState *env, vaddr *pc, void cpu_get_tb_cpu_state(CPUHPPAState *env, vaddr *pc,
uint64_t *cs_base, uint32_t *pflags) uint64_t *cs_base, uint32_t *pflags);
{
uint32_t flags = env->psw_n * PSW_N;
/* TB lookup assumes that PC contains the complete virtual address.
If we leave space+offset separate, we'll get ITLB misses to an
incomplete virtual address. This also means that we must separate
out current cpu privilege from the low bits of IAOQ_F. */
#ifdef CONFIG_USER_ONLY
*pc = env->iaoq_f & -4;
*cs_base = env->iaoq_b & -4;
flags |= TB_FLAG_UNALIGN * !env_cpu(env)->prctl_unalign_sigbus;
#else
/* ??? E, T, H, L, B bits need to be here, when implemented. */
flags |= env->psw & (PSW_W | PSW_C | PSW_D | PSW_P);
flags |= (env->iaoq_f & 3) << TB_FLAG_PRIV_SHIFT;
*pc = hppa_form_gva_psw(env->psw, (env->psw & PSW_C ? env->iasq_f : 0),
env->iaoq_f & -4);
*cs_base = env->iasq_f;
/* Insert a difference between IAOQ_B and IAOQ_F within the otherwise zero
low 32-bits of CS_BASE. This will succeed for all direct branches,
which is the primary case we care about -- using goto_tb within a page.
Failure is indicated by a zero difference. */
if (env->iasq_f == env->iasq_b) {
target_long diff = env->iaoq_b - env->iaoq_f;
if (diff == (int32_t)diff) {
*cs_base |= (uint32_t)diff;
}
}
if ((env->sr[4] == env->sr[5])
& (env->sr[4] == env->sr[6])
& (env->sr[4] == env->sr[7])) {
flags |= TB_FLAG_SR_SAME;
}
#endif
*pflags = flags;
}
target_ulong cpu_hppa_get_psw(CPUHPPAState *env); target_ulong cpu_hppa_get_psw(CPUHPPAState *env);
void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong); void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong);
@ -379,8 +371,7 @@ bool hppa_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
void hppa_cpu_do_interrupt(CPUState *cpu); void hppa_cpu_do_interrupt(CPUState *cpu);
bool hppa_cpu_exec_interrupt(CPUState *cpu, int int_req); bool hppa_cpu_exec_interrupt(CPUState *cpu, int int_req);
int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
int type, hwaddr *pphys, int *pprot, int type, hwaddr *pphys, int *pprot);
HPPATLBEntry **tlb_entry);
void hppa_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, void hppa_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
vaddr addr, unsigned size, vaddr addr, unsigned size,
MMUAccessType access_type, MMUAccessType access_type,
@ -389,7 +380,6 @@ void hppa_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
extern const MemoryRegionOps hppa_io_eir_ops; extern const MemoryRegionOps hppa_io_eir_ops;
extern const VMStateDescription vmstate_hppa_cpu; extern const VMStateDescription vmstate_hppa_cpu;
void hppa_cpu_alarm_timer(void *); void hppa_cpu_alarm_timer(void *);
int hppa_artype_for_page(CPUHPPAState *env, target_ulong vaddr);
#endif #endif
G_NORETURN void hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t ra); G_NORETURN void hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t ra);

View file

@ -30,7 +30,7 @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
env->fr0_shadow = shadow; env->fr0_shadow = shadow;
switch (extract32(shadow, 9, 2)) { switch (FIELD_EX32(shadow, FPSR, RM)) {
default: default:
rm = float_round_nearest_even; rm = float_round_nearest_even;
break; break;
@ -46,7 +46,7 @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
} }
set_float_rounding_mode(rm, &env->fp_status); set_float_rounding_mode(rm, &env->fp_status);
d = extract32(shadow, 5, 1); d = FIELD_EX32(shadow, FPSR, D);
set_flush_to_zero(d, &env->fp_status); set_flush_to_zero(d, &env->fp_status);
set_flush_inputs_to_zero(d, &env->fp_status); set_flush_inputs_to_zero(d, &env->fp_status);
} }
@ -57,7 +57,7 @@ void cpu_hppa_loaded_fr0(CPUHPPAState *env)
} }
#define CONVERT_BIT(X, SRC, DST) \ #define CONVERT_BIT(X, SRC, DST) \
((SRC) > (DST) \ ((unsigned)(SRC) > (unsigned)(DST) \
? (X) / ((SRC) / (DST)) & (DST) \ ? (X) / ((SRC) / (DST)) & (DST) \
: ((X) & (SRC)) * ((DST) / (SRC))) : ((X) & (SRC)) * ((DST) / (SRC)))
@ -73,12 +73,12 @@ static void update_fr0_op(CPUHPPAState *env, uintptr_t ra)
} }
set_float_exception_flags(0, &env->fp_status); set_float_exception_flags(0, &env->fp_status);
hard_exp |= CONVERT_BIT(soft_exp, float_flag_inexact, 1u << 0); hard_exp |= CONVERT_BIT(soft_exp, float_flag_inexact, R_FPSR_ENA_I_MASK);
hard_exp |= CONVERT_BIT(soft_exp, float_flag_underflow, 1u << 1); hard_exp |= CONVERT_BIT(soft_exp, float_flag_underflow, R_FPSR_ENA_U_MASK);
hard_exp |= CONVERT_BIT(soft_exp, float_flag_overflow, 1u << 2); hard_exp |= CONVERT_BIT(soft_exp, float_flag_overflow, R_FPSR_ENA_O_MASK);
hard_exp |= CONVERT_BIT(soft_exp, float_flag_divbyzero, 1u << 3); hard_exp |= CONVERT_BIT(soft_exp, float_flag_divbyzero, R_FPSR_ENA_Z_MASK);
hard_exp |= CONVERT_BIT(soft_exp, float_flag_invalid, 1u << 4); hard_exp |= CONVERT_BIT(soft_exp, float_flag_invalid, R_FPSR_ENA_V_MASK);
shadow |= hard_exp << (32 - 5); shadow |= hard_exp << (R_FPSR_FLAGS_SHIFT - R_FPSR_ENABLES_SHIFT);
env->fr0_shadow = shadow; env->fr0_shadow = shadow;
env->fr[0] = (uint64_t)shadow << 32; env->fr[0] = (uint64_t)shadow << 32;
@ -378,15 +378,15 @@ static void update_fr0_cmp(CPUHPPAState *env, uint32_t y,
if (y) { if (y) {
/* targeted comparison */ /* targeted comparison */
/* set fpsr[ca[y - 1]] to current compare */ /* set fpsr[ca[y - 1]] to current compare */
shadow = deposit32(shadow, 21 - (y - 1), 1, c); shadow = deposit32(shadow, R_FPSR_CA0_SHIFT - (y - 1), 1, c);
} else { } else {
/* queued comparison */ /* queued comparison */
/* shift cq right by one place */ /* shift cq right by one place */
shadow = deposit32(shadow, 11, 10, extract32(shadow, 12, 10)); shadow = (shadow & ~R_FPSR_CQ_MASK) | ((shadow >> 1) & R_FPSR_CQ_MASK);
/* move fpsr[c] to fpsr[cq[0]] */ /* move fpsr[c] to fpsr[cq[0]] */
shadow = deposit32(shadow, 21, 1, extract32(shadow, 26, 1)); shadow = FIELD_DP32(shadow, FPSR, CQ0, FIELD_EX32(shadow, FPSR, C));
/* set fpsr[c] to current compare */ /* set fpsr[c] to current compare */
shadow = deposit32(shadow, 26, 1, c); shadow = FIELD_DP32(shadow, FPSR, C, c);
} }
env->fr0_shadow = shadow; env->fr0_shadow = shadow;

View file

@ -163,12 +163,18 @@ int hppa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
env->cr[CR_SAR] = val & (hppa_is_pa20(env) ? 63 : 31); env->cr[CR_SAR] = val & (hppa_is_pa20(env) ? 63 : 31);
break; break;
case 33: case 33:
#ifdef CONFIG_USER_ONLY
val |= PRIV_USER;
#endif
env->iaoq_f = val; env->iaoq_f = val;
break; break;
case 34: case 34:
env->iasq_f = (uint64_t)val << 32; env->iasq_f = (uint64_t)val << 32;
break; break;
case 35: case 35:
#ifdef CONFIG_USER_ONLY
val |= PRIV_USER;
#endif
env->iaoq_b = val; env->iaoq_b = val;
break; break;
case 36: case 36:

View file

@ -54,7 +54,7 @@ target_ulong cpu_hppa_get_psw(CPUHPPAState *env)
psw |= env->psw_n * PSW_N; psw |= env->psw_n * PSW_N;
psw |= (env->psw_v < 0) * PSW_V; psw |= (env->psw_v < 0) * PSW_V;
psw |= env->psw; psw |= env->psw | env->psw_xb;
return psw; return psw;
} }
@ -76,8 +76,8 @@ void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong psw)
} }
psw &= ~reserved; psw &= ~reserved;
env->psw = psw & (uint32_t)~(PSW_N | PSW_V | PSW_CB); env->psw = psw & (uint32_t)~(PSW_B | PSW_N | PSW_V | PSW_X | PSW_CB);
env->psw_xb = psw & (PSW_X | PSW_B);
env->psw_n = (psw / PSW_N) & 1; env->psw_n = (psw / PSW_N) & 1;
env->psw_v = -((psw / PSW_V) & 1); env->psw_v = -((psw / PSW_V) & 1);
@ -102,6 +102,19 @@ void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong psw)
void hppa_cpu_dump_state(CPUState *cs, FILE *f, int flags) void hppa_cpu_dump_state(CPUState *cs, FILE *f, int flags)
{ {
#ifndef CONFIG_USER_ONLY
static const char cr_name[32][5] = {
"RC", "CR1", "CR2", "CR3",
"CR4", "CR5", "CR6", "CR7",
"PID1", "PID2", "CCR", "SAR",
"PID3", "PID4", "IVA", "EIEM",
"ITMR", "ISQF", "IOQF", "IIR",
"ISR", "IOR", "IPSW", "EIRR",
"TR0", "TR1", "TR2", "TR3",
"TR4", "TR5", "TR6", "TR7",
};
#endif
CPUHPPAState *env = cpu_env(cs); CPUHPPAState *env = cpu_env(cs);
target_ulong psw = cpu_hppa_get_psw(env); target_ulong psw = cpu_hppa_get_psw(env);
target_ulong psw_cb; target_ulong psw_cb;
@ -117,11 +130,12 @@ void hppa_cpu_dump_state(CPUState *cs, FILE *f, int flags)
m = UINT32_MAX; m = UINT32_MAX;
} }
qemu_fprintf(f, "IA_F " TARGET_FMT_lx " IA_B " TARGET_FMT_lx qemu_fprintf(f, "IA_F %08" PRIx64 ":%0*" PRIx64 " (" TARGET_FMT_lx ")\n"
" IIR %0*" PRIx64 "\n", "IA_B %08" PRIx64 ":%0*" PRIx64 " (" TARGET_FMT_lx ")\n",
env->iasq_f >> 32, w, m & env->iaoq_f,
hppa_form_gva_psw(psw, env->iasq_f, env->iaoq_f), hppa_form_gva_psw(psw, env->iasq_f, env->iaoq_f),
hppa_form_gva_psw(psw, env->iasq_b, env->iaoq_b), env->iasq_b >> 32, w, m & env->iaoq_b,
w, m & env->cr[CR_IIR]); hppa_form_gva_psw(psw, env->iasq_b, env->iaoq_b));
psw_c[0] = (psw & PSW_W ? 'W' : '-'); psw_c[0] = (psw & PSW_W ? 'W' : '-');
psw_c[1] = (psw & PSW_E ? 'E' : '-'); psw_c[1] = (psw & PSW_E ? 'E' : '-');
@ -154,12 +168,46 @@ void hppa_cpu_dump_state(CPUState *cs, FILE *f, int flags)
(i & 3) == 3 ? '\n' : ' '); (i & 3) == 3 ? '\n' : ' ');
} }
#ifndef CONFIG_USER_ONLY #ifndef CONFIG_USER_ONLY
for (i = 0; i < 32; i++) {
qemu_fprintf(f, "%-4s %0*" PRIx64 "%c",
cr_name[i], w, m & env->cr[i],
(i & 3) == 3 ? '\n' : ' ');
}
qemu_fprintf(f, "ISQB %0*" PRIx64 " IOQB %0*" PRIx64 "\n",
w, m & env->cr_back[0], w, m & env->cr_back[1]);
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
qemu_fprintf(f, "SR%02d %08x%c", i, (uint32_t)(env->sr[i] >> 32), qemu_fprintf(f, "SR%02d %08x%c", i, (uint32_t)(env->sr[i] >> 32),
(i & 3) == 3 ? '\n' : ' '); (i & 3) == 3 ? '\n' : ' ');
} }
#endif #endif
qemu_fprintf(f, "\n");
/* ??? FR */ if (flags & CPU_DUMP_FPU) {
static const char rm[4][4] = { "RN", "RZ", "R+", "R-" };
char flg[6], ena[6];
uint32_t fpsr = env->fr0_shadow;
flg[0] = (fpsr & R_FPSR_FLG_V_MASK ? 'V' : '-');
flg[1] = (fpsr & R_FPSR_FLG_Z_MASK ? 'Z' : '-');
flg[2] = (fpsr & R_FPSR_FLG_O_MASK ? 'O' : '-');
flg[3] = (fpsr & R_FPSR_FLG_U_MASK ? 'U' : '-');
flg[4] = (fpsr & R_FPSR_FLG_I_MASK ? 'I' : '-');
flg[5] = '\0';
ena[0] = (fpsr & R_FPSR_ENA_V_MASK ? 'V' : '-');
ena[1] = (fpsr & R_FPSR_ENA_Z_MASK ? 'Z' : '-');
ena[2] = (fpsr & R_FPSR_ENA_O_MASK ? 'O' : '-');
ena[3] = (fpsr & R_FPSR_ENA_U_MASK ? 'U' : '-');
ena[4] = (fpsr & R_FPSR_ENA_I_MASK ? 'I' : '-');
ena[5] = '\0';
qemu_fprintf(f, "FPSR %08x flag %s enable %s %s\n",
fpsr, flg, ena, rm[FIELD_EX32(fpsr, FPSR, RM)]);
for (i = 0; i < 32; i++) {
qemu_fprintf(f, "FR%02d %016" PRIx64 "%c",
i, env->fr[i], (i & 3) == 3 ? '\n' : ' ');
}
}
qemu_fprintf(f, "\n");
} }

View file

@ -1,6 +1,4 @@
DEF_HELPER_2(excp, noreturn, env, int) DEF_HELPER_2(excp, noreturn, env, int)
DEF_HELPER_FLAGS_2(tsv, TCG_CALL_NO_WG, void, env, tl)
DEF_HELPER_FLAGS_2(tcond, TCG_CALL_NO_WG, void, env, tl)
DEF_HELPER_FLAGS_3(stby_b, TCG_CALL_NO_WG, void, env, tl, tl) DEF_HELPER_FLAGS_3(stby_b, TCG_CALL_NO_WG, void, env, tl, tl)
DEF_HELPER_FLAGS_3(stby_b_parallel, TCG_CALL_NO_WG, void, env, tl, tl) DEF_HELPER_FLAGS_3(stby_b_parallel, TCG_CALL_NO_WG, void, env, tl, tl)
@ -88,6 +86,7 @@ DEF_HELPER_1(halt, noreturn, env)
DEF_HELPER_1(reset, noreturn, env) DEF_HELPER_1(reset, noreturn, env)
DEF_HELPER_1(rfi, void, env) DEF_HELPER_1(rfi, void, env)
DEF_HELPER_1(rfi_r, void, env) DEF_HELPER_1(rfi_r, void, env)
DEF_HELPER_FLAGS_2(b_gate_priv, TCG_CALL_NO_WG, i64, env, i64)
DEF_HELPER_FLAGS_2(write_interval_timer, TCG_CALL_NO_RWG, void, env, tl) DEF_HELPER_FLAGS_2(write_interval_timer, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_2(write_eirr, TCG_CALL_NO_RWG, void, env, tl) DEF_HELPER_FLAGS_2(write_eirr, TCG_CALL_NO_RWG, void, env, tl)
DEF_HELPER_FLAGS_2(swap_system_mask, TCG_CALL_NO_RWG, tl, env, tl) DEF_HELPER_FLAGS_2(swap_system_mask, TCG_CALL_NO_RWG, tl, env, tl)

View file

@ -134,13 +134,13 @@ void hppa_cpu_do_interrupt(CPUState *cs)
switch (i) { switch (i) {
case EXCP_ILL: case EXCP_ILL:
case EXCP_BREAK: case EXCP_BREAK:
case EXCP_OVERFLOW:
case EXCP_COND:
case EXCP_PRIV_REG: case EXCP_PRIV_REG:
case EXCP_PRIV_OPR: case EXCP_PRIV_OPR:
/* IIR set via translate.c. */ /* IIR set via translate.c. */
break; break;
case EXCP_OVERFLOW:
case EXCP_COND:
case EXCP_ASSIST: case EXCP_ASSIST:
case EXCP_DTLB_MISS: case EXCP_DTLB_MISS:
case EXCP_NA_ITLB_MISS: case EXCP_NA_ITLB_MISS:
@ -167,7 +167,7 @@ void hppa_cpu_do_interrupt(CPUState *cs)
vaddr = hppa_form_gva_psw(old_psw, env->iasq_f, vaddr); vaddr = hppa_form_gva_psw(old_psw, env->iasq_f, vaddr);
t = hppa_get_physical_address(env, vaddr, MMU_KERNEL_IDX, t = hppa_get_physical_address(env, vaddr, MMU_KERNEL_IDX,
0, &paddr, &prot, NULL); 0, &paddr, &prot);
if (t >= 0) { if (t >= 0) {
/* We can't re-load the instruction. */ /* We can't re-load the instruction. */
env->cr[CR_IIR] = 0; env->cr[CR_IIR] = 0;
@ -241,21 +241,22 @@ void hppa_cpu_do_interrupt(CPUState *cs)
[EXCP_SYSCALL_LWS] = "syscall-lws", [EXCP_SYSCALL_LWS] = "syscall-lws",
[EXCP_TOC] = "TOC (transfer of control)", [EXCP_TOC] = "TOC (transfer of control)",
}; };
static int count;
const char *name = NULL;
char unknown[16];
if (i >= 0 && i < ARRAY_SIZE(names)) { FILE *logfile = qemu_log_trylock();
name = names[i]; if (logfile) {
const char *name = NULL;
if (i >= 0 && i < ARRAY_SIZE(names)) {
name = names[i];
}
if (name) {
fprintf(logfile, "INT: cpu %d %s\n", cs->cpu_index, name);
} else {
fprintf(logfile, "INT: cpu %d unknown %d\n", cs->cpu_index, i);
}
hppa_cpu_dump_state(cs, logfile, 0);
qemu_log_unlock(logfile);
} }
if (!name) {
snprintf(unknown, sizeof(unknown), "unknown %d", i);
name = unknown;
}
qemu_log("INT %6d: %s @ " TARGET_FMT_lx ":" TARGET_FMT_lx
" for " TARGET_FMT_lx ":" TARGET_FMT_lx "\n",
++count, name, env->cr[CR_IIASQ], env->cr[CR_IIAOQ],
env->cr[CR_ISR], env->cr[CR_IOR]);
} }
cs->exception_index = -1; cs->exception_index = -1;
} }

View file

@ -197,18 +197,13 @@ static int match_prot_id64(CPUHPPAState *env, uint32_t access_id)
} }
int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx, int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
int type, hwaddr *pphys, int *pprot, int type, hwaddr *pphys, int *pprot)
HPPATLBEntry **tlb_entry)
{ {
hwaddr phys; hwaddr phys;
int prot, r_prot, w_prot, x_prot, priv; int prot, r_prot, w_prot, x_prot, priv;
HPPATLBEntry *ent; HPPATLBEntry *ent;
int ret = -1; int ret = -1;
if (tlb_entry) {
*tlb_entry = NULL;
}
/* Virtual translation disabled. Map absolute to physical. */ /* Virtual translation disabled. Map absolute to physical. */
if (MMU_IDX_MMU_DISABLED(mmu_idx)) { if (MMU_IDX_MMU_DISABLED(mmu_idx)) {
switch (mmu_idx) { switch (mmu_idx) {
@ -238,10 +233,6 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
goto egress; goto egress;
} }
if (tlb_entry) {
*tlb_entry = ent;
}
/* We now know the physical address. */ /* We now know the physical address. */
phys = ent->pa + (addr - ent->itree.start); phys = ent->pa + (addr - ent->itree.start);
@ -296,30 +287,38 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
goto egress; goto egress;
} }
/* In reverse priority order, check for conditions which raise faults. /*
As we go, remove PROT bits that cover the condition we want to check. * In priority order, check for conditions which raise faults.
In this way, the resulting PROT will force a re-check of the * Remove PROT bits that cover the condition we want to check,
architectural TLB entry for the next access. */ * so that the resulting PROT will force a re-check of the
if (unlikely(!ent->d)) { * architectural TLB entry for the next access.
if (type & PAGE_WRITE) { */
/* The D bit is not set -- TLB Dirty Bit Fault. */
ret = EXCP_TLB_DIRTY;
}
prot &= PAGE_READ | PAGE_EXEC;
}
if (unlikely(ent->b)) {
if (type & PAGE_WRITE) {
/* The B bit is set -- Data Memory Break Fault. */
ret = EXCP_DMB;
}
prot &= PAGE_READ | PAGE_EXEC;
}
if (unlikely(ent->t)) { if (unlikely(ent->t)) {
prot &= PAGE_EXEC;
if (!(type & PAGE_EXEC)) { if (!(type & PAGE_EXEC)) {
/* The T bit is set -- Page Reference Fault. */ /* The T bit is set -- Page Reference Fault. */
ret = EXCP_PAGE_REF; ret = EXCP_PAGE_REF;
} }
prot &= PAGE_EXEC; } else if (!ent->d) {
prot &= PAGE_READ | PAGE_EXEC;
if (type & PAGE_WRITE) {
/* The D bit is not set -- TLB Dirty Bit Fault. */
ret = EXCP_TLB_DIRTY;
}
} else if (unlikely(ent->b)) {
prot &= PAGE_READ | PAGE_EXEC;
if (type & PAGE_WRITE) {
/*
* The B bit is set -- Data Memory Break Fault.
* Except when PSW_X is set, allow this single access to succeed.
* The write bit will be invalidated for subsequent accesses.
*/
if (env->psw_xb & PSW_X) {
prot |= PAGE_WRITE_INV;
} else {
ret = EXCP_DMB;
}
}
} }
egress: egress:
@ -342,7 +341,7 @@ hwaddr hppa_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
cpu->env.psw & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX); cpu->env.psw & PSW_W ? MMU_ABS_W_IDX : MMU_ABS_IDX);
excp = hppa_get_physical_address(&cpu->env, addr, mmu_idx, 0, excp = hppa_get_physical_address(&cpu->env, addr, mmu_idx, 0,
&phys, &prot, NULL); &phys, &prot);
/* Since we're translating for debugging, the only error that is a /* Since we're translating for debugging, the only error that is a
hard error is no translation at all. Otherwise, while a real cpu hard error is no translation at all. Otherwise, while a real cpu
@ -424,7 +423,6 @@ bool hppa_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
{ {
HPPACPU *cpu = HPPA_CPU(cs); HPPACPU *cpu = HPPA_CPU(cs);
CPUHPPAState *env = &cpu->env; CPUHPPAState *env = &cpu->env;
HPPATLBEntry *ent;
int prot, excp, a_prot; int prot, excp, a_prot;
hwaddr phys; hwaddr phys;
@ -440,8 +438,7 @@ bool hppa_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
break; break;
} }
excp = hppa_get_physical_address(env, addr, mmu_idx, excp = hppa_get_physical_address(env, addr, mmu_idx, a_prot, &phys, &prot);
a_prot, &phys, &prot, &ent);
if (unlikely(excp >= 0)) { if (unlikely(excp >= 0)) {
if (probe) { if (probe) {
return false; return false;
@ -682,7 +679,7 @@ target_ulong HELPER(lpa)(CPUHPPAState *env, target_ulong addr)
int prot, excp; int prot, excp;
excp = hppa_get_physical_address(env, addr, MMU_KERNEL_IDX, 0, excp = hppa_get_physical_address(env, addr, MMU_KERNEL_IDX, 0,
&phys, &prot, NULL); &phys, &prot);
if (excp >= 0) { if (excp >= 0) {
if (excp == EXCP_DTLB_MISS) { if (excp == EXCP_DTLB_MISS) {
excp = EXCP_NA_DTLB_MISS; excp = EXCP_NA_DTLB_MISS;
@ -694,13 +691,6 @@ target_ulong HELPER(lpa)(CPUHPPAState *env, target_ulong addr)
return phys; return phys;
} }
/* Return the ar_type of the TLB at VADDR, or -1. */
int hppa_artype_for_page(CPUHPPAState *env, target_ulong vaddr)
{
HPPATLBEntry *ent = hppa_find_tlb(env, vaddr);
return ent ? ent->ar_type : -1;
}
/* /*
* diag_btlb() emulates the PDC PDC_BLOCK_TLB firmware call to * diag_btlb() emulates the PDC PDC_BLOCK_TLB firmware call to
* allow operating systems to modify the Block TLB (BTLB) entries. * allow operating systems to modify the Block TLB (BTLB) entries.
@ -796,3 +786,30 @@ void HELPER(diag_btlb)(CPUHPPAState *env)
break; break;
} }
} }
uint64_t HELPER(b_gate_priv)(CPUHPPAState *env, uint64_t iaoq_f)
{
uint64_t gva = hppa_form_gva(env, env->iasq_f, iaoq_f);
HPPATLBEntry *ent = hppa_find_tlb(env, gva);
if (ent == NULL) {
raise_exception_with_ior(env, EXCP_ITLB_MISS, GETPC(), gva, false);
}
/*
* There should be no need to check page permissions, as that will
* already have been done by tb_lookup via get_page_addr_code.
* All we need at this point is to check the ar_type.
*
* No change for non-gateway pages or for priv decrease.
*/
if (ent->ar_type & 4) {
int old_priv = iaoq_f & 3;
int new_priv = ent->ar_type & 3;
if (new_priv < old_priv) {
iaoq_f = (iaoq_f & -4) | new_priv;
}
}
return iaoq_f;
}

View file

@ -42,20 +42,6 @@ G_NORETURN void hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t ra)
cpu_loop_exit_restore(cs, ra); cpu_loop_exit_restore(cs, ra);
} }
void HELPER(tsv)(CPUHPPAState *env, target_ulong cond)
{
if (unlikely((target_long)cond < 0)) {
hppa_dynamic_excp(env, EXCP_OVERFLOW, GETPC());
}
}
void HELPER(tcond)(CPUHPPAState *env, target_ulong cond)
{
if (unlikely(cond)) {
hppa_dynamic_excp(env, EXCP_COND, GETPC());
}
}
static void atomic_store_mask32(CPUHPPAState *env, target_ulong addr, static void atomic_store_mask32(CPUHPPAState *env, target_ulong addr,
uint32_t val, uint32_t mask, uintptr_t ra) uint32_t val, uint32_t mask, uintptr_t ra)
{ {
@ -348,8 +334,7 @@ target_ulong HELPER(probe)(CPUHPPAState *env, target_ulong addr,
} }
mmu_idx = PRIV_P_TO_MMU_IDX(level, env->psw & PSW_P); mmu_idx = PRIV_P_TO_MMU_IDX(level, env->psw & PSW_P);
excp = hppa_get_physical_address(env, addr, mmu_idx, 0, &phys, excp = hppa_get_physical_address(env, addr, mmu_idx, 0, &phys, &prot);
&prot, NULL);
if (excp >= 0) { if (excp >= 0) {
cpu_restore_state(env_cpu(env), GETPC()); cpu_restore_state(env_cpu(env), GETPC());
hppa_set_ior_and_isr(env, addr, MMU_IDX_MMU_DISABLED(mmu_idx)); hppa_set_ior_and_isr(env, addr, MMU_IDX_MMU_DISABLED(mmu_idx));

View file

@ -18,6 +18,7 @@
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu/log.h"
#include "cpu.h" #include "cpu.h"
#include "exec/exec-all.h" #include "exec/exec-all.h"
#include "exec/helper-proto.h" #include "exec/helper-proto.h"
@ -93,6 +94,17 @@ void HELPER(rfi)(CPUHPPAState *env)
env->iaoq_b = env->cr_back[1]; env->iaoq_b = env->cr_back[1];
env->iasq_f = (env->cr[CR_IIASQ] << 32) & ~(env->iaoq_f & mask); env->iasq_f = (env->cr[CR_IIASQ] << 32) & ~(env->iaoq_f & mask);
env->iasq_b = (env->cr_back[0] << 32) & ~(env->iaoq_b & mask); env->iasq_b = (env->cr_back[0] << 32) & ~(env->iaoq_b & mask);
if (qemu_loglevel_mask(CPU_LOG_INT)) {
FILE *logfile = qemu_log_trylock();
if (logfile) {
CPUState *cs = env_cpu(env);
fprintf(logfile, "RFI: cpu %d\n", cs->cpu_index);
hppa_cpu_dump_state(cs, logfile, 0);
qemu_log_unlock(logfile);
}
}
} }
static void getshadowregs(CPUHPPAState *env) static void getshadowregs(CPUHPPAState *env)

File diff suppressed because it is too large Load diff