#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;
int flags;
unsigned char loc_contents[SIM_BREAKPOINT_SIZE];
};
#define SIM_BREAK_INSERTED 0x1
#define SIM_BREAK_DISABLED 0x2
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));
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;
}
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;
}
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);
}
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;
}
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;
}
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;
else
break;
bp = ZALLOC (struct sim_breakpoint);
bp->addr = addr;
bp->next = STATE_BREAKPOINTS (sd);
bp->flags = 0;
STATE_BREAKPOINTS (sd) = bp;
return SIM_RC_OK;
}
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;
}