diff options
Diffstat (limited to 'target/loongarch/tcg/csr_helper.c')
-rw-r--r-- | target/loongarch/tcg/csr_helper.c | 35 |
1 files changed, 31 insertions, 4 deletions
diff --git a/target/loongarch/tcg/csr_helper.c b/target/loongarch/tcg/csr_helper.c index 6a7a65c..5ebe15f 100644 --- a/target/loongarch/tcg/csr_helper.c +++ b/target/loongarch/tcg/csr_helper.c @@ -13,9 +13,10 @@ #include "qemu/host-utils.h" #include "exec/helper-proto.h" #include "exec/cputlb.h" -#include "exec/cpu_ldst.h" +#include "accel/tcg/cpu-ldst.h" #include "hw/irq.h" #include "cpu-csr.h" +#include "cpu-mmu.h" target_ulong helper_csrwr_stlbps(CPULoongArchState *env, target_ulong val) { @@ -25,11 +26,16 @@ target_ulong helper_csrwr_stlbps(CPULoongArchState *env, target_ulong val) * The real hardware only supports the min tlb_ps is 12 * tlb_ps=0 may cause undefined-behavior. */ - uint8_t tlb_ps = FIELD_EX64(env->CSR_STLBPS, CSR_STLBPS, PS); + uint8_t tlb_ps = FIELD_EX64(val, CSR_STLBPS, PS); if (!check_ps(env, tlb_ps)) { qemu_log_mask(LOG_GUEST_ERROR, "Attempted set ps %d\n", tlb_ps); + } else { + /* Only update PS field, reserved bit keeps zero */ + val = FIELD_DP64(val, CSR_STLBPS, RESERVE, 0); + env->CSR_STLBPS = val; } + return old_v; } @@ -68,6 +74,27 @@ target_ulong helper_csrrd_tval(CPULoongArchState *env) return cpu_loongarch_get_constant_timer_ticks(cpu); } +target_ulong helper_csrrd_msgir(CPULoongArchState *env) +{ + int irq, new; + + irq = find_first_bit((unsigned long *)env->CSR_MSGIS, 256); + if (irq < 256) { + clear_bit(irq, (unsigned long *)env->CSR_MSGIS); + new = find_first_bit((unsigned long *)env->CSR_MSGIS, 256); + if (new < 256) { + return irq; + } + + env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, MSGINT, 0); + } else { + /* bit 31 set 1 for no invalid irq */ + irq = BIT(31); + } + + return irq; +} + target_ulong helper_csrwr_estat(CPULoongArchState *env, target_ulong val) { int64_t old_v = env->CSR_ESTAT; @@ -131,8 +158,8 @@ target_ulong helper_csrwr_pwcl(CPULoongArchState *env, target_ulong val) } if (!check_ps(env, ptbase)) { qemu_log_mask(LOG_GUEST_ERROR, - "Attrmpted set ptbase 2^%d\n", ptbase); + "Attempted set ptbase 2^%d\n", ptbase); } - env->CSR_PWCL =val; + env->CSR_PWCL = val; return old_v; } |