xref: /netbsd-src/sys/ddb/db_run.c (revision f1926b3d6fe75d06c59eb7c67a0dc491c408de67)
1*f1926b3dSmatt /*	$NetBSD: db_run.c,v 1.33 2014/09/19 17:29:01 matt Exp $	*/
2cf92afd6Scgd 
361f28255Scgd /*
461f28255Scgd  * Mach Operating System
5d9f8d88aSthorpej  * Copyright (c) 1993-1990 Carnegie Mellon University
661f28255Scgd  * All Rights Reserved.
761f28255Scgd  *
861f28255Scgd  * Permission to use, copy, modify and distribute this software and its
961f28255Scgd  * documentation is hereby granted, provided that both the copyright
1061f28255Scgd  * notice and this permission notice appear in all copies of the
1161f28255Scgd  * software, derivative works or modified versions, and any portions
1261f28255Scgd  * thereof, and that both notices appear in supporting documentation.
1361f28255Scgd  *
14b13e5d14Spk  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
1561f28255Scgd  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
1661f28255Scgd  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1761f28255Scgd  *
1861f28255Scgd  * Carnegie Mellon requests users of this software to return to
1961f28255Scgd  *
2061f28255Scgd  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
2161f28255Scgd  *  School of Computer Science
2261f28255Scgd  *  Carnegie Mellon University
2361f28255Scgd  *  Pittsburgh PA 15213-3890
2461f28255Scgd  *
2561f28255Scgd  * any improvements or extensions that they make and grant Carnegie the
2661f28255Scgd  * rights to redistribute these changes.
2737cabe30Scgd  *
2861f28255Scgd  * 	Author: David B. Golub, Carnegie Mellon University
2961f28255Scgd  *	Date:	7/90
3061f28255Scgd  */
3161f28255Scgd 
3261f28255Scgd /*
3361f28255Scgd  * Commands to run process.
3461f28255Scgd  */
35466e784eSjonathan 
361ac69d9cSlukem #include <sys/cdefs.h>
37*f1926b3dSmatt __KERNEL_RCSID(0, "$NetBSD: db_run.c,v 1.33 2014/09/19 17:29:01 matt Exp $");
381ac69d9cSlukem 
39466e784eSjonathan #include "opt_ddb.h"
40466e784eSjonathan 
4190856010Smycroft #include <sys/param.h>
4290856010Smycroft #include <sys/proc.h>
4390856010Smycroft 
4490856010Smycroft #include <machine/db_machdep.h>
4590856010Smycroft 
46da4e97dcSmycroft #include <ddb/db_run.h>
4761f28255Scgd #include <ddb/db_access.h>
48df2b2654Spk #include <ddb/db_break.h>
49df2b2654Spk 
504eaa4d66Ssimonb int	db_inst_count;
514eaa4d66Ssimonb int	db_load_count;
524eaa4d66Ssimonb int	db_store_count;
534eaa4d66Ssimonb 
54df2b2654Spk #ifdef	SOFTWARE_SSTEP
554eaa4d66Ssimonb static void	db_set_temp_breakpoint(db_breakpoint_t, db_addr_t);
564eaa4d66Ssimonb static void	db_delete_temp_breakpoint(db_breakpoint_t);
57df2b2654Spk static struct	db_breakpoint	db_not_taken_bkpt;
58df2b2654Spk static struct	db_breakpoint	db_taken_bkpt;
59df2b2654Spk #endif
60df2b2654Spk 
61df2b2654Spk #if defined(DDB)
62df2b2654Spk #include <ddb/db_lex.h>
638c2e3b4bSchristos #include <ddb/db_watch.h>
648c2e3b4bSchristos #include <ddb/db_output.h>
658c2e3b4bSchristos #include <ddb/db_sym.h>
668c2e3b4bSchristos #include <ddb/db_extern.h>
6761f28255Scgd 
684eaa4d66Ssimonb static int	db_run_mode;
6961f28255Scgd #define	STEP_NONE	0
7061f28255Scgd #define	STEP_ONCE	1
7161f28255Scgd #define	STEP_RETURN	2
7261f28255Scgd #define	STEP_CALLT	3
7361f28255Scgd #define	STEP_CONTINUE	4
7461f28255Scgd #define STEP_INVISIBLE	5
7561f28255Scgd #define	STEP_COUNT	6
7661f28255Scgd 
77712239e3Sthorpej static bool		db_sstep_print;
784eaa4d66Ssimonb static int		db_loop_count;
794eaa4d66Ssimonb static int		db_call_depth;
8061f28255Scgd 
81712239e3Sthorpej bool
db_stop_at_pc(db_regs_t * regs,bool * is_breakpoint)82712239e3Sthorpej db_stop_at_pc(db_regs_t *regs, bool *is_breakpoint)
8361f28255Scgd {
845e3d7e53Saugustss 	db_addr_t	pc;
855e3d7e53Saugustss 	db_breakpoint_t bkpt;
8661f28255Scgd 
871581707bSpk 	pc = PC_REGS(regs);
881581707bSpk 
8961f28255Scgd #ifdef	FIXUP_PC_AFTER_BREAK
9061f28255Scgd 	if (*is_breakpoint) {
9161f28255Scgd 		/*
92dc63f8c3Sthorpej 		 * Breakpoint trap.  Regardless if we treat this as a
93dc63f8c3Sthorpej 		 * real breakpoint (e.g. software single-step), fix up the PC.
9461f28255Scgd 		 */
95ea3925f5Sgwr 		FIXUP_PC_AFTER_BREAK(regs);
96da4e97dcSmycroft 		pc = PC_REGS(regs);
9761f28255Scgd 	}
9861f28255Scgd #endif
9961f28255Scgd 
100dc63f8c3Sthorpej #ifdef	SOFTWARE_SSTEP
101dc63f8c3Sthorpej 	/*
102dc63f8c3Sthorpej 	 * If we stopped at one of the single-step breakpoints, say it's not
103dc63f8c3Sthorpej 	 * really a breakpoint so that we don't skip over the real instruction.
104dc63f8c3Sthorpej 	 */
105dc63f8c3Sthorpej 	if (db_taken_bkpt.address == pc || db_not_taken_bkpt.address == pc)
1064f3d5a9cSthorpej 		*is_breakpoint = false;
107dc63f8c3Sthorpej #endif	/* SOFTWARE_SSTEP */
108dc63f8c3Sthorpej 
109dc63f8c3Sthorpej 	db_clear_single_step(regs);
110dc63f8c3Sthorpej 	db_clear_breakpoints();
111dc63f8c3Sthorpej 	db_clear_watchpoints();
112dc63f8c3Sthorpej 
11361f28255Scgd 	/*
11461f28255Scgd 	 * Now check for a breakpoint at this address.
11561f28255Scgd 	 */
11661f28255Scgd 	bkpt = db_find_breakpoint_here(pc);
11761f28255Scgd 	if (bkpt) {
11861f28255Scgd 		if (--bkpt->count == 0) {
11961f28255Scgd 			bkpt->count = bkpt->init_count;
1204f3d5a9cSthorpej 			*is_breakpoint = true;
1214f3d5a9cSthorpej 			return (true);	/* stop here */
12261f28255Scgd 		}
12361f28255Scgd 	} else if (*is_breakpoint) {
124ae6bc354Spk #ifdef PC_ADVANCE
125ae6bc354Spk 		PC_ADVANCE(regs);
126ae6bc354Spk #else
127da4e97dcSmycroft 		PC_REGS(regs) += BKPT_SIZE;
128ae6bc354Spk #endif
12961f28255Scgd 	}
13061f28255Scgd 
1314f3d5a9cSthorpej 	*is_breakpoint = false;
13261f28255Scgd 
13361f28255Scgd 	if (db_run_mode == STEP_INVISIBLE) {
13461f28255Scgd 		db_run_mode = STEP_CONTINUE;
1354f3d5a9cSthorpej 		return (false);	/* continue */
13661f28255Scgd 	}
13761f28255Scgd 	if (db_run_mode == STEP_COUNT) {
1384f3d5a9cSthorpej 		return (false); /* continue */
13961f28255Scgd 	}
14061f28255Scgd 	if (db_run_mode == STEP_ONCE) {
14161f28255Scgd 		if (--db_loop_count > 0) {
14261f28255Scgd 			if (db_sstep_print) {
14361f28255Scgd 				db_printf("\t\t");
14461f28255Scgd 				db_print_loc_and_inst(pc);
14561f28255Scgd 				db_printf("\n");
14661f28255Scgd 			}
1474f3d5a9cSthorpej 			return (false);	/* continue */
14861f28255Scgd 		}
14961f28255Scgd 	}
15061f28255Scgd 	if (db_run_mode == STEP_RETURN) {
1514f3d5a9cSthorpej 		db_expr_t ins = db_get_value(pc, sizeof(int), false);
15261f28255Scgd 
15361f28255Scgd 		/* continue until matching return */
15461f28255Scgd 
15561f28255Scgd 		if (!inst_trap_return(ins) &&
15661f28255Scgd 		    (!inst_return(ins) || --db_call_depth != 0)) {
15761f28255Scgd 			if (db_sstep_print) {
15861f28255Scgd 				if (inst_call(ins) || inst_return(ins)) {
1595e3d7e53Saugustss 					int i;
16061f28255Scgd 
1614eaa4d66Ssimonb 					db_printf("[after %6d]     ",
1624eaa4d66Ssimonb 					    db_inst_count);
16361f28255Scgd 					for (i = db_call_depth; --i > 0; )
16461f28255Scgd 						db_printf("  ");
16561f28255Scgd 					db_print_loc_and_inst(pc);
16661f28255Scgd 					db_printf("\n");
16761f28255Scgd 				}
16861f28255Scgd 			}
16961f28255Scgd 			if (inst_call(ins))
17061f28255Scgd 				db_call_depth++;
1714f3d5a9cSthorpej 			return (false);	/* continue */
17261f28255Scgd 		}
17361f28255Scgd 	}
17461f28255Scgd 	if (db_run_mode == STEP_CALLT) {
1754f3d5a9cSthorpej 		db_expr_t ins = db_get_value(pc, sizeof(int), false);
17661f28255Scgd 
17761f28255Scgd 		/* continue until call or return */
17861f28255Scgd 
17961f28255Scgd 		if (!inst_call(ins) &&
18061f28255Scgd 		    !inst_return(ins) &&
18161f28255Scgd 		    !inst_trap_return(ins)) {
1824f3d5a9cSthorpej 			return (false);	/* continue */
18361f28255Scgd 		}
18461f28255Scgd 	}
18561f28255Scgd 	db_run_mode = STEP_NONE;
1864f3d5a9cSthorpej 	return (true);
18761f28255Scgd }
18861f28255Scgd 
18961f28255Scgd void
db_restart_at_pc(db_regs_t * regs,bool watchpt)190712239e3Sthorpej db_restart_at_pc(db_regs_t *regs, bool watchpt)
19161f28255Scgd {
1925e3d7e53Saugustss 	db_addr_t pc = PC_REGS(regs);
1934eaa4d66Ssimonb #ifdef SOFTWARE_SSTEP
1944eaa4d66Ssimonb 	db_addr_t brpc;
1954eaa4d66Ssimonb #endif
19661f28255Scgd 
19761f28255Scgd 	if ((db_run_mode == STEP_COUNT) ||
19861f28255Scgd 	    (db_run_mode == STEP_RETURN) ||
19961f28255Scgd 	    (db_run_mode == STEP_CALLT)) {
2009197dcbbSmartin 		db_expr_t		ins __unused;
20161f28255Scgd 
20261f28255Scgd 		/*
20361f28255Scgd 		 * We are about to execute this instruction,
20461f28255Scgd 		 * so count it now.
20561f28255Scgd 		 */
2064f3d5a9cSthorpej 		ins = db_get_value(pc, sizeof(int), false);
20761f28255Scgd 		db_inst_count++;
20861f28255Scgd 		db_load_count += inst_load(ins);
20961f28255Scgd 		db_store_count += inst_store(ins);
210d9f8d88aSthorpej 
211d9f8d88aSthorpej #ifdef SOFTWARE_SSTEP
212d9f8d88aSthorpej 		/*
213d9f8d88aSthorpej 		 * Account for instructions in delay slots.
214d9f8d88aSthorpej 		 */
2154f3d5a9cSthorpej 		brpc = next_instr_address(pc, true);
21626a93b89Smycroft 		if ((brpc != pc) &&
21726a93b89Smycroft 		    (inst_branch(ins) || inst_call(ins) || inst_return(ins))) {
2184f3d5a9cSthorpej 			ins = db_get_value(brpc, sizeof(int), false);
21961f28255Scgd 			db_inst_count++;
22061f28255Scgd 			db_load_count += inst_load(ins);
22161f28255Scgd 			db_store_count += inst_store(ins);
22261f28255Scgd 		}
223a34fffe6Scgd #endif
22461f28255Scgd 	}
22561f28255Scgd 
22661f28255Scgd 	if (db_run_mode == STEP_CONTINUE) {
22761f28255Scgd 		if (watchpt || db_find_breakpoint_here(pc)) {
22861f28255Scgd 			/*
22961f28255Scgd 			 * Step over breakpoint/watchpoint.
23061f28255Scgd 			 */
23161f28255Scgd 			db_run_mode = STEP_INVISIBLE;
232da4e97dcSmycroft 			db_set_single_step(regs);
23361f28255Scgd 		} else {
23461f28255Scgd 			db_set_breakpoints();
23561f28255Scgd 			db_set_watchpoints();
23661f28255Scgd 		}
23761f28255Scgd 	} else {
238da4e97dcSmycroft 		db_set_single_step(regs);
23961f28255Scgd 	}
24061f28255Scgd }
24161f28255Scgd 
24261f28255Scgd void
db_single_step(db_regs_t * regs)2434eaa4d66Ssimonb db_single_step(db_regs_t *regs)
24461f28255Scgd {
2454eaa4d66Ssimonb 
24661f28255Scgd 	if (db_run_mode == STEP_CONTINUE) {
24761f28255Scgd 		db_run_mode = STEP_INVISIBLE;
24861f28255Scgd 		db_set_single_step(regs);
24961f28255Scgd 	}
25061f28255Scgd }
25161f28255Scgd 
25261f28255Scgd /* single-step */
25361f28255Scgd /*ARGSUSED*/
25461f28255Scgd void
db_single_step_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)25593feeb12Smatt db_single_step_cmd(db_expr_t addr, bool have_addr,
2564d595fd7Schristos     db_expr_t count, const char *modif)
25761f28255Scgd {
2584f3d5a9cSthorpej 	bool print = false;
25961f28255Scgd 
26061f28255Scgd 	if (count == -1)
26161f28255Scgd 		count = 1;
26261f28255Scgd 
26361f28255Scgd 	if (modif[0] == 'p')
2644f3d5a9cSthorpej 		print = true;
26561f28255Scgd 
26661f28255Scgd 	db_run_mode = STEP_ONCE;
26761f28255Scgd 	db_loop_count = count;
26861f28255Scgd 	db_sstep_print = print;
26961f28255Scgd 	db_inst_count = 0;
27061f28255Scgd 	db_load_count = 0;
27161f28255Scgd 	db_store_count = 0;
27261f28255Scgd 
27334bb6e19Smartin 	db_cmd_loop_done = true;
27461f28255Scgd }
27561f28255Scgd 
27661f28255Scgd /* trace and print until call/return */
27761f28255Scgd /*ARGSUSED*/
27861f28255Scgd void
db_trace_until_call_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)27993feeb12Smatt db_trace_until_call_cmd(db_expr_t addr, bool have_addr,
280168cd830Schristos     db_expr_t count, const char *modif)
28161f28255Scgd {
2824f3d5a9cSthorpej 	bool print = false;
28361f28255Scgd 
28461f28255Scgd 	if (modif[0] == 'p')
2854f3d5a9cSthorpej 		print = true;
28661f28255Scgd 
28761f28255Scgd 	db_run_mode = STEP_CALLT;
28861f28255Scgd 	db_sstep_print = print;
28961f28255Scgd 	db_inst_count = 0;
29061f28255Scgd 	db_load_count = 0;
29161f28255Scgd 	db_store_count = 0;
29261f28255Scgd 
29334bb6e19Smartin 	db_cmd_loop_done = true;
29461f28255Scgd }
29561f28255Scgd 
29661f28255Scgd /*ARGSUSED*/
29761f28255Scgd void
db_trace_until_matching_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)29893feeb12Smatt db_trace_until_matching_cmd(db_expr_t addr, bool have_addr,
299168cd830Schristos     db_expr_t count, const char *modif)
30061f28255Scgd {
3014f3d5a9cSthorpej 	bool print = false;
30261f28255Scgd 
30361f28255Scgd 	if (modif[0] == 'p')
3044f3d5a9cSthorpej 		print = true;
30561f28255Scgd 
30661f28255Scgd 	db_run_mode = STEP_RETURN;
30761f28255Scgd 	db_call_depth = 1;
30861f28255Scgd 	db_sstep_print = print;
30961f28255Scgd 	db_inst_count = 0;
31061f28255Scgd 	db_load_count = 0;
31161f28255Scgd 	db_store_count = 0;
31261f28255Scgd 
31334bb6e19Smartin 	db_cmd_loop_done = true;
31461f28255Scgd }
31561f28255Scgd 
31661f28255Scgd /* continue */
31761f28255Scgd /*ARGSUSED*/
31861f28255Scgd void
db_continue_cmd(db_expr_t addr,bool have_addr,db_expr_t count,const char * modif)31993feeb12Smatt db_continue_cmd(db_expr_t addr, bool have_addr,
320168cd830Schristos     db_expr_t count, const char *modif)
32161f28255Scgd {
3224eaa4d66Ssimonb 
32361f28255Scgd 	if (modif[0] == 'c')
32461f28255Scgd 		db_run_mode = STEP_COUNT;
32561f28255Scgd 	else
32661f28255Scgd 		db_run_mode = STEP_CONTINUE;
32761f28255Scgd 	db_inst_count = 0;
32861f28255Scgd 	db_load_count = 0;
32961f28255Scgd 	db_store_count = 0;
33061f28255Scgd 
33134bb6e19Smartin 	db_cmd_loop_done = true;
33261f28255Scgd }
333df2b2654Spk #endif /* DDB */
334df2b2654Spk 
335df2b2654Spk #ifdef SOFTWARE_SSTEP
336df2b2654Spk /*
337df2b2654Spk  *	Software implementation of single-stepping.
338df2b2654Spk  *	If your machine does not have a trace mode
339df2b2654Spk  *	similar to the vax or sun ones you can use
340df2b2654Spk  *	this implementation, done for the mips.
341df2b2654Spk  *	Just define the above conditional and provide
342df2b2654Spk  *	the functions/macros defined below.
343df2b2654Spk  *
344712239e3Sthorpej  * bool inst_branch(int inst)
345712239e3Sthorpej  * bool inst_call(int inst)
3464f3d5a9cSthorpej  *	returns true if the instruction might branch
347df2b2654Spk  *
348*f1926b3dSmatt  * bool inst_return(int inst)
349*f1926b3dSmatt  *	returns true is the instruction will return to its caller
350*f1926b3dSmatt  *
351712239e3Sthorpej  * bool inst_unconditional_flow_transfer(int inst)
3524f3d5a9cSthorpej  *	returns true if the instruction is an unconditional
353df2b2654Spk  *	transter of flow (i.e. unconditional branch)
354df2b2654Spk  *
355df2b2654Spk  * db_addr_t branch_taken(int inst, db_addr_t pc, db_regs_t *regs)
356df2b2654Spk  *	returns the target address of the branch
357df2b2654Spk  *
358712239e3Sthorpej  * db_addr_t next_instr_address(db_addr_t pc, bool bd)
359df2b2654Spk  *	returns the address of the first instruction following the
360df2b2654Spk  *	one at "pc", which is either in the taken path of the branch
3614f3d5a9cSthorpej  *	(bd == true) or not.  This is for machines (e.g. mips) with
362df2b2654Spk  *	branch delays.
363df2b2654Spk  *
364df2b2654Spk  *	A single-step may involve at most 2 breakpoints -
365df2b2654Spk  *	one for branch-not-taken and one for branch taken.
366df2b2654Spk  *	If one of these addresses does not already have a breakpoint,
367df2b2654Spk  *	we allocate a breakpoint and save it here.
368df2b2654Spk  *	These breakpoints are deleted on return.
369df2b2654Spk  */
370df2b2654Spk 
371df2b2654Spk #if !defined(DDB)
372df2b2654Spk /* XXX - don't check for existing breakpoints in KGDB-only case */
373df2b2654Spk #define db_find_breakpoint_here(pc)	(0)
374df2b2654Spk #endif
375df2b2654Spk 
376df2b2654Spk void
db_set_single_step(db_regs_t * regs)3774eaa4d66Ssimonb db_set_single_step(db_regs_t *regs)
378df2b2654Spk {
379df2b2654Spk 	db_addr_t pc = PC_REGS(regs), brpc = pc;
380712239e3Sthorpej 	bool unconditional;
381df2b2654Spk 	unsigned int inst;
382df2b2654Spk 
383df2b2654Spk 	/*
384df2b2654Spk 	 *	User was stopped at pc, e.g. the instruction
385df2b2654Spk 	 *	at pc was not executed.
386df2b2654Spk 	 */
3874f3d5a9cSthorpej 	inst = db_get_value(pc, sizeof(int), false);
38826a93b89Smycroft 	if (inst_branch(inst) || inst_call(inst) || inst_return(inst)) {
389df2b2654Spk 		brpc = branch_taken(inst, pc, regs);
390df2b2654Spk 		if (brpc != pc) {	/* self-branches are hopeless */
391df2b2654Spk 			db_set_temp_breakpoint(&db_taken_bkpt, brpc);
392df2b2654Spk 		} else
393df2b2654Spk 			db_taken_bkpt.address = 0;
3944f3d5a9cSthorpej 		pc = next_instr_address(pc, true);
395df2b2654Spk 	}
396df2b2654Spk 
397df2b2654Spk 	/*
398df2b2654Spk 	 *	Check if this control flow instruction is an
399df2b2654Spk 	 *	unconditional transfer.
400df2b2654Spk 	 */
401df2b2654Spk 	unconditional = inst_unconditional_flow_transfer(inst);
402df2b2654Spk 
4034f3d5a9cSthorpej 	pc = next_instr_address(pc, false);
404df2b2654Spk 
405df2b2654Spk 	/*
406df2b2654Spk 	 *	We only set the sequential breakpoint if previous
407df2b2654Spk 	 *	instruction was not an unconditional change of flow
408df2b2654Spk 	 *	control.  If the previous instruction is an
409df2b2654Spk 	 *	unconditional change of flow control, setting a
410df2b2654Spk 	 *	breakpoint in the next sequential location may set
411df2b2654Spk 	 *	a breakpoint in data or in another routine, which
412df2b2654Spk 	 *	could screw up in either the program or the debugger.
413df2b2654Spk 	 *	(Consider, for instance, that the next sequential
414df2b2654Spk 	 *	instruction is the start of a routine needed by the
415df2b2654Spk 	 *	debugger.)
416df2b2654Spk 	 *
417df2b2654Spk 	 *	Also, don't set both the taken and not-taken breakpoints
418df2b2654Spk 	 *	in the same place even if the MD code would otherwise
419df2b2654Spk 	 *	have us do so.
420df2b2654Spk 	 */
4214f3d5a9cSthorpej 	if (unconditional == false &&
422df2b2654Spk 	    db_find_breakpoint_here(pc) == 0 &&
423df2b2654Spk 	    pc != brpc)
424df2b2654Spk 		db_set_temp_breakpoint(&db_not_taken_bkpt, pc);
425df2b2654Spk 	else
426df2b2654Spk 		db_not_taken_bkpt.address = 0;
427df2b2654Spk }
428df2b2654Spk 
429df2b2654Spk void
db_clear_single_step(db_regs_t * regs)4304eaa4d66Ssimonb db_clear_single_step(db_regs_t *regs)
431df2b2654Spk {
432df2b2654Spk 
433df2b2654Spk 	if (db_taken_bkpt.address != 0)
434df2b2654Spk 		db_delete_temp_breakpoint(&db_taken_bkpt);
435df2b2654Spk 
436df2b2654Spk 	if (db_not_taken_bkpt.address != 0)
437df2b2654Spk 		db_delete_temp_breakpoint(&db_not_taken_bkpt);
438df2b2654Spk }
439df2b2654Spk 
440df2b2654Spk void
db_set_temp_breakpoint(db_breakpoint_t bkpt,db_addr_t addr)4414eaa4d66Ssimonb db_set_temp_breakpoint(db_breakpoint_t bkpt, db_addr_t addr)
442df2b2654Spk {
443df2b2654Spk 
444df2b2654Spk 	bkpt->map = NULL;
445df2b2654Spk 	bkpt->address = addr;
446df2b2654Spk 	/* bkpt->flags = BKPT_TEMP;	- this is not used */
447df2b2654Spk 	bkpt->init_count = 1;
448df2b2654Spk 	bkpt->count = 1;
449df2b2654Spk 
4504f3d5a9cSthorpej 	bkpt->bkpt_inst = db_get_value(bkpt->address, BKPT_SIZE, false);
451f2b7814eShe 	db_put_value(bkpt->address, BKPT_SIZE,
452f2b7814eShe 		BKPT_SET(bkpt->bkpt_inst, bkpt->address));
453df2b2654Spk }
454df2b2654Spk 
455df2b2654Spk void
db_delete_temp_breakpoint(db_breakpoint_t bkpt)4564eaa4d66Ssimonb db_delete_temp_breakpoint(db_breakpoint_t bkpt)
457df2b2654Spk {
4584eaa4d66Ssimonb 
459df2b2654Spk 	db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst);
460df2b2654Spk 	bkpt->address = 0;
461df2b2654Spk }
462df2b2654Spk #endif /* SOFTWARE_SSTEP */
463