Index: gdb.git/gdb/breakpoint.c =================================================================== --- gdb.git.orig/gdb/breakpoint.c 2010-06-05 00:27:58.000000000 -0300 +++ gdb.git/gdb/breakpoint.c 2010-06-06 12:14:22.000000000 -0300 @@ -1789,7 +1789,8 @@ Note: automatically using hardware break { val = target_insert_watchpoint (bpt->address, bpt->length, - bpt->watchpoint_type); + bpt->watchpoint_type, + bpt->owner->cond_exp); /* If trying to set a read-watchpoint, and it turns out it's not supported, try emulating one with an access watchpoint. */ @@ -1817,7 +1818,8 @@ Note: automatically using hardware break { val = target_insert_watchpoint (bpt->address, bpt->length, - hw_access); + hw_access, + bpt->owner->cond_exp); if (val == 0) bpt->watchpoint_type = hw_access; } @@ -2477,8 +2479,8 @@ remove_breakpoint_1 (struct bp_location else if (b->loc_type == bp_loc_hardware_watchpoint) { b->inserted = (is == mark_inserted); - val = target_remove_watchpoint (b->address, b->length, - b->watchpoint_type); + val = target_remove_watchpoint (b->address, b->length, + b->watchpoint_type, b->owner->cond_exp); /* Failure to remove any of the hardware watchpoints comes here. */ if ((is == mark_uninserted) && (b->inserted)) @@ -5211,6 +5213,21 @@ breakpoint_address_is_meaningful (struct static int watchpoint_locations_match (struct bp_location *loc1, struct bp_location *loc2) { + /* If the target can evaluate the condition expression in hardware, then we + we need to insert both watchpoints even if they are at the same place. + Otherwise the watchpoint will only trigger when the condition of whichever + watchpoint was inserted evaluates to true, not giving a chance for GDB to + check the condition of the other watchpoint. */ + if ((loc1->owner->cond_exp + && target_can_accel_watchpoint_condition (loc1->address, loc1->length, + loc1->watchpoint_type, + loc1->owner->cond_exp)) + || (loc2->owner->cond_exp + && target_can_accel_watchpoint_condition (loc2->address, loc2->length, + loc2->watchpoint_type, + loc2->owner->cond_exp))) + return 0; + /* Note that this checks the owner's type, not the location's. In case the target does not support read watchpoints, but does support access watchpoints, we'll have bp_read_watchpoint Index: gdb.git/gdb/i386-nat.c =================================================================== --- gdb.git.orig/gdb/i386-nat.c 2010-06-05 00:27:58.000000000 -0300 +++ gdb.git/gdb/i386-nat.c 2010-06-06 12:14:22.000000000 -0300 @@ -484,7 +484,8 @@ Invalid value %d of operation in i386_ha of the type TYPE. Return 0 on success, -1 on failure. */ static int -i386_insert_watchpoint (CORE_ADDR addr, int len, int type) +i386_insert_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { int retval; @@ -511,7 +512,8 @@ i386_insert_watchpoint (CORE_ADDR addr, address ADDR, whose length is LEN bytes, and for accesses of the type TYPE. Return 0 on success, -1 on failure. */ static int -i386_remove_watchpoint (CORE_ADDR addr, int len, int type) +i386_remove_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { int retval; Index: gdb.git/gdb/ia64-linux-nat.c =================================================================== --- gdb.git.orig/gdb/ia64-linux-nat.c 2010-06-05 00:27:58.000000000 -0300 +++ gdb.git/gdb/ia64-linux-nat.c 2010-06-06 12:14:22.000000000 -0300 @@ -530,7 +530,8 @@ is_power_of_2 (int val) } static int -ia64_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw) +ia64_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw, + struct expression *cond) { struct lwp_info *lp; ptid_t ptid; @@ -584,7 +585,8 @@ ia64_linux_insert_watchpoint (CORE_ADDR } static int -ia64_linux_remove_watchpoint (CORE_ADDR addr, int len, int type) +ia64_linux_remove_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { int idx; long dbr_addr, dbr_mask; Index: gdb.git/gdb/inf-ttrace.c =================================================================== --- gdb.git.orig/gdb/inf-ttrace.c 2010-06-05 00:27:58.000000000 -0300 +++ gdb.git/gdb/inf-ttrace.c 2010-06-06 12:14:22.000000000 -0300 @@ -314,7 +314,8 @@ inf_ttrace_disable_page_protections (pid type TYPE. */ static int -inf_ttrace_insert_watchpoint (CORE_ADDR addr, int len, int type) +inf_ttrace_insert_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { const int pagesize = inf_ttrace_page_dict.pagesize; pid_t pid = ptid_get_pid (inferior_ptid); @@ -337,7 +338,8 @@ inf_ttrace_insert_watchpoint (CORE_ADDR type TYPE. */ static int -inf_ttrace_remove_watchpoint (CORE_ADDR addr, int len, int type) +inf_ttrace_remove_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { const int pagesize = inf_ttrace_page_dict.pagesize; pid_t pid = ptid_get_pid (inferior_ptid); Index: gdb.git/gdb/mips-linux-nat.c =================================================================== --- gdb.git.orig/gdb/mips-linux-nat.c 2010-06-05 00:27:58.000000000 -0300 +++ gdb.git/gdb/mips-linux-nat.c 2010-06-06 12:14:22.000000000 -0300 @@ -926,7 +926,8 @@ populate_regs_from_watches (struct pt_wa watch. Return zero on success. */ static int -mips_linux_insert_watchpoint (CORE_ADDR addr, int len, int type) +mips_linux_insert_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { struct pt_watch_regs regs; struct mips_watchpoint *new_watch; @@ -975,7 +976,8 @@ mips_linux_insert_watchpoint (CORE_ADDR Return zero on success. */ static int -mips_linux_remove_watchpoint (CORE_ADDR addr, int len, int type) +mips_linux_remove_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { int retval; int deleted_one; Index: gdb.git/gdb/nto-procfs.c =================================================================== --- gdb.git.orig/gdb/nto-procfs.c 2010-06-05 00:27:58.000000000 -0300 +++ gdb.git/gdb/nto-procfs.c 2010-06-06 12:14:22.000000000 -0300 @@ -1506,13 +1506,15 @@ procfs_can_use_hw_breakpoint (int type, } static int -procfs_remove_hw_watchpoint (CORE_ADDR addr, int len, int type) +procfs_remove_hw_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { return procfs_hw_watchpoint (addr, -1, type); } static int -procfs_insert_hw_watchpoint (CORE_ADDR addr, int len, int type) +procfs_insert_hw_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { return procfs_hw_watchpoint (addr, len, type); } Index: gdb.git/gdb/ppc-linux-nat.c =================================================================== --- gdb.git.orig/gdb/ppc-linux-nat.c 2010-06-05 00:27:58.000000000 -0300 +++ gdb.git/gdb/ppc-linux-nat.c 2010-06-08 22:25:39.000000000 -0300 @@ -1492,7 +1492,7 @@ ppc_linux_region_ok_for_hw_watchpoint (C if (booke_debug_info.data_bp_alignment && (addr + len > (addr & ~(booke_debug_info.data_bp_alignment - 1)) + booke_debug_info.data_bp_alignment)) - return 0; + return 0; } /* addr+len must fall in the 8 byte watchable region for DABR-based processors (i.e., server processors). Without the new BookE ptrace @@ -1685,8 +1685,149 @@ get_trigger_type (int rw) return t; } +/* Check whether we have at least one free DVC register. */ static int -ppc_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw) +can_use_watchpoint_cond_accel (void) +{ + 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_booke_interface () || cnt == 0) + 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; + } + + return 1; +} + +/* Calculate the enable bits and the contents of the Data Value Compare + debug register present in BookE processors. + + ADDR is the address to be watched, LEN is the length of watched data + and DATA_VALUE is the value which will trigger the watchpoint. On exit, + CONDITION_MODE will hold the enable bits for the DVC, and CONDITION_VALUE + will hold the value which should be put in the DVC register. */ +static void +calculate_dvc (CORE_ADDR addr, int len, CORE_ADDR data_value, + int data_value_len, uint32_t *condition_mode, + uint64_t *condition_value) +{ + int i, num_byte_enable, align_offset, num_bytes_off_dvc, + rightmost_enabled_byte; + CORE_ADDR addr_end_data, addr_end_dvc; + + /* The DVC register compares bytes within fixed-length windows which + are word-aligned, with length equal to that of the DVC register. + We need to calculate where our watch region is relative to that + window and enable comparison of the bytes which fall within it. */ + + align_offset = addr % booke_debug_info.sizeof_condition; + addr_end_data = addr + len; + addr_end_dvc = (addr - align_offset + + booke_debug_info.sizeof_condition); + num_bytes_off_dvc = (addr_end_data > addr_end_dvc)? + addr_end_data - addr_end_dvc : 0; + num_byte_enable = len - num_bytes_off_dvc; + /* Here, bytes are numbered from right to left. */ + rightmost_enabled_byte = (addr_end_data < addr_end_dvc)? + addr_end_dvc - addr_end_data : 0; + + *condition_mode = PPC_BREAKPOINT_CONDITION_AND; + for (i = 0; i < num_byte_enable; i++) + *condition_mode |= PPC_BREAKPOINT_CONDITION_BE (i + rightmost_enabled_byte); + + /* Now we need to match the position within the DVC of the comparison + value with where the watch region is relative to the window + (i.e., the ALIGN_OFFSET). */ + + /* The size of the user-provided data value matters because the value is + "left-aligned" within DATA_VALUE, e.g: a 1-byte data type will occupy the + first byte of DATA_VALUE, a two-byte data type the first two, and so on. + This means that we need to adjust the user-provided value within + DATA_VALUE when copying it to CONDITION_VALUE. */ + + if (data_value_len - len > align_offset) + /* The user-provided value type is larger than the watched value type, + and it is also to the right of the offset within the DVC register + where it should be. */ + *condition_value = (uint64_t) data_value << (data_value_len - len + - align_offset) * 8; + else + /* The user-provided value type is either smaller than the watched + value type, or else it is equal or larger than the watched value + type but to the left of the offset within the DVC register where + it should be. */ + *condition_value = (uint64_t) data_value >> (align_offset + - (data_value_len - len)) * 8; +} + +/* Verifies whether the expression COND can be implemented using the + DVC (Data Value Compare) register in BookE processors. The expression + must test the watch value for equality with a constant expression. */ +static int +check_condition (CORE_ADDR watch_addr, struct expression *cond, + CORE_ADDR *data_value, int *data_value_len) +{ + int pc = 1, copy_len; + struct value *v_left, *v_right, *val; + + if (cond->elts[0].opcode != BINOP_EQUAL) + return 0; + + v_left = evaluate_subexp (NULL_TYPE, cond, &pc, EVAL_NORMAL); + v_right = evaluate_subexp (NULL_TYPE, cond, &pc, EVAL_NORMAL); + + if (VALUE_LVAL (v_left) == lval_memory && VALUE_LVAL (v_right) == not_lval + && value_address (v_left) == watch_addr) + val = v_right; + else if (VALUE_LVAL (v_left) == not_lval && VALUE_LVAL (v_right) == lval_memory + && value_address (v_right) == watch_addr) + val = v_left; + else + return 0; + + *data_value = 0; + *data_value_len = TYPE_LENGTH (value_type (val)); + copy_len = *data_value_len > sizeof (CORE_ADDR)? + sizeof (CORE_ADDR) : *data_value_len; + memcpy (data_value, value_contents (val), copy_len); + + return 1; +} + +/* Return non-zero if the target is capable of using hardware to evaluate + the condition expression, thus only triggering the watchpoint when it is + true. */ +static int +ppc_linux_can_accel_watchpoint_condition (CORE_ADDR addr, int len, int rw, + struct expression *cond) +{ + int data_value_len; + CORE_ADDR data_value; + + return (have_ptrace_booke_interface () + && booke_debug_info.num_condition_regs > 0 + && check_condition (addr, cond, &data_value, &data_value_len)); +} + +static int +ppc_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw, + struct expression *cond) { struct lwp_info *lp; ptid_t ptid; @@ -1694,15 +1835,25 @@ ppc_linux_insert_watchpoint (CORE_ADDR a if (have_ptrace_booke_interface ()) { + int data_value_len; struct ppc_hw_breakpoint p; + CORE_ADDR data_value; + + if (cond && can_use_watchpoint_cond_accel () + && check_condition (addr, cond, &data_value, &data_value_len)) + calculate_dvc (addr, len, data_value, data_value_len, + &p.condition_mode, &p.condition_value); + else + { + p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE; + p.condition_value = 0; + } 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_NONE; p.addr = (uint64_t) addr; p.addr2 = 0; - p.condition_value = 0; ALL_LWPS (lp, ptid) booke_insert_point (&p, TIDGET (ptid)); @@ -1749,7 +1900,8 @@ ppc_linux_insert_watchpoint (CORE_ADDR a saved_dabr_value = dabr_value; ALL_LWPS (lp, ptid) - if (ptrace (PTRACE_SET_DEBUGREG, TIDGET (ptid), 0, saved_dabr_value) < 0) + if (ptrace (PTRACE_SET_DEBUGREG, TIDGET (ptid), 0, + saved_dabr_value) < 0) return -1; ret = 0; @@ -1759,7 +1911,8 @@ ppc_linux_insert_watchpoint (CORE_ADDR a } static int -ppc_linux_remove_watchpoint (CORE_ADDR addr, int len, int rw) +ppc_linux_remove_watchpoint (CORE_ADDR addr, int len, int rw, + struct expression *cond) { struct lwp_info *lp; ptid_t ptid; @@ -1767,15 +1920,25 @@ ppc_linux_remove_watchpoint (CORE_ADDR a if (have_ptrace_booke_interface ()) { + int data_value_len; struct ppc_hw_breakpoint p; + CORE_ADDR data_value; + + if (cond && booke_debug_info.num_condition_regs > 0 + && check_condition (addr, cond, &data_value, &data_value_len)) + calculate_dvc (addr, len, data_value, data_value_len, + &p.condition_mode, &p.condition_value); + else + { + p.condition_mode = PPC_BREAKPOINT_CONDITION_NONE; + p.condition_value = 0; + } 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_NONE; p.addr = (uint64_t) addr; p.addr2 = 0; - p.condition_value = 0; ALL_LWPS (lp, ptid) booke_remove_point (&p, TIDGET (ptid)); @@ -1786,7 +1949,8 @@ ppc_linux_remove_watchpoint (CORE_ADDR a { saved_dabr_value = 0; ALL_LWPS (lp, ptid) - if (ptrace (PTRACE_SET_DEBUGREG, TIDGET (ptid), 0, saved_dabr_value) < 0) + if (ptrace (PTRACE_SET_DEBUGREG, TIDGET (ptid), 0, + saved_dabr_value) < 0) return -1; ret = 0; @@ -2137,6 +2301,7 @@ _initialize_ppc_linux_nat (void) 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; + t->to_can_accel_watchpoint_condition = ppc_linux_can_accel_watchpoint_condition; t->to_read_description = ppc_linux_read_description; t->to_auxv_parse = ppc_linux_auxv_parse; Index: gdb.git/gdb/procfs.c =================================================================== --- gdb.git.orig/gdb/procfs.c 2010-06-05 00:27:58.000000000 -0300 +++ gdb.git/gdb/procfs.c 2010-06-06 12:14:22.000000000 -0300 @@ -5161,7 +5161,8 @@ procfs_stopped_data_address (struct targ } static int -procfs_insert_watchpoint (CORE_ADDR addr, int len, int type) +procfs_insert_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { if (!target_have_steppable_watchpoint && !gdbarch_have_nonsteppable_watchpoint (target_gdbarch)) @@ -5182,7 +5183,8 @@ procfs_insert_watchpoint (CORE_ADDR addr } static int -procfs_remove_watchpoint (CORE_ADDR addr, int len, int type) +procfs_remove_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { return procfs_set_watchpoint (inferior_ptid, addr, 0, 0, 0); } Index: gdb.git/gdb/remote-m32r-sdi.c =================================================================== --- gdb.git.orig/gdb/remote-m32r-sdi.c 2010-06-05 00:27:58.000000000 -0300 +++ gdb.git/gdb/remote-m32r-sdi.c 2010-06-06 12:14:22.000000000 -0300 @@ -1421,7 +1421,8 @@ m32r_can_use_hw_watchpoint (int type, in watchpoint. */ static int -m32r_insert_watchpoint (CORE_ADDR addr, int len, int type) +m32r_insert_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { int i; @@ -1445,7 +1446,8 @@ m32r_insert_watchpoint (CORE_ADDR addr, } static int -m32r_remove_watchpoint (CORE_ADDR addr, int len, int type) +m32r_remove_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { int i; Index: gdb.git/gdb/remote-mips.c =================================================================== --- gdb.git.orig/gdb/remote-mips.c 2010-06-05 00:27:58.000000000 -0300 +++ gdb.git/gdb/remote-mips.c 2010-06-06 12:14:22.000000000 -0300 @@ -2401,7 +2401,8 @@ calculate_mask (CORE_ADDR addr, int len) watchpoint. */ int -mips_insert_watchpoint (CORE_ADDR addr, int len, int type) +mips_insert_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { if (mips_set_breakpoint (addr, len, type)) return -1; @@ -2412,7 +2413,8 @@ mips_insert_watchpoint (CORE_ADDR addr, /* Remove a watchpoint. */ int -mips_remove_watchpoint (CORE_ADDR addr, int len, int type) +mips_remove_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { if (mips_clear_breakpoint (addr, len, type)) return -1; Index: gdb.git/gdb/remote.c =================================================================== --- gdb.git.orig/gdb/remote.c 2010-06-05 00:27:58.000000000 -0300 +++ gdb.git/gdb/remote.c 2010-06-06 12:14:22.000000000 -0300 @@ -7497,7 +7497,8 @@ watchpoint_to_Z_packet (int type) } static int -remote_insert_watchpoint (CORE_ADDR addr, int len, int type) +remote_insert_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { struct remote_state *rs = get_remote_state (); char *p; @@ -7530,7 +7531,8 @@ remote_insert_watchpoint (CORE_ADDR addr static int -remote_remove_watchpoint (CORE_ADDR addr, int len, int type) +remote_remove_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { struct remote_state *rs = get_remote_state (); char *p; Index: gdb.git/gdb/s390-nat.c =================================================================== --- gdb.git.orig/gdb/s390-nat.c 2010-06-05 00:27:58.000000000 -0300 +++ gdb.git/gdb/s390-nat.c 2010-06-06 12:14:22.000000000 -0300 @@ -335,7 +335,8 @@ s390_fix_watch_points (ptid_t ptid) } static int -s390_insert_watchpoint (CORE_ADDR addr, int len, int type) +s390_insert_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { struct lwp_info *lp; ptid_t ptid; @@ -356,7 +357,8 @@ s390_insert_watchpoint (CORE_ADDR addr, } static int -s390_remove_watchpoint (CORE_ADDR addr, int len, int type) +s390_remove_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { struct lwp_info *lp; ptid_t ptid; Index: gdb.git/gdb/target.c =================================================================== --- gdb.git.orig/gdb/target.c 2010-06-05 00:27:58.000000000 -0300 +++ gdb.git/gdb/target.c 2010-06-06 12:14:22.000000000 -0300 @@ -117,9 +117,11 @@ static int debug_to_insert_hw_breakpoint static int debug_to_remove_hw_breakpoint (struct gdbarch *, struct bp_target_info *); -static int debug_to_insert_watchpoint (CORE_ADDR, int, int); +static int debug_to_insert_watchpoint (CORE_ADDR, int, int, + struct expression *); -static int debug_to_remove_watchpoint (CORE_ADDR, int, int); +static int debug_to_remove_watchpoint (CORE_ADDR, int, int, + struct expression *); static int debug_to_stopped_by_watchpoint (void); @@ -130,6 +132,9 @@ static int debug_to_watchpoint_addr_with static int debug_to_region_ok_for_hw_watchpoint (CORE_ADDR, int); +static int debug_to_can_accel_watchpoint_condition (CORE_ADDR, int, int, + struct expression *); + static void debug_to_terminal_init (void); static void debug_to_terminal_inferior (void); @@ -591,6 +596,7 @@ update_current_target (void) INHERIT (to_stopped_by_watchpoint, t); INHERIT (to_watchpoint_addr_within_range, t); INHERIT (to_region_ok_for_hw_watchpoint, t); + INHERIT (to_can_accel_watchpoint_condition, t); INHERIT (to_terminal_init, t); INHERIT (to_terminal_inferior, t); INHERIT (to_terminal_ours_for_output, t); @@ -709,10 +715,10 @@ update_current_target (void) (int (*) (struct gdbarch *, struct bp_target_info *)) return_minus_one); de_fault (to_insert_watchpoint, - (int (*) (CORE_ADDR, int, int)) + (int (*) (CORE_ADDR, int, int, struct expression *)) return_minus_one); de_fault (to_remove_watchpoint, - (int (*) (CORE_ADDR, int, int)) + (int (*) (CORE_ADDR, int, int, struct expression *)) return_minus_one); de_fault (to_stopped_by_watchpoint, (int (*) (void)) @@ -724,6 +730,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_can_accel_watchpoint_condition, + (int (*) (CORE_ADDR, int, int, struct expression *)) + return_zero); de_fault (to_terminal_init, (void (*) (void)) target_ignore); @@ -3237,6 +3246,21 @@ debug_to_region_ok_for_hw_watchpoint (CO } static int +debug_to_can_accel_watchpoint_condition (CORE_ADDR addr, int len, int rw, + struct expression *cond) +{ + int retval; + + retval = debug_target.to_can_accel_watchpoint_condition (addr, len, rw, cond); + + fprintf_unfiltered (gdb_stdlog, + "target_can_accel_watchpoint_condition (0x%lx, %d, %d, 0x%lx) = %ld\n", + (unsigned long) addr, len, rw, (unsigned long) cond, + (unsigned long) retval); + return retval; +} + +static int debug_to_stopped_by_watchpoint (void) { int retval; @@ -3311,28 +3335,32 @@ debug_to_remove_hw_breakpoint (struct gd } static int -debug_to_insert_watchpoint (CORE_ADDR addr, int len, int type) +debug_to_insert_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { int retval; - retval = debug_target.to_insert_watchpoint (addr, len, type); + retval = debug_target.to_insert_watchpoint (addr, len, type, cond); fprintf_unfiltered (gdb_stdlog, - "target_insert_watchpoint (0x%lx, %d, %d) = %ld\n", - (unsigned long) addr, len, type, (unsigned long) retval); + "target_insert_watchpoint (0x%lx, %d, %d, 0x%ld) = %ld\n", + (unsigned long) addr, len, type, (unsigned long) cond, + (unsigned long) retval); return retval; } static int -debug_to_remove_watchpoint (CORE_ADDR addr, int len, int type) +debug_to_remove_watchpoint (CORE_ADDR addr, int len, int type, + struct expression *cond) { int retval; - retval = debug_target.to_remove_watchpoint (addr, len, type); + retval = debug_target.to_remove_watchpoint (addr, len, type, cond); fprintf_unfiltered (gdb_stdlog, - "target_remove_watchpoint (0x%lx, %d, %d) = %ld\n", - (unsigned long) addr, len, type, (unsigned long) retval); + "target_remove_watchpoint (0x%lx, %d, %d, 0x%ld) = %ld\n", + (unsigned long) addr, len, type, (unsigned long) cond, + (unsigned long) retval); return retval; } @@ -3587,6 +3615,7 @@ setup_target_debug (void) current_target.to_stopped_data_address = debug_to_stopped_data_address; current_target.to_watchpoint_addr_within_range = debug_to_watchpoint_addr_within_range; current_target.to_region_ok_for_hw_watchpoint = debug_to_region_ok_for_hw_watchpoint; + current_target.to_can_accel_watchpoint_condition = debug_to_can_accel_watchpoint_condition; current_target.to_terminal_init = debug_to_terminal_init; current_target.to_terminal_inferior = debug_to_terminal_inferior; current_target.to_terminal_ours_for_output = debug_to_terminal_ours_for_output; Index: gdb.git/gdb/target.h =================================================================== --- gdb.git.orig/gdb/target.h 2010-06-05 00:27:58.000000000 -0300 +++ gdb.git/gdb/target.h 2010-06-06 12:14:22.000000000 -0300 @@ -36,6 +36,8 @@ struct trace_status; struct uploaded_tsv; struct uploaded_tp; +struct expression; + /* 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 @@ -420,8 +422,12 @@ struct target_ops int (*to_can_use_hw_breakpoint) (int, int, int); 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); + + /* Documentation of what the two routines belwo are expected to do is + provided with the corresponding target_* macros. */ + int (*to_remove_watchpoint) (CORE_ADDR, int, int, struct expression *); + int (*to_insert_watchpoint) (CORE_ADDR, int, int, struct expression *); + int (*to_stopped_by_watchpoint) (void); int to_have_steppable_watchpoint; int to_have_continuable_watchpoint; @@ -429,6 +435,8 @@ struct target_ops int (*to_watchpoint_addr_within_range) (struct target_ops *, CORE_ADDR, CORE_ADDR, int); int (*to_region_ok_for_hw_watchpoint) (CORE_ADDR, int); + int (*to_can_accel_watchpoint_condition) (CORE_ADDR, int, int, + struct expression *); void (*to_terminal_init) (void); void (*to_terminal_inferior) (void); void (*to_terminal_ours_for_output) (void); @@ -1279,14 +1287,15 @@ extern char *normal_pid_to_str (ptid_t p /* 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. + COND is the expression for its condition, or NULL if there's none. Returns 0 for success, 1 if the watchpoint type is not supported, -1 for failure. */ -#define target_insert_watchpoint(addr, len, type) \ - (*current_target.to_insert_watchpoint) (addr, len, type) +#define target_insert_watchpoint(addr, len, type, cond) \ + (*current_target.to_insert_watchpoint) (addr, len, type, cond) -#define target_remove_watchpoint(addr, len, type) \ - (*current_target.to_remove_watchpoint) (addr, len, type) +#define target_remove_watchpoint(addr, len, type, cond) \ + (*current_target.to_remove_watchpoint) (addr, len, type, cond) #define target_insert_hw_breakpoint(gdbarch, bp_tgt) \ (*current_target.to_insert_hw_breakpoint) (gdbarch, bp_tgt) @@ -1303,6 +1312,12 @@ extern char *normal_pid_to_str (ptid_t p #define target_watchpoint_addr_within_range(target, addr, start, length) \ (*target.to_watchpoint_addr_within_range) (target, addr, start, length) +/* Return non-zero if the target is capable of using hardware to evaluate + the condition expression, thus only triggering the watchpoint when it is + true. */ +#define target_can_accel_watchpoint_condition(addr, len, type, cond) \ + (*current_target.to_can_accel_watchpoint_condition) (addr, len, type, cond) + /* Target can execute in reverse? */ #define target_can_execute_reverse \ (current_target.to_can_execute_reverse ? \