First-fault or no-fault doesn't mean only access one page. When cross pages, for first-fault, if there is no fault in the first access, the second page should be accessed. And for no-fault, the second page should always be accessed.
Signed-off-by: LIU Zhiwei <zhiwei_...@c-sky.com> --- target/arm/sve_helper.c | 35 ++++++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c index 91d1d24725..700a8a7585 100644 --- a/target/arm/sve_helper.c +++ b/target/arm/sve_helper.c @@ -4916,17 +4916,6 @@ void sve_ldnfff1_r(CPUARMState *env, void *vg, const target_ulong addr, } while (reg_off <= reg_last && (reg_off & 63)); } while (reg_off <= reg_last); - /* - * MemSingleNF is allowed to fail for any reason. We have special - * code above to handle the first element crossing a page boundary. - * As an implementation choice, decline to handle a cross-page element - * in any other position. - */ - reg_off = info.reg_off_split; - if (reg_off >= 0) { - goto do_fault; - } - second_page: reg_off = info.reg_off_first[1]; if (likely(reg_off < 0)) { @@ -4934,6 +4923,30 @@ void sve_ldnfff1_r(CPUARMState *env, void *vg, const target_ulong addr, return; } + mem_off = info.mem_off_first[1]; + reg_last = info.reg_off_last[1]; + host = info.page[1].host; + + do { + uint64_t pg = *(uint64_t *)(vg + (reg_off >> 3)); + do { + if ((pg >> (reg_off & 63)) & 1) { + if (unlikely(flags & TLB_WATCHPOINT) && + (cpu_watchpoint_address_matches + (env_cpu(env), addr + mem_off, 1 << msz) + & BP_MEM_READ)) { + goto do_fault; + } + if (mtedesc && !mte_probe1(env, mtedesc, addr + mem_off)) { + goto do_fault; + } + host_fn(vd, reg_off, host + mem_off); + } + reg_off += 1 << esz; + mem_off += 1 << msz; + } while (reg_off <= reg_last && (reg_off & 63)); + } while (reg_off <= reg_last); + /* * MemSingleNF is allowed to fail for any reason. As an implementation * choice, decline to handle elements on the second page. This should -- 2.23.0