Misc fixes affecting HP-UX 10.20.
-----BEGIN PGP SIGNATURE----- iQEcBAABAgAGBQJch9tgAAoJEGTfOOivfiFfKtoH/RzN42QeTfH60VrqsxIcOQ3t 6vuDzO071zCPUMWLpIizhGH2FDRbUS2H4oihtoaoZza0IllewdhjXr4EabmXBlbz GD1louz73+AvOJ88dmfCC8tvEVW0Ga+MgljDBGwNAPPTEXlYUZGYGq8r4Mv9sxHu TGNkb4Q/nSsIXeaSaXUHECVJNJ43o+naCgoO6odTgjcN5Dr99t5Uk8GK2wgfLMaE iz+c9EsEDPtPnJ7vmwbS/sJuS5D6fqBX2Ag0UNvNlJObImZfkxDi6g4h/VKDHrpa Ycxoog+EaCBV1iVkHhl8GV8hwzNFJ0EMFcK95Bf0KxcOVbL6jh59uINR2zVjS7M= =pjDE -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/rth/tags/pull-hppa-20190312' into staging Misc fixes affecting HP-UX 10.20. # gpg: Signature made Tue 12 Mar 2019 16:16:32 GMT # gpg: using RSA key 64DF38E8AF7E215F # gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full] # Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A 05C0 64DF 38E8 AF7E 215F * remotes/rth/tags/pull-hppa-20190312: target/hppa: exit TB if either Data or Instruction TLB changes target/hppa: add TLB protection id check target/hppa: allow multiple itlbp without itlba target/hppa: fix b,gate instruction target/hppa: ignore DIAG opcode target/hppa: remove PSW I/R/Q bit check target/hppa: add TLB trace events target/hppa: report ITLB_EXCP_MISS for ITLB misses target/hppa: fix TLB handling for page 0 target/hppa: fix overwriting source reg in addb target/hppa: Check for page crossings in use_goto_tb Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
9298a4e8a6
|
@ -182,6 +182,7 @@ trace-events-subdirs += qapi
|
|||
trace-events-subdirs += qom
|
||||
trace-events-subdirs += scsi
|
||||
trace-events-subdirs += target/arm
|
||||
trace-events-subdirs += target/hppa
|
||||
trace-events-subdirs += target/i386
|
||||
trace-events-subdirs += target/mips
|
||||
trace-events-subdirs += target/ppc
|
||||
|
|
|
@ -143,6 +143,10 @@
|
|||
#endif
|
||||
|
||||
#define CR_RC 0
|
||||
#define CR_PID1 8
|
||||
#define CR_PID2 9
|
||||
#define CR_PID3 12
|
||||
#define CR_PID4 13
|
||||
#define CR_SCRCCR 10
|
||||
#define CR_SAR 11
|
||||
#define CR_IVA 14
|
||||
|
@ -341,6 +345,12 @@ target_ureg cpu_hppa_get_psw(CPUHPPAState *env);
|
|||
void cpu_hppa_put_psw(CPUHPPAState *env, target_ureg);
|
||||
void cpu_hppa_loaded_fr0(CPUHPPAState *env);
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
static inline void cpu_hppa_change_prot_id(CPUHPPAState *env) { }
|
||||
#else
|
||||
void cpu_hppa_change_prot_id(CPUHPPAState *env);
|
||||
#endif
|
||||
|
||||
#define cpu_signal_handler cpu_hppa_signal_handler
|
||||
|
||||
int cpu_hppa_signal_handler(int host_signum, void *pinfo, void *puc);
|
||||
|
|
|
@ -93,19 +93,19 @@ int hppa_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
|
|||
val = env->cr[CR_RC];
|
||||
break;
|
||||
case 52:
|
||||
val = env->cr[8];
|
||||
val = env->cr[CR_PID1];
|
||||
break;
|
||||
case 53:
|
||||
val = env->cr[9];
|
||||
val = env->cr[CR_PID2];
|
||||
break;
|
||||
case 54:
|
||||
val = env->cr[CR_SCRCCR];
|
||||
break;
|
||||
case 55:
|
||||
val = env->cr[12];
|
||||
val = env->cr[CR_PID3];
|
||||
break;
|
||||
case 56:
|
||||
val = env->cr[13];
|
||||
val = env->cr[CR_PID4];
|
||||
break;
|
||||
case 57:
|
||||
val = env->cr[24];
|
||||
|
@ -224,19 +224,23 @@ int hppa_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
|||
env->cr[CR_RC] = val;
|
||||
break;
|
||||
case 52:
|
||||
env->cr[8] = val;
|
||||
env->cr[CR_PID1] = val;
|
||||
cpu_hppa_change_prot_id(env);
|
||||
break;
|
||||
case 53:
|
||||
env->cr[9] = val;
|
||||
env->cr[CR_PID2] = val;
|
||||
cpu_hppa_change_prot_id(env);
|
||||
break;
|
||||
case 54:
|
||||
env->cr[CR_SCRCCR] = val;
|
||||
break;
|
||||
case 55:
|
||||
env->cr[12] = val;
|
||||
env->cr[CR_PID3] = val;
|
||||
cpu_hppa_change_prot_id(env);
|
||||
break;
|
||||
case 56:
|
||||
env->cr[13] = val;
|
||||
env->cr[CR_PID4] = val;
|
||||
cpu_hppa_change_prot_id(env);
|
||||
break;
|
||||
case 57:
|
||||
env->cr[24] = val;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "cpu.h"
|
||||
#include "fpu/softfloat.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/helper-proto.h"
|
||||
|
||||
target_ureg cpu_hppa_get_psw(CPUHPPAState *env)
|
||||
|
@ -49,6 +50,7 @@ target_ureg cpu_hppa_get_psw(CPUHPPAState *env)
|
|||
|
||||
void cpu_hppa_put_psw(CPUHPPAState *env, target_ureg psw)
|
||||
{
|
||||
target_ureg old_psw = env->psw;
|
||||
target_ureg cb = 0;
|
||||
|
||||
env->psw = psw & ~(PSW_N | PSW_V | PSW_CB);
|
||||
|
@ -64,6 +66,14 @@ void cpu_hppa_put_psw(CPUHPPAState *env, target_ureg psw)
|
|||
cb |= ((psw >> 9) & 1) << 8;
|
||||
cb |= ((psw >> 8) & 1) << 4;
|
||||
env->psw_cb = cb;
|
||||
|
||||
/* If PSW_P changes, it affects how we translate addresses. */
|
||||
if ((psw ^ old_psw) & PSW_P) {
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
CPUState *src = CPU(hppa_env_get_cpu(env));
|
||||
tlb_flush_by_mmuidx(src, 0xf);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void hppa_cpu_dump_state(CPUState *cs, FILE *f,
|
||||
|
|
|
@ -92,4 +92,5 @@ DEF_HELPER_FLAGS_3(itlbp, TCG_CALL_NO_RWG, void, env, tl, tr)
|
|||
DEF_HELPER_FLAGS_2(ptlb, TCG_CALL_NO_RWG, void, env, tl)
|
||||
DEF_HELPER_FLAGS_1(ptlbe, TCG_CALL_NO_RWG, void, env)
|
||||
DEF_HELPER_FLAGS_2(lpa, TCG_CALL_NO_WG, tr, env, tl)
|
||||
DEF_HELPER_FLAGS_1(change_prot_id, TCG_CALL_NO_RWG, void, env)
|
||||
#endif
|
||||
|
|
|
@ -525,3 +525,6 @@ fmpy_d 001110 ..... ..... 010 ..... ... ..... @f0e_d_3
|
|||
fdiv_d 001110 ..... ..... 011 ..... ... ..... @f0e_d_3
|
||||
|
||||
xmpyu 001110 ..... ..... 010 .0111 .00 t:5 r1=%ra64 r2=%rb64
|
||||
|
||||
# diag
|
||||
diag 000101 ----- ----- ---- ---- ---- ----
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "exec/exec-all.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "qom/cpu.h"
|
||||
#include "trace.h"
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
int hppa_cpu_handle_mmu_fault(CPUState *cs, vaddr address,
|
||||
|
@ -43,9 +44,12 @@ static hppa_tlb_entry *hppa_find_tlb(CPUHPPAState *env, vaddr addr)
|
|||
for (i = 0; i < ARRAY_SIZE(env->tlb); ++i) {
|
||||
hppa_tlb_entry *ent = &env->tlb[i];
|
||||
if (ent->va_b <= addr && addr <= ent->va_e) {
|
||||
trace_hppa_tlb_find_entry(env, ent + i, ent->entry_valid,
|
||||
ent->va_b, ent->va_e, ent->pa);
|
||||
return ent;
|
||||
}
|
||||
}
|
||||
trace_hppa_tlb_find_entry_not_found(env, addr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -55,6 +59,8 @@ static void hppa_flush_tlb_ent(CPUHPPAState *env, hppa_tlb_entry *ent)
|
|||
unsigned i, n = 1 << (2 * ent->page_size);
|
||||
uint64_t addr = ent->va_b;
|
||||
|
||||
trace_hppa_tlb_flush_ent(env, ent, ent->va_b, ent->va_e, ent->pa);
|
||||
|
||||
for (i = 0; i < n; ++i, addr += TARGET_PAGE_SIZE) {
|
||||
/* Do not flush MMU_PHYS_IDX. */
|
||||
tlb_flush_page_by_mmuidx(cs, addr, 0xf);
|
||||
|
@ -96,9 +102,7 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
|
|||
if (ent == NULL || !ent->entry_valid) {
|
||||
phys = 0;
|
||||
prot = 0;
|
||||
/* ??? Unconditionally report data tlb miss,
|
||||
even if this is an instruction fetch. */
|
||||
ret = EXCP_DTLB_MISS;
|
||||
ret = (type == PAGE_EXEC) ? EXCP_ITLB_MISS : EXCP_DTLB_MISS;
|
||||
goto egress;
|
||||
}
|
||||
|
||||
|
@ -127,7 +131,20 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
|
|||
break;
|
||||
}
|
||||
|
||||
/* ??? Check PSW_P and ent->access_prot. This can remove PAGE_WRITE. */
|
||||
/* access_id == 0 means public page and no check is performed */
|
||||
if ((env->psw & PSW_P) && ent->access_id) {
|
||||
/* If bits [31:1] match, and bit 0 is set, suppress write. */
|
||||
int match = ent->access_id * 2 + 1;
|
||||
|
||||
if (match == env->cr[CR_PID1] || match == env->cr[CR_PID2] ||
|
||||
match == env->cr[CR_PID3] || match == env->cr[CR_PID4]) {
|
||||
prot &= PAGE_READ | PAGE_EXEC;
|
||||
if (type == PAGE_WRITE) {
|
||||
ret = EXCP_DMPI;
|
||||
goto egress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* No guest access type indicates a non-architectural access from
|
||||
within QEMU. Bypass checks for access, D, B and T bits. */
|
||||
|
@ -171,6 +188,7 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
|
|||
egress:
|
||||
*pphys = phys;
|
||||
*pprot = prot;
|
||||
trace_hppa_tlb_get_physical_address(env, ret, prot, addr, phys);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -200,6 +218,7 @@ void tlb_fill(CPUState *cs, target_ulong addr, int size,
|
|||
MMUAccessType type, int mmu_idx, uintptr_t retaddr)
|
||||
{
|
||||
HPPACPU *cpu = HPPA_CPU(cs);
|
||||
CPUHPPAState *env = &cpu->env;
|
||||
int prot, excp, a_prot;
|
||||
hwaddr phys;
|
||||
|
||||
|
@ -215,9 +234,10 @@ void tlb_fill(CPUState *cs, target_ulong addr, int size,
|
|||
break;
|
||||
}
|
||||
|
||||
excp = hppa_get_physical_address(&cpu->env, addr, mmu_idx,
|
||||
excp = hppa_get_physical_address(env, addr, mmu_idx,
|
||||
a_prot, &phys, &prot);
|
||||
if (unlikely(excp >= 0)) {
|
||||
trace_hppa_tlb_fill_excp(env, addr, size, type, mmu_idx);
|
||||
/* Failure. Raise the indicated exception. */
|
||||
cs->exception_index = excp;
|
||||
if (cpu->env.psw & PSW_Q) {
|
||||
|
@ -228,6 +248,8 @@ void tlb_fill(CPUState *cs, target_ulong addr, int size,
|
|||
cpu_loop_exit_restore(cs, retaddr);
|
||||
}
|
||||
|
||||
trace_hppa_tlb_fill_success(env, addr & TARGET_PAGE_MASK,
|
||||
phys & TARGET_PAGE_MASK, size, type, mmu_idx);
|
||||
/* Success! Store the translation into the QEMU TLB. */
|
||||
tlb_set_page(cs, addr & TARGET_PAGE_MASK, phys & TARGET_PAGE_MASK,
|
||||
prot, mmu_idx, TARGET_PAGE_SIZE);
|
||||
|
@ -242,11 +264,13 @@ void HELPER(itlba)(CPUHPPAState *env, target_ulong addr, target_ureg reg)
|
|||
/* Zap any old entries covering ADDR; notice empty entries on the way. */
|
||||
for (i = 0; i < ARRAY_SIZE(env->tlb); ++i) {
|
||||
hppa_tlb_entry *ent = &env->tlb[i];
|
||||
if (!ent->entry_valid) {
|
||||
empty = ent;
|
||||
} else if (ent->va_b <= addr && addr <= ent->va_e) {
|
||||
hppa_flush_tlb_ent(env, ent);
|
||||
empty = ent;
|
||||
if (ent->va_b <= addr && addr <= ent->va_e) {
|
||||
if (ent->entry_valid) {
|
||||
hppa_flush_tlb_ent(env, ent);
|
||||
}
|
||||
if (!empty) {
|
||||
empty = ent;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -259,6 +283,7 @@ void HELPER(itlba)(CPUHPPAState *env, target_ulong addr, target_ureg reg)
|
|||
empty->va_b = addr & TARGET_PAGE_MASK;
|
||||
empty->va_e = empty->va_b + TARGET_PAGE_SIZE - 1;
|
||||
empty->pa = extract32(reg, 5, 20) << TARGET_PAGE_BITS;
|
||||
trace_hppa_tlb_itlba(env, empty, empty->va_b, empty->va_e, empty->pa);
|
||||
}
|
||||
|
||||
/* Insert (Insn/Data) TLB Protection. Note this is PA 1.1 only. */
|
||||
|
@ -266,7 +291,7 @@ void HELPER(itlbp)(CPUHPPAState *env, target_ulong addr, target_ureg reg)
|
|||
{
|
||||
hppa_tlb_entry *ent = hppa_find_tlb(env, addr);
|
||||
|
||||
if (unlikely(ent == NULL || ent->entry_valid)) {
|
||||
if (unlikely(ent == NULL)) {
|
||||
qemu_log_mask(LOG_GUEST_ERROR, "ITLBP not following ITLBA\n");
|
||||
return;
|
||||
}
|
||||
|
@ -280,6 +305,8 @@ void HELPER(itlbp)(CPUHPPAState *env, target_ulong addr, target_ureg reg)
|
|||
ent->d = extract32(reg, 28, 1);
|
||||
ent->t = extract32(reg, 29, 1);
|
||||
ent->entry_valid = 1;
|
||||
trace_hppa_tlb_itlbp(env, ent, ent->access_id, ent->u, ent->ar_pl2,
|
||||
ent->ar_pl1, ent->ar_type, ent->b, ent->d, ent->t);
|
||||
}
|
||||
|
||||
/* Purge (Insn/Data) TLB. This is explicitly page-based, and is
|
||||
|
@ -299,6 +326,7 @@ void HELPER(ptlb)(CPUHPPAState *env, target_ulong addr)
|
|||
{
|
||||
CPUState *src = CPU(hppa_env_get_cpu(env));
|
||||
CPUState *cpu;
|
||||
trace_hppa_tlb_ptlb(env);
|
||||
run_on_cpu_data data = RUN_ON_CPU_TARGET_PTR(addr);
|
||||
|
||||
CPU_FOREACH(cpu) {
|
||||
|
@ -314,11 +342,24 @@ void HELPER(ptlb)(CPUHPPAState *env, target_ulong addr)
|
|||
void HELPER(ptlbe)(CPUHPPAState *env)
|
||||
{
|
||||
CPUState *src = CPU(hppa_env_get_cpu(env));
|
||||
|
||||
trace_hppa_tlb_ptlbe(env);
|
||||
memset(env->tlb, 0, sizeof(env->tlb));
|
||||
tlb_flush_by_mmuidx(src, 0xf);
|
||||
}
|
||||
|
||||
void cpu_hppa_change_prot_id(CPUHPPAState *env)
|
||||
{
|
||||
if (env->psw & PSW_P) {
|
||||
CPUState *src = CPU(hppa_env_get_cpu(env));
|
||||
tlb_flush_by_mmuidx(src, 0xf);
|
||||
}
|
||||
}
|
||||
|
||||
void HELPER(change_prot_id)(CPUHPPAState *env)
|
||||
{
|
||||
cpu_hppa_change_prot_id(env);
|
||||
}
|
||||
|
||||
target_ureg HELPER(lpa)(CPUHPPAState *env, target_ulong addr)
|
||||
{
|
||||
hwaddr phys;
|
||||
|
@ -335,8 +376,10 @@ target_ureg HELPER(lpa)(CPUHPPAState *env, target_ulong addr)
|
|||
if (excp == EXCP_DTLB_MISS) {
|
||||
excp = EXCP_NA_DTLB_MISS;
|
||||
}
|
||||
trace_hppa_tlb_lpa_failed(env, addr);
|
||||
hppa_dynamic_excp(env, excp, GETPC());
|
||||
}
|
||||
trace_hppa_tlb_lpa_success(env, addr, phys);
|
||||
return phys;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "sysemu/sysemu.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "fpu/softfloat.h"
|
||||
#include "trace.h"
|
||||
|
||||
void QEMU_NORETURN HELPER(excp)(CPUHPPAState *env, int excp)
|
||||
{
|
||||
|
@ -165,6 +166,7 @@ target_ureg HELPER(probe)(CPUHPPAState *env, target_ulong addr,
|
|||
int prot, excp;
|
||||
hwaddr phys;
|
||||
|
||||
trace_hppa_tlb_probe(addr, level, want);
|
||||
/* Fail if the requested privilege level is higher than current. */
|
||||
if (level < (env->iaoq_f & 3)) {
|
||||
return 0;
|
||||
|
@ -676,11 +678,6 @@ target_ureg HELPER(swap_system_mask)(CPUHPPAState *env, target_ureg nsm)
|
|||
|
||||
void HELPER(rfi)(CPUHPPAState *env)
|
||||
{
|
||||
/* ??? On second reading this condition simply seems
|
||||
to be undefined rather than a diagnosed trap. */
|
||||
if (env->psw & (PSW_I | PSW_R | PSW_Q)) {
|
||||
helper_excp(env, EXCP_ILL);
|
||||
}
|
||||
env->iasq_f = (uint64_t)env->cr[CR_IIASQ] << 32;
|
||||
env->iasq_b = (uint64_t)env->cr_back[0] << 32;
|
||||
env->iaoq_f = env->cr[CR_IIAOQ];
|
||||
|
|
18
target/hppa/trace-events
Normal file
18
target/hppa/trace-events
Normal file
|
@ -0,0 +1,18 @@
|
|||
# See docs/devel/tracing.txt for syntax documentation.
|
||||
|
||||
# target/hppa/mem_helper.c
|
||||
disable hppa_tlb_flush_ent(void *env, void *ent, uint64_t va_b, uint64_t va_e, uint64_t pa) "env=%p ent=%p va_b=0x%lx va_e=0x%lx pa=0x%lx"
|
||||
disable hppa_tlb_find_entry(void *env, void *ent, int valid, uint64_t va_b, uint64_t va_e, uint64_t pa) "env=%p ent=%p valid=%d va_b=0x%lx va_e=0x%lx pa=0x%lx"
|
||||
disable hppa_tlb_find_entry_not_found(void *env, uint64_t addr) "env=%p addr=%08lx"
|
||||
disable hppa_tlb_get_physical_address(void *env, int ret, int prot, uint64_t addr, uint64_t phys) "env=%p ret=%d prot=%d addr=0x%lx phys=0x%lx"
|
||||
disable hppa_tlb_fill_excp(void *env, uint64_t addr, int size, int type, int mmu_idx) "env=%p addr=0x%lx size=%d type=%d mmu_idx=%d"
|
||||
disable hppa_tlb_fill_success(void *env, uint64_t addr, uint64_t phys, int size, int type, int mmu_idx) "env=%p addr=0x%lx phys=0x%lx size=%d type=%d mmu_idx=%d"
|
||||
disable hppa_tlb_itlba(void *env, void *ent, uint64_t va_b, uint64_t va_e, uint64_t pa) "env=%p ent=%p va_b=0x%lx va_e=0x%lx pa=0x%lx"
|
||||
disable hppa_tlb_itlbp(void *env, void *ent, int access_id, int u, int pl2, int pl1, int type, int b, int d, int t) "env=%p ent=%p access_id=%x u=%d pl2=%d pl1=%d type=%d b=%d d=%d t=%d"
|
||||
disable hppa_tlb_ptlb(void *env) "env=%p"
|
||||
disable hppa_tlb_ptlbe(void *env) "env=%p"
|
||||
disable hppa_tlb_lpa_success(void *env, uint64_t addr, uint64_t phys) "env=%p addr=0x%lx phys=0x%lx"
|
||||
disable hppa_tlb_lpa_failed(void *env, uint64_t addr) "env=%p addr=0x%lx"
|
||||
|
||||
# target/hppa/op_helper.c
|
||||
disable hppa_tlb_probe(uint64_t addr, int level, int want) "addr=0x%lx level=%d want=%d"
|
|
@ -816,12 +816,10 @@ static bool gen_illegal(DisasContext *ctx)
|
|||
|
||||
static bool use_goto_tb(DisasContext *ctx, target_ureg dest)
|
||||
{
|
||||
/* Suppress goto_tb in the case of single-steping and IO. */
|
||||
if ((tb_cflags(ctx->base.tb) & CF_LAST_IO)
|
||||
|| ctx->base.singlestep_enabled) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
/* Suppress goto_tb for page crossing, IO, or single-steping. */
|
||||
return !(((ctx->base.pc_first ^ dest) & TARGET_PAGE_MASK)
|
||||
|| (tb_cflags(ctx->base.tb) & CF_LAST_IO)
|
||||
|| ctx->base.singlestep_enabled);
|
||||
}
|
||||
|
||||
/* If the next insn is to be nullified, and it's on the same page,
|
||||
|
@ -2258,6 +2256,16 @@ static bool trans_mtctl(DisasContext *ctx, arg_mtctl *a)
|
|||
offsetof(CPUHPPAState, cr_back[ctl - CR_IIASQ]));
|
||||
break;
|
||||
|
||||
case CR_PID1:
|
||||
case CR_PID2:
|
||||
case CR_PID3:
|
||||
case CR_PID4:
|
||||
tcg_gen_st_reg(reg, cpu_env, offsetof(CPUHPPAState, cr[ctl]));
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
gen_helper_change_prot_id(cpu_env);
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
tcg_gen_st_reg(reg, cpu_env, offsetof(CPUHPPAState, cr[ctl]));
|
||||
break;
|
||||
|
@ -2474,9 +2482,8 @@ static bool trans_ixtlbx(DisasContext *ctx, arg_ixtlbx *a)
|
|||
gen_helper_itlbp(cpu_env, addr, reg);
|
||||
}
|
||||
|
||||
/* Exit TB for ITLB change if mmu is enabled. This *should* not be
|
||||
the case, since the OS TLB fill handler runs with mmu disabled. */
|
||||
if (!a->data && (ctx->tb_flags & PSW_C)) {
|
||||
/* Exit TB for TLB change if mmu is enabled. */
|
||||
if (ctx->tb_flags & PSW_C) {
|
||||
ctx->base.is_jmp = DISAS_IAQ_N_STALE;
|
||||
}
|
||||
return nullify_end(ctx);
|
||||
|
@ -2503,7 +2510,7 @@ static bool trans_pxtlbx(DisasContext *ctx, arg_pxtlbx *a)
|
|||
}
|
||||
|
||||
/* Exit TB for TLB change if mmu is enabled. */
|
||||
if (!a->data && (ctx->tb_flags & PSW_C)) {
|
||||
if (ctx->tb_flags & PSW_C) {
|
||||
ctx->base.is_jmp = DISAS_IAQ_N_STALE;
|
||||
}
|
||||
return nullify_end(ctx);
|
||||
|
@ -3033,7 +3040,7 @@ static bool do_addb(DisasContext *ctx, unsigned r, TCGv_reg in1,
|
|||
DisasCond cond;
|
||||
|
||||
in2 = load_gpr(ctx, r);
|
||||
dest = dest_gpr(ctx, r);
|
||||
dest = tcg_temp_new();
|
||||
sv = NULL;
|
||||
cb_msb = NULL;
|
||||
|
||||
|
@ -3049,6 +3056,8 @@ static bool do_addb(DisasContext *ctx, unsigned r, TCGv_reg in1,
|
|||
}
|
||||
|
||||
cond = do_cond(c * 2 + f, dest, cb_msb, sv);
|
||||
save_gpr(ctx, r, dest);
|
||||
tcg_temp_free(dest);
|
||||
return do_cbranch(ctx, disp, n, &cond);
|
||||
}
|
||||
|
||||
|
@ -3446,6 +3455,8 @@ static bool trans_b_gate(DisasContext *ctx, arg_b_gate *a)
|
|||
{
|
||||
target_ureg dest = iaoq_dest(ctx, a->disp);
|
||||
|
||||
nullify_over(ctx);
|
||||
|
||||
/* Make sure the caller hasn't done something weird with the queue.
|
||||
* ??? This is not quite the same as the PSW[B] bit, which would be
|
||||
* expensive to track. Real hardware will trap for
|
||||
|
@ -3483,7 +3494,16 @@ static bool trans_b_gate(DisasContext *ctx, arg_b_gate *a)
|
|||
}
|
||||
#endif
|
||||
|
||||
return do_dbranch(ctx, dest, a->l, a->n);
|
||||
if (a->l) {
|
||||
TCGv_reg tmp = dest_gpr(ctx, a->l);
|
||||
if (ctx->privilege < 3) {
|
||||
tcg_gen_andi_reg(tmp, tmp, -4);
|
||||
}
|
||||
tcg_gen_ori_reg(tmp, tmp, ctx->privilege);
|
||||
save_gpr(ctx, a->l, tmp);
|
||||
}
|
||||
|
||||
return do_dbranch(ctx, dest, 0, a->n);
|
||||
}
|
||||
|
||||
static bool trans_blr(DisasContext *ctx, arg_blr *a)
|
||||
|
@ -4048,6 +4068,13 @@ static bool trans_fmpyfadd_d(DisasContext *ctx, arg_fmpyfadd_d *a)
|
|||
return nullify_end(ctx);
|
||||
}
|
||||
|
||||
static bool trans_diag(DisasContext *ctx, arg_diag *a)
|
||||
{
|
||||
qemu_log_mask(LOG_UNIMP, "DIAG opcode ignored\n");
|
||||
cond_free(&ctx->null_cond);
|
||||
return true;
|
||||
}
|
||||
|
||||
static void hppa_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
|
||||
{
|
||||
DisasContext *ctx = container_of(dcbase, DisasContext, base);
|
||||
|
|
Loading…
Reference in a new issue