-/* Watchpoint access routines. Watchpoints are inserted using TLB tricks,
- so these check for a hit then pass through to the normal out-of-line
- phys routines. */
-static MemTxResult watch_mem_read(void *opaque, hwaddr addr, uint64_t *pdata,
- unsigned size, MemTxAttrs attrs)
-{
- MemTxResult res;
- uint64_t data;
- int asidx = cpu_asidx_from_attrs(current_cpu, attrs);
- AddressSpace *as = current_cpu->cpu_ases[asidx].as;
-
- check_watchpoint(addr & ~TARGET_PAGE_MASK, size, attrs, BP_MEM_READ);
- switch (size) {
- case 1:
- data = address_space_ldub(as, addr, attrs, &res);
- break;
- case 2:
- data = address_space_lduw(as, addr, attrs, &res);
- break;
- case 4:
- data = address_space_ldl(as, addr, attrs, &res);
- break;
- case 8:
- data = address_space_ldq(as, addr, attrs, &res);
- break;
- default: abort();
- }
- *pdata = data;
- return res;
-}
-
-static MemTxResult watch_mem_write(void *opaque, hwaddr addr,
- uint64_t val, unsigned size,
- MemTxAttrs attrs)
-{
- MemTxResult res;
- int asidx = cpu_asidx_from_attrs(current_cpu, attrs);
- AddressSpace *as = current_cpu->cpu_ases[asidx].as;
-
- check_watchpoint(addr & ~TARGET_PAGE_MASK, size, attrs, BP_MEM_WRITE);
- switch (size) {
- case 1:
- address_space_stb(as, addr, val, attrs, &res);
- break;
- case 2:
- address_space_stw(as, addr, val, attrs, &res);
- break;
- case 4:
- address_space_stl(as, addr, val, attrs, &res);
- break;
- case 8:
- address_space_stq(as, addr, val, attrs, &res);
- break;
- default: abort();
- }
- return res;
-}
-
-static const MemoryRegionOps watch_mem_ops = {
- .read_with_attrs = watch_mem_read,
- .write_with_attrs = watch_mem_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
- .valid = {
- .min_access_size = 1,
- .max_access_size = 8,
- .unaligned = false,
- },
- .impl = {
- .min_access_size = 1,
- .max_access_size = 8,
- .unaligned = false,
- },
-};
-