Loading target/hppa/helper.h +3 −0 Original line number Diff line number Diff line Loading @@ -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) target/hppa/op_helper.c +10 −0 Original line number Diff line number Diff line Loading @@ -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; Loading target/hppa/translate.c +206 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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 Loading
target/hppa/helper.h +3 −0 Original line number Diff line number Diff line Loading @@ -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)
target/hppa/op_helper.c +10 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
target/hppa/translate.c +206 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading Loading @@ -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