diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2023-08-01 10:10:45 -0700 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2023-08-05 18:17:17 +0000 |
commit | 190aba803fbcac30b29bdab25f454b1284a96201 (patch) | |
tree | 522602ce9b545c02f15cde85818eb7d5ab8b63e7 | |
parent | 1966855e567686e6547b058d8664aefd0e969a0f (diff) |
accel/tcg: Issue wider aligned i/o in do_{ld,st}_mmio_*
If the address and size are aligned, send larger chunks
to the memory subsystem. This will be required to make
more use of these helpers.
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r-- | accel/tcg/cputlb.c | 76 |
1 files changed, 69 insertions, 7 deletions
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index 23386ecfde..a308cb7534 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -2081,10 +2081,40 @@ static uint64_t do_ld_mmio_beN(CPUArchState *env, CPUTLBEntryFull *full, uint64_t ret_be, vaddr addr, int size, int mmu_idx, MMUAccessType type, uintptr_t ra) { - for (int i = 0; i < size; i++) { - uint8_t x = io_readx(env, full, mmu_idx, addr + i, ra, type, MO_UB); - ret_be = (ret_be << 8) | x; - } + uint64_t t; + + tcg_debug_assert(size > 0 && size <= 8); + do { + /* Read aligned pieces up to 8 bytes. */ + switch ((size | (int)addr) & 7) { + case 1: + case 3: + case 5: + case 7: + t = io_readx(env, full, mmu_idx, addr, ra, type, MO_UB); + ret_be = (ret_be << 8) | t; + size -= 1; + addr += 1; + break; + case 2: + case 6: + t = io_readx(env, full, mmu_idx, addr, ra, type, MO_BEUW); + ret_be = (ret_be << 16) | t; + size -= 2; + addr += 2; + break; + case 4: + t = io_readx(env, full, mmu_idx, addr, ra, type, MO_BEUL); + ret_be = (ret_be << 32) | t; + size -= 4; + addr += 4; + break; + case 0: + return io_readx(env, full, mmu_idx, addr, ra, type, MO_BEUQ); + default: + qemu_build_not_reached(); + } + } while (size); return ret_be; } @@ -2680,9 +2710,41 @@ static uint64_t do_st_mmio_leN(CPUArchState *env, CPUTLBEntryFull *full, uint64_t val_le, vaddr addr, int size, int mmu_idx, uintptr_t ra) { - for (int i = 0; i < size; i++, val_le >>= 8) { - io_writex(env, full, mmu_idx, val_le, addr + i, ra, MO_UB); - } + tcg_debug_assert(size > 0 && size <= 8); + + do { + /* Store aligned pieces up to 8 bytes. */ + switch ((size | (int)addr) & 7) { + case 1: + case 3: + case 5: + case 7: + io_writex(env, full, mmu_idx, val_le, addr, ra, MO_UB); + val_le >>= 8; + size -= 1; + addr += 1; + break; + case 2: + case 6: + io_writex(env, full, mmu_idx, val_le, addr, ra, MO_LEUW); + val_le >>= 16; + size -= 2; + addr += 2; + break; + case 4: + io_writex(env, full, mmu_idx, val_le, addr, ra, MO_LEUL); + val_le >>= 32; + size -= 4; + addr += 4; + break; + case 0: + io_writex(env, full, mmu_idx, val_le, addr, ra, MO_LEUQ); + return 0; + default: + qemu_build_not_reached(); + } + } while (size); + return val_le; } |