mirror of https://github.com/xemu-project/xemu.git
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:
commit
922582ace2
|
@ -1887,8 +1887,8 @@ static inline void init_thread(struct target_pt_regs *regs,
|
|||
static inline void init_thread(struct target_pt_regs *regs,
|
||||
struct image_info *infop)
|
||||
{
|
||||
regs->iaoq[0] = infop->entry;
|
||||
regs->iaoq[1] = infop->entry + 4;
|
||||
regs->iaoq[0] = infop->entry | PRIV_USER;
|
||||
regs->iaoq[1] = regs->iaoq[0] + 4;
|
||||
regs->gr[23] = 0;
|
||||
regs->gr[24] = infop->argv;
|
||||
regs->gr[25] = infop->argc;
|
||||
|
|
|
@ -129,8 +129,8 @@ void cpu_loop(CPUHPPAState *env)
|
|||
default:
|
||||
env->gr[28] = ret;
|
||||
/* We arrived here by faking the gateway page. Return. */
|
||||
env->iaoq_f = env->gr[31];
|
||||
env->iaoq_b = env->gr[31] + 4;
|
||||
env->iaoq_f = env->gr[31] | PRIV_USER;
|
||||
env->iaoq_b = env->iaoq_f + 4;
|
||||
break;
|
||||
case -QEMU_ERESTARTSYS:
|
||||
case -QEMU_ESIGRETURN:
|
||||
|
@ -140,8 +140,8 @@ void cpu_loop(CPUHPPAState *env)
|
|||
case EXCP_SYSCALL_LWS:
|
||||
env->gr[21] = hppa_lws(env);
|
||||
/* We arrived here by faking the gateway page. Return. */
|
||||
env->iaoq_f = env->gr[31];
|
||||
env->iaoq_b = env->gr[31] + 4;
|
||||
env->iaoq_f = env->gr[31] | PRIV_USER;
|
||||
env->iaoq_b = env->iaoq_f + 4;
|
||||
break;
|
||||
case EXCP_IMP:
|
||||
force_sig_fault(TARGET_SIGSEGV, TARGET_SEGV_MAPERR, env->iaoq_f);
|
||||
|
@ -152,9 +152,9 @@ void cpu_loop(CPUHPPAState *env)
|
|||
case EXCP_PRIV_OPR:
|
||||
/* check for glibc ABORT_INSTRUCTION "iitlbp %r0,(%sr0, %r0)" */
|
||||
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 {
|
||||
force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->iaoq_f);
|
||||
force_sig_fault(TARGET_SIGILL, TARGET_ILL_PRVOPC, env->iaoq_f);
|
||||
}
|
||||
break;
|
||||
case EXCP_PRIV_REG:
|
||||
|
@ -170,7 +170,7 @@ void cpu_loop(CPUHPPAState *env)
|
|||
force_sig_fault(TARGET_SIGFPE, 0, env->iaoq_f);
|
||||
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;
|
||||
case EXCP_DEBUG:
|
||||
force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, env->iaoq_f);
|
||||
|
|
|
@ -101,7 +101,9 @@ static void restore_sigcontext(CPUArchState *env, struct target_sigcontext *sc)
|
|||
cpu_hppa_loaded_fr0(env);
|
||||
|
||||
__get_user(env->iaoq_f, &sc->sc_iaoq[0]);
|
||||
env->iaoq_f |= PRIV_USER;
|
||||
__get_user(env->iaoq_b, &sc->sc_iaoq[1]);
|
||||
env->iaoq_b |= PRIV_USER;
|
||||
__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);
|
||||
haddr = dest;
|
||||
}
|
||||
env->iaoq_f = haddr;
|
||||
env->iaoq_b = haddr + 4;
|
||||
env->iaoq_f = haddr | PRIV_USER;
|
||||
env->iaoq_b = env->iaoq_f + 4;
|
||||
env->psw_n = 0;
|
||||
return;
|
||||
|
||||
|
|
|
@ -28,8 +28,8 @@ static inline void cpu_clone_regs_child(CPUHPPAState *env, target_ulong newsp,
|
|||
/* Indicate child in return value. */
|
||||
env->gr[28] = 0;
|
||||
/* Return from the syscall. */
|
||||
env->iaoq_f = env->gr[31];
|
||||
env->iaoq_b = env->gr[31] + 4;
|
||||
env->iaoq_f = env->gr[31] | PRIV_USER;
|
||||
env->iaoq_b = env->iaoq_f + 4;
|
||||
}
|
||||
|
||||
static inline void cpu_clone_regs_parent(CPUHPPAState *env, unsigned flags)
|
||||
|
|
|
@ -32,15 +32,67 @@ static void hppa_cpu_set_pc(CPUState *cs, vaddr value)
|
|||
{
|
||||
HPPACPU *cpu = HPPA_CPU(cs);
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
value |= PRIV_USER;
|
||||
#endif
|
||||
cpu->env.iaoq_f = value;
|
||||
cpu->env.iaoq_b = value + 4;
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -48,45 +100,28 @@ static void hppa_cpu_synchronize_from_tb(CPUState *cs,
|
|||
{
|
||||
HPPACPU *cpu = HPPA_CPU(cs);
|
||||
|
||||
tcg_debug_assert(!tcg_cflags_has(cs, CF_PCREL));
|
||||
|
||||
#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
|
||||
|
||||
/* IAQ is always up-to-date before goto_tb. */
|
||||
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,
|
||||
const TranslationBlock *tb,
|
||||
const uint64_t *data)
|
||||
{
|
||||
HPPACPU *cpu = HPPA_CPU(cs);
|
||||
CPUHPPAState *env = cpu_env(cs);
|
||||
|
||||
cpu->env.iaoq_f = data[0];
|
||||
if (data[1] != (target_ulong)-1) {
|
||||
cpu->env.iaoq_b = data[1];
|
||||
env->iaoq_f = (env->iaoq_f & TARGET_PAGE_MASK) | data[0];
|
||||
if (data[1] != INT32_MIN) {
|
||||
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
|
||||
* sort of action that provoked the cpu_restore_state, we can infer
|
||||
* that the instruction was not nullified.
|
||||
*/
|
||||
cpu->env.psw_n = 0;
|
||||
env->psw_n = 0;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Use pc-relative instructions always to simplify the translator. */
|
||||
tcg_cflags_set(cs, CF_PCREL);
|
||||
}
|
||||
|
||||
static void hppa_cpu_initfn(Object *obj)
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "exec/cpu-defs.h"
|
||||
#include "qemu/cpu-float.h"
|
||||
#include "qemu/interval-tree.h"
|
||||
#include "hw/registerfields.h"
|
||||
|
||||
#define MMU_ABS_W_IDX 6
|
||||
#define MMU_ABS_IDX 7
|
||||
|
@ -41,6 +42,9 @@
|
|||
#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_KERNEL 0
|
||||
#define PRIV_USER 3
|
||||
|
||||
#define TARGET_INSN_START_EXTRA_WORDS 2
|
||||
|
||||
/* No need to flush MMU_ABS*_IDX */
|
||||
|
@ -152,6 +156,30 @@
|
|||
#define CR_IPSW 22
|
||||
#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 {
|
||||
union {
|
||||
IntervalTreeNode itree;
|
||||
|
@ -180,7 +208,8 @@ typedef struct CPUArchState {
|
|||
uint64_t fr[32];
|
||||
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_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_PRIV_SHIFT 8
|
||||
#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,
|
||||
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;
|
||||
}
|
||||
void cpu_get_tb_cpu_state(CPUHPPAState *env, vaddr *pc,
|
||||
uint64_t *cs_base, uint32_t *pflags);
|
||||
|
||||
target_ulong cpu_hppa_get_psw(CPUHPPAState *env);
|
||||
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);
|
||||
bool hppa_cpu_exec_interrupt(CPUState *cpu, int int_req);
|
||||
int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
|
||||
int type, hwaddr *pphys, int *pprot,
|
||||
HPPATLBEntry **tlb_entry);
|
||||
int type, hwaddr *pphys, int *pprot);
|
||||
void hppa_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
|
||||
vaddr addr, unsigned size,
|
||||
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 VMStateDescription vmstate_hppa_cpu;
|
||||
void hppa_cpu_alarm_timer(void *);
|
||||
int hppa_artype_for_page(CPUHPPAState *env, target_ulong vaddr);
|
||||
#endif
|
||||
G_NORETURN void hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t ra);
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
|
|||
|
||||
env->fr0_shadow = shadow;
|
||||
|
||||
switch (extract32(shadow, 9, 2)) {
|
||||
switch (FIELD_EX32(shadow, FPSR, RM)) {
|
||||
default:
|
||||
rm = float_round_nearest_even;
|
||||
break;
|
||||
|
@ -46,7 +46,7 @@ void HELPER(loaded_fr0)(CPUHPPAState *env)
|
|||
}
|
||||
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_inputs_to_zero(d, &env->fp_status);
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ void cpu_hppa_loaded_fr0(CPUHPPAState *env)
|
|||
}
|
||||
|
||||
#define CONVERT_BIT(X, SRC, DST) \
|
||||
((SRC) > (DST) \
|
||||
((unsigned)(SRC) > (unsigned)(DST) \
|
||||
? (X) / ((SRC) / (DST)) & (DST) \
|
||||
: ((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);
|
||||
|
||||
hard_exp |= CONVERT_BIT(soft_exp, float_flag_inexact, 1u << 0);
|
||||
hard_exp |= CONVERT_BIT(soft_exp, float_flag_underflow, 1u << 1);
|
||||
hard_exp |= CONVERT_BIT(soft_exp, float_flag_overflow, 1u << 2);
|
||||
hard_exp |= CONVERT_BIT(soft_exp, float_flag_divbyzero, 1u << 3);
|
||||
hard_exp |= CONVERT_BIT(soft_exp, float_flag_invalid, 1u << 4);
|
||||
shadow |= hard_exp << (32 - 5);
|
||||
hard_exp |= CONVERT_BIT(soft_exp, float_flag_inexact, R_FPSR_ENA_I_MASK);
|
||||
hard_exp |= CONVERT_BIT(soft_exp, float_flag_underflow, R_FPSR_ENA_U_MASK);
|
||||
hard_exp |= CONVERT_BIT(soft_exp, float_flag_overflow, R_FPSR_ENA_O_MASK);
|
||||
hard_exp |= CONVERT_BIT(soft_exp, float_flag_divbyzero, R_FPSR_ENA_Z_MASK);
|
||||
hard_exp |= CONVERT_BIT(soft_exp, float_flag_invalid, R_FPSR_ENA_V_MASK);
|
||||
shadow |= hard_exp << (R_FPSR_FLAGS_SHIFT - R_FPSR_ENABLES_SHIFT);
|
||||
env->fr0_shadow = shadow;
|
||||
env->fr[0] = (uint64_t)shadow << 32;
|
||||
|
||||
|
@ -378,15 +378,15 @@ static void update_fr0_cmp(CPUHPPAState *env, uint32_t y,
|
|||
if (y) {
|
||||
/* targeted comparison */
|
||||
/* 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 {
|
||||
/* queued comparison */
|
||||
/* 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]] */
|
||||
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 */
|
||||
shadow = deposit32(shadow, 26, 1, c);
|
||||
shadow = FIELD_DP32(shadow, FPSR, C, c);
|
||||
}
|
||||
|
||||
env->fr0_shadow = shadow;
|
||||
|
|
|
@ -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);
|
||||
break;
|
||||
case 33:
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
val |= PRIV_USER;
|
||||
#endif
|
||||
env->iaoq_f = val;
|
||||
break;
|
||||
case 34:
|
||||
env->iasq_f = (uint64_t)val << 32;
|
||||
break;
|
||||
case 35:
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
val |= PRIV_USER;
|
||||
#endif
|
||||
env->iaoq_b = val;
|
||||
break;
|
||||
case 36:
|
||||
|
|
|
@ -54,7 +54,7 @@ target_ulong cpu_hppa_get_psw(CPUHPPAState *env)
|
|||
|
||||
psw |= env->psw_n * PSW_N;
|
||||
psw |= (env->psw_v < 0) * PSW_V;
|
||||
psw |= env->psw;
|
||||
psw |= env->psw | env->psw_xb;
|
||||
|
||||
return psw;
|
||||
}
|
||||
|
@ -76,8 +76,8 @@ void cpu_hppa_put_psw(CPUHPPAState *env, target_ulong psw)
|
|||
}
|
||||
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_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)
|
||||
{
|
||||
#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);
|
||||
target_ulong psw = cpu_hppa_get_psw(env);
|
||||
target_ulong psw_cb;
|
||||
|
@ -117,11 +130,12 @@ void hppa_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
|||
m = UINT32_MAX;
|
||||
}
|
||||
|
||||
qemu_fprintf(f, "IA_F " TARGET_FMT_lx " IA_B " TARGET_FMT_lx
|
||||
" IIR %0*" PRIx64 "\n",
|
||||
qemu_fprintf(f, "IA_F %08" PRIx64 ":%0*" PRIx64 " (" TARGET_FMT_lx ")\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_b, env->iaoq_b),
|
||||
w, m & env->cr[CR_IIR]);
|
||||
env->iasq_b >> 32, w, m & env->iaoq_b,
|
||||
hppa_form_gva_psw(psw, env->iasq_b, env->iaoq_b));
|
||||
|
||||
psw_c[0] = (psw & PSW_W ? 'W' : '-');
|
||||
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' : ' ');
|
||||
}
|
||||
#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++) {
|
||||
qemu_fprintf(f, "SR%02d %08x%c", i, (uint32_t)(env->sr[i] >> 32),
|
||||
(i & 3) == 3 ? '\n' : ' ');
|
||||
}
|
||||
#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");
|
||||
}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
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_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(rfi, 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_eirr, TCG_CALL_NO_RWG, void, env, tl)
|
||||
DEF_HELPER_FLAGS_2(swap_system_mask, TCG_CALL_NO_RWG, tl, env, tl)
|
||||
|
|
|
@ -134,13 +134,13 @@ void hppa_cpu_do_interrupt(CPUState *cs)
|
|||
switch (i) {
|
||||
case EXCP_ILL:
|
||||
case EXCP_BREAK:
|
||||
case EXCP_OVERFLOW:
|
||||
case EXCP_COND:
|
||||
case EXCP_PRIV_REG:
|
||||
case EXCP_PRIV_OPR:
|
||||
/* IIR set via translate.c. */
|
||||
break;
|
||||
|
||||
case EXCP_OVERFLOW:
|
||||
case EXCP_COND:
|
||||
case EXCP_ASSIST:
|
||||
case EXCP_DTLB_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);
|
||||
t = hppa_get_physical_address(env, vaddr, MMU_KERNEL_IDX,
|
||||
0, &paddr, &prot, NULL);
|
||||
0, &paddr, &prot);
|
||||
if (t >= 0) {
|
||||
/* We can't re-load the instruction. */
|
||||
env->cr[CR_IIR] = 0;
|
||||
|
@ -241,21 +241,22 @@ void hppa_cpu_do_interrupt(CPUState *cs)
|
|||
[EXCP_SYSCALL_LWS] = "syscall-lws",
|
||||
[EXCP_TOC] = "TOC (transfer of control)",
|
||||
};
|
||||
static int count;
|
||||
const char *name = NULL;
|
||||
char unknown[16];
|
||||
|
||||
if (i >= 0 && i < ARRAY_SIZE(names)) {
|
||||
name = names[i];
|
||||
FILE *logfile = qemu_log_trylock();
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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 type, hwaddr *pphys, int *pprot,
|
||||
HPPATLBEntry **tlb_entry)
|
||||
int type, hwaddr *pphys, int *pprot)
|
||||
{
|
||||
hwaddr phys;
|
||||
int prot, r_prot, w_prot, x_prot, priv;
|
||||
HPPATLBEntry *ent;
|
||||
int ret = -1;
|
||||
|
||||
if (tlb_entry) {
|
||||
*tlb_entry = NULL;
|
||||
}
|
||||
|
||||
/* Virtual translation disabled. Map absolute to physical. */
|
||||
if (MMU_IDX_MMU_DISABLED(mmu_idx)) {
|
||||
switch (mmu_idx) {
|
||||
|
@ -238,10 +233,6 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
|
|||
goto egress;
|
||||
}
|
||||
|
||||
if (tlb_entry) {
|
||||
*tlb_entry = ent;
|
||||
}
|
||||
|
||||
/* We now know the physical address. */
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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 this way, the resulting PROT will force a re-check of the
|
||||
architectural TLB entry for the next access. */
|
||||
if (unlikely(!ent->d)) {
|
||||
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;
|
||||
}
|
||||
/*
|
||||
* In priority order, check for conditions which raise faults.
|
||||
* Remove PROT bits that cover the condition we want to check,
|
||||
* so that the resulting PROT will force a re-check of the
|
||||
* architectural TLB entry for the next access.
|
||||
*/
|
||||
if (unlikely(ent->t)) {
|
||||
prot &= PAGE_EXEC;
|
||||
if (!(type & PAGE_EXEC)) {
|
||||
/* The T bit is set -- Page Reference Fault. */
|
||||
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:
|
||||
|
@ -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);
|
||||
|
||||
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
|
||||
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);
|
||||
CPUHPPAState *env = &cpu->env;
|
||||
HPPATLBEntry *ent;
|
||||
int prot, excp, a_prot;
|
||||
hwaddr phys;
|
||||
|
||||
|
@ -440,8 +438,7 @@ bool hppa_cpu_tlb_fill(CPUState *cs, vaddr addr, int size,
|
|||
break;
|
||||
}
|
||||
|
||||
excp = hppa_get_physical_address(env, addr, mmu_idx,
|
||||
a_prot, &phys, &prot, &ent);
|
||||
excp = hppa_get_physical_address(env, addr, mmu_idx, a_prot, &phys, &prot);
|
||||
if (unlikely(excp >= 0)) {
|
||||
if (probe) {
|
||||
return false;
|
||||
|
@ -682,7 +679,7 @@ target_ulong HELPER(lpa)(CPUHPPAState *env, target_ulong addr)
|
|||
int prot, excp;
|
||||
|
||||
excp = hppa_get_physical_address(env, addr, MMU_KERNEL_IDX, 0,
|
||||
&phys, &prot, NULL);
|
||||
&phys, &prot);
|
||||
if (excp >= 0) {
|
||||
if (excp == EXCP_DTLB_MISS) {
|
||||
excp = EXCP_NA_DTLB_MISS;
|
||||
|
@ -694,13 +691,6 @@ target_ulong HELPER(lpa)(CPUHPPAState *env, target_ulong addr)
|
|||
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
|
||||
* allow operating systems to modify the Block TLB (BTLB) entries.
|
||||
|
@ -796,3 +786,30 @@ void HELPER(diag_btlb)(CPUHPPAState *env)
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -42,20 +42,6 @@ G_NORETURN void hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t 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,
|
||||
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);
|
||||
excp = hppa_get_physical_address(env, addr, mmu_idx, 0, &phys,
|
||||
&prot, NULL);
|
||||
excp = hppa_get_physical_address(env, addr, mmu_idx, 0, &phys, &prot);
|
||||
if (excp >= 0) {
|
||||
cpu_restore_state(env_cpu(env), GETPC());
|
||||
hppa_set_ior_and_isr(env, addr, MMU_IDX_MMU_DISABLED(mmu_idx));
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/log.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
@ -93,6 +94,17 @@ void HELPER(rfi)(CPUHPPAState *env)
|
|||
env->iaoq_b = env->cr_back[1];
|
||||
env->iasq_f = (env->cr[CR_IIASQ] << 32) & ~(env->iaoq_f & 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)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue