translate.c (698240d19b0d8c880a6e8c1baeec6d6048d2ca4b) translate.c (741322f471627b829fc1ac01c16ae40cacb0c133)
1/*
2 * HPPA emulation cpu translation for qemu.
3 *
4 * Copyright (c) 2016 Richard Henderson <rth@twiddle.net>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either

--- 703 unchanged lines hidden (view full) ---

712
713static target_ureg gva_offset_mask(DisasContext *ctx)
714{
715 return (ctx->tb_flags & PSW_W
716 ? MAKE_64BIT_MASK(0, 62)
717 : MAKE_64BIT_MASK(0, 32));
718}
719
1/*
2 * HPPA emulation cpu translation for qemu.
3 *
4 * Copyright (c) 2016 Richard Henderson <rth@twiddle.net>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either

--- 703 unchanged lines hidden (view full) ---

712
713static target_ureg gva_offset_mask(DisasContext *ctx)
714{
715 return (ctx->tb_flags & PSW_W
716 ? MAKE_64BIT_MASK(0, 62)
717 : MAKE_64BIT_MASK(0, 32));
718}
719
720static void copy_iaoq_entry(TCGv_reg dest, target_ureg ival, TCGv_reg vval)
720static void copy_iaoq_entry(DisasContext *ctx, TCGv_reg dest,
721 target_ureg ival, TCGv_reg vval)
721{
722 if (unlikely(ival == -1)) {
723 tcg_gen_mov_reg(dest, vval);
724 } else {
725 tcg_gen_movi_reg(dest, ival);
726 }
727}
728

--- 4 unchanged lines hidden (view full) ---

733
734static void gen_excp_1(int exception)
735{
736 gen_helper_excp(tcg_env, tcg_constant_i32(exception));
737}
738
739static void gen_excp(DisasContext *ctx, int exception)
740{
722{
723 if (unlikely(ival == -1)) {
724 tcg_gen_mov_reg(dest, vval);
725 } else {
726 tcg_gen_movi_reg(dest, ival);
727 }
728}
729

--- 4 unchanged lines hidden (view full) ---

734
735static void gen_excp_1(int exception)
736{
737 gen_helper_excp(tcg_env, tcg_constant_i32(exception));
738}
739
740static void gen_excp(DisasContext *ctx, int exception)
741{
741 copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f);
742 copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b);
742 copy_iaoq_entry(ctx, cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f);
743 copy_iaoq_entry(ctx, cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b);
743 nullify_save(ctx);
744 gen_excp_1(exception);
745 ctx->base.is_jmp = DISAS_NORETURN;
746}
747
748static bool gen_excp_iir(DisasContext *ctx, int exc)
749{
750 nullify_over(ctx);

--- 39 unchanged lines hidden (view full) ---

790 target_ureg f, target_ureg b)
791{
792 if (f != -1 && b != -1 && use_goto_tb(ctx, f)) {
793 tcg_gen_goto_tb(which);
794 tcg_gen_movi_reg(cpu_iaoq_f, f);
795 tcg_gen_movi_reg(cpu_iaoq_b, b);
796 tcg_gen_exit_tb(ctx->base.tb, which);
797 } else {
744 nullify_save(ctx);
745 gen_excp_1(exception);
746 ctx->base.is_jmp = DISAS_NORETURN;
747}
748
749static bool gen_excp_iir(DisasContext *ctx, int exc)
750{
751 nullify_over(ctx);

--- 39 unchanged lines hidden (view full) ---

791 target_ureg f, target_ureg b)
792{
793 if (f != -1 && b != -1 && use_goto_tb(ctx, f)) {
794 tcg_gen_goto_tb(which);
795 tcg_gen_movi_reg(cpu_iaoq_f, f);
796 tcg_gen_movi_reg(cpu_iaoq_b, b);
797 tcg_gen_exit_tb(ctx->base.tb, which);
798 } else {
798 copy_iaoq_entry(cpu_iaoq_f, f, cpu_iaoq_b);
799 copy_iaoq_entry(cpu_iaoq_b, b, ctx->iaoq_n_var);
799 copy_iaoq_entry(ctx, cpu_iaoq_f, f, cpu_iaoq_b);
800 copy_iaoq_entry(ctx, cpu_iaoq_b, b, ctx->iaoq_n_var);
800 tcg_gen_lookup_and_goto_ptr();
801 }
802}
803
804static bool cond_need_sv(int c)
805{
806 return c == 2 || c == 3 || c == 6;
807}

--- 939 unchanged lines hidden (view full) ---

1747
1748/* Emit an unconditional branch to a direct target, which may or may not
1749 have already had nullification handled. */
1750static bool do_dbranch(DisasContext *ctx, target_ureg dest,
1751 unsigned link, bool is_n)
1752{
1753 if (ctx->null_cond.c == TCG_COND_NEVER && ctx->null_lab == NULL) {
1754 if (link != 0) {
801 tcg_gen_lookup_and_goto_ptr();
802 }
803}
804
805static bool cond_need_sv(int c)
806{
807 return c == 2 || c == 3 || c == 6;
808}

--- 939 unchanged lines hidden (view full) ---

1748
1749/* Emit an unconditional branch to a direct target, which may or may not
1750 have already had nullification handled. */
1751static bool do_dbranch(DisasContext *ctx, target_ureg dest,
1752 unsigned link, bool is_n)
1753{
1754 if (ctx->null_cond.c == TCG_COND_NEVER && ctx->null_lab == NULL) {
1755 if (link != 0) {
1755 copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1756 copy_iaoq_entry(ctx, cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1756 }
1757 ctx->iaoq_n = dest;
1758 if (is_n) {
1759 ctx->null_cond.c = TCG_COND_ALWAYS;
1760 }
1761 } else {
1762 nullify_over(ctx);
1763
1764 if (link != 0) {
1757 }
1758 ctx->iaoq_n = dest;
1759 if (is_n) {
1760 ctx->null_cond.c = TCG_COND_ALWAYS;
1761 }
1762 } else {
1763 nullify_over(ctx);
1764
1765 if (link != 0) {
1765 copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1766 copy_iaoq_entry(ctx, cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1766 }
1767
1768 if (is_n && use_nullify_skip(ctx)) {
1769 nullify_set(ctx, 0);
1770 gen_goto_tb(ctx, 0, dest, dest + 4);
1771 } else {
1772 nullify_set(ctx, is_n);
1773 gen_goto_tb(ctx, 0, ctx->iaoq_b, dest);

--- 81 unchanged lines hidden (view full) ---

1855{
1856 TCGv_reg a0, a1, next, tmp;
1857 TCGCond c;
1858
1859 assert(ctx->null_lab == NULL);
1860
1861 if (ctx->null_cond.c == TCG_COND_NEVER) {
1862 if (link != 0) {
1767 }
1768
1769 if (is_n && use_nullify_skip(ctx)) {
1770 nullify_set(ctx, 0);
1771 gen_goto_tb(ctx, 0, dest, dest + 4);
1772 } else {
1773 nullify_set(ctx, is_n);
1774 gen_goto_tb(ctx, 0, ctx->iaoq_b, dest);

--- 81 unchanged lines hidden (view full) ---

1856{
1857 TCGv_reg a0, a1, next, tmp;
1858 TCGCond c;
1859
1860 assert(ctx->null_lab == NULL);
1861
1862 if (ctx->null_cond.c == TCG_COND_NEVER) {
1863 if (link != 0) {
1863 copy_iaoq_entry(cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1864 copy_iaoq_entry(ctx, cpu_gr[link], ctx->iaoq_n, ctx->iaoq_n_var);
1864 }
1865 next = tcg_temp_new();
1866 tcg_gen_mov_reg(next, dest);
1867 if (is_n) {
1868 if (use_nullify_skip(ctx)) {
1869 tcg_gen_mov_reg(cpu_iaoq_f, next);
1870 tcg_gen_addi_reg(cpu_iaoq_b, next, 4);
1871 nullify_set(ctx, 0);

--- 29 unchanged lines hidden (view full) ---

1901 } else {
1902 c = ctx->null_cond.c;
1903 a0 = ctx->null_cond.a0;
1904 a1 = ctx->null_cond.a1;
1905
1906 tmp = tcg_temp_new();
1907 next = tcg_temp_new();
1908
1865 }
1866 next = tcg_temp_new();
1867 tcg_gen_mov_reg(next, dest);
1868 if (is_n) {
1869 if (use_nullify_skip(ctx)) {
1870 tcg_gen_mov_reg(cpu_iaoq_f, next);
1871 tcg_gen_addi_reg(cpu_iaoq_b, next, 4);
1872 nullify_set(ctx, 0);

--- 29 unchanged lines hidden (view full) ---

1902 } else {
1903 c = ctx->null_cond.c;
1904 a0 = ctx->null_cond.a0;
1905 a1 = ctx->null_cond.a1;
1906
1907 tmp = tcg_temp_new();
1908 next = tcg_temp_new();
1909
1909 copy_iaoq_entry(tmp, ctx->iaoq_n, ctx->iaoq_n_var);
1910 copy_iaoq_entry(ctx, tmp, ctx->iaoq_n, ctx->iaoq_n_var);
1910 tcg_gen_movcond_reg(c, next, a0, a1, tmp, dest);
1911 ctx->iaoq_n = -1;
1912 ctx->iaoq_n_var = next;
1913
1914 if (link != 0) {
1915 tcg_gen_movcond_reg(c, cpu_gr[link], a0, a1, cpu_gr[link], tmp);
1916 }
1917

--- 720 unchanged lines hidden (view full) ---

2638 * currently implemented as idle.
2639 */
2640 if ((rt == 10 || rt == 31) && r1 == rt && r2 == rt) { /* PAUSE */
2641 /* No need to check for supervisor, as userland can only pause
2642 until the next timer interrupt. */
2643 nullify_over(ctx);
2644
2645 /* Advance the instruction queue. */
1911 tcg_gen_movcond_reg(c, next, a0, a1, tmp, dest);
1912 ctx->iaoq_n = -1;
1913 ctx->iaoq_n_var = next;
1914
1915 if (link != 0) {
1916 tcg_gen_movcond_reg(c, cpu_gr[link], a0, a1, cpu_gr[link], tmp);
1917 }
1918

--- 720 unchanged lines hidden (view full) ---

2639 * currently implemented as idle.
2640 */
2641 if ((rt == 10 || rt == 31) && r1 == rt && r2 == rt) { /* PAUSE */
2642 /* No need to check for supervisor, as userland can only pause
2643 until the next timer interrupt. */
2644 nullify_over(ctx);
2645
2646 /* Advance the instruction queue. */
2646 copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
2647 copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var);
2647 copy_iaoq_entry(ctx, cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
2648 copy_iaoq_entry(ctx, cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var);
2648 nullify_set(ctx, 0);
2649
2650 /* Tell the qemu main loop to halt until this cpu has work. */
2651 tcg_gen_st_i32(tcg_constant_i32(1), tcg_env,
2652 offsetof(CPUState, halted) - offsetof(HPPACPU, env));
2653 gen_excp_1(EXCP_HALTED);
2654 ctx->base.is_jmp = DISAS_NORETURN;
2655

--- 772 unchanged lines hidden (view full) ---

3428
3429#ifdef CONFIG_USER_ONLY
3430 return do_ibranch(ctx, tmp, a->l, a->n);
3431#else
3432 TCGv_i64 new_spc = tcg_temp_new_i64();
3433
3434 load_spr(ctx, new_spc, a->sp);
3435 if (a->l) {
2649 nullify_set(ctx, 0);
2650
2651 /* Tell the qemu main loop to halt until this cpu has work. */
2652 tcg_gen_st_i32(tcg_constant_i32(1), tcg_env,
2653 offsetof(CPUState, halted) - offsetof(HPPACPU, env));
2654 gen_excp_1(EXCP_HALTED);
2655 ctx->base.is_jmp = DISAS_NORETURN;
2656

--- 772 unchanged lines hidden (view full) ---

3429
3430#ifdef CONFIG_USER_ONLY
3431 return do_ibranch(ctx, tmp, a->l, a->n);
3432#else
3433 TCGv_i64 new_spc = tcg_temp_new_i64();
3434
3435 load_spr(ctx, new_spc, a->sp);
3436 if (a->l) {
3436 copy_iaoq_entry(cpu_gr[31], ctx->iaoq_n, ctx->iaoq_n_var);
3437 copy_iaoq_entry(ctx, cpu_gr[31], ctx->iaoq_n, ctx->iaoq_n_var);
3437 tcg_gen_mov_i64(cpu_sr[0], cpu_iasq_f);
3438 }
3439 if (a->n && use_nullify_skip(ctx)) {
3440 tcg_gen_mov_reg(cpu_iaoq_f, tmp);
3441 tcg_gen_addi_reg(cpu_iaoq_b, cpu_iaoq_f, 4);
3442 tcg_gen_mov_i64(cpu_iasq_f, new_spc);
3443 tcg_gen_mov_i64(cpu_iasq_b, cpu_iasq_f);
3444 } else {
3438 tcg_gen_mov_i64(cpu_sr[0], cpu_iasq_f);
3439 }
3440 if (a->n && use_nullify_skip(ctx)) {
3441 tcg_gen_mov_reg(cpu_iaoq_f, tmp);
3442 tcg_gen_addi_reg(cpu_iaoq_b, cpu_iaoq_f, 4);
3443 tcg_gen_mov_i64(cpu_iasq_f, new_spc);
3444 tcg_gen_mov_i64(cpu_iasq_b, cpu_iasq_f);
3445 } else {
3445 copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
3446 copy_iaoq_entry(ctx, cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
3446 if (ctx->iaoq_b == -1) {
3447 tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
3448 }
3449 tcg_gen_mov_reg(cpu_iaoq_b, tmp);
3450 tcg_gen_mov_i64(cpu_iasq_b, new_spc);
3451 nullify_set(ctx, a->n);
3452 }
3453 tcg_gen_lookup_and_goto_ptr();

--- 97 unchanged lines hidden (view full) ---

3551
3552#ifdef CONFIG_USER_ONLY
3553 dest = do_ibranch_priv(ctx, load_gpr(ctx, a->b));
3554 return do_ibranch(ctx, dest, a->l, a->n);
3555#else
3556 nullify_over(ctx);
3557 dest = do_ibranch_priv(ctx, load_gpr(ctx, a->b));
3558
3447 if (ctx->iaoq_b == -1) {
3448 tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
3449 }
3450 tcg_gen_mov_reg(cpu_iaoq_b, tmp);
3451 tcg_gen_mov_i64(cpu_iasq_b, new_spc);
3452 nullify_set(ctx, a->n);
3453 }
3454 tcg_gen_lookup_and_goto_ptr();

--- 97 unchanged lines hidden (view full) ---

3552
3553#ifdef CONFIG_USER_ONLY
3554 dest = do_ibranch_priv(ctx, load_gpr(ctx, a->b));
3555 return do_ibranch(ctx, dest, a->l, a->n);
3556#else
3557 nullify_over(ctx);
3558 dest = do_ibranch_priv(ctx, load_gpr(ctx, a->b));
3559
3559 copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
3560 copy_iaoq_entry(ctx, cpu_iaoq_f, ctx->iaoq_b, cpu_iaoq_b);
3560 if (ctx->iaoq_b == -1) {
3561 tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
3562 }
3561 if (ctx->iaoq_b == -1) {
3562 tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
3563 }
3563 copy_iaoq_entry(cpu_iaoq_b, -1, dest);
3564 copy_iaoq_entry(ctx, cpu_iaoq_b, -1, dest);
3564 tcg_gen_mov_i64(cpu_iasq_b, space_select(ctx, 0, dest));
3565 if (a->l) {
3565 tcg_gen_mov_i64(cpu_iasq_b, space_select(ctx, 0, dest));
3566 if (a->l) {
3566 copy_iaoq_entry(cpu_gr[a->l], ctx->iaoq_n, ctx->iaoq_n_var);
3567 copy_iaoq_entry(ctx, cpu_gr[a->l], ctx->iaoq_n, ctx->iaoq_n_var);
3567 }
3568 nullify_set(ctx, a->n);
3569 tcg_gen_lookup_and_goto_ptr();
3570 ctx->base.is_jmp = DISAS_NORETURN;
3571 return nullify_end(ctx);
3572#endif
3573}
3574

--- 638 unchanged lines hidden (view full) ---

4213 case DISAS_IAQ_N_UPDATED:
4214 break;
4215
4216 case DISAS_NEXT:
4217 case DISAS_IAQ_N_STALE:
4218 case DISAS_IAQ_N_STALE_EXIT:
4219 if (ctx->iaoq_f == -1) {
4220 tcg_gen_mov_reg(cpu_iaoq_f, cpu_iaoq_b);
3568 }
3569 nullify_set(ctx, a->n);
3570 tcg_gen_lookup_and_goto_ptr();
3571 ctx->base.is_jmp = DISAS_NORETURN;
3572 return nullify_end(ctx);
3573#endif
3574}
3575

--- 638 unchanged lines hidden (view full) ---

4214 case DISAS_IAQ_N_UPDATED:
4215 break;
4216
4217 case DISAS_NEXT:
4218 case DISAS_IAQ_N_STALE:
4219 case DISAS_IAQ_N_STALE_EXIT:
4220 if (ctx->iaoq_f == -1) {
4221 tcg_gen_mov_reg(cpu_iaoq_f, cpu_iaoq_b);
4221 copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var);
4222 copy_iaoq_entry(ctx, cpu_iaoq_b, ctx->iaoq_n, ctx->iaoq_n_var);
4222#ifndef CONFIG_USER_ONLY
4223 tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
4224#endif
4225 nullify_save(ctx);
4226 ctx->base.is_jmp = (ret == DISAS_IAQ_N_STALE_EXIT
4227 ? DISAS_EXIT
4228 : DISAS_IAQ_N_UPDATED);
4229 } else if (ctx->iaoq_b == -1) {

--- 12 unchanged lines hidden (view full) ---

4242 DisasJumpType is_jmp = ctx->base.is_jmp;
4243
4244 switch (is_jmp) {
4245 case DISAS_NORETURN:
4246 break;
4247 case DISAS_TOO_MANY:
4248 case DISAS_IAQ_N_STALE:
4249 case DISAS_IAQ_N_STALE_EXIT:
4223#ifndef CONFIG_USER_ONLY
4224 tcg_gen_mov_i64(cpu_iasq_f, cpu_iasq_b);
4225#endif
4226 nullify_save(ctx);
4227 ctx->base.is_jmp = (ret == DISAS_IAQ_N_STALE_EXIT
4228 ? DISAS_EXIT
4229 : DISAS_IAQ_N_UPDATED);
4230 } else if (ctx->iaoq_b == -1) {

--- 12 unchanged lines hidden (view full) ---

4243 DisasJumpType is_jmp = ctx->base.is_jmp;
4244
4245 switch (is_jmp) {
4246 case DISAS_NORETURN:
4247 break;
4248 case DISAS_TOO_MANY:
4249 case DISAS_IAQ_N_STALE:
4250 case DISAS_IAQ_N_STALE_EXIT:
4250 copy_iaoq_entry(cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f);
4251 copy_iaoq_entry(cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b);
4251 copy_iaoq_entry(ctx, cpu_iaoq_f, ctx->iaoq_f, cpu_iaoq_f);
4252 copy_iaoq_entry(ctx, cpu_iaoq_b, ctx->iaoq_b, cpu_iaoq_b);
4252 nullify_save(ctx);
4253 /* FALLTHRU */
4254 case DISAS_IAQ_N_UPDATED:
4255 if (is_jmp != DISAS_IAQ_N_STALE_EXIT) {
4256 tcg_gen_lookup_and_goto_ptr();
4257 break;
4258 }
4259 /* FALLTHRU */

--- 49 unchanged lines hidden ---
4253 nullify_save(ctx);
4254 /* FALLTHRU */
4255 case DISAS_IAQ_N_UPDATED:
4256 if (is_jmp != DISAS_IAQ_N_STALE_EXIT) {
4257 tcg_gen_lookup_and_goto_ptr();
4258 break;
4259 }
4260 /* FALLTHRU */

--- 49 unchanged lines hidden ---