diff options
Diffstat (limited to 'target/mips')
-rw-r--r-- | target/mips/tcg/mxu_translate.c | 36 | ||||
-rw-r--r-- | target/mips/tcg/sysemu/tlb_helper.c | 48 |
2 files changed, 49 insertions, 35 deletions
diff --git a/target/mips/tcg/mxu_translate.c b/target/mips/tcg/mxu_translate.c index deb8060..e662acd 100644 --- a/target/mips/tcg/mxu_translate.c +++ b/target/mips/tcg/mxu_translate.c @@ -609,7 +609,7 @@ enum { static TCGv mxu_gpr[NUMBER_OF_MXU_REGISTERS - 1]; static TCGv mxu_CR; -static const char mxuregnames[][4] = { +static const char mxuregnames[NUMBER_OF_MXU_REGISTERS][4] = { "XR1", "XR2", "XR3", "XR4", "XR5", "XR6", "XR7", "XR8", "XR9", "XR10", "XR11", "XR12", "XR13", "XR14", "XR15", "XCR", }; @@ -644,6 +644,16 @@ static inline void gen_store_mxu_gpr(TCGv t, unsigned int reg) } } +static inline void gen_extract_mxu_gpr(TCGv t, unsigned int reg, + unsigned int ofs, unsigned int len) +{ + if (reg == 0) { + tcg_gen_movi_tl(t, 0); + } else if (reg <= 15) { + tcg_gen_extract_tl(t, mxu_gpr[reg - 1], ofs, len); + } +} + /* MXU control register moves. */ static inline void gen_load_mxu_cr(TCGv t) { @@ -2434,8 +2444,12 @@ static void gen_mxu_S32SLT(DisasContext *ctx) tcg_gen_movi_tl(mxu_gpr[XRa - 1], 0); } else { /* the most general case */ - tcg_gen_setcond_tl(TCG_COND_LT, mxu_gpr[XRa - 1], - mxu_gpr[XRb - 1], mxu_gpr[XRc - 1]); + TCGv t0 = tcg_temp_new(); + TCGv t1 = tcg_temp_new(); + + gen_load_mxu_gpr(t0, XRb); + gen_load_mxu_gpr(t1, XRc); + tcg_gen_setcond_tl(TCG_COND_LT, mxu_gpr[XRa - 1], t0, t1); } } @@ -3000,10 +3014,10 @@ static void gen_mxu_q8adde(DisasContext *ctx, bool accumulate) TCGv t5 = tcg_temp_new(); if (XRa != 0) { - tcg_gen_extract_tl(t0, mxu_gpr[XRb - 1], 16, 8); - tcg_gen_extract_tl(t1, mxu_gpr[XRc - 1], 16, 8); - tcg_gen_extract_tl(t2, mxu_gpr[XRb - 1], 24, 8); - tcg_gen_extract_tl(t3, mxu_gpr[XRc - 1], 24, 8); + gen_extract_mxu_gpr(t0, XRb, 16, 8); + gen_extract_mxu_gpr(t1, XRc, 16, 8); + gen_extract_mxu_gpr(t2, XRb, 24, 8); + gen_extract_mxu_gpr(t3, XRc, 24, 8); if (aptn2 & 2) { tcg_gen_sub_tl(t0, t0, t1); tcg_gen_sub_tl(t2, t2, t3); @@ -3023,10 +3037,10 @@ static void gen_mxu_q8adde(DisasContext *ctx, bool accumulate) tcg_gen_or_tl(t4, t2, t0); } if (XRd != 0) { - tcg_gen_extract_tl(t0, mxu_gpr[XRb - 1], 0, 8); - tcg_gen_extract_tl(t1, mxu_gpr[XRc - 1], 0, 8); - tcg_gen_extract_tl(t2, mxu_gpr[XRb - 1], 8, 8); - tcg_gen_extract_tl(t3, mxu_gpr[XRc - 1], 8, 8); + gen_extract_mxu_gpr(t0, XRb, 0, 8); + gen_extract_mxu_gpr(t1, XRc, 0, 8); + gen_extract_mxu_gpr(t2, XRb, 8, 8); + gen_extract_mxu_gpr(t3, XRc, 8, 8); if (aptn2 & 1) { tcg_gen_sub_tl(t0, t0, t1); tcg_gen_sub_tl(t2, t2, t3); diff --git a/target/mips/tcg/sysemu/tlb_helper.c b/target/mips/tcg/sysemu/tlb_helper.c index e5e1e9d..7dbc2e2 100644 --- a/target/mips/tcg/sysemu/tlb_helper.c +++ b/target/mips/tcg/sysemu/tlb_helper.c @@ -623,18 +623,13 @@ static uint64_t get_tlb_entry_layout(CPUMIPSState *env, uint64_t entry, static int walk_directory(CPUMIPSState *env, uint64_t *vaddr, int directory_index, bool *huge_page, bool *hgpg_directory_hit, - uint64_t *pw_entrylo0, uint64_t *pw_entrylo1) + uint64_t *pw_entrylo0, uint64_t *pw_entrylo1, + unsigned directory_shift, unsigned leaf_shift) { int dph = (env->CP0_PWCtl >> CP0PC_DPH) & 0x1; int psn = (env->CP0_PWCtl >> CP0PC_PSN) & 0x3F; int hugepg = (env->CP0_PWCtl >> CP0PC_HUGEPG) & 0x1; int pf_ptew = (env->CP0_PWField >> CP0PF_PTEW) & 0x3F; - int ptew = (env->CP0_PWSize >> CP0PS_PTEW) & 0x3F; - int native_shift = (((env->CP0_PWSize >> CP0PS_PS) & 1) == 0) ? 2 : 3; - int directory_shift = (ptew > 1) ? -1 : - (hugepg && (ptew == 1)) ? native_shift + 1 : native_shift; - int leaf_shift = (ptew > 1) ? -1 : - (ptew == 1) ? native_shift + 1 : native_shift; uint32_t direntry_size = 1 << (directory_shift + 3); uint32_t leafentry_size = 1 << (leaf_shift + 3); uint64_t entry; @@ -735,21 +730,11 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr address, /* Other HTW configs */ int hugepg = (env->CP0_PWCtl >> CP0PC_HUGEPG) & 0x1; - - /* HTW Shift values (depend on entry size) */ - int directory_shift = (ptew > 1) ? -1 : - (hugepg && (ptew == 1)) ? native_shift + 1 : native_shift; - int leaf_shift = (ptew > 1) ? -1 : - (ptew == 1) ? native_shift + 1 : native_shift; + unsigned directory_shift, leaf_shift; /* Offsets into tables */ - int goffset = gindex << directory_shift; - int uoffset = uindex << directory_shift; - int moffset = mindex << directory_shift; - int ptoffset0 = (ptindex >> 1) << (leaf_shift + 1); - int ptoffset1 = ptoffset0 | (1 << (leaf_shift)); - - uint32_t leafentry_size = 1 << (leaf_shift + 3); + unsigned goffset, uoffset, moffset, ptoffset0, ptoffset1; + uint32_t leafentry_size; /* Starting address - Page Table Base */ uint64_t vaddr = env->CP0_PWBase; @@ -771,15 +756,28 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr address, /* no structure to walk */ return false; } - if ((directory_shift == -1) || (leaf_shift == -1)) { + if (ptew > 1) { return false; } + /* HTW Shift values (depend on entry size) */ + directory_shift = (hugepg && (ptew == 1)) ? native_shift + 1 : native_shift; + leaf_shift = (ptew == 1) ? native_shift + 1 : native_shift; + + goffset = gindex << directory_shift; + uoffset = uindex << directory_shift; + moffset = mindex << directory_shift; + ptoffset0 = (ptindex >> 1) << (leaf_shift + 1); + ptoffset1 = ptoffset0 | (1 << (leaf_shift)); + + leafentry_size = 1 << (leaf_shift + 3); + /* Global Directory */ if (gdw > 0) { vaddr |= goffset; switch (walk_directory(env, &vaddr, pf_gdw, &huge_page, &hgpg_gdhit, - &pw_entrylo0, &pw_entrylo1)) + &pw_entrylo0, &pw_entrylo1, + directory_shift, leaf_shift)) { case 0: return false; @@ -795,7 +793,8 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr address, if (udw > 0) { vaddr |= uoffset; switch (walk_directory(env, &vaddr, pf_udw, &huge_page, &hgpg_udhit, - &pw_entrylo0, &pw_entrylo1)) + &pw_entrylo0, &pw_entrylo1, + directory_shift, leaf_shift)) { case 0: return false; @@ -811,7 +810,8 @@ static bool page_table_walk_refill(CPUMIPSState *env, vaddr address, if (mdw > 0) { vaddr |= moffset; switch (walk_directory(env, &vaddr, pf_mdw, &huge_page, &hgpg_mdhit, - &pw_entrylo0, &pw_entrylo1)) + &pw_entrylo0, &pw_entrylo1, + directory_shift, leaf_shift)) { case 0: return false; |