Skip to content

Commit

Permalink
Experimental: flush cache after writing a software break point.
Browse files Browse the repository at this point in the history
  • Loading branch information
[email protected] committed Aug 20, 2013
1 parent de77fa4 commit 3caae4d
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 11 deletions.
2 changes: 2 additions & 0 deletions mips.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#define MIPS_OP_ORI 0x0D
#define MIPS_OP_XOR 0x26
#define MIPS_OP_SRL 0x03
#define MIPS_OP_CACHE 0x2f

#define MIPS_COP0_MF 0x00
#define MIPS_COP0_MT 0x04
Expand Down Expand Up @@ -86,6 +87,7 @@
#define MIPS_SW(reg, off, base) MIPS_I_INST(MIPS_OP_SW, base, reg, off)
#define MIPS_XOR(reg, val1, val2) MIPS_R_INST(0, val1, val2, reg, 0, MIPS_OP_XOR)
#define MIPS_SRL(reg, src, off) MIPS_R_INST(0, 0, src, reg, off, MIPS_OP_SRL)
#define MIPS_CACHE(op, off, base) MIPS_I_INST(MIPS_OP_CACHE, base, op, off)

#define MIPS_DRET 0x4200001F
#define MIPS_BREAK 0x0000000D
Expand Down
32 changes: 21 additions & 11 deletions proxy-mips.c
Original file line number Diff line number Diff line change
Expand Up @@ -612,18 +612,22 @@ static int mips_write_mem(uint64_t addr,
}
unsigned offset = (addr & 3);

if (offset == 0 && write_size == 4 &&
target_is_rom_address (target.device, addr))
{
/* Software breakpoint: use hardware breakpoint instead. */
unsigned opcode = *(uint32_t*) buf;

if ((opcode & MIPS_BREAK_MASK) == MIPS_BREAK)
target_add_break (target.device, addr, 'b');
else
target_remove_break (target.device, addr);
return RP_VAL_TARGETRET_OK;
unsigned need_cache_flush = 0, cache_flush_addr = 0;
if (offset == 0 && write_size == 4) {
if (target_is_rom_address (target.device, addr)) {
unsigned opcode = *(uint32_t*) buf;

/* Software breakpoint in read only memory: use hardware breakpoint instead. */
if ((opcode & MIPS_BREAK_MASK) == MIPS_BREAK)
target_add_break (target.device, addr, 'b');
else
target_remove_break (target.device, addr);
return RP_VAL_TARGETRET_OK;
}
need_cache_flush = 1;
cache_flush_addr = addr;
}

if (offset != 0) {
/* Nonaligned address.
* Read a word and construct the value. */
Expand Down Expand Up @@ -681,6 +685,12 @@ static int mips_write_mem(uint64_t addr,
memcpy ((unsigned char*) &data, buf, write_size);
target_write_word (target.device, addr, data);
}
#if 1
// Experimental: Flush cache after writing a software break opcode.
if (need_cache_flush) {
target_cache_flush (target.device, cache_flush_addr);
}
#endif
return RP_VAL_TARGETRET_OK;
}

Expand Down
32 changes: 32 additions & 0 deletions target-ejtag.c
Original file line number Diff line number Diff line change
Expand Up @@ -952,6 +952,38 @@ void target_write_word (target_t *t, unsigned addr, unsigned word)
}
}

/*
* Flush the D-cache and invalidate I-cache on a given address.
*/
void target_cache_flush (target_t *t, unsigned addr)
{
static const unsigned code[] = { /* start: */
MIPS_MTC0 (15, 31, 0), /* move $15 to COP0 DeSave */
MIPS_LUI (15, UPPER16(PRACC_STACK)), /* $15 = PRACC_STACK */
MIPS_ORI (15, 15, LOWER16(PRACC_STACK)),
MIPS_SW (9, 0, 15), /* sw $9,($15) */

MIPS_LW (9, NEG16(PRACC_STACK - PRACC_PARAM_IN), 15), /* load R9 @ param_in[0] = address */

MIPS_CACHE (8+6, 0, 9), /* cache 8+6,0($9) - writeback D cache */
MIPS_CACHE (0+4, 0, 9), /* cache 0+4,0($9) - invalidate I cache */

MIPS_LW (9, 0, 15), /* lw $9,($15) */
MIPS_B (NEG16(9)), /* b start */
MIPS_MFC0 (15, 31, 0), /* move COP0 DeSave to $15 */
MIPS_NOP,
MIPS_NOP,
};
unsigned param_in [1];

param_in[0] = addr;
if (! t->adapter->exec (t->adapter, 1, ARRAY_SIZE(code), code,
ARRAY_SIZE(param_in), param_in, 0, 0))
{
fprintf (stderr, "ERROR: cannot flush cache at address %08x\n", addr);
}
}

/*
* Write chunk of data to memory.
*/
Expand Down
1 change: 1 addition & 0 deletions target.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ void target_read_block (target_t *t, unsigned addr,
void target_write_word (target_t *t, unsigned addr, unsigned word);
void target_write_block (target_t *t, unsigned addr,
unsigned nwords, unsigned *data);
void target_cache_flush (target_t *t, unsigned addr);

void target_stop (target_t *t);
void target_step (target_t *t);
Expand Down

0 comments on commit 3caae4d

Please sign in to comment.