Virtualmips: implement SDBBP instruction.

This commit is contained in:
Serge Vakulenko
2015-10-29 17:44:44 -07:00
parent 5bff2b428c
commit 8d15906495
5 changed files with 118 additions and 4 deletions

View File

@@ -299,9 +299,10 @@ int init_instance (vm_instance_t * vm)
cpu->cp0.config_reg[3] = 0x00000020;
/* set PC and PRID */
cpu->cp0.reg[MIPS_CP0_PRID] = 0x00018700;
cpu->cp0.tlb_entries = 0;
cpu->pc = m4k->start_address;
cpu->cp0.tlb_entries = 0;
cpu->cp0.reg[MIPS_CP0_PRID] = 0x00018700;
cpu->cp0.reg[MIPS_CP0_DEBUG] = 0x00010000;
/* Enable magic opcodes. */
cpu->magic_opcodes = 1;

View File

@@ -505,6 +505,70 @@ void mips_trigger_exception (cpu_mips_t * cpu, u_int exc_code, int bd_slot)
cpu->irq_pending = 0;
}
/*
* Generate a Debug exception
*/
void mips_trigger_debug_exception (cpu_mips_t *cpu, u_int dexc_type)
{
mips_cp0_t *cp0 = &cpu->cp0;
int old_dm = cpu->cp0.reg[MIPS_CP0_DEBUG] & MIPS_CP0_DEBUG_DM;
/* Set DEPC. */
cp0->reg[MIPS_CP0_DEPC] = cpu->pc;
/* Update exception type bits. */
cpu->cp0.reg[MIPS_CP0_DEBUG] &= ~(MIPS_CP0_DEBUG_DSS |
MIPS_CP0_DEBUG_DBP | MIPS_CP0_DEBUG_DDBL | MIPS_CP0_DEBUG_DDBS |
MIPS_CP0_DEBUG_DIB | MIPS_CP0_DEBUG_DINT |
MIPS_CP0_DEBUG_DDBLIMPR | MIPS_CP0_DEBUG_DDBSIMPR);
if (! old_dm) {
cpu->cp0.reg[MIPS_CP0_DEBUG] |= dexc_type;
}
/* Update delay slot flag. */
if (cpu->is_in_bdslot)
cpu->cp0.reg[MIPS_CP0_DEBUG] |= MIPS_CP0_DEBUG_DBD;
else
cpu->cp0.reg[MIPS_CP0_DEBUG] &= ~MIPS_CP0_DEBUG_DBD;
/* Set Debug mode. */
cpu->cp0.reg[MIPS_CP0_DEBUG] |= MIPS_CP0_DEBUG_DM;
cpu->cp0.reg[MIPS_CP0_DEBUG] |= MIPS_CP0_DEBUG_IEXI;
if (cpu->vm->debug_level > 2) {
char *type = 0;
printf ("--- 0x%08x: ", cpu->pc);
if (old_dm)
type = " Debug exception in Debug mode";
else
switch (dexc_type) {
case MIPS_CP0_DEBUG_DSS: type = "Debug Single Step exception"; break;
case MIPS_CP0_DEBUG_DBP: type = "Debug Breakpoint exception"; break;
case MIPS_CP0_DEBUG_DDBL: type = "Debug Data Break Load exception"; break;
case MIPS_CP0_DEBUG_DDBS: type = "Debug Data Break Store exception"; break;
case MIPS_CP0_DEBUG_DIB: type = "Debug Instruction Break exception"; break;
case MIPS_CP0_DEBUG_DINT: type = "Debug Interrupt exception"; break;
case MIPS_CP0_DEBUG_DDBLIMPR: type = "Debug Data Break Load Impresize exception"; break;
case MIPS_CP0_DEBUG_DDBSIMPR: type = "Debug Data Break Store Impresize exception"; break;
}
if (type)
printf ("%s\n", type);
else
printf ("Debug exception %#x\n", dexc_type);
printf (" c0_debug := %08x\n", cpu->cp0.reg[MIPS_CP0_DEBUG]);
printf (" c0_depc := %08x\n", cpu->cp0.reg[MIPS_CP0_DEPC]);
}
/* Debug exception vector. */
cpu->pc = (m_va_t) 0xffffffffbfc00480ULL;
cpu->is_mips16e = 0;
/* Clear the pending IRQ flag */
cpu->irq_pending = 0;
}
/* Execute fpu instruction */
void fastcall mips_exec_soft_fpu (cpu_mips_t * cpu)
{

View File

@@ -76,6 +76,8 @@
#define MIPS_CP0_WATCHLO 18 /* Low Watch address */
#define MIPS_CP0_WATCHHI 19 /* High Watch address */
#define MIPS_CP0_XCONTEXT 20 /* Extended context */
#define MIPS_CP0_DEBUG 23 /* Debug */
#define MIPS_CP0_DEPC 24 /* DEPC */
#define MIPS_CP0_ECC 26 /* ECC and parity */
#define MIPS_CP0_CACHERR 27 /* Cache Err/Status */
#define MIPS_CP0_TAGLO 28 /* Cache Tag Lo */
@@ -127,7 +129,6 @@
/*
* CP0 Cause register
*/
#define MIPS_CP0_CAUSE_BD_SLOT 0x80000000
#define MIPS_CP0_CAUSE_MASK 0x0000007C
@@ -175,6 +176,25 @@
#define MIPS_CP0_CONTEXT_PTEBASE_MASK 0xff800000
#define MIPS_CP0_CONTEXT_BADVPN2_MASK 0x0007ffff0
/*
* CP0 Debug register
*/
#define MIPS_CP0_DEBUG_DBD 0x80000000 /* Debug exception on delay slot */
#define MIPS_CP0_DEBUG_DM 0x40000000 /* Debug mode */
#define MIPS_CP0_DEBUG_IEXI 0x00100000 /* Imprecise Error eXception Inhibit */
#define MIPS_CP0_DEBUG_DDBSIMPR 0x00080000 /* Debug Data Break Store Impresize exception */
#define MIPS_CP0_DEBUG_DDBLIMPR 0x00040000 /* Debug Data Break Load Impresize exception */
#define MIPS_CP0_DEBUG_DEXCCODE 0x00003c00 /* Debug exception code */
#define MIPS_CP0_DEBUG_DEXCCODE_SHIFT 10
#define MIPS_CP0_DEBUG_DINT 0x00000020 /* Debug Interrupt exception */
#define MIPS_CP0_DEBUG_DIB 0x00000010 /* Debug Instruction Break exception */
#define MIPS_CP0_DEBUG_DDBS 0x00000008 /* Debug Data Break Store exception */
#define MIPS_CP0_DEBUG_DDBL 0x00000004 /* Debug Data Break Load exception */
#define MIPS_CP0_DEBUG_DBP 0x00000002 /* Debug Breakpoint exception */
#define MIPS_CP0_DEBUG_DSS 0x00000001 /* Debug Single Step exception */
#define MIPS_CP0_DEBUG_WMASK 0x10700180 /* Writable bits */
/* TLB masks and shifts */
#define MIPS_TLB_PAGE_MASK 0x01ffe000
#define MIPS_TLB_PAGE_SHIFT 13
@@ -479,6 +499,7 @@ int mips_load_elf_image (cpu_mips_t * cpu, char *filename,
void mips_delete (cpu_mips_t * cpu);
int fastcall mips_update_irq_flag (cpu_mips_t * cpu);
void mips_trigger_exception (cpu_mips_t * cpu, u_int exc_code, int bd_slot);
void mips_trigger_debug_exception (cpu_mips_t * cpu, u_int dexc_type);
void fastcall mips_exec_soft_fpu (cpu_mips_t * cpu);
void fastcall mips_exec_eret (cpu_mips_t * cpu);
void fastcall mips_exec_break (cpu_mips_t * cpu, u_int code);

View File

@@ -1813,6 +1813,26 @@ static int xori_op (cpu_mips_t * cpu, mips_insn_t insn)
return (0);
}
static int sdbbp_op (cpu_mips_t * cpu, mips_insn_t insn)
{
/* Clear status of previos Debug exception. */
cpu->cp0.reg[MIPS_CP0_DEBUG] &= ~MIPS_CP0_DEBUG_DEXCCODE;
if (cpu->cp0.reg[MIPS_CP0_DEBUG] & MIPS_CP0_DEBUG_DM) {
/* Already in Debug mode: take nested debug exception. */
mips_trigger_debug_exception (cpu, 0);
/* Set nested exception type. */
cpu->cp0.reg[MIPS_CP0_DEBUG] |=
MIPS_CP0_CAUSE_BP << MIPS_CP0_DEBUG_DEXCCODE_SHIFT;
} else {
/* Take a Breakpoint exception. */
mips_trigger_debug_exception (cpu, MIPS_CP0_DEBUG_DBP);
}
return 1;
}
static int undef_op (cpu_mips_t * cpu, mips_insn_t insn)
{
return unknown_op (cpu, insn);
@@ -2131,7 +2151,7 @@ static const struct mips_op_desc mips_spec2_opcodes[] = {
{"?spec2", undef_spec2,0x3c},
{"?spec2", undef_spec2,0x3d},
{"?spec2", undef_spec2,0x3e},
{"?spec2", undef_spec2,0x3f},
{"?spec2", sdbbp_op, 0x3f},
};
/*

View File

@@ -227,6 +227,14 @@ void mips_cp0_set_reg (cpu_mips_t * cpu, u_int cp0_reg, u_int sel,
}
break;
case MIPS_CP0_DEBUG:
/* Only some bits of Debug register are writable. */
if (sel != 0)
goto unimpl;
cp0->reg[cp0_reg] &= ~MIPS_CP0_DEBUG_WMASK;
cp0->reg[cp0_reg] |= val & MIPS_CP0_DEBUG_WMASK;
break;
default:
if (sel != 0) {
unimpl: fprintf (stderr,