- case hw_write:
- ttype = 2;
- break;
- case hw_read:
- ttype = 1;
- break;
- case hw_access:
- ttype = 3;
- break;
- case hw_execute:
- ttype = 0;
- break;
- default:
- perror_with_name (_("Unrecognized breakpoint/watchpoint type"));
- }
- ctrl = ttype << 3;
-
- /* length bitmask */
- ctrl |= ((1 << len) - 1) << 5;
- /* enabled at el0 */
- ctrl |= (2 << 1) | 1;
-
- return ctrl;
-}
-
-/* Addresses to be written to the hardware breakpoint and watchpoint
- value registers need to be aligned; the alignment is 4-byte and
- 8-type respectively. Linux kernel rejects any non-aligned address
- it receives from the related ptrace call. Furthermore, the kernel
- currently only supports the following Byte Address Select (BAS)
- values: 0x1, 0x3, 0xf and 0xff, which means that for a hardware
- watchpoint to be accepted by the kernel (via ptrace call), its
- valid length can only be 1 byte, 2 bytes, 4 bytes or 8 bytes.
- Despite these limitations, the unaligned watchpoint is supported in
- this port.
-
- Return 0 for any non-compliant ADDR and/or LEN; return 1 otherwise. */
-
-static int
-aarch64_point_is_aligned (int is_watchpoint, CORE_ADDR addr, int len)
-{
- unsigned int alignment = is_watchpoint ? AARCH64_HWP_ALIGNMENT
- : AARCH64_HBP_ALIGNMENT;
-
- if (addr & (alignment - 1))
- return 0;
-
- if (len != 8 && len != 4 && len != 2 && len != 1)
- return 0;
-
- return 1;
-}
-
-/* Record the insertion of one breakpoint/watchpoint, as represented
- by ADDR and CTRL, in the cached debug register state area *STATE. */
-
-static int
-aarch64_dr_state_insert_one_point (struct aarch64_debug_reg_state *state,
- int type, CORE_ADDR addr, int len)
-{
- int i, idx, num_regs, is_watchpoint;
- unsigned int ctrl, *dr_ctrl_p, *dr_ref_count;
- CORE_ADDR *dr_addr_p;
-
- /* Set up state pointers. */
- is_watchpoint = (type != hw_execute);
- gdb_assert (aarch64_point_is_aligned (is_watchpoint, addr, len));
- if (is_watchpoint)
- {
- num_regs = aarch64_num_wp_regs;
- dr_addr_p = state->dr_addr_wp;
- dr_ctrl_p = state->dr_ctrl_wp;
- dr_ref_count = state->dr_ref_count_wp;
- }
- else
- {
- num_regs = aarch64_num_bp_regs;
- dr_addr_p = state->dr_addr_bp;
- dr_ctrl_p = state->dr_ctrl_bp;
- dr_ref_count = state->dr_ref_count_bp;
- }
-
- ctrl = aarch64_point_encode_ctrl_reg (type, len);
-
- /* Find an existing or free register in our cache. */
- idx = -1;
- for (i = 0; i < num_regs; ++i)
- {
- if ((dr_ctrl_p[i] & 1) == 0)
- {
- gdb_assert (dr_ref_count[i] == 0);
- idx = i;
- /* no break; continue hunting for an existing one. */
- }
- else if (dr_addr_p[i] == addr && dr_ctrl_p[i] == ctrl)
- {
- gdb_assert (dr_ref_count[i] != 0);
- idx = i;
- break;
- }
- }
-
- /* No space. */
- if (idx == -1)
- return -1;
-
- /* Update our cache. */
- if ((dr_ctrl_p[idx] & 1) == 0)
- {
- /* new entry */
- dr_addr_p[idx] = addr;
- dr_ctrl_p[idx] = ctrl;
- dr_ref_count[idx] = 1;
- /* Notify the change. */
- aarch64_notify_debug_reg_change (state, is_watchpoint, idx);