Got rid of loop step + added some comments
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2928 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
65daec3554
commit
7dccebfef2
|
@ -138,6 +138,12 @@ void ret(const UDSPInstruction& opc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RTI
|
||||||
|
// 0000 0010 1111 1111
|
||||||
|
// Return from exception. Pops stored status register $sr from data stack
|
||||||
|
// $st1 and program counter PC from call stack $st0 and sets $pc to this
|
||||||
|
// location.
|
||||||
|
// FIXME: is it also conditional? unknown opcodes 0x02fx
|
||||||
void rti(const UDSPInstruction& opc)
|
void rti(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
g_dsp.r[DSP_REG_SR] = dsp_reg_load_stack(DSP_STACK_D);
|
g_dsp.r[DSP_REG_SR] = dsp_reg_load_stack(DSP_STACK_D);
|
||||||
|
@ -155,37 +161,64 @@ void halt(const UDSPInstruction& opc)
|
||||||
g_dsp.pc = g_dsp.err_pc;
|
g_dsp.pc = g_dsp.err_pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// LOOP handling: Loop stack is used to control execution of repeated blocks of
|
||||||
|
// instructions. Whenever there is value on stack $st2 and current PC is equal
|
||||||
|
// value at $st2, then value at stack $st3 is decremented. If value is not zero
|
||||||
|
// then PC is modified with calue from call stack $st0. Otherwise values from
|
||||||
|
// callstack $st0 and both loop stacks $st2 and $st3 are poped and execution
|
||||||
|
// continues at next opcode.
|
||||||
|
|
||||||
|
|
||||||
|
// LOOP $R
|
||||||
|
// 0000 0000 010r rrrr
|
||||||
|
// Repeatedly execute following opcode until counter specified by value
|
||||||
|
// from register $R reaches zero. Each execution decrement counter. Register
|
||||||
|
// $R remains unchanged. If register $R is set to zero at the beginning of loop
|
||||||
|
// then looped instruction will not get executed.
|
||||||
void loop(const UDSPInstruction& opc)
|
void loop(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u16 reg = opc.hex & 0x1f;
|
u16 reg = opc.hex & 0x1f;
|
||||||
u16 cnt = g_dsp.r[reg];
|
u16 cnt = g_dsp.r[reg];
|
||||||
u16 loop_pc = g_dsp.pc;
|
u16 loop_pc = g_dsp.pc;
|
||||||
|
|
||||||
while (cnt--)
|
if (cnt)
|
||||||
{
|
{
|
||||||
gdsp_loop_step();
|
dsp_reg_store_stack(0, g_dsp.pc);
|
||||||
g_dsp.pc = loop_pc;
|
dsp_reg_store_stack(2, loop_pc);
|
||||||
|
dsp_reg_store_stack(3, cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// g_dsp.pc = loop_pc;
|
|
||||||
g_dsp.pc += opSize[dsp_peek_code()];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LOOPI #I
|
||||||
|
// 0001 0000 iiii iiii
|
||||||
|
// Repeatedly execute following opcode until counter specified by
|
||||||
|
// immediate value I reaches zero. Each execution decrement counter. If
|
||||||
|
// immediate value I is set to zero at the beginning of loop then looped
|
||||||
|
// instruction will not get executed.
|
||||||
void loopi(const UDSPInstruction& opc)
|
void loopi(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u16 cnt = opc.hex & 0xff;
|
u16 cnt = opc.hex & 0xff;
|
||||||
u16 loop_pc = g_dsp.pc;
|
u16 loop_pc = g_dsp.pc;
|
||||||
|
|
||||||
while (cnt--)
|
if (cnt)
|
||||||
{
|
{
|
||||||
gdsp_loop_step();
|
dsp_reg_store_stack(0, g_dsp.pc);
|
||||||
g_dsp.pc = loop_pc;
|
dsp_reg_store_stack(2, loop_pc);
|
||||||
|
dsp_reg_store_stack(3, cnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// g_dsp.pc = loop_pc;
|
|
||||||
g_dsp.pc += opSize[dsp_peek_code()];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// BLOOP $R, addrA
|
||||||
|
// 0000 0000 011r rrrr
|
||||||
|
// aaaa aaaa aaaa aaaa
|
||||||
|
// Repeatedly execute block of code starting at following opcode until
|
||||||
|
// counter specified by value from register $R reaches zero. Block ends at
|
||||||
|
// specified address addrA inclusive, ie. opcode at addrA is the last opcode
|
||||||
|
// included in loop. Counter is pushed on loop stack $st3, end of block address
|
||||||
|
// is pushed on loop stack $st2 and repeat address is pushed on call stack $st0.
|
||||||
|
// Up to 4 nested loops is allowed.
|
||||||
void bloop(const UDSPInstruction& opc)
|
void bloop(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u16 reg = opc.hex & 0x1f;
|
u16 reg = opc.hex & 0x1f;
|
||||||
|
@ -205,6 +238,15 @@ void bloop(const UDSPInstruction& opc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BLOOPI #I, addrA
|
||||||
|
// 0001 0001 iiii iiii
|
||||||
|
// aaaa aaaa aaaa aaaa
|
||||||
|
// Repeatedly execute block of code starting at following opcode until
|
||||||
|
// counter specified by immediate value I reaches zero. Block ends at specified
|
||||||
|
// address addrA inclusive, ie. opcode at addrA is the last opcode included in
|
||||||
|
// loop. Counter is pushed on loop stack $st3, end of block address is pushed
|
||||||
|
// on loop stack $st2 and repeat address is pushed on call stack $st0. Up to 4
|
||||||
|
// nested loops is allowed.
|
||||||
void bloopi(const UDSPInstruction& opc)
|
void bloopi(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u16 cnt = opc.hex & 0xff;
|
u16 cnt = opc.hex & 0xff;
|
||||||
|
@ -344,8 +386,7 @@ void srri(const UDSPInstruction& opc)
|
||||||
// SRRN @$D, $S
|
// SRRN @$D, $S
|
||||||
// 0001 1011 1dds ssss
|
// 0001 1011 1dds ssss
|
||||||
// Store value from source register $S to a memory location pointed by
|
// Store value from source register $S to a memory location pointed by
|
||||||
// addressing register $D. Add indexing register $(0x4+D) to register $D.
|
// addressing register $D. Add DSP_REG_IX0 register to register $D.
|
||||||
|
|
||||||
// FIXME: Perform additional operation depending on source register.
|
// FIXME: Perform additional operation depending on source register.
|
||||||
void srrn(const UDSPInstruction& opc)
|
void srrn(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
|
@ -354,7 +395,7 @@ void srrn(const UDSPInstruction& opc)
|
||||||
|
|
||||||
u16 val = dsp_op_read_reg(sreg);
|
u16 val = dsp_op_read_reg(sreg);
|
||||||
dsp_dmem_write(g_dsp.r[dreg], val);
|
dsp_dmem_write(g_dsp.r[dreg], val);
|
||||||
g_dsp.r[dreg] += g_dsp.r[dreg + 4];
|
g_dsp.r[dreg] += g_dsp.r[DSP_REG_IX0 + dreg];
|
||||||
}
|
}
|
||||||
|
|
||||||
// ILRR $acD.m, @$arS
|
// ILRR $acD.m, @$arS
|
||||||
|
@ -426,11 +467,11 @@ void lri(const UDSPInstruction& opc)
|
||||||
|
|
||||||
// LRIS $(0x18+D), #I
|
// LRIS $(0x18+D), #I
|
||||||
// 0000 1ddd iiii iiii
|
// 0000 1ddd iiii iiii
|
||||||
// Load immediate value I (8-bit sign extended) to accumulator register$(0x18+D).
|
// Load immediate value I (8-bit sign extended) to accumulator register.
|
||||||
// FIXME: Perform additional operation depending on destination register.
|
// FIXME: Perform additional operation depending on destination register.
|
||||||
void lris(const UDSPInstruction& opc)
|
void lris(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
|
u8 reg = ((opc.hex >> 8) & 0x7) + DSP_REG_AXL0;
|
||||||
u16 imm = (s8)opc.hex;
|
u16 imm = (s8)opc.hex;
|
||||||
dsp_op_write_reg(reg, imm);
|
dsp_op_write_reg(reg, imm);
|
||||||
}
|
}
|
||||||
|
@ -516,7 +557,7 @@ void clrl(const UDSPInstruction& opc)
|
||||||
g_dsp.r[reg] &= 0x0000;
|
g_dsp.r[reg] &= 0x0000;
|
||||||
|
|
||||||
// Should this be 64bit?
|
// Should this be 64bit?
|
||||||
// nakee: it says the whole reg in doddie's doc sounds weird
|
// nakee: it says the whole reg in duddie's doc sounds weird
|
||||||
Update_SR_Register64((s64)reg);
|
Update_SR_Register64((s64)reg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,7 +566,7 @@ void clrl(const UDSPInstruction& opc)
|
||||||
// Clears product register $prod.
|
// Clears product register $prod.
|
||||||
void clrp(const UDSPInstruction& opc)
|
void clrp(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
// Magic numbers taken from doddie's doc
|
// Magic numbers taken from duddie's doc
|
||||||
g_dsp.r[0x14] = 0x0000;
|
g_dsp.r[0x14] = 0x0000;
|
||||||
g_dsp.r[0x15] = 0xfff0;
|
g_dsp.r[0x15] = 0xfff0;
|
||||||
g_dsp.r[0x16] = 0x00ff;
|
g_dsp.r[0x16] = 0x00ff;
|
||||||
|
@ -687,6 +728,10 @@ void movax(const UDSPInstruction& opc)
|
||||||
Update_SR_Register64(acx);
|
Update_SR_Register64(acx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XORR $acD.m, $axS.h
|
||||||
|
// 0011 00sd xxxx xxxx
|
||||||
|
// Logic XOR (exclusive or) middle part of accumulator $acD.m with
|
||||||
|
// high part of secondary accumulator $axS.h.
|
||||||
void xorr(const UDSPInstruction& opc)
|
void xorr(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 sreg = (opc.hex >> 9) & 0x1;
|
u8 sreg = (opc.hex >> 9) & 0x1;
|
||||||
|
@ -699,7 +744,7 @@ void xorr(const UDSPInstruction& opc)
|
||||||
|
|
||||||
// ANDR $acD.m, $axS.h
|
// ANDR $acD.m, $axS.h
|
||||||
// 0011 01sd xxxx xxxx
|
// 0011 01sd xxxx xxxx
|
||||||
// Logic AND middle part of accumulator $acD.m with hight part of
|
// Logic AND middle part of accumulator $acD.m with high part of
|
||||||
// secondary accumulator $axS.h.
|
// secondary accumulator $axS.h.
|
||||||
void andr(const UDSPInstruction& opc)
|
void andr(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
|
@ -711,6 +756,11 @@ void andr(const UDSPInstruction& opc)
|
||||||
tsta(dreg);
|
tsta(dreg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ORR $acD.m, $axS.h
|
||||||
|
// 0011 10sd xxxx xxxx
|
||||||
|
// Logic OR middle part of accumulator $acD.m with high part of
|
||||||
|
// secondary accumulator $axS.h.
|
||||||
|
|
||||||
void orr(const UDSPInstruction& opc)
|
void orr(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 sreg = (opc.hex >> 9) & 0x1;
|
u8 sreg = (opc.hex >> 9) & 0x1;
|
||||||
|
@ -1379,7 +1429,7 @@ void mul(const UDSPInstruction& opc)
|
||||||
|
|
||||||
dsp_set_long_prod(prod);
|
dsp_set_long_prod(prod);
|
||||||
|
|
||||||
// FIXME: no update in doddie's docs
|
// FIXME: no update in duddie's docs
|
||||||
Update_SR_Register64(prod);
|
Update_SR_Register64(prod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1400,7 +1450,7 @@ void mulac(const UDSPInstruction& opc)
|
||||||
s64 prod = dsp_get_ax_l(sreg) * dsp_get_ax_h(sreg) * GetMultiplyModifier();
|
s64 prod = dsp_get_ax_l(sreg) * dsp_get_ax_h(sreg) * GetMultiplyModifier();
|
||||||
dsp_set_long_prod(prod);
|
dsp_set_long_prod(prod);
|
||||||
|
|
||||||
// FIXME: no update in doddie's docs
|
// FIXME: no update in duddie's docs
|
||||||
Update_SR_Register64(prod);
|
Update_SR_Register64(prod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1626,7 +1676,7 @@ void msubc(const UDSPInstruction& opc)
|
||||||
// Store value from register $(0x18+S) to a memory pointed by address M.
|
// Store value from register $(0x18+S) to a memory pointed by address M.
|
||||||
// (8-bit sign extended).
|
// (8-bit sign extended).
|
||||||
// FIXME: Perform additional operation depending on destination register.
|
// FIXME: Perform additional operation depending on destination register.
|
||||||
// Note: pc+=2 in doddie's doc seems wrong
|
// Note: pc+=2 in duddie's doc seems wrong
|
||||||
void srs(const UDSPInstruction& opc)
|
void srs(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
|
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
|
||||||
|
@ -1639,7 +1689,7 @@ void srs(const UDSPInstruction& opc)
|
||||||
// Move value from data memory pointed by address M (8-bit sign
|
// Move value from data memory pointed by address M (8-bit sign
|
||||||
// extended) to register $(0x18+D).
|
// extended) to register $(0x18+D).
|
||||||
// FIXME: Perform additional operation depending on destination register.
|
// FIXME: Perform additional operation depending on destination register.
|
||||||
// Note: pc+=2 in doddie's doc seems wrong
|
// Note: pc+=2 in duddie's doc seems wrong
|
||||||
void lrs(const UDSPInstruction& opc)
|
void lrs(const UDSPInstruction& opc)
|
||||||
{
|
{
|
||||||
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
|
u8 reg = ((opc.hex >> 8) & 0x7) + 0x18;
|
||||||
|
|
|
@ -66,6 +66,10 @@ void nop(const UDSPInstruction& opc) {if(opc.hex) DSPInterpreter::unknown(opc);}
|
||||||
DSPOPCTemplate opcodes[] =
|
DSPOPCTemplate opcodes[] =
|
||||||
{
|
{
|
||||||
{"NOP", 0x0000, 0xffff, nop, nop, 1, 0, {}, NULL, NULL},
|
{"NOP", 0x0000, 0xffff, nop, nop, 1, 0, {}, NULL, NULL},
|
||||||
|
|
||||||
|
{"DAR", 0x0004, 0xfffc, DSPInterpreter::dar, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL},
|
||||||
|
{"IAR", 0x0008, 0xfffc, DSPInterpreter::iar, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL},
|
||||||
|
|
||||||
{"HALT", 0x0021, 0xffff, DSPInterpreter::halt, nop, 1, 0, {}, NULL, NULL},
|
{"HALT", 0x0021, 0xffff, DSPInterpreter::halt, nop, 1, 0, {}, NULL, NULL},
|
||||||
|
|
||||||
{"RETNS", 0x02d0, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
|
{"RETNS", 0x02d0, 0xffff, DSPInterpreter::ret, nop, 1, 0, {}, NULL, NULL},
|
||||||
|
@ -117,8 +121,6 @@ DSPOPCTemplate opcodes[] =
|
||||||
{"JLZ", 0x029d, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
{"JLZ", 0x029d, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||||
{"JMP", 0x029f, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
{"JMP", 0x029f, 0xffff, DSPInterpreter::jcc, nop, 2, 1, {{P_VAL, 2, 1, 0, 0xffff}}, NULL, NULL},
|
||||||
|
|
||||||
{"DAR", 0x0004, 0xfffc, DSPInterpreter::dar, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL},
|
|
||||||
{"IAR", 0x0008, 0xfffc, DSPInterpreter::iar, nop, 1, 1, {{P_REG, 1, 0, 0, 0x0003}}, NULL, NULL},
|
|
||||||
|
|
||||||
{"JRNS", 0x1700, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
|
{"JRNS", 0x1700, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
|
||||||
{"JRS", 0x1701, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
|
{"JRS", 0x1701, 0xff1f, DSPInterpreter::jmprcc, nop, 1, 1, {{P_REG, 1, 0, 5, 0x00e0}}, NULL, NULL},
|
||||||
|
@ -341,7 +343,7 @@ dspInstFunc epilogueTable[OPTABLE_SIZE];
|
||||||
|
|
||||||
const DSPOPCTemplate *GetOpTemplate(const UDSPInstruction &inst)
|
const DSPOPCTemplate *GetOpTemplate(const UDSPInstruction &inst)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < opcodes_size; i++)
|
for (u32 i = 0; i < opcodes_size; i++)
|
||||||
{
|
{
|
||||||
u16 mask = opcodes[i].opcode_mask;
|
u16 mask = opcodes[i].opcode_mask;
|
||||||
if (opcodes[i].size & P_EXT) {
|
if (opcodes[i].size & P_EXT) {
|
||||||
|
|
|
@ -207,21 +207,6 @@ u16 gdsp_read_cr()
|
||||||
return g_dsp.cr;
|
return g_dsp.cr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// special loop step.. because exception in loop or loopi fails
|
|
||||||
// dunno how we have to fix it
|
|
||||||
// atm we execute this instructions directly inside the loop command
|
|
||||||
// so it cant be interrupted by an exception.
|
|
||||||
// TODO - we really should figure this out - on the real DSP, exception inside
|
|
||||||
// loop should work. Think through the stack management and how it works
|
|
||||||
// with exceptions and in loops.
|
|
||||||
void gdsp_loop_step()
|
|
||||||
{
|
|
||||||
g_dsp.err_pc = g_dsp.pc;
|
|
||||||
u16 opc = dsp_fetch_code();
|
|
||||||
ComputeInstruction(UDSPInstruction(opc));
|
|
||||||
}
|
|
||||||
|
|
||||||
void gdsp_step()
|
void gdsp_step()
|
||||||
{
|
{
|
||||||
g_dsp.step_counter++;
|
g_dsp.step_counter++;
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
|
|
||||||
#define DSP_REG_AXL0 0x18
|
#define DSP_REG_AXL0 0x18
|
||||||
#define DSP_REG_AXL1 0x19
|
#define DSP_REG_AXL1 0x19
|
||||||
#define DSP_REG_AXH0 0x1A // SMP_R accel
|
#define DSP_REG_AXH0 0x1a // SMP_R accel
|
||||||
#define DSP_REG_AXH1 0x1b // SMP_L accel
|
#define DSP_REG_AXH1 0x1b // SMP_L accel
|
||||||
|
|
||||||
#define DSP_REG_ACC0 0x1c // accumulator (global)
|
#define DSP_REG_ACC0 0x1c // accumulator (global)
|
||||||
|
|
Loading…
Reference in New Issue