target/hppa: Implement B,GATE insn
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
c643603a85
commit
43e056522f
@ -354,6 +354,7 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
|
|||||||
extern const MemoryRegionOps hppa_io_eir_ops;
|
extern const MemoryRegionOps hppa_io_eir_ops;
|
||||||
extern const struct VMStateDescription vmstate_hppa_cpu;
|
extern const struct 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
|
||||||
void QEMU_NORETURN hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t ra);
|
void QEMU_NORETURN hppa_dynamic_excp(CPUHPPAState *env, int excp, uintptr_t ra);
|
||||||
|
|
||||||
|
@ -122,6 +122,7 @@ int hppa_get_physical_address(CPUHPPAState *env, vaddr addr, int mmu_idx,
|
|||||||
break;
|
break;
|
||||||
default: /* execute: promote to privilege level type & 3 */
|
default: /* execute: promote to privilege level type & 3 */
|
||||||
prot = x_prot;
|
prot = x_prot;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ??? Check PSW_P and ent->access_prot. This can remove PAGE_WRITE. */
|
/* ??? Check PSW_P and ent->access_prot. This can remove PAGE_WRITE. */
|
||||||
@ -335,4 +336,11 @@ target_ureg 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)
|
||||||
|
{
|
||||||
|
hppa_tlb_entry *ent = hppa_find_tlb(env, vaddr);
|
||||||
|
return ent ? ent->ar_type : -1;
|
||||||
|
}
|
||||||
#endif /* CONFIG_USER_ONLY */
|
#endif /* CONFIG_USER_ONLY */
|
||||||
|
@ -3782,6 +3782,53 @@ static DisasJumpType trans_bl(DisasContext *ctx, uint32_t insn,
|
|||||||
return do_dbranch(ctx, iaoq_dest(ctx, disp), link, n);
|
return do_dbranch(ctx, iaoq_dest(ctx, disp), link, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DisasJumpType trans_b_gate(DisasContext *ctx, uint32_t insn,
|
||||||
|
const DisasInsn *di)
|
||||||
|
{
|
||||||
|
unsigned n = extract32(insn, 1, 1);
|
||||||
|
unsigned link = extract32(insn, 21, 5);
|
||||||
|
target_sreg disp = assemble_17(insn);
|
||||||
|
target_ureg dest = iaoq_dest(ctx, disp);
|
||||||
|
|
||||||
|
/* 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
|
||||||
|
* b gateway
|
||||||
|
* b gateway+4 (in delay slot of first branch)
|
||||||
|
* However, checking for a non-sequential instruction queue *will*
|
||||||
|
* diagnose the security hole
|
||||||
|
* b gateway
|
||||||
|
* b evil
|
||||||
|
* in which instructions at evil would run with increased privs.
|
||||||
|
*/
|
||||||
|
if (ctx->iaoq_b == -1 || ctx->iaoq_b != ctx->iaoq_f + 4) {
|
||||||
|
return gen_illegal(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
if (ctx->tb_flags & PSW_C) {
|
||||||
|
CPUHPPAState *env = ctx->cs->env_ptr;
|
||||||
|
int type = hppa_artype_for_page(env, ctx->base.pc_next);
|
||||||
|
/* If we could not find a TLB entry, then we need to generate an
|
||||||
|
ITLB miss exception so the kernel will provide it.
|
||||||
|
The resulting TLB fill operation will invalidate this TB and
|
||||||
|
we will re-translate, at which point we *will* be able to find
|
||||||
|
the TLB entry and determine if this is in fact a gateway page. */
|
||||||
|
if (type < 0) {
|
||||||
|
return gen_excp(ctx, EXCP_ITLB_MISS);
|
||||||
|
}
|
||||||
|
/* No change for non-gateway pages or for priv decrease. */
|
||||||
|
if (type >= 4 && type - 4 < ctx->privilege) {
|
||||||
|
dest = deposit32(dest, 0, 2, type - 4);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dest &= -4; /* priv = 0 */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return do_dbranch(ctx, dest, link, n);
|
||||||
|
}
|
||||||
|
|
||||||
static DisasJumpType trans_bl_long(DisasContext *ctx, uint32_t insn,
|
static DisasJumpType trans_bl_long(DisasContext *ctx, uint32_t insn,
|
||||||
const DisasInsn *di)
|
const DisasInsn *di)
|
||||||
{
|
{
|
||||||
@ -3860,6 +3907,7 @@ static const DisasInsn table_branch[] = {
|
|||||||
{ 0xe8004000u, 0xfc00fffdu, trans_blr },
|
{ 0xe8004000u, 0xfc00fffdu, trans_blr },
|
||||||
{ 0xe800c000u, 0xfc00fffdu, trans_bv },
|
{ 0xe800c000u, 0xfc00fffdu, trans_bv },
|
||||||
{ 0xe800d000u, 0xfc00dffcu, trans_bve },
|
{ 0xe800d000u, 0xfc00dffcu, trans_bve },
|
||||||
|
{ 0xe8002000u, 0xfc00e000u, trans_b_gate },
|
||||||
};
|
};
|
||||||
|
|
||||||
static DisasJumpType trans_fop_wew_0c(DisasContext *ctx, uint32_t insn,
|
static DisasJumpType trans_fop_wew_0c(DisasContext *ctx, uint32_t insn,
|
||||||
|
Loading…
Reference in New Issue
Block a user