diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 94ae19b..cdd2997 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -1236,6 +1236,17 @@ update_watchpoint (struct breakpoint *b, int reparse) { char *s = b->cond_string; b->loc->cond = parse_exp_1 (&s, b->exp_valid_block, 0); + + if (b->type == bp_hardware_watchpoint + && target_can_use_special_hw_point_p (HW_POINT_COND_HW_ACCEL) + && target_can_use_watchpoint_cond_accel_p (b->loc)) + { + target_get_watchpoint_cond_accel_addr (b->loc, + &b->loc->cond_hw_addr); + b->hw_point_flag = HW_POINT_COND_HW_ACCEL; + } + else + b->hw_point_flag = HW_POINT_NONE; } } else if (!within_current_scope) @@ -1479,9 +1490,15 @@ Note: automatically using hardware breakpoints for read-only addresses.\n")); watchpoints. It's not clear that it's necessary... */ && bpt->owner->disposition != disp_del_at_next_stop) { - val = target_insert_watchpoint (bpt->address, - bpt->length, - bpt->watchpoint_type); + if (bpt->owner->hw_point_flag == HW_POINT_COND_HW_ACCEL) + val = target_insert_cond_accel_watchpoint (bpt->address, + bpt->length, + bpt->watchpoint_type, + bpt->cond_hw_addr); + else + val = target_insert_watchpoint (bpt->address, + bpt->length, + bpt->watchpoint_type); bpt->inserted = (val != -1); } @@ -2107,8 +2124,13 @@ remove_breakpoint_1 (struct bp_location *b, insertion_state_t is) struct value *n; b->inserted = (is == mark_inserted); - val = target_remove_watchpoint (b->address, b->length, - b->watchpoint_type); + if (b->owner->hw_point_flag == HW_POINT_COND_HW_ACCEL) + val = target_remove_cond_accel_watchpoint (b->address, b->length, + b->watchpoint_type, + b->cond_hw_addr); + else + val = target_remove_watchpoint (b->address, b->length, + b->watchpoint_type); /* Failure to remove any of the hardware watchpoints comes here. */ if ((is == mark_uninserted) && (b->inserted)) @@ -4877,6 +4899,7 @@ set_raw_breakpoint_without_location (struct gdbarch *gdbarch, b->syscalls_to_be_caught = NULL; b->ops = NULL; b->condition_not_parsed = 0; + b->hw_point_flag = HW_POINT_NONE; /* Add this breakpoint to the end of the chain so that a list of breakpoints will come out in order @@ -7327,6 +7350,10 @@ watch_command_1 (char *arg, int accessflag, int from_tty) that should be inserted. */ update_watchpoint (b, 1); + if (b->hw_point_flag == HW_POINT_COND_HW_ACCEL) + printf_filtered (_("This watchpoint will have its condition evaluation \ +assisted by hardware.\n")); + mention (b); update_global_location_list (1); } @@ -8881,6 +8908,18 @@ update_breakpoint_locations (struct breakpoint *b, b->number, e.message); new_loc->enabled = 0; } + + if (b->type == bp_hardware_watchpoint + && new_loc->cond + && target_can_use_special_hw_point_p (HW_POINT_COND_HW_ACCEL) + && target_can_use_watchpoint_cond_accel_p (new_loc)) + { + target_get_watchpoint_cond_accel_addr (new_loc, + &new_loc->cond_hw_addr); + new_loc->owner->hw_point_flag = HW_POINT_COND_HW_ACCEL; + } + else + new_loc->owner->hw_point_flag = HW_POINT_NONE; } if (b->source_file != NULL) @@ -10046,6 +10085,250 @@ tracepoint_save_command (char *args, int from_tty) return; } +/* This function checks if the expression associated + with the breakpoint `b' is of the form "*
". + It returns 1 if it is, 0 otherwise. */ +static int +exp_is_address_p (struct breakpoint *b) +{ + /* Check that the associated tree corresponds to that expression, + that is 5 elements, first a UNOP_IND, and then an OP_LONG. */ + if (b->exp->nelts != 5 + || b->exp->elts[0].opcode != UNOP_IND + || b->exp->elts[1].opcode != OP_LONG) + return 0; + return 1; +} + +/* This function checks if the expression associated + with the breakpoint `b' is of the form "". + It returns 1 if it is, 0 otherwise. */ +static int +exp_is_var_p (struct breakpoint *b) +{ + /* Check that the associated tree corresponds to that expression, + that is 4 elements, first a OP_VAR_VALUE. */ + if (b->exp->nelts != 4 + || b->exp->elts[0].opcode != OP_VAR_VALUE) + return 0; + return 1; +} + +/* This function checks if the condition associated + with the bp_location `b' is of the form "*
== LITERAL". + It returns 1 if it is, 0 otherwise. */ +static int +cond_is_address_equal_literal_p (struct bp_location *b) +{ + /* Check the watchpoint condition expression. It should be + of the form "*
EQUAL ", where EQUAL is the + equality binary operator. */ + if (b->cond->nelts == 10 + && b->cond->elts[0].opcode == BINOP_EQUAL + && b->cond->elts[1].opcode == UNOP_IND + && b->cond->elts[2].opcode == OP_LONG + && b->cond->elts[6].opcode == OP_LONG) + return 1; + else if (b->cond->nelts == 11 + && b->cond->elts[0].opcode == BINOP_EQUAL + && b->cond->elts[1].opcode == UNOP_IND + && b->cond->elts[2].opcode == OP_LONG + && b->cond->elts[6].opcode == UNOP_NEG + && b->cond->elts[7].opcode == OP_LONG) + return 1; + + return 0; +} + +/* This function checks if the condition associated + with the bp_location `b' is of the form " == LITERAL". + It returns 1 if it is, 0 otherwise. */ +static int +cond_is_var_equal_literal_p (struct bp_location *b) +{ + /* Check the watchpoint condition expression. It should be + of the form " EQUAL ", where EQUAL is the + equality binary operator. */ + if (b->cond->nelts == 9 + && b->cond->elts[0].opcode == BINOP_EQUAL + && b->cond->elts[1].opcode == OP_VAR_VALUE + && b->cond->elts[5].opcode == OP_LONG) + return 1; + else if (b->cond->nelts == 10 + && b->cond->elts[0].opcode == BINOP_EQUAL + && b->cond->elts[1].opcode == OP_VAR_VALUE + && b->cond->elts[5].opcode == UNOP_NEG + && b->cond->elts[6].opcode == OP_LONG) + return 1; + + return 0; +} + +/* This function is used to determine whether the condition associated + with bp_location B is of the form: + + watch *
if == + + If it is, then it sets DATA_VALUE to LITERAL and returns 1. + Otherwise, it returns 0. */ +int +default_watch_address_if_var_equal_literal_p (struct bp_location *b, + CORE_ADDR *data_value) +{ + int pc; + CORE_ADDR exp_address, + cond_address; + struct breakpoint *bp = b->owner; + + if (!exp_is_address_p (bp) + || !cond_is_var_equal_literal_p (b)) + return 0; + + exp_address = bp->exp->elts[3].longconst; + cond_address = value_as_address (address_of_variable (b->cond->elts[3].symbol, + b->cond->elts[2].block)); + + /* Make sure that the two addresses are the same. */ + if (exp_address != cond_address) + { + printf_filtered (_("\ +Memory location for the watchpoint expression and its condition need\n\ +to be the same.\n")); + return 0; + } + + /* At this point, all verifications were positive, so we can use + hardware-assisted data-matching. Set the data value, and return + non-zero. */ + pc = 5; + *data_value = value_as_long (evaluate_subexp (NULL_TYPE, b->cond, &pc, EVAL_NORMAL)); + + return 1; +} + +/* This function is used to determine whether the condition associated + with bp_location B is of the form: + + watch if *
== + + If it is, then it sets DATA_VALUE to LITERAL and returns 1. + Otherwise, it returns 0. */ +int +default_watch_var_if_address_equal_literal_p (struct bp_location *b, + CORE_ADDR *data_value) +{ + int pc; + CORE_ADDR exp_address, + cond_address; + struct breakpoint *bp = b->owner; + + if (!exp_is_var_p (bp) + || !cond_is_address_equal_literal_p (b)) + return 0; + + exp_address = value_as_address (address_of_variable (bp->exp->elts[2].symbol, + bp->exp->elts[1].block)); + cond_address = b->cond->elts[4].longconst; + + /* Make sure that the two addresses are the same. */ + if (exp_address != cond_address) + { + printf_filtered (_("\ +Memory location for the watchpoint expression and its condition need\n\ +to be the same.\n")); + return 0; + } + + /* At this point, all verifications were positive, so we can use + hardware-assisted data-matching. Set the data value, and return + non-zero. */ + pc = 6; + *data_value = value_as_long (evaluate_subexp (NULL_TYPE, b->cond, &pc, EVAL_NORMAL)); + + return 1; +} + +/* This function is used to determine whether the condition associated + with bp_location B is of the form: + + watch if == + + If it is, then it sets DATA_VALUE to LITERAL and returns 1. + Otherwise, it returns 0. */ +int +default_watch_var_if_var_equal_literal_p (struct bp_location *b, + CORE_ADDR *data_value) +{ + int pc; + char *name_exp, *name_cond; + struct breakpoint *bp = b->owner; + + if (!exp_is_var_p (bp) + || !cond_is_var_equal_literal_p (b)) + return 0; + + name_exp = bp->exp->elts[2].symbol->ginfo.name; + name_cond = b->cond->elts[3].symbol->ginfo.name; + + /* Make sure that the two variables' names are the same. */ + if (strcmp (name_cond, name_exp) != 0) + { + printf_filtered (_("\ +Memory location for the watchpoint expression and its condition need\n\ +to be the same.\n")); + return 0; + } + + /* At this point, all verifications were positive, so we can use + hardware-assisted data-matching. Set the data value, and return + non-zero. */ + pc = 5; + *data_value = value_as_long (evaluate_subexp (NULL_TYPE, b->cond, &pc, EVAL_NORMAL)); + + return 1; +} + +/* This function is used to determine whether the condition associated + with bp_location B is of the form: + + watch *
if *
== + + If it is, then it sets DATA_VALUE to LITERAL and returns 1. + Otherwise, it returns 0. */ +int +default_watch_address_if_address_equal_literal_p (struct bp_location *b, + CORE_ADDR *data_value) +{ + int pc; + CORE_ADDR exp_address, + cond_address; + struct breakpoint *bp = b->owner; + + if (!exp_is_address_p (bp) + || !cond_is_address_equal_literal_p (b)) + return 0; + + exp_address = bp->exp->elts[3].longconst; + cond_address = b->cond->elts[4].longconst; + + /* Make sure that the two addresses are the same. */ + if (exp_address != cond_address) + { + printf_filtered (_("\ +Memory location for the watchpoint expression and its condition need\n\ +to be the same.\n")); + return 0; + } + + /* At this point, all verifications were positive, so we can use + hardware-assisted data-matching. Set the data value, and return + non-zero. */ + pc = 6; + *data_value = value_as_long (evaluate_subexp (NULL_TYPE, b->cond, &pc, EVAL_NORMAL)); + + return 1; +} + /* Create a vector of all tracepoints. */ VEC(breakpoint_p) * diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 5ebd36c..d0c52a9 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -186,6 +186,11 @@ struct bp_target_info is used to determine the type of breakpoint to insert. */ CORE_ADDR placed_address; + /* If this is a ranged hardware breakpoint, then we can use this + field in order to store the length of the range that will be + watched for execution. */ + ULONGEST length; + /* If the breakpoint lives in memory and reading that memory would give back the breakpoint, instead of the original contents, then the original contents are cached here. Only SHADOW_LEN bytes of @@ -246,6 +251,17 @@ struct bp_location different locations. */ struct expression *cond; + /* Flag to indicate if the condition is going to be accelerated + by hardware. If its value is non-zero, then GDB checks the + condition using hardware acceleration; otherwise it uses the + regular software-based checking. */ + int cond_hw_accel : 1; + + /* If the condition can be hardware-accelerated, then we must + get the condition's variable address so that GDB can + properly set the evaluation via hardware. */ + CORE_ADDR cond_hw_addr; + /* This location's address is in an unloaded solib, and so this location should not be inserted. It will be automatically enabled when that solib is loaded. */ @@ -373,6 +389,13 @@ DEF_VEC_I(int); typedef struct bp_location *bp_location_p; DEF_VEC_P(bp_location_p); +/* Special flags for hardware breakpoints/watchpoints. */ +enum hw_point_flag { + HW_POINT_NONE = 0, + HW_POINT_COND_HW_ACCEL, /* Hardware watchpoint with condition + hardware-accelerated. */ +}; + /* Note that the ->silent field is not currently used by any commands (though the code is in there if it was to be, and set_raw_breakpoint does set it to 0). I implemented it because I thought it would be @@ -512,6 +535,9 @@ struct breakpoint /* Chain of action lines to execute when this tracepoint is hit. */ struct action_line *actions; + + /* Special flags. */ + enum hw_point_flag hw_point_flag; }; typedef struct breakpoint *breakpoint_p; @@ -992,4 +1018,20 @@ extern struct breakpoint *get_tracepoint_by_number (char **arg, int multi_p, is newly allocated; the caller should free when done with it. */ extern VEC(breakpoint_p) *all_tracepoints (void); +/* Return greater than zero if the condition associated with + the watchpoint `b' can be treated by the hardware; zero otherwise. + + Also stores the data value in `data_value'. */ +extern int default_watch_address_if_address_equal_literal_p (struct bp_location *b, + CORE_ADDR *data_value); + +extern int default_watch_var_if_var_equal_literal_p (struct bp_location *b, + CORE_ADDR *data_value); + +extern int default_watch_address_if_var_equal_literal_p (struct bp_location *b, + CORE_ADDR *data_value); + +extern int default_watch_var_if_address_equal_literal_p (struct bp_location *b, + CORE_ADDR *data_value); + #endif /* !defined (BREAKPOINT_H) */ diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c index 2c930c9..4697164 100644 --- a/gdb/ppc-linux-nat.c +++ b/gdb/ppc-linux-nat.c @@ -1445,6 +1445,26 @@ ppc_linux_can_use_hw_breakpoint (int type, int cnt, int ot) } static int +ppc_linux_can_use_special_hw_point_p (enum hw_point_flag flag) +{ + uint64_t features = booke_debug_info.features; + + if (!have_ptrace_new_debug_booke) + return 0; + + switch (flag) + { + case HW_POINT_COND_HW_ACCEL: + return booke_debug_info.num_condition_regs > 0; + /* We also accept non-special *points. */ + case HW_POINT_NONE: + return 1; + } + + return 0; +} + +static int ppc_linux_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len) { /* Handle sub-8-byte quantities. */ @@ -1655,6 +1675,70 @@ static int get_trigger_type (int rw) } static int +ppc_linux_insert_cond_accel_watchpoint (CORE_ADDR addr, int len, int rw, + CORE_ADDR cond) +{ + struct ppc_hw_breakpoint p; + unsigned long a = (unsigned long) addr, + c = (unsigned long) cond; + struct lwp_info *lp; + ptid_t ptid; + int byte_to_enable; + + if (!have_ptrace_new_debug_booke) + return -1; + + byte_to_enable = a % 4; + c >>= (byte_to_enable * 8); + + p.version = PPC_DEBUG_CURRENT_VERSION; + p.trigger_type = get_trigger_type (rw); + p.addr_mode = PPC_BREAKPOINT_MODE_EXACT; + p.condition_mode = PPC_BREAKPOINT_CONDITION_AND + | PPC_BREAKPOINT_CONDITION_BE (byte_to_enable); + p.addr = (uint64_t) a; + p.addr2 = 0; + p.condition_value = (uint64_t) c; + + ALL_LWPS (lp, ptid) + booke_insert_point (&p, TIDGET (ptid)); + + return 0; +} + +static int +ppc_linux_remove_cond_accel_watchpoint (CORE_ADDR addr, int len, int rw, + CORE_ADDR cond) +{ + struct ppc_hw_breakpoint p; + unsigned long a = (unsigned long) addr, + c = (unsigned long) cond; + struct lwp_info *lp; + ptid_t ptid; + int byte_to_enable; + + if (!have_ptrace_new_debug_booke) + return -1; + + byte_to_enable = a % 4; + c >>= (byte_to_enable * 8); + + p.version = PPC_DEBUG_CURRENT_VERSION; + p.trigger_type = get_trigger_type (rw); + p.addr_mode = PPC_BREAKPOINT_MODE_EXACT; + p.condition_mode = PPC_BREAKPOINT_CONDITION_AND + | PPC_BREAKPOINT_CONDITION_BE (byte_to_enable); + p.addr = (uint64_t) a; + p.addr2 = 0; + p.condition_value = (uint64_t) c; + + ALL_LWPS (lp, ptid) + booke_remove_point (&p, TIDGET (ptid)); + + return 0; +} + +static int ppc_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw) { struct lwp_info *lp; @@ -1854,6 +1938,52 @@ ppc_linux_watchpoint_addr_within_range (struct target_ops *target, return start <= addr + mask && start + length - 1 >= addr; } +static int +ppc_linux_get_watchpoint_cond_accel_addr (struct bp_location *b, + CORE_ADDR *addr) +{ + if (have_ptrace_new_debug_booke) + return default_watch_address_if_address_equal_literal_p (b, addr) + || default_watch_var_if_var_equal_literal_p (b, addr) + || default_watch_var_if_address_equal_literal_p (b, addr) + || default_watch_address_if_var_equal_literal_p (b, addr); + + *addr = 0; + + return 0; +} + +static int +ppc_linux_can_use_watchpoint_cond_accel_p (struct bp_location *b) +{ + struct thread_points *p; + int tid = TIDGET (inferior_ptid); + int cnt = booke_debug_info.num_condition_regs, i; + CORE_ADDR tmp_value; + + if (!have_ptrace_new_debug_booke) + return 0; + + p = booke_find_thread_points_by_tid (tid, 0); + + if (p) + { + for (i = 0; i < max_slots_number; i++) + if (p->hw_breaks[i].hw_break != NULL + && p->hw_breaks[i].hw_break->condition_mode + != PPC_BREAKPOINT_CONDITION_NONE) + cnt--; + + /* There are no available slots now. */ + if (cnt <= 0) + return 0; + } + + /* We have to know if the condition associated with the bp_location + can be hardware-accelerated. */ + return ppc_linux_get_watchpoint_cond_accel_addr (b, &tmp_value); +} + static void ppc_linux_store_inferior_registers (struct target_ops *ops, struct regcache *regcache, int regno) @@ -2076,11 +2206,18 @@ _initialize_ppc_linux_nat (void) /* Add our breakpoint/watchpoint methods. */ t->to_can_use_hw_breakpoint = ppc_linux_can_use_hw_breakpoint; + t->to_can_use_special_hw_point_p = ppc_linux_can_use_special_hw_point_p; t->to_insert_hw_breakpoint = ppc_linux_insert_hw_breakpoint; t->to_remove_hw_breakpoint = ppc_linux_remove_hw_breakpoint; t->to_region_ok_for_hw_watchpoint = ppc_linux_region_ok_for_hw_watchpoint; + t->to_get_watchpoint_cond_accel_addr = + ppc_linux_get_watchpoint_cond_accel_addr; + t->to_can_use_watchpoint_cond_accel_p = + ppc_linux_can_use_watchpoint_cond_accel_p; t->to_insert_watchpoint = ppc_linux_insert_watchpoint; t->to_remove_watchpoint = ppc_linux_remove_watchpoint; + t->to_insert_cond_accel_watchpoint = ppc_linux_insert_cond_accel_watchpoint; + t->to_remove_cond_accel_watchpoint = ppc_linux_remove_cond_accel_watchpoint; t->to_stopped_by_watchpoint = ppc_linux_stopped_by_watchpoint; t->to_stopped_data_address = ppc_linux_stopped_data_address; t->to_watchpoint_addr_within_range = ppc_linux_watchpoint_addr_within_range; diff --git a/gdb/target.c b/gdb/target.c index cd1614b..3b1476d 100644 --- a/gdb/target.c +++ b/gdb/target.c @@ -619,11 +619,16 @@ update_current_target (void) INHERIT (to_files_info, t); INHERIT (to_insert_breakpoint, t); INHERIT (to_remove_breakpoint, t); + INHERIT (to_can_use_special_hw_point_p, t); + INHERIT (to_can_use_watchpoint_cond_accel_p, t); INHERIT (to_can_use_hw_breakpoint, t); INHERIT (to_insert_hw_breakpoint, t); INHERIT (to_remove_hw_breakpoint, t); INHERIT (to_insert_watchpoint, t); INHERIT (to_remove_watchpoint, t); + INHERIT (to_insert_cond_accel_watchpoint, t); + INHERIT (to_remove_cond_accel_watchpoint, t); + INHERIT (to_get_watchpoint_cond_accel_addr, t); INHERIT (to_stopped_data_address, t); INHERIT (to_have_steppable_watchpoint, t); INHERIT (to_have_continuable_watchpoint, t); @@ -725,6 +730,12 @@ update_current_target (void) de_fault (to_can_use_hw_breakpoint, (int (*) (int, int, int)) return_zero); + de_fault (to_can_use_special_hw_point_p, + (int (*) (enum hw_point_flag)) + return_zero); + de_fault (to_can_use_watchpoint_cond_accel_p, + (int (*) (struct bp_location *)) + return_zero); de_fault (to_insert_hw_breakpoint, (int (*) (struct gdbarch *, struct bp_target_info *)) return_minus_one); @@ -737,6 +748,12 @@ update_current_target (void) de_fault (to_remove_watchpoint, (int (*) (CORE_ADDR, int, int)) return_minus_one); + de_fault (to_insert_cond_accel_watchpoint, + (int (*) (CORE_ADDR, int, int, CORE_ADDR)) + return_minus_one); + de_fault (to_remove_cond_accel_watchpoint, + (int (*) (CORE_ADDR, int, int, CORE_ADDR)) + return_minus_one); de_fault (to_stopped_by_watchpoint, (int (*) (void)) return_zero); @@ -747,6 +764,9 @@ update_current_target (void) default_watchpoint_addr_within_range); de_fault (to_region_ok_for_hw_watchpoint, default_region_ok_for_hw_watchpoint); + de_fault (to_get_watchpoint_cond_accel_addr, + (int (*) (struct bp_location *, CORE_ADDR *)) + return_zero); de_fault (to_terminal_init, (void (*) (void)) target_ignore); diff --git a/gdb/target.h b/gdb/target.h index ebe6056..c604846 100644 --- a/gdb/target.h +++ b/gdb/target.h @@ -32,6 +32,11 @@ struct bp_target_info; struct regcache; struct target_section_table; +struct bp_location; +struct breakpoint; + +enum hw_point_flag; + /* This include file defines the interface between the main part of the debugger, and the part which is target-specific, or specific to the communications interface between us and the @@ -400,16 +405,22 @@ struct target_ops int (*to_insert_breakpoint) (struct gdbarch *, struct bp_target_info *); int (*to_remove_breakpoint) (struct gdbarch *, struct bp_target_info *); int (*to_can_use_hw_breakpoint) (int, int, int); + int (*to_can_use_special_hw_point_p) (enum hw_point_flag); + int (*to_can_use_watchpoint_cond_accel_p) (struct bp_location *); int (*to_insert_hw_breakpoint) (struct gdbarch *, struct bp_target_info *); int (*to_remove_hw_breakpoint) (struct gdbarch *, struct bp_target_info *); int (*to_remove_watchpoint) (CORE_ADDR, int, int); int (*to_insert_watchpoint) (CORE_ADDR, int, int); + int (*to_insert_cond_accel_watchpoint) (CORE_ADDR, int, int, CORE_ADDR); + int (*to_remove_cond_accel_watchpoint) (CORE_ADDR, int, int, CORE_ADDR); int (*to_stopped_by_watchpoint) (void); int to_have_steppable_watchpoint; int to_have_continuable_watchpoint; int (*to_stopped_data_address) (struct target_ops *, CORE_ADDR *); int (*to_watchpoint_addr_within_range) (struct target_ops *, CORE_ADDR, CORE_ADDR, int); + int (*to_get_watchpoint_cond_accel_addr) (struct bp_location *, + CORE_ADDR *); int (*to_region_ok_for_hw_watchpoint) (CORE_ADDR, int); void (*to_terminal_init) (void); void (*to_terminal_inferior) (void); @@ -1184,9 +1195,29 @@ extern char *normal_pid_to_str (ptid_t ptid); #define target_can_use_hardware_watchpoint(TYPE,CNT,OTHERTYPE) \ (*current_target.to_can_use_hw_breakpoint) (TYPE, CNT, OTHERTYPE); +#ifndef target_region_ok_for_hw_watchpoint #define target_region_ok_for_hw_watchpoint(addr, len) \ (*current_target.to_region_ok_for_hw_watchpoint) (addr, len) - +#endif + +/* Returns non-zero if the target supports the special type of hardware + breakpoint/watchpoint represented by FLAG. */ +#ifndef target_can_use_special_hw_point_p +#define target_can_use_special_hw_point_p(flag) \ + (*current_target.to_can_use_special_hw_point_p) (flag) +#endif + +/* Returns greater than zero if the target supports hardware-accelerated + condition. */ +#ifndef target_can_use_watchpoint_cond_accel_p +#define target_can_use_watchpoint_cond_accel_p(loc) \ + (*current_target.to_can_use_watchpoint_cond_accel_p) (loc) +#endif + +#ifndef target_get_watchpoint_cond_accel_addr +#define target_get_watchpoint_cond_accel_addr(loc, addr) \ + (*current_target.to_get_watchpoint_cond_accel_addr) (loc, addr) +#endif /* Set/clear a hardware watchpoint starting at ADDR, for LEN bytes. TYPE is 0 for write, 1 for read, and 2 for read/write accesses. Returns 0 for @@ -1198,6 +1229,18 @@ extern char *normal_pid_to_str (ptid_t ptid); #define target_remove_watchpoint(addr, len, type) \ (*current_target.to_remove_watchpoint) (addr, len, type) +/* Hardware watchpoint with a condition associated (to be + hardware-accelerated). */ +#ifndef target_insert_cond_accel_watchpoint +#define target_insert_cond_accel_watchpoint(addr, len, type, cond) \ + (*current_target.to_insert_cond_accel_watchpoint) (addr, len, type, cond) +#endif + +#ifndef target_remove_cond_accel_watchpoint +#define target_remove_cond_accel_watchpoint(addr, len, type, cond) \ + (*current_target.to_remove_cond_accel_watchpoint) (addr, len, type, cond) +#endif + #define target_insert_hw_breakpoint(gdbarch, bp_tgt) \ (*current_target.to_insert_hw_breakpoint) (gdbarch, bp_tgt)