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 --- |