Virtualmips: implement SDBBP instruction.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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},
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user