Loading target/hppa/insns.decode +12 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ %assemble_sr3 13:1 14:2 %sm_imm 16:10 !function=expand_sm_imm #### # System #### Loading @@ -37,3 +39,13 @@ mtsm 000000 00000 r:5 000 11000011 00000 mfia 000000 ----- 00000 --- 10100101 t:5 mfsp 000000 ----- 00000 ... 00100101 t:5 sp=%assemble_sr3 mfctl 000000 r:5 00000- e:1 -01000101 t:5 sync 000000 ----- ----- 000 00100000 00000 # sync, syncdma ldsid 000000 b:5 ----- sp:2 0 10000101 t:5 rsm 000000 .......... 000 01110011 t:5 i=%sm_imm ssm 000000 .......... 000 01101011 t:5 i=%sm_imm rfi 000000 ----- ----- --- 01100000 00000 rfi_r 000000 ----- ----- --- 01100101 00000 target/hppa/translate.c +44 −55 Original line number Diff line number Diff line Loading @@ -278,6 +278,18 @@ typedef struct DisasContext { bool psw_n_nonzero; } DisasContext; /* Note that ssm/rsm instructions number PSW_W and PSW_E differently. */ static int expand_sm_imm(int val) { if (val & PSW_SM_E) { val = (val & ~PSW_SM_E) | PSW_E; } if (val & PSW_SM_W) { val = (val & ~PSW_SM_W) | PSW_W; } return val; } /* Include the auto-generated decoder. */ #include "decode.inc.c" Loading Loading @@ -1996,7 +2008,7 @@ static bool trans_break(DisasContext *ctx, arg_break *a) return gen_excp_iir(ctx, EXCP_BREAK); } static bool trans_sync(DisasContext *ctx, uint32_t insn, const DisasInsn *di) static bool trans_sync(DisasContext *ctx, arg_sync *a) { /* No point in nullifying the memory barrier. */ tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL); Loading Loading @@ -2178,86 +2190,67 @@ static bool trans_mtsarcm(DisasContext *ctx, arg_mtsarcm *a) return true; } static bool trans_ldsid(DisasContext *ctx, uint32_t insn, const DisasInsn *di) static bool trans_ldsid(DisasContext *ctx, arg_ldsid *a) { unsigned rt = extract32(insn, 0, 5); TCGv_reg dest = dest_gpr(ctx, rt); TCGv_reg dest = dest_gpr(ctx, a->t); #ifdef CONFIG_USER_ONLY /* We don't implement space registers in user mode. */ tcg_gen_movi_reg(dest, 0); #else unsigned rb = extract32(insn, 21, 5); unsigned sp = extract32(insn, 14, 2); TCGv_i64 t0 = tcg_temp_new_i64(); tcg_gen_mov_i64(t0, space_select(ctx, sp, load_gpr(ctx, rb))); tcg_gen_mov_i64(t0, space_select(ctx, a->sp, load_gpr(ctx, a->b))); tcg_gen_shri_i64(t0, t0, 32); tcg_gen_trunc_i64_reg(dest, t0); tcg_temp_free_i64(t0); #endif save_gpr(ctx, rt, dest); save_gpr(ctx, a->t, dest); cond_free(&ctx->null_cond); return true; } #ifndef CONFIG_USER_ONLY /* Note that ssm/rsm instructions number PSW_W and PSW_E differently. */ static target_ureg extract_sm_imm(uint32_t insn) { target_ureg val = extract32(insn, 16, 10); if (val & PSW_SM_E) { val = (val & ~PSW_SM_E) | PSW_E; } if (val & PSW_SM_W) { val = (val & ~PSW_SM_W) | PSW_W; } return val; } static bool trans_rsm(DisasContext *ctx, uint32_t insn, const DisasInsn *di) static bool trans_rsm(DisasContext *ctx, arg_rsm *a) { unsigned rt = extract32(insn, 0, 5); target_ureg sm = extract_sm_imm(insn); CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); #ifndef CONFIG_USER_ONLY TCGv_reg tmp; CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); nullify_over(ctx); tmp = get_temp(ctx); tcg_gen_ld_reg(tmp, cpu_env, offsetof(CPUHPPAState, psw)); tcg_gen_andi_reg(tmp, tmp, ~sm); tcg_gen_andi_reg(tmp, tmp, ~a->i); gen_helper_swap_system_mask(tmp, cpu_env, tmp); save_gpr(ctx, rt, tmp); save_gpr(ctx, a->t, tmp); /* Exit the TB to recognize new interrupts, e.g. PSW_M. */ ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT; return nullify_end(ctx); #endif } static bool trans_ssm(DisasContext *ctx, uint32_t insn, const DisasInsn *di) static bool trans_ssm(DisasContext *ctx, arg_ssm *a) { unsigned rt = extract32(insn, 0, 5); target_ureg sm = extract_sm_imm(insn); CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); #ifndef CONFIG_USER_ONLY TCGv_reg tmp; CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); nullify_over(ctx); tmp = get_temp(ctx); tcg_gen_ld_reg(tmp, cpu_env, offsetof(CPUHPPAState, psw)); tcg_gen_ori_reg(tmp, tmp, sm); tcg_gen_ori_reg(tmp, tmp, a->i); gen_helper_swap_system_mask(tmp, cpu_env, tmp); save_gpr(ctx, rt, tmp); save_gpr(ctx, a->t, tmp); /* Exit the TB to recognize new interrupts, e.g. PSW_I. */ ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT; return nullify_end(ctx); #endif } #endif /* !CONFIG_USER_ONLY */ static bool trans_mtsm(DisasContext *ctx, arg_mtsm *a) { Loading @@ -2276,15 +2269,13 @@ static bool trans_mtsm(DisasContext *ctx, arg_mtsm *a) #endif } #ifndef CONFIG_USER_ONLY static bool trans_rfi(DisasContext *ctx, uint32_t insn, const DisasInsn *di) static bool do_rfi(DisasContext *ctx, bool rfi_r) { unsigned comp = extract32(insn, 5, 4); CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); #ifndef CONFIG_USER_ONLY nullify_over(ctx); if (comp == 5) { if (rfi_r) { gen_helper_rfi_r(cpu_env); } else { gen_helper_rfi(cpu_env); Loading @@ -2298,8 +2289,20 @@ static bool trans_rfi(DisasContext *ctx, uint32_t insn, const DisasInsn *di) ctx->base.is_jmp = DISAS_NORETURN; return nullify_end(ctx); #endif } static bool trans_rfi(DisasContext *ctx, arg_rfi *a) { return do_rfi(ctx, false); } static bool trans_rfi_r(DisasContext *ctx, arg_rfi_r *a) { return do_rfi(ctx, true); } #ifndef CONFIG_USER_ONLY static bool gen_hlt(DisasContext *ctx, int reset) { CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); Loading @@ -2314,17 +2317,6 @@ static bool gen_hlt(DisasContext *ctx, int reset) } #endif /* !CONFIG_USER_ONLY */ static const DisasInsn table_system[] = { { 0x00000400u, 0xffffffffu, trans_sync }, /* sync */ { 0x00100400u, 0xffffffffu, trans_sync }, /* syncdma */ { 0x000010a0u, 0xfc1f3fe0u, trans_ldsid }, #ifndef CONFIG_USER_ONLY { 0x00000e60u, 0xfc00ffe0u, trans_rsm }, { 0x00000d60u, 0xfc00ffe0u, trans_ssm }, { 0x00000c00u, 0xfffffe1fu, trans_rfi }, #endif }; static bool trans_base_idx_mod(DisasContext *ctx, uint32_t insn, const DisasInsn *di) { Loading Loading @@ -4542,9 +4534,6 @@ static void translate_one(DisasContext *ctx, uint32_t insn) opc = extract32(insn, 26, 6); switch (opc) { case 0x00: /* system op */ translate_table(ctx, insn, table_system); return; case 0x01: translate_table(ctx, insn, table_mem_mgmt); return; Loading Loading
target/hppa/insns.decode +12 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,8 @@ %assemble_sr3 13:1 14:2 %sm_imm 16:10 !function=expand_sm_imm #### # System #### Loading @@ -37,3 +39,13 @@ mtsm 000000 00000 r:5 000 11000011 00000 mfia 000000 ----- 00000 --- 10100101 t:5 mfsp 000000 ----- 00000 ... 00100101 t:5 sp=%assemble_sr3 mfctl 000000 r:5 00000- e:1 -01000101 t:5 sync 000000 ----- ----- 000 00100000 00000 # sync, syncdma ldsid 000000 b:5 ----- sp:2 0 10000101 t:5 rsm 000000 .......... 000 01110011 t:5 i=%sm_imm ssm 000000 .......... 000 01101011 t:5 i=%sm_imm rfi 000000 ----- ----- --- 01100000 00000 rfi_r 000000 ----- ----- --- 01100101 00000
target/hppa/translate.c +44 −55 Original line number Diff line number Diff line Loading @@ -278,6 +278,18 @@ typedef struct DisasContext { bool psw_n_nonzero; } DisasContext; /* Note that ssm/rsm instructions number PSW_W and PSW_E differently. */ static int expand_sm_imm(int val) { if (val & PSW_SM_E) { val = (val & ~PSW_SM_E) | PSW_E; } if (val & PSW_SM_W) { val = (val & ~PSW_SM_W) | PSW_W; } return val; } /* Include the auto-generated decoder. */ #include "decode.inc.c" Loading Loading @@ -1996,7 +2008,7 @@ static bool trans_break(DisasContext *ctx, arg_break *a) return gen_excp_iir(ctx, EXCP_BREAK); } static bool trans_sync(DisasContext *ctx, uint32_t insn, const DisasInsn *di) static bool trans_sync(DisasContext *ctx, arg_sync *a) { /* No point in nullifying the memory barrier. */ tcg_gen_mb(TCG_BAR_SC | TCG_MO_ALL); Loading Loading @@ -2178,86 +2190,67 @@ static bool trans_mtsarcm(DisasContext *ctx, arg_mtsarcm *a) return true; } static bool trans_ldsid(DisasContext *ctx, uint32_t insn, const DisasInsn *di) static bool trans_ldsid(DisasContext *ctx, arg_ldsid *a) { unsigned rt = extract32(insn, 0, 5); TCGv_reg dest = dest_gpr(ctx, rt); TCGv_reg dest = dest_gpr(ctx, a->t); #ifdef CONFIG_USER_ONLY /* We don't implement space registers in user mode. */ tcg_gen_movi_reg(dest, 0); #else unsigned rb = extract32(insn, 21, 5); unsigned sp = extract32(insn, 14, 2); TCGv_i64 t0 = tcg_temp_new_i64(); tcg_gen_mov_i64(t0, space_select(ctx, sp, load_gpr(ctx, rb))); tcg_gen_mov_i64(t0, space_select(ctx, a->sp, load_gpr(ctx, a->b))); tcg_gen_shri_i64(t0, t0, 32); tcg_gen_trunc_i64_reg(dest, t0); tcg_temp_free_i64(t0); #endif save_gpr(ctx, rt, dest); save_gpr(ctx, a->t, dest); cond_free(&ctx->null_cond); return true; } #ifndef CONFIG_USER_ONLY /* Note that ssm/rsm instructions number PSW_W and PSW_E differently. */ static target_ureg extract_sm_imm(uint32_t insn) { target_ureg val = extract32(insn, 16, 10); if (val & PSW_SM_E) { val = (val & ~PSW_SM_E) | PSW_E; } if (val & PSW_SM_W) { val = (val & ~PSW_SM_W) | PSW_W; } return val; } static bool trans_rsm(DisasContext *ctx, uint32_t insn, const DisasInsn *di) static bool trans_rsm(DisasContext *ctx, arg_rsm *a) { unsigned rt = extract32(insn, 0, 5); target_ureg sm = extract_sm_imm(insn); CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); #ifndef CONFIG_USER_ONLY TCGv_reg tmp; CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); nullify_over(ctx); tmp = get_temp(ctx); tcg_gen_ld_reg(tmp, cpu_env, offsetof(CPUHPPAState, psw)); tcg_gen_andi_reg(tmp, tmp, ~sm); tcg_gen_andi_reg(tmp, tmp, ~a->i); gen_helper_swap_system_mask(tmp, cpu_env, tmp); save_gpr(ctx, rt, tmp); save_gpr(ctx, a->t, tmp); /* Exit the TB to recognize new interrupts, e.g. PSW_M. */ ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT; return nullify_end(ctx); #endif } static bool trans_ssm(DisasContext *ctx, uint32_t insn, const DisasInsn *di) static bool trans_ssm(DisasContext *ctx, arg_ssm *a) { unsigned rt = extract32(insn, 0, 5); target_ureg sm = extract_sm_imm(insn); CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); #ifndef CONFIG_USER_ONLY TCGv_reg tmp; CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); nullify_over(ctx); tmp = get_temp(ctx); tcg_gen_ld_reg(tmp, cpu_env, offsetof(CPUHPPAState, psw)); tcg_gen_ori_reg(tmp, tmp, sm); tcg_gen_ori_reg(tmp, tmp, a->i); gen_helper_swap_system_mask(tmp, cpu_env, tmp); save_gpr(ctx, rt, tmp); save_gpr(ctx, a->t, tmp); /* Exit the TB to recognize new interrupts, e.g. PSW_I. */ ctx->base.is_jmp = DISAS_IAQ_N_STALE_EXIT; return nullify_end(ctx); #endif } #endif /* !CONFIG_USER_ONLY */ static bool trans_mtsm(DisasContext *ctx, arg_mtsm *a) { Loading @@ -2276,15 +2269,13 @@ static bool trans_mtsm(DisasContext *ctx, arg_mtsm *a) #endif } #ifndef CONFIG_USER_ONLY static bool trans_rfi(DisasContext *ctx, uint32_t insn, const DisasInsn *di) static bool do_rfi(DisasContext *ctx, bool rfi_r) { unsigned comp = extract32(insn, 5, 4); CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); #ifndef CONFIG_USER_ONLY nullify_over(ctx); if (comp == 5) { if (rfi_r) { gen_helper_rfi_r(cpu_env); } else { gen_helper_rfi(cpu_env); Loading @@ -2298,8 +2289,20 @@ static bool trans_rfi(DisasContext *ctx, uint32_t insn, const DisasInsn *di) ctx->base.is_jmp = DISAS_NORETURN; return nullify_end(ctx); #endif } static bool trans_rfi(DisasContext *ctx, arg_rfi *a) { return do_rfi(ctx, false); } static bool trans_rfi_r(DisasContext *ctx, arg_rfi_r *a) { return do_rfi(ctx, true); } #ifndef CONFIG_USER_ONLY static bool gen_hlt(DisasContext *ctx, int reset) { CHECK_MOST_PRIVILEGED(EXCP_PRIV_OPR); Loading @@ -2314,17 +2317,6 @@ static bool gen_hlt(DisasContext *ctx, int reset) } #endif /* !CONFIG_USER_ONLY */ static const DisasInsn table_system[] = { { 0x00000400u, 0xffffffffu, trans_sync }, /* sync */ { 0x00100400u, 0xffffffffu, trans_sync }, /* syncdma */ { 0x000010a0u, 0xfc1f3fe0u, trans_ldsid }, #ifndef CONFIG_USER_ONLY { 0x00000e60u, 0xfc00ffe0u, trans_rsm }, { 0x00000d60u, 0xfc00ffe0u, trans_ssm }, { 0x00000c00u, 0xfffffe1fu, trans_rfi }, #endif }; static bool trans_base_idx_mod(DisasContext *ctx, uint32_t insn, const DisasInsn *di) { Loading Loading @@ -4542,9 +4534,6 @@ static void translate_one(DisasContext *ctx, uint32_t insn) opc = extract32(insn, 26, 6); switch (opc) { case 0x00: /* system op */ translate_table(ctx, insn, table_system); return; case 0x01: translate_table(ctx, insn, table_mem_mgmt); return; Loading