target-hppa: Implement system and memory-management insns
Signed-off-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
parent
96d6407f36
commit
98a9cb792c
@ -5,4 +5,7 @@ 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_e, TCG_CALL_NO_WG, void, env, tl, tl)
|
||||
|
||||
DEF_HELPER_FLAGS_1(probe_r, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
DEF_HELPER_FLAGS_1(probe_w, TCG_CALL_NO_RWG_SE, tl, tl)
|
||||
|
||||
DEF_HELPER_FLAGS_1(loaded_fr0, TCG_CALL_NO_RWG, void, env)
|
||||
|
@ -132,6 +132,16 @@ void HELPER(stby_e)(CPUHPPAState *env, target_ulong addr, target_ulong val)
|
||||
}
|
||||
}
|
||||
|
||||
target_ulong HELPER(probe_r)(target_ulong addr)
|
||||
{
|
||||
return page_check_range(addr, 1, PAGE_READ);
|
||||
}
|
||||
|
||||
target_ulong HELPER(probe_w)(target_ulong addr)
|
||||
{
|
||||
return page_check_range(addr, 1, PAGE_WRITE);
|
||||
}
|
||||
|
||||
void HELPER(loaded_fr0)(CPUHPPAState *env)
|
||||
{
|
||||
uint32_t shadow = env->fr[0] >> 32;
|
||||
|
@ -1465,6 +1465,208 @@ static ExitStatus trans_nop(DisasContext *ctx, uint32_t insn,
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus trans_break(DisasContext *ctx, uint32_t insn,
|
||||
const DisasInsn *di)
|
||||
{
|
||||
nullify_over(ctx);
|
||||
return nullify_end(ctx, gen_excp(ctx, EXCP_DEBUG));
|
||||
}
|
||||
|
||||
static ExitStatus trans_sync(DisasContext *ctx, uint32_t insn,
|
||||
const DisasInsn *di)
|
||||
{
|
||||
/* No point in nullifying the memory barrier. */
|
||||
tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL);
|
||||
|
||||
cond_free(&ctx->null_cond);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus trans_mfia(DisasContext *ctx, uint32_t insn,
|
||||
const DisasInsn *di)
|
||||
{
|
||||
unsigned rt = extract32(insn, 0, 5);
|
||||
TCGv tmp = dest_gpr(ctx, rt);
|
||||
tcg_gen_movi_tl(tmp, ctx->iaoq_f);
|
||||
save_gpr(ctx, rt, tmp);
|
||||
|
||||
cond_free(&ctx->null_cond);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus trans_mfsp(DisasContext *ctx, uint32_t insn,
|
||||
const DisasInsn *di)
|
||||
{
|
||||
unsigned rt = extract32(insn, 0, 5);
|
||||
TCGv tmp = dest_gpr(ctx, rt);
|
||||
|
||||
/* ??? We don't implement space registers. */
|
||||
tcg_gen_movi_tl(tmp, 0);
|
||||
save_gpr(ctx, rt, tmp);
|
||||
|
||||
cond_free(&ctx->null_cond);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus trans_mfctl(DisasContext *ctx, uint32_t insn,
|
||||
const DisasInsn *di)
|
||||
{
|
||||
unsigned rt = extract32(insn, 0, 5);
|
||||
unsigned ctl = extract32(insn, 21, 5);
|
||||
TCGv tmp;
|
||||
|
||||
switch (ctl) {
|
||||
case 11: /* SAR */
|
||||
#ifdef TARGET_HPPA64
|
||||
if (extract32(insn, 14, 1) == 0) {
|
||||
/* MFSAR without ,W masks low 5 bits. */
|
||||
tmp = dest_gpr(ctx, rt);
|
||||
tcg_gen_andi_tl(tmp, cpu_sar, 31);
|
||||
save_gpr(ctx, rt, tmp);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
save_gpr(ctx, rt, cpu_sar);
|
||||
break;
|
||||
case 16: /* Interval Timer */
|
||||
tmp = dest_gpr(ctx, rt);
|
||||
tcg_gen_movi_tl(tmp, 0); /* FIXME */
|
||||
save_gpr(ctx, rt, tmp);
|
||||
break;
|
||||
case 26:
|
||||
save_gpr(ctx, rt, cpu_cr26);
|
||||
break;
|
||||
case 27:
|
||||
save_gpr(ctx, rt, cpu_cr27);
|
||||
break;
|
||||
default:
|
||||
/* All other control registers are privileged. */
|
||||
return gen_illegal(ctx);
|
||||
}
|
||||
|
||||
cond_free(&ctx->null_cond);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus trans_mtctl(DisasContext *ctx, uint32_t insn,
|
||||
const DisasInsn *di)
|
||||
{
|
||||
unsigned rin = extract32(insn, 16, 5);
|
||||
unsigned ctl = extract32(insn, 21, 5);
|
||||
TCGv tmp;
|
||||
|
||||
if (ctl == 11) { /* SAR */
|
||||
tmp = tcg_temp_new();
|
||||
tcg_gen_andi_tl(tmp, load_gpr(ctx, rin), TARGET_LONG_BITS - 1);
|
||||
save_or_nullify(ctx, cpu_sar, tmp);
|
||||
tcg_temp_free(tmp);
|
||||
} else {
|
||||
/* All other control registers are privileged or read-only. */
|
||||
return gen_illegal(ctx);
|
||||
}
|
||||
|
||||
cond_free(&ctx->null_cond);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus trans_mtsarcm(DisasContext *ctx, uint32_t insn,
|
||||
const DisasInsn *di)
|
||||
{
|
||||
unsigned rin = extract32(insn, 16, 5);
|
||||
TCGv tmp = tcg_temp_new();
|
||||
|
||||
tcg_gen_not_tl(tmp, load_gpr(ctx, rin));
|
||||
tcg_gen_andi_tl(tmp, tmp, TARGET_LONG_BITS - 1);
|
||||
save_or_nullify(ctx, cpu_sar, tmp);
|
||||
tcg_temp_free(tmp);
|
||||
|
||||
cond_free(&ctx->null_cond);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus trans_ldsid(DisasContext *ctx, uint32_t insn,
|
||||
const DisasInsn *di)
|
||||
{
|
||||
unsigned rt = extract32(insn, 0, 5);
|
||||
TCGv dest = dest_gpr(ctx, rt);
|
||||
|
||||
/* Since we don't implement space registers, this returns zero. */
|
||||
tcg_gen_movi_tl(dest, 0);
|
||||
save_gpr(ctx, rt, dest);
|
||||
|
||||
cond_free(&ctx->null_cond);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static const DisasInsn table_system[] = {
|
||||
{ 0x00000000u, 0xfc001fe0u, trans_break },
|
||||
/* We don't implement space register, so MTSP is a nop. */
|
||||
{ 0x00001820u, 0xffe01fffu, trans_nop },
|
||||
{ 0x00001840u, 0xfc00ffffu, trans_mtctl },
|
||||
{ 0x016018c0u, 0xffe0ffffu, trans_mtsarcm },
|
||||
{ 0x000014a0u, 0xffffffe0u, trans_mfia },
|
||||
{ 0x000004a0u, 0xffff1fe0u, trans_mfsp },
|
||||
{ 0x000008a0u, 0xfc1fffe0u, trans_mfctl },
|
||||
{ 0x00000400u, 0xffffffffu, trans_sync },
|
||||
{ 0x000010a0u, 0xfc1f3fe0u, trans_ldsid },
|
||||
};
|
||||
|
||||
static ExitStatus trans_base_idx_mod(DisasContext *ctx, uint32_t insn,
|
||||
const DisasInsn *di)
|
||||
{
|
||||
unsigned rb = extract32(insn, 21, 5);
|
||||
unsigned rx = extract32(insn, 16, 5);
|
||||
TCGv dest = dest_gpr(ctx, rb);
|
||||
TCGv src1 = load_gpr(ctx, rb);
|
||||
TCGv src2 = load_gpr(ctx, rx);
|
||||
|
||||
/* The only thing we need to do is the base register modification. */
|
||||
tcg_gen_add_tl(dest, src1, src2);
|
||||
save_gpr(ctx, rb, dest);
|
||||
|
||||
cond_free(&ctx->null_cond);
|
||||
return NO_EXIT;
|
||||
}
|
||||
|
||||
static ExitStatus trans_probe(DisasContext *ctx, uint32_t insn,
|
||||
const DisasInsn *di)
|
||||
{
|
||||
unsigned rt = extract32(insn, 0, 5);
|
||||
unsigned rb = extract32(insn, 21, 5);
|
||||
unsigned is_write = extract32(insn, 6, 1);
|
||||
TCGv dest;
|
||||
|
||||
nullify_over(ctx);
|
||||
|
||||
/* ??? Do something with priv level operand. */
|
||||
dest = dest_gpr(ctx, rt);
|
||||
if (is_write) {
|
||||
gen_helper_probe_w(dest, load_gpr(ctx, rb));
|
||||
} else {
|
||||
gen_helper_probe_r(dest, load_gpr(ctx, rb));
|
||||
}
|
||||
save_gpr(ctx, rt, dest);
|
||||
return nullify_end(ctx, NO_EXIT);
|
||||
}
|
||||
|
||||
static const DisasInsn table_mem_mgmt[] = {
|
||||
{ 0x04003280u, 0xfc003fffu, trans_nop }, /* fdc, disp */
|
||||
{ 0x04001280u, 0xfc003fffu, trans_nop }, /* fdc, index */
|
||||
{ 0x040012a0u, 0xfc003fffu, trans_base_idx_mod }, /* fdc, index, base mod */
|
||||
{ 0x040012c0u, 0xfc003fffu, trans_nop }, /* fdce */
|
||||
{ 0x040012e0u, 0xfc003fffu, trans_base_idx_mod }, /* fdce, base mod */
|
||||
{ 0x04000280u, 0xfc001fffu, trans_nop }, /* fic 0a */
|
||||
{ 0x040002a0u, 0xfc001fffu, trans_base_idx_mod }, /* fic 0a, base mod */
|
||||
{ 0x040013c0u, 0xfc003fffu, trans_nop }, /* fic 4f */
|
||||
{ 0x040013e0u, 0xfc003fffu, trans_base_idx_mod }, /* fic 4f, base mod */
|
||||
{ 0x040002c0u, 0xfc001fffu, trans_nop }, /* fice */
|
||||
{ 0x040002e0u, 0xfc001fffu, trans_base_idx_mod }, /* fice, base mod */
|
||||
{ 0x04002700u, 0xfc003fffu, trans_nop }, /* pdc */
|
||||
{ 0x04002720u, 0xfc003fffu, trans_base_idx_mod }, /* pdc, base mod */
|
||||
{ 0x04001180u, 0xfc003fa0u, trans_probe }, /* probe */
|
||||
{ 0x04003180u, 0xfc003fa0u, trans_probe }, /* probei */
|
||||
};
|
||||
|
||||
static ExitStatus trans_add(DisasContext *ctx, uint32_t insn,
|
||||
const DisasInsn *di)
|
||||
{
|
||||
@ -2711,6 +2913,10 @@ static ExitStatus translate_one(DisasContext *ctx, uint32_t insn)
|
||||
uint32_t opc = extract32(insn, 26, 6);
|
||||
|
||||
switch (opc) {
|
||||
case 0x00: /* system op */
|
||||
return translate_table(ctx, insn, table_system);
|
||||
case 0x01:
|
||||
return translate_table(ctx, insn, table_mem_mgmt);
|
||||
case 0x02:
|
||||
return translate_table(ctx, insn, table_arith_log);
|
||||
case 0x03:
|
||||
|
Loading…
Reference in New Issue
Block a user