* that are to be ignored.
         */
        if (gdb_connection->frontend_state == TARGET_RUNNING) {
-               char sig_reply[4];
+               char sig_reply[20];
+               char stop_reason[20];
+               int sig_reply_len;
                int signal_var;
 
                /* stop forwarding log packets! */
                } else
                        signal_var = gdb_last_signal(target);
 
-               snprintf(sig_reply, 4, "T%2.2x", signal_var);
-               gdb_put_packet(connection, sig_reply, 3);
+               stop_reason[0] = '\0';
+               if (target->debug_reason == DBG_REASON_WATCHPOINT) {
+                       enum watchpoint_rw hit_wp_type;
+                       uint32_t hit_wp_address;
+
+                       if (watchpoint_hit(target, &hit_wp_type, &hit_wp_address) == ERROR_OK) {
+
+                               switch (hit_wp_type) {
+                                       case WPT_WRITE:
+                                               snprintf(stop_reason, sizeof(stop_reason),
+                                                               "watch:%08x;", hit_wp_address);
+                                               break;
+                                       case WPT_READ:
+                                               snprintf(stop_reason, sizeof(stop_reason),
+                                                               "rwatch:%08x;", hit_wp_address);
+                                               break;
+                                       case WPT_ACCESS:
+                                               snprintf(stop_reason, sizeof(stop_reason),
+                                                               "awatch:%08x;", hit_wp_address);
+                                               break;
+                                       default:
+                                               break;
+                               }
+                       }
+               }
+
+               sig_reply_len = snprintf(sig_reply, sizeof(sig_reply), "T%2.2x%s",
+                               signal_var, stop_reason);
+
+               gdb_put_packet(connection, sig_reply, sig_reply_len);
                gdb_connection->frontend_state = TARGET_HALTED;
                rtos_update_threads(target);
        }
 
        while (target->watchpoints != NULL)
                watchpoint_free(target, target->watchpoints);
 }
+
+int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, uint32_t *address)
+{
+       int retval;
+       struct watchpoint *hit_watchpoint;
+
+       retval = target_hit_watchpoint(target, &hit_watchpoint);
+       if (retval != ERROR_OK)
+               return ERROR_FAIL;
+
+       *rw = hit_watchpoint->rw;
+       *address = hit_watchpoint->address;
+
+       LOG_DEBUG("Found hit watchpoint at 0x%8.8" PRIx32 " (WPID: %d)",
+               hit_watchpoint->address,
+               hit_watchpoint->unique_id);
+
+       return ERROR_OK;
+}
 
                enum watchpoint_rw rw, uint32_t value, uint32_t mask);
 void watchpoint_remove(struct target *target, uint32_t address);
 
+/* report type and address of just hit watchpoint */
+int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, uint32_t *address);
+
 #endif /* BREAKPOINTS_H */
 
        return ERROR_OK;
 }
 
+/**
+ * find out which watchpoint hits
+ * get exception address and compare the address to watchpoints
+ */
+static int nds32_v2_hit_watchpoint(struct target *target,
+               struct watchpoint **hit_watchpoint)
+{
+       uint32_t exception_address;
+       struct watchpoint *wp;
+       static struct watchpoint scan_all_watchpoint;
+       struct nds32 *nds32 = target_to_nds32(target);
+
+       scan_all_watchpoint.address = 0;
+       scan_all_watchpoint.rw = WPT_WRITE;
+       scan_all_watchpoint.next = 0;
+       scan_all_watchpoint.unique_id = 0x5CA8;
+
+       exception_address = nds32->watched_address;
+
+       if (exception_address == 0) {
+               /* send watch:0 to tell GDB to do software scan for hitting multiple watchpoints */
+               *hit_watchpoint = &scan_all_watchpoint;
+               return ERROR_OK;
+       }
+
+       for (wp = target->watchpoints; wp; wp = wp->next) {
+               if (((exception_address ^ wp->address) & (~wp->mask)) == 0) {
+                       /* TODO: dispel false match */
+                       *hit_watchpoint = wp;
+                       return ERROR_OK;
+               }
+       }
+
+       return ERROR_FAIL;
+}
+
 static int nds32_v2_run_algorithm(struct target *target,
                int num_mem_params,
                struct mem_param *mem_params,
        .remove_breakpoint = nds32_v2_remove_breakpoint,
        .add_watchpoint = nds32_v2_add_watchpoint,
        .remove_watchpoint = nds32_v2_remove_watchpoint,
+       .hit_watchpoint = nds32_v2_hit_watchpoint,
 
        /* MMU */
        .mmu = nds32_mmu,
 
        .remove_breakpoint = nds32_v3_remove_breakpoint,
        .add_watchpoint = nds32_v3_add_watchpoint,
        .remove_watchpoint = nds32_v3_remove_watchpoint,
+       .hit_watchpoint = nds32_v3_hit_watchpoint,
 
        /* MMU */
        .mmu = nds32_mmu,
 
        return ERROR_FAIL;
 }
 
+/**
+ * find out which watchpoint hits
+ * get exception address and compare the address to watchpoints
+ */
+int nds32_v3_hit_watchpoint(struct target *target,
+               struct watchpoint **hit_watchpoint)
+{
+       static struct watchpoint scan_all_watchpoint;
+
+       uint32_t exception_address;
+       struct watchpoint *wp;
+       struct nds32 *nds32 = target_to_nds32(target);
+
+       exception_address = nds32->watched_address;
+
+       if (exception_address == 0xFFFFFFFF)
+               return ERROR_FAIL;
+
+       if (exception_address == 0) {
+               scan_all_watchpoint.address = 0;
+               scan_all_watchpoint.rw = WPT_WRITE;
+               scan_all_watchpoint.next = 0;
+               scan_all_watchpoint.unique_id = 0x5CA8;
+
+               *hit_watchpoint = &scan_all_watchpoint;
+               return ERROR_OK;
+       }
+
+       for (wp = target->watchpoints; wp; wp = wp->next) {
+               if (((exception_address ^ wp->address) & (~wp->mask)) == 0) {
+                       *hit_watchpoint = wp;
+
+                       return ERROR_OK;
+               }
+       }
+
+       return ERROR_FAIL;
+}
+
 int nds32_v3_target_create_common(struct target *target, struct nds32 *nds32)
 {
        nds32->register_map = nds32_v3_register_mapping;
 
        .remove_breakpoint = nds32_v3m_remove_breakpoint,
        .add_watchpoint = nds32_v3m_add_watchpoint,
        .remove_watchpoint = nds32_v3m_remove_watchpoint,
+       .hit_watchpoint = nds32_v3_hit_watchpoint,
 
        /* MMU */
        .mmu = nds32_mmu,
 
 {
        return target->type->remove_watchpoint(target, watchpoint);
 }
+int target_hit_watchpoint(struct target *target,
+               struct watchpoint **hit_watchpoint)
+{
+       if (target->state != TARGET_HALTED) {
+               LOG_WARNING("target %s is not halted", target->cmd_name);
+               return ERROR_TARGET_NOT_HALTED;
+       }
+
+       if (target->type->hit_watchpoint == NULL) {
+               /* For backward compatible, if hit_watchpoint is not implemented,
+                * return ERROR_FAIL such that gdb_server will not take the nonsense
+                * information. */
+               return ERROR_FAIL;
+       }
+
+       return target->type->hit_watchpoint(target, hit_watchpoint);
+}
 
 int target_get_gdb_reg_list(struct target *target,
                struct reg **reg_list[], int *reg_list_size,
 
 int target_remove_watchpoint(struct target *target,
                struct watchpoint *watchpoint);
 
+/**
+ * Find out the just hit @a watchpoint for @a target.
+ *
+ * This routine is a wrapper for target->type->hit_watchpoint.
+ */
+int target_hit_watchpoint(struct target *target,
+               struct watchpoint **watchpoint);
+
 /**
  * Obtain the registers for GDB.
  *
 
         */
        int (*remove_watchpoint)(struct target *target, struct watchpoint *watchpoint);
 
+       /* Find out just hit watchpoint. After the target hits a watchpoint, the
+        * information could assist gdb to locate where the modified/accessed memory is.
+        */
+       int (*hit_watchpoint)(struct target *target, struct watchpoint **hit_watchpoint);
+
        /**
         * Target algorithm support.  Do @b not call this method directly,
         * use target_run_algorithm() instead.