From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 42228 invoked by alias); 17 Mar 2015 21:03:27 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 42156 invoked by uid 89); 17 Mar 2015 21:03:26 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.5 required=5.0 tests=AWL,BAYES_00,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 X-HELO: bin-vsp-out-03.atm.binero.net Received: from vsp-unauthed01.binero.net (HELO bin-vsp-out-03.atm.binero.net) (195.74.38.225) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Tue, 17 Mar 2015 21:03:23 +0000 X-Halon-ID: 08110440-cce9-11e4-9958-0050569116f7 Authorized-sender: jiri@gaisler.se Received: from localhost.localdomain (unknown [46.246.62.93]) by bin-vsp-out-03.atm.binero.net (Halon Mail Gateway) with ESMTPSA; Tue, 17 Mar 2015 22:03:16 +0100 (CET) From: Jiri Gaisler To: gdb-patches@sourceware.org Cc: Jiri Gaisler Subject: [PATCH v4 12/13] sim/erc32: Add data watchpoint support Date: Tue, 17 Mar 2015 21:03:00 -0000 Message-Id: <1426626170-21401-13-git-send-email-jiri@gaisler.se> In-Reply-To: <1426626170-21401-1-git-send-email-jiri@gaisler.se> References: <1426626170-21401-1-git-send-email-jiri@gaisler.se> X-IsSubscribed: yes X-SW-Source: 2015-03/txt/msg00517.txt.bz2 Add watchpoint to all SPARC targets (erc32, leon2, leon3). --- sim/erc32/exec.c | 54 ++++++++++++++++++++++++++------ sim/erc32/func.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++- sim/erc32/interf.c | 3 +- sim/erc32/sis.c | 32 ++++++++++++++----- sim/erc32/sis.h | 23 +++++++++++++- 5 files changed, 181 insertions(+), 22 deletions(-) diff --git a/sim/erc32/exec.c b/sim/erc32/exec.c index 65d7487..44d4dda 100644 --- a/sim/erc32/exec.c +++ b/sim/erc32/exec.c @@ -395,6 +395,20 @@ extract_byte_signed (uint32 data, uint32 address) return tmp; } +/* Decode watchpoint address mask from opcode. Not correct for LDST, + SWAP and STFSR but watchpoints will work anyway. */ + +static unsigned char +wpmask(uint32 op3) +{ + switch (op3 & 3) { + case 0: return(3); /* word */ + case 1: return(0); /* byte */ + case 2: return(1); /* half-word */ + case 3: return(7); /* double word */ + } +} + int dispatch_instruction (sregs) struct pstate *sregs; @@ -698,6 +712,12 @@ dispatch_instruction (sregs) } if (eicc & 1) { sregs->trap = (0x80 | ((rs1 + operand2) & 0x7f)); + if ((sregs->trap == 129) && (sis_gdb_break) && + (sregs->inst == 0x91d02001)) + { + sregs->trap = WPT_TRAP; + sregs->bphit = 1; + } } break; @@ -1211,18 +1231,25 @@ dispatch_instruction (sregs) address = rs1 + operand2; - if (sregs->psr & PSR_S) - asi = 11; - else - asi = 10; - if (op3 & 4) { sregs->icnt = T_ST; /* Set store instruction count */ + if (sregs->wpwnum) { + if (sregs->wphit = check_wpw(sregs, address, wpmask(op3))) { + sregs->trap = WPT_TRAP; + break; + } + } #ifdef STAT sregs->nstore++; #endif } else { sregs->icnt = T_LD; /* Set load instruction count */ + if (sregs->wprnum) { + if (sregs->wphit = check_wpr(sregs, address, wpmask(op3))) { + sregs->trap = WPT_TRAP; + break; + } + } #ifdef STAT sregs->nload++; #endif @@ -2133,12 +2160,18 @@ execute_trap(sregs) { int32 cwp; - if (sregs->trap == 256) { - sregs->pc = 0; - sregs->npc = 4; - sregs->trap = 0; - } else if (sregs->trap == 257) { + if (sregs->trap >= 256) { + switch (sregs->trap) { + case 256: + sregs->pc = 0; + sregs->npc = 4; + sregs->trap = 0; + break; + case ERROR_TRAP: return (ERROR); + case WPT_TRAP: + return (WPT_HIT); + } } else { if ((sregs->psr & PSR_ET) == 0) @@ -2231,6 +2264,7 @@ init_regs(sregs) sregs->fpu_pres = !nfp; set_fsr(sregs->fsr); sregs->bphit = 0; + sregs->wphit = 0; sregs->ildreg = 0; sregs->ildtime = 0; diff --git a/sim/erc32/func.c b/sim/erc32/func.c index ae740ec..0be47f0 100644 --- a/sim/erc32/func.c +++ b/sim/erc32/func.c @@ -62,7 +62,9 @@ uint32 last_load_addr = 0; int nouartrx = 0; host_callback *sim_callback; const struct memsys *ms = &erc32sys; -int cputype = 0; /* 0 = erc32, 3 = leon3 */ +int cputype = 0; /* 0 = erc32, 2 = leon2,3 = leon3 */ +int sis_gdb_break; + #ifdef ERRINJ uint32 errcnt = 0; @@ -626,6 +628,53 @@ exec_cmd(struct pstate *sregs, const char *cmd) stat = run_sim(sregs, UINT64_MAX, 0); daddr = sregs->pc; ms->sim_halt(); + } else if (strncmp(cmd1, "wp", clen) == 0) { + for (i = 0; i < sregs->wprnum; i++) { + printf(" %d : 0x%08x (read)\n", i + 1, sregs->wprs[i]); + } + for (i = 0; i < sregs->wpwnum; i++) { + printf(" %d : 0x%08x (write)\n", i + 1, sregs->wpws[i]); + } + } else if (strncmp(cmd1, "+wpr", clen) == 0) { + if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) { + sregs->wprs[sregs->wprnum] = VAL(cmd1) & ~0x3; + sregs->wprm[sregs->wprnum] = 3; + printf("added read watchpoint %d at 0x%08x\n", + sregs->wprnum + 1, sregs->wprs[sregs->wprnum]); + sregs->wprnum += 1; + } + } else if (strncmp(cmd1, "-wpr", clen) == 0) { + if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) { + i = VAL(cmd1) - 1; + if ((i >= 0) && (i < sregs->wprnum)) { + printf("deleted read watchpoint %d at 0x%08x\n", i + 1, + sregs->wprs[i]); + for (; i < sregs->wprnum - 1; i++) { + sregs->wprs[i] = sregs->wprs[i + 1]; + } + sregs->wprnum -= 1; + } + } + } else if (strncmp(cmd1, "+wpw", clen) == 0) { + if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) { + sregs->wpws[sregs->wpwnum] = VAL(cmd1) & ~0x3; + sregs->wpwm[sregs->wpwnum] = 3; + printf("added write watchpoint %d at 0x%08x\n", + sregs->wpwnum + 1, sregs->wpws[sregs->wpwnum]); + sregs->wpwnum += 1; + } + } else if (strncmp(cmd1, "-wpw", clen) == 0) { + if ((cmd1 = strtok(NULL, " \t\n\r")) != NULL) { + i = VAL(cmd1) - 1; + if ((i >= 0) && (i < sregs->wpwnum)) { + printf("deleted write watchpoint %d at 0x%08x\n", i + 1, + sregs->wpws[i]); + for (; i < sregs->wpwnum - 1; i++) { + sregs->wpws[i] = sregs->wpws[i + 1]; + } + sregs->wpwnum -= 1; + } + } } else printf("syntax error\n"); } @@ -716,6 +765,8 @@ init_bpt(sregs) struct pstate *sregs; { sregs->bptnum = 0; + sregs->wprnum = 0; + sregs->wpwnum = 0; sregs->histlen = 0; sregs->histind = 0; sregs->histbuf = NULL; @@ -1029,6 +1080,44 @@ check_bpt(sregs) return (0); } +int +check_wpr(sregs, address, mask) + struct pstate *sregs; + int32 address; + unsigned char mask; +{ + int32 i, msk; + + for (i = 0; i < sregs->wprnum; i++) { + msk = ~(mask | sregs->wprm[i]); + if (((address ^ sregs->wprs[i]) & msk) == 0) { + sregs->wpaddress = address; + if (sregs->wphit) return (0); + return (WPT_HIT); + } + } + return (0); +} + +int +check_wpw(sregs, address, mask) + struct pstate *sregs; + int32 address; + unsigned char mask; +{ + int32 i, msk; + + for (i = 0; i < sregs->wpwnum; i++) { + msk = ~(mask | sregs->wpwm[i]); + if (((address ^ sregs->wpws[i]) & msk) == 0) { + sregs->wpaddress = address; + if (sregs->wphit) return (0); + return (WPT_HIT); + } + } + return (0); +} + void reset_all() { diff --git a/sim/erc32/interf.c b/sim/erc32/interf.c index 2ed9914..f04041c 100644 --- a/sim/erc32/interf.c +++ b/sim/erc32/interf.c @@ -37,8 +37,6 @@ #define PSR_CWP 0x7 -int sis_gdb_break = 1; - int run_sim(sregs, icount, dis) struct pstate *sregs; @@ -163,6 +161,7 @@ sim_open (kind, callback, abfd, argv) int freq = 0; sim_callback = callback; + sis_gdb_break = 1; while (argv[argc]) argc++; diff --git a/sim/erc32/sis.c b/sim/erc32/sis.c index 99d5286..7c984bc 100644 --- a/sim/erc32/sis.c +++ b/sim/erc32/sis.c @@ -75,11 +75,7 @@ run_sim(sregs, icount, dis) sregs->trap = I_ACC_EXC; } else { if (deb) { - if ((sregs->bphit = check_bpt(sregs)) != 0) { - ms->restore_stdio(); - return (BPT_HIT); - } - if (sregs->histlen) { + if (sregs->histlen) { sregs->histbuf[sregs->histind].addr = sregs->pc; sregs->histbuf[sregs->histind].time = ebase.simtime; sregs->histind++; @@ -90,14 +86,25 @@ run_sim(sregs, icount, dis) printf(" %8" PRIu64 " ", ebase.simtime); dis_mem(sregs->pc, 1, &dinfo); } + if ((sregs->bptnum) && (sregs->bphit = check_bpt(sregs))) + icount = 0; + else { + dispatch_instruction(sregs); + icount--; + } + } else { + dispatch_instruction(sregs); + icount--; } - dispatch_instruction(sregs); - icount--; } } if (sregs->trap) { irq = 0; - sregs->err_mode = execute_trap(sregs); + if ((sregs->err_mode = execute_trap(sregs)) == WPT_HIT) { + sregs->err_mode = 0; + sregs->trap = 0; + icount = 0; + } if (sregs->err_mode) { ms->error_mode(sregs->pc); icount = 0; @@ -118,6 +125,10 @@ run_sim(sregs, icount, dis) ctrl_c = 0; return (CTRL_C); } + if (sregs->bphit) + return (BPT_HIT); + if (sregs->wphit) + return (WPT_HIT); return (TIME_OUT); } @@ -283,6 +294,11 @@ main(argc, argv) printf(" %8" PRIu64 " ", ebase.simtime); dis_mem(sregs.pc, 1, &dinfo); break; + case WPT_HIT: + printf("watchpoint at 0x%08x reached, pc = 0x%08x\n", + sregs.wpaddress, sregs.pc); + sregs.wphit = 1; + break; default: break; } diff --git a/sim/erc32/sis.h b/sim/erc32/sis.h index aef501b..abd21da 100644 --- a/sim/erc32/sis.h +++ b/sim/erc32/sis.h @@ -40,8 +40,10 @@ /* Maximum # of floating point queue */ #define FPUQN 1 -/* Maximum # of breakpoints */ +/* Maximum # of breakpoints and watchpoints */ #define BPT_MAX 256 +#define WPR_MAX 256 +#define WPW_MAX 256 struct histype { unsigned addr; @@ -101,6 +103,14 @@ struct pstate { uint32 bptnum; uint32 bphit; uint32 bpts[BPT_MAX]; /* Breakpoints */ + uint32 wprnum; + uint32 wphit; + uint32 wprs[WPR_MAX]; /* Read Watchpoints */ + unsigned char wprm[WPR_MAX]; /* Read Watchpoint masks*/ + uint32 wpwnum; + uint32 wpws[WPW_MAX]; /* Write Watchpoints */ + unsigned char wpwm[WPW_MAX]; /* Write Watchpoint masks */ + uint32 wpaddress; uint32 ltime; /* Load interlock time */ uint32 hold; /* IU hold cycles in current inst */ @@ -176,12 +186,19 @@ struct memsys { void (*boot_init) (void); }; +/* return values for run_sim */ #define OK 0 #define TIME_OUT 1 #define BPT_HIT 2 #define ERROR 3 #define CTRL_C 4 +#define WPT_HIT 5 +/* special simulator trap types */ +#define ERROR_TRAP 257 +#define WPT_TRAP 258 + +/* cpu type defines */ #define CPU_LEON2 2 #define CPU_LEON3 3 @@ -230,6 +247,9 @@ extern void advance_time (struct pstate *sregs); extern uint32 now (void); extern int wait_for_irq (void); extern int check_bpt (struct pstate *sregs); +extern int check_wpr(struct pstate *sregs, int32 address, unsigned char mask); +extern int check_wpw(struct pstate *sregs, int32 address, unsigned char mask); + extern void reset_all (void); extern void sys_reset (void); extern void sys_halt (void); @@ -240,6 +260,7 @@ extern host_callback *sim_callback; extern int current_target_byte_order; extern int dumbio; extern int cputype; +extern int sis_gdb_break; /* exec.c */ extern int dispatch_instruction (struct pstate *sregs); -- 1.9.1