mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-01 20:12:01 +08:00
Initial creation of sourceware repository
This commit is contained in:
278
sim/common/sim-break.c
Normal file
278
sim/common/sim-break.c
Normal file
@ -0,0 +1,278 @@
|
||||
/* Simulator breakpoint support.
|
||||
Copyright (C) 1997 Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support.
|
||||
|
||||
This file is part of GDB, the GNU debugger.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sim-main.h"
|
||||
#include "sim-assert.h"
|
||||
#include "sim-break.h"
|
||||
|
||||
#ifndef SIM_BREAKPOINT
|
||||
#define SIM_BREAKPOINT {0x00}
|
||||
#define SIM_BREAKPOINT_SIZE (1)
|
||||
#endif
|
||||
|
||||
struct
|
||||
sim_breakpoint
|
||||
{
|
||||
struct sim_breakpoint *next;
|
||||
SIM_ADDR addr; /* Address of this breakpoint */
|
||||
int flags;
|
||||
unsigned char loc_contents[SIM_BREAKPOINT_SIZE]; /* Contents of addr while
|
||||
BP is enabled */
|
||||
};
|
||||
|
||||
#define SIM_BREAK_INSERTED 0x1 /* Breakpoint has been inserted */
|
||||
#define SIM_BREAK_DISABLED 0x2 /* Breakpoint is disabled */
|
||||
|
||||
static unsigned char sim_breakpoint [] = SIM_BREAKPOINT;
|
||||
|
||||
static void insert_breakpoint PARAMS ((SIM_DESC sd,
|
||||
struct sim_breakpoint *bp));
|
||||
static void remove_breakpoint PARAMS ((SIM_DESC sd,
|
||||
struct sim_breakpoint *bp));
|
||||
static SIM_RC resume_handler PARAMS ((SIM_DESC sd));
|
||||
static SIM_RC suspend_handler PARAMS ((SIM_DESC sd));
|
||||
|
||||
|
||||
/* Do the actual work of inserting a breakpoint into the instruction
|
||||
stream. */
|
||||
|
||||
static void
|
||||
insert_breakpoint (sd, bp)
|
||||
SIM_DESC sd;
|
||||
struct sim_breakpoint *bp;
|
||||
{
|
||||
if (bp->flags & (SIM_BREAK_INSERTED | SIM_BREAK_DISABLED))
|
||||
return;
|
||||
|
||||
sim_core_read_buffer (sd, NULL, exec_map, bp->loc_contents,
|
||||
bp->addr, SIM_BREAKPOINT_SIZE);
|
||||
sim_core_write_buffer (sd, NULL, exec_map, sim_breakpoint,
|
||||
bp->addr, SIM_BREAKPOINT_SIZE);
|
||||
bp->flags |= SIM_BREAK_INSERTED;
|
||||
}
|
||||
|
||||
/* Do the actual work of removing a breakpoint. */
|
||||
|
||||
static void
|
||||
remove_breakpoint (sd, bp)
|
||||
SIM_DESC sd;
|
||||
struct sim_breakpoint *bp;
|
||||
{
|
||||
if (!(bp->flags & SIM_BREAK_INSERTED))
|
||||
return;
|
||||
|
||||
sim_core_write_buffer (sd, NULL, exec_map, bp->loc_contents,
|
||||
bp->addr, SIM_BREAKPOINT_SIZE);
|
||||
bp->flags &= ~SIM_BREAK_INSERTED;
|
||||
}
|
||||
|
||||
/* Come here when a breakpoint insn is hit. If it's really a breakpoint, we
|
||||
halt things, and never return. If it's a false hit, we return to let the
|
||||
caller handle things. */
|
||||
|
||||
void
|
||||
sim_handle_breakpoint (sd, cpu, cia)
|
||||
SIM_DESC sd;
|
||||
sim_cpu *cpu;
|
||||
sim_cia cia;
|
||||
{
|
||||
struct sim_breakpoint *bp;
|
||||
|
||||
for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next)
|
||||
if (bp->addr == CIA_ADDR (cia))
|
||||
break;
|
||||
|
||||
if (!bp || !(bp->flags & SIM_BREAK_INSERTED))
|
||||
return;
|
||||
|
||||
sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, cia, sim_stopped, SIM_SIGTRAP);
|
||||
}
|
||||
|
||||
/* Handler functions for simulator resume and suspend events. */
|
||||
|
||||
static SIM_RC
|
||||
resume_handler (sd)
|
||||
SIM_DESC sd;
|
||||
{
|
||||
struct sim_breakpoint *bp;
|
||||
|
||||
for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next)
|
||||
insert_breakpoint (sd, bp);
|
||||
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
static SIM_RC
|
||||
suspend_handler (sd)
|
||||
SIM_DESC sd;
|
||||
{
|
||||
struct sim_breakpoint *bp;
|
||||
|
||||
for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next)
|
||||
remove_breakpoint (sd, bp);
|
||||
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
/* Called from simulator module initialization. */
|
||||
|
||||
SIM_RC
|
||||
sim_break_install (sd)
|
||||
SIM_DESC sd;
|
||||
{
|
||||
sim_module_add_resume_fn (sd, resume_handler);
|
||||
sim_module_add_suspend_fn (sd, suspend_handler);
|
||||
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
/* Install a breakpoint. This is a user-function. The breakpoint isn't
|
||||
actually installed here. We just record it. Resume_handler does the
|
||||
actual work.
|
||||
*/
|
||||
|
||||
SIM_RC
|
||||
sim_set_breakpoint (sd, addr)
|
||||
SIM_DESC sd;
|
||||
SIM_ADDR addr;
|
||||
{
|
||||
struct sim_breakpoint *bp;
|
||||
|
||||
for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next)
|
||||
if (bp->addr == addr)
|
||||
return SIM_RC_DUPLICATE_BREAKPOINT; /* Already there */
|
||||
else
|
||||
break; /* FIXME: why not scan all bp's? */
|
||||
|
||||
bp = ZALLOC (struct sim_breakpoint);
|
||||
|
||||
bp->addr = addr;
|
||||
bp->next = STATE_BREAKPOINTS (sd);
|
||||
bp->flags = 0;
|
||||
STATE_BREAKPOINTS (sd) = bp;
|
||||
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
/* Delete a breakpoint. All knowlege of the breakpoint is removed from the
|
||||
simulator.
|
||||
*/
|
||||
|
||||
SIM_RC
|
||||
sim_clear_breakpoint (sd, addr)
|
||||
SIM_DESC sd;
|
||||
SIM_ADDR addr;
|
||||
{
|
||||
struct sim_breakpoint *bp, *bpprev;
|
||||
|
||||
for (bp = STATE_BREAKPOINTS (sd), bpprev = NULL;
|
||||
bp;
|
||||
bpprev = bp, bp = bp->next)
|
||||
if (bp->addr == addr)
|
||||
break;
|
||||
|
||||
if (!bp)
|
||||
return SIM_RC_UNKNOWN_BREAKPOINT;
|
||||
|
||||
remove_breakpoint (sd, bp);
|
||||
|
||||
if (bpprev)
|
||||
bpprev->next = bp->next;
|
||||
else
|
||||
STATE_BREAKPOINTS (sd) = NULL;
|
||||
|
||||
zfree (bp);
|
||||
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
SIM_RC
|
||||
sim_clear_all_breakpoints (sd)
|
||||
SIM_DESC sd;
|
||||
{
|
||||
while (STATE_BREAKPOINTS (sd))
|
||||
sim_clear_breakpoint (sd, STATE_BREAKPOINTS (sd)->addr);
|
||||
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
SIM_RC
|
||||
sim_enable_breakpoint (sd, addr)
|
||||
SIM_DESC sd;
|
||||
SIM_ADDR addr;
|
||||
{
|
||||
struct sim_breakpoint *bp;
|
||||
|
||||
for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next)
|
||||
if (bp->addr == addr)
|
||||
break;
|
||||
|
||||
if (!bp)
|
||||
return SIM_RC_UNKNOWN_BREAKPOINT;
|
||||
|
||||
bp->flags &= ~SIM_BREAK_DISABLED;
|
||||
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
SIM_RC
|
||||
sim_disable_breakpoint (sd, addr)
|
||||
SIM_DESC sd;
|
||||
SIM_ADDR addr;
|
||||
{
|
||||
struct sim_breakpoint *bp;
|
||||
|
||||
for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next)
|
||||
if (bp->addr == addr)
|
||||
break;
|
||||
|
||||
if (!bp)
|
||||
return SIM_RC_UNKNOWN_BREAKPOINT;
|
||||
|
||||
bp->flags |= SIM_BREAK_DISABLED;
|
||||
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
SIM_RC
|
||||
sim_enable_all_breakpoints (sd)
|
||||
SIM_DESC sd;
|
||||
{
|
||||
struct sim_breakpoint *bp;
|
||||
|
||||
for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next)
|
||||
bp->flags &= ~SIM_BREAK_DISABLED;
|
||||
|
||||
return SIM_RC_OK;
|
||||
}
|
||||
|
||||
SIM_RC
|
||||
sim_disable_all_breakpoints (sd)
|
||||
SIM_DESC sd;
|
||||
{
|
||||
struct sim_breakpoint *bp;
|
||||
|
||||
for (bp = STATE_BREAKPOINTS (sd); bp; bp = bp->next)
|
||||
bp->flags |= SIM_BREAK_DISABLED;
|
||||
|
||||
return SIM_RC_OK;
|
||||
}
|
Reference in New Issue
Block a user