[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v3 02/16] tcg/mips: Support unaligned access for softmmu
From: |
Jiaxun Yang |
Subject: |
Re: [PATCH v3 02/16] tcg/mips: Support unaligned access for softmmu |
Date: |
Sat, 21 Aug 2021 14:39:10 +0800 |
User-agent: |
Cyrus-JMAP/3.5.0-alpha0-1118-g75eff666e5-fm-20210816.002-g75eff666 |
在2021年8月19日八月 上午4:19,Richard Henderson写道:
> We can use the routines just added for user-only to emit
> unaligned accesses in softmmu mode too.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Thanks!
> ---
> tcg/mips/tcg-target.c.inc | 91 ++++++++++++++++++++++-----------------
> 1 file changed, 51 insertions(+), 40 deletions(-)
>
> diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
> index 7ed0de9dae..3d6a0ba39e 100644
> --- a/tcg/mips/tcg-target.c.inc
> +++ b/tcg/mips/tcg-target.c.inc
> @@ -1154,8 +1154,10 @@ static void tcg_out_tlb_load(TCGContext *s,
> TCGReg base, TCGReg addrl,
> tcg_insn_unit *label_ptr[2], bool is_load)
> {
> MemOp opc = get_memop(oi);
> - unsigned s_bits = opc & MO_SIZE;
> unsigned a_bits = get_alignment_bits(opc);
> + unsigned s_bits = opc & MO_SIZE;
> + unsigned a_mask = (1 << a_bits) - 1;
> + unsigned s_mask = (1 << s_bits) - 1;
> int mem_index = get_mmuidx(oi);
> int fast_off = TLB_MASK_TABLE_OFS(mem_index);
> int mask_off = fast_off + offsetof(CPUTLBDescFast, mask);
> @@ -1163,7 +1165,7 @@ static void tcg_out_tlb_load(TCGContext *s,
> TCGReg base, TCGReg addrl,
> int add_off = offsetof(CPUTLBEntry, addend);
> int cmp_off = (is_load ? offsetof(CPUTLBEntry, addr_read)
> : offsetof(CPUTLBEntry, addr_write));
> - target_ulong mask;
> + target_ulong tlb_mask;
>
> /* Load tlb_mask[mmu_idx] and tlb_table[mmu_idx]. */
> tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_AREG0, mask_off);
> @@ -1177,27 +1179,13 @@ static void tcg_out_tlb_load(TCGContext *s,
> TCGReg base, TCGReg addrl,
> /* Add the tlb_table pointer, creating the CPUTLBEntry address in
> TMP3. */
> tcg_out_opc_reg(s, ALIAS_PADD, TCG_TMP3, TCG_TMP3, TCG_TMP1);
>
> - /* We don't currently support unaligned accesses.
> - We could do so with mips32r6. */
> - if (a_bits < s_bits) {
> - a_bits = s_bits;
> - }
> -
> - /* Mask the page bits, keeping the alignment bits to compare against. */
> - mask = (target_ulong)TARGET_PAGE_MASK | ((1 << a_bits) - 1);
> -
> /* Load the (low-half) tlb comparator. */
> if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
> - tcg_out_ld(s, TCG_TYPE_I32, TCG_TMP0, TCG_TMP3, cmp_off + LO_OFF);
> - tcg_out_movi(s, TCG_TYPE_I32, TCG_TMP1, mask);
> + tcg_out_ldst(s, OPC_LW, TCG_TMP0, TCG_TMP3, cmp_off + LO_OFF);
> } else {
> tcg_out_ldst(s, (TARGET_LONG_BITS == 64 ? OPC_LD
> : TCG_TARGET_REG_BITS == 64 ? OPC_LWU : OPC_LW),
> TCG_TMP0, TCG_TMP3, cmp_off);
> - tcg_out_movi(s, TCG_TYPE_TL, TCG_TMP1, mask);
> - /* No second compare is required here;
> - load the tlb addend for the fast path. */
> - tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP2, TCG_TMP3, add_off);
> }
>
> /* Zero extend a 32-bit guest address for a 64-bit host. */
> @@ -1205,7 +1193,25 @@ static void tcg_out_tlb_load(TCGContext *s,
> TCGReg base, TCGReg addrl,
> tcg_out_ext32u(s, base, addrl);
> addrl = base;
> }
> - tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, addrl);
> +
> + /*
> + * Mask the page bits, keeping the alignment bits to compare
> against.
> + * For unaligned accesses, compare against the end of the access to
> + * verify that it does not cross a page boundary.
> + */
> + tlb_mask = (target_ulong)TARGET_PAGE_MASK | a_mask;
> + tcg_out_movi(s, TCG_TYPE_I32, TCG_TMP1, tlb_mask);
> + if (a_mask >= s_mask) {
> + tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, addrl);
> + } else {
> + tcg_out_opc_imm(s, ALIAS_PADDI, TCG_TMP2, addrl, s_mask -
> a_mask);
> + tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, TCG_TMP2);
> + }
> +
> + if (TCG_TARGET_REG_BITS >= TARGET_LONG_BITS) {
> + /* Load the tlb addend for the fast path. */
> + tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP2, TCG_TMP3, add_off);
> + }
>
> label_ptr[0] = s->code_ptr;
> tcg_out_opc_br(s, OPC_BNE, TCG_TMP1, TCG_TMP0);
> @@ -1213,7 +1219,7 @@ static void tcg_out_tlb_load(TCGContext *s,
> TCGReg base, TCGReg addrl,
> /* Load and test the high half tlb comparator. */
> if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
> /* delay slot */
> - tcg_out_ld(s, TCG_TYPE_I32, TCG_TMP0, TCG_TMP3, cmp_off +
> HI_OFF);
> + tcg_out_ldst(s, OPC_LW, TCG_TMP0, TCG_TMP3, cmp_off + HI_OFF);
>
> /* Load the tlb addend for the fast path. */
> tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP2, TCG_TMP3, add_off);
> @@ -1535,8 +1541,7 @@ static void tcg_out_qemu_ld_direct(TCGContext *s,
> TCGReg lo, TCGReg hi,
> }
> }
>
> -static void __attribute__((unused))
> -tcg_out_qemu_ld_unalign(TCGContext *s, TCGReg lo, TCGReg hi,
> +static void tcg_out_qemu_ld_unalign(TCGContext *s, TCGReg lo, TCGReg
> hi,
> TCGReg base, MemOp opc, bool is_64)
> {
> const MIPSInsn lw1 = MIPS_BE ? OPC_LWL : OPC_LWR;
> @@ -1655,8 +1660,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const
> TCGArg *args, bool is_64)
> #if defined(CONFIG_SOFTMMU)
> tcg_insn_unit *label_ptr[2];
> #else
> - unsigned a_bits, s_bits;
> #endif
> + unsigned a_bits, s_bits;
> TCGReg base = TCG_REG_A0;
>
> data_regl = *args++;
> @@ -1665,10 +1670,20 @@ static void tcg_out_qemu_ld(TCGContext *s,
> const TCGArg *args, bool is_64)
> addr_regh = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0);
> oi = *args++;
> opc = get_memop(oi);
> + a_bits = get_alignment_bits(opc);
> + s_bits = opc & MO_SIZE;
>
> + /*
> + * R6 removes the left/right instructions but requires the
> + * system to support misaligned memory accesses.
> + */
> #if defined(CONFIG_SOFTMMU)
> tcg_out_tlb_load(s, base, addr_regl, addr_regh, oi, label_ptr, 1);
> - tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64);
> + if (use_mips32r6_instructions || a_bits >= s_bits) {
> + tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc,
> is_64);
> + } else {
> + tcg_out_qemu_ld_unalign(s, data_regl, data_regh, base, opc,
> is_64);
> + }
> add_qemu_ldst_label(s, 1, oi,
> (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32),
> data_regl, data_regh, addr_regl, addr_regh,
> @@ -1685,12 +1700,6 @@ static void tcg_out_qemu_ld(TCGContext *s, const
> TCGArg *args, bool is_64)
> } else {
> tcg_out_opc_reg(s, ALIAS_PADD, base, TCG_GUEST_BASE_REG,
> addr_regl);
> }
> - a_bits = get_alignment_bits(opc);
> - s_bits = opc & MO_SIZE;
> - /*
> - * R6 removes the left/right instructions but requires the
> - * system to support misaligned memory accesses.
> - */
> if (use_mips32r6_instructions) {
> if (a_bits) {
> tcg_out_test_alignment(s, true, addr_regl, addr_regh,
> a_bits);
> @@ -1770,8 +1779,7 @@ static void tcg_out_qemu_st_direct(TCGContext *s,
> TCGReg lo, TCGReg hi,
> }
> }
>
> -static void __attribute__((unused))
> -tcg_out_qemu_st_unalign(TCGContext *s, TCGReg lo, TCGReg hi,
> +static void tcg_out_qemu_st_unalign(TCGContext *s, TCGReg lo, TCGReg
> hi,
> TCGReg base, MemOp opc)
> {
> const MIPSInsn sw1 = MIPS_BE ? OPC_SWL : OPC_SWR;
> @@ -1851,9 +1859,8 @@ static void tcg_out_qemu_st(TCGContext *s, const
> TCGArg *args, bool is_64)
> MemOp opc;
> #if defined(CONFIG_SOFTMMU)
> tcg_insn_unit *label_ptr[2];
> -#else
> - unsigned a_bits, s_bits;
> #endif
> + unsigned a_bits, s_bits;
> TCGReg base = TCG_REG_A0;
>
> data_regl = *args++;
> @@ -1862,10 +1869,20 @@ static void tcg_out_qemu_st(TCGContext *s,
> const TCGArg *args, bool is_64)
> addr_regh = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0);
> oi = *args++;
> opc = get_memop(oi);
> + a_bits = get_alignment_bits(opc);
> + s_bits = opc & MO_SIZE;
>
> + /*
> + * R6 removes the left/right instructions but requires the
> + * system to support misaligned memory accesses.
> + */
> #if defined(CONFIG_SOFTMMU)
> tcg_out_tlb_load(s, base, addr_regl, addr_regh, oi, label_ptr, 0);
> - tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
> + if (use_mips32r6_instructions || a_bits >= s_bits) {
> + tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
> + } else {
> + tcg_out_qemu_st_unalign(s, data_regl, data_regh, base, opc);
> + }
> add_qemu_ldst_label(s, 0, oi,
> (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32),
> data_regl, data_regh, addr_regl, addr_regh,
> @@ -1882,12 +1899,6 @@ static void tcg_out_qemu_st(TCGContext *s, const
> TCGArg *args, bool is_64)
> } else {
> tcg_out_opc_reg(s, ALIAS_PADD, base, TCG_GUEST_BASE_REG,
> addr_regl);
> }
> - a_bits = get_alignment_bits(opc);
> - s_bits = opc & MO_SIZE;
> - /*
> - * R6 removes the left/right instructions but requires the
> - * system to support misaligned memory accesses.
> - */
> if (use_mips32r6_instructions) {
> if (a_bits) {
> tcg_out_test_alignment(s, true, addr_regl, addr_regh,
> a_bits);
> --
> 2.25.1
>
>
>
--
- Jiaxun
- [PATCH v3 00/16] tcg/mips: Unaligned access and other cleanup, Richard Henderson, 2021/08/18
- [PATCH v3 01/16] tcg/mips: Support unaligned access for user-only, Richard Henderson, 2021/08/18
- [PATCH v3 02/16] tcg/mips: Support unaligned access for softmmu, Richard Henderson, 2021/08/18
- Re: [PATCH v3 02/16] tcg/mips: Support unaligned access for softmmu,
Jiaxun Yang <=
- [PATCH v3 06/16] tcg/mips: Unify TCG_GUEST_BASE_REG tests, Richard Henderson, 2021/08/18
- [PATCH v3 08/16] tcg/mips: Unset TCG_TARGET_HAS_direct_jump, Richard Henderson, 2021/08/18
- [PATCH v3 04/16] tcg/mips: Move TCG_AREG0 to S8, Richard Henderson, 2021/08/18
- [PATCH v3 07/16] tcg/mips: Allow JAL to be out of range in tcg_out_bswap_subr, Richard Henderson, 2021/08/18
- [PATCH v3 05/16] tcg/mips: Move TCG_GUEST_BASE_REG to S7, Richard Henderson, 2021/08/18
- [PATCH v3 11/16] tcg/mips: Split out tcg_out_movi_one, Richard Henderson, 2021/08/18
- [PATCH v3 03/16] tcg/mips: Drop inline markers, Richard Henderson, 2021/08/18