Compare commits

..

No commits in common. "master" and "073u5" have entirely different histories.

8 changed files with 53 additions and 42 deletions

View file

@ -100,7 +100,6 @@ void NECDSP::exec_op(uint24 opcode) {
flag.s0 = (r & 0x8000); flag.s0 = (r & 0x8000);
flag.z = (r == 0); flag.z = (r == 0);
if (!flag.ov1) flag.s1 = flag.s0;
switch(alu) { switch(alu) {
case 1: case 2: case 3: case 10: case 13: case 14: case 15: { case 1: case 2: case 3: case 10: case 13: case 14: case 15: {
@ -112,14 +111,17 @@ void NECDSP::exec_op(uint24 opcode) {
case 4: case 5: case 6: case 7: case 8: case 9: { case 4: case 5: case 6: case 7: case 8: case 9: {
if(alu & 1) { if(alu & 1) {
//addition //addition
flag.ov0 = (q ^ r) & (p ^ r) & 0x8000; flag.ov0 = (q ^ r) & ~(q ^ p) & 0x8000;
flag.c = (r < q); flag.c = (r < q);
} else { } else {
//subtraction //subtraction
flag.ov0 = (q ^ r) & (q ^ p) & 0x8000; flag.ov0 = (q ^ r) & (q ^ p) & 0x8000;
flag.c = (r > q); flag.c = (r > q);
} }
flag.ov1 = (flag.ov0 & flag.ov1) ? (flag.s1 == flag.s0) : (flag.ov0 | flag.ov1); if(flag.ov0) {
flag.s1 = flag.ov1 ^ !(r & 0x8000);
flag.ov1 = !flag.ov1;
}
break; break;
} }
case 11: { case 11: {
@ -144,16 +146,15 @@ void NECDSP::exec_op(uint24 opcode) {
exec_ld((idb << 6) + dst); exec_ld((idb << 6) + dst);
if (dst != 4) { switch(dpl) {
switch(dpl) { case 1: regs.dp = (regs.dp & 0xf0) + ((regs.dp + 1) & 0x0f); break; //DPINC
case 1: regs.dp = (regs.dp & 0xf0) + ((regs.dp + 1) & 0x0f); break; //DPINC case 2: regs.dp = (regs.dp & 0xf0) + ((regs.dp - 1) & 0x0f); break; //DPDEC
case 2: regs.dp = (regs.dp & 0xf0) + ((regs.dp - 1) & 0x0f); break; //DPDEC case 3: regs.dp = (regs.dp & 0xf0); break; //DPCLR
case 3: regs.dp = (regs.dp & 0xf0); break; //DPCLR
}
regs.dp ^= dphm << 4;
} }
if(rpdcr && dst != 5) regs.rp--; regs.dp ^= dphm << 4;
if(rpdcr) regs.rp--;
} }
void NECDSP::exec_rt(uint24 opcode) { void NECDSP::exec_rt(uint24 opcode) {

View file

@ -80,12 +80,14 @@ alwaysinline void SMP::op_buswrite(uint16 addr, uint8 data) {
if(regs.p.p) break; //writes only valid when P flag is clear if(regs.p.p) break; //writes only valid when P flag is clear
status.clock_speed = (data >> 6) & 3; status.clock_speed = (data >> 6) & 3;
status.ram_speed = (data >> 4) & 3; status.timer_speed = (data >> 4) & 3;
status.timers_enabled = data & 0x08; status.timers_enabled = data & 0x08;
status.ram_disabled = data & 0x04; status.ram_disabled = data & 0x04;
status.ram_writable = data & 0x02; status.ram_writable = data & 0x02;
status.timers_disabled = data & 0x01; status.timers_disabled = data & 0x01;
status.timer_step = (1 << status.clock_speed) + (2 << status.timer_speed);
t0.sync_stage1(); t0.sync_stage1();
t1.sync_stage1(); t1.sync_stage1();
t2.sync_stage1(); t2.sync_stage1();
@ -174,29 +176,23 @@ alwaysinline void SMP::op_buswrite(uint16 addr, uint8 data) {
ram_write(addr, data); ram_write(addr, data);
} }
unsigned SMP::speed(uint16 addr) const {
if((addr & 0xfff0) == 0x00f0) return status.clock_speed;
if(addr >= 0xffc0 && status.iplrom_enabled) return status.clock_speed;
return status.ram_speed;
}
void SMP::op_io() { void SMP::op_io() {
add_clocks(24); add_clocks(24);
cycle_edge(status.clock_speed); cycle_edge();
} }
uint8 SMP::op_read(uint16 addr) { uint8 SMP::op_read(uint16 addr) {
add_clocks(12); add_clocks(12);
uint8 r = op_busread(addr); uint8 r = op_busread(addr);
add_clocks(12); add_clocks(12);
cycle_edge(speed(addr)); cycle_edge();
return r; return r;
} }
void SMP::op_write(uint16 addr, uint8 data) { void SMP::op_write(uint16 addr, uint8 data) {
add_clocks(24); add_clocks(24);
op_buswrite(addr, data); op_buswrite(addr, data);
cycle_edge(speed(addr)); cycle_edge();
} }
#endif #endif

View file

@ -4,8 +4,6 @@ void ram_write(uint16 addr, uint8 data);
uint8 op_busread(uint16 addr); uint8 op_busread(uint16 addr);
void op_buswrite(uint16 addr, uint8 data); void op_buswrite(uint16 addr, uint8 data);
alwaysinline unsigned speed(uint16 addr) const;
void op_io(); void op_io();
debugvirtual uint8 op_read(uint16 addr); debugvirtual uint8 op_read(uint16 addr);
debugvirtual void op_write(uint16 addr, uint8 data); debugvirtual void op_write(uint16 addr, uint8 data);

View file

@ -4,8 +4,12 @@ void SMP::serialize(serializer &s) {
Processor::serialize(s); Processor::serialize(s);
SMPcore::core_serialize(s); SMPcore::core_serialize(s);
s.integer(status.clock_counter);
s.integer(status.dsp_counter);
s.integer(status.timer_step);
s.integer(status.clock_speed); s.integer(status.clock_speed);
s.integer(status.ram_speed); s.integer(status.timer_speed);
s.integer(status.timers_enabled); s.integer(status.timers_enabled);
s.integer(status.ram_disabled); s.integer(status.ram_disabled);
s.integer(status.ram_writable); s.integer(status.ram_writable);

View file

@ -76,9 +76,13 @@ void SMP::reset() {
memory::apuram.write(i, 0x00); memory::apuram.write(i, 0x00);
} }
status.clock_counter = 0;
status.dsp_counter = 0;
status.timer_step = 3;
//$00f0 //$00f0
status.clock_speed = 0; status.clock_speed = 0;
status.ram_speed = 0; status.timer_speed = 0;
status.timers_enabled = true; status.timers_enabled = true;
status.ram_disabled = false; status.ram_disabled = false;
status.ram_writable = true; status.ram_writable = true;

View file

@ -21,9 +21,14 @@ private:
#include "timing/timing.hpp" #include "timing/timing.hpp"
struct { struct {
//timing
unsigned clock_counter;
unsigned dsp_counter;
unsigned timer_step;
//$00f0 //$00f0
uint8 clock_speed; uint8 clock_speed;
uint8 ram_speed; uint8 timer_speed;
bool timers_enabled; bool timers_enabled;
bool ram_disabled; bool ram_disabled;
bool ram_writable; bool ram_writable;

View file

@ -9,22 +9,25 @@ void SMP::add_clocks(unsigned clocks) {
if(clock > +(768 * 24 * (int64)24000000)) synchronize_cpu(); if(clock > +(768 * 24 * (int64)24000000)) synchronize_cpu();
} }
void SMP::cycle_edge(unsigned speed) { void SMP::cycle_edge() {
static const uint8 wait_states[] = {0, 24*1, 24*4, 24*9}; t0.tick();
t1.tick();
unsigned ticks = 1 << speed; t2.tick();
t0.tick(ticks);
t1.tick(ticks);
t2.tick(ticks);
//TEST register S-SMP speed control
//24 clocks have already been added for this cycle at this point //24 clocks have already been added for this cycle at this point
if(speed) add_clocks(wait_states[speed]); switch(status.clock_speed) {
case 0: break; //100% speed
case 1: add_clocks(24); break; // 50% speed
case 2: while(true) add_clocks(24); // 0% speed -- locks S-SMP
case 3: add_clocks(24 * 9); break; // 10% speed
}
} }
template<unsigned timer_frequency> template<unsigned timer_frequency>
void SMP::sSMPTimer<timer_frequency>::tick(unsigned step) { void SMP::sSMPTimer<timer_frequency>::tick() {
//stage 0 increment //stage 0 increment
stage0_ticks += step; stage0_ticks += smp.status.timer_step;
if(stage0_ticks < timer_frequency) return; if(stage0_ticks < timer_frequency) return;
stage0_ticks -= timer_frequency; stage0_ticks -= timer_frequency;

View file

@ -9,13 +9,13 @@ public:
bool enabled; bool enabled;
uint8 target; uint8 target;
void tick(unsigned step); void tick();
void sync_stage1(); void sync_stage1();
}; };
sSMPTimer<64> t0; sSMPTimer<192> t0;
sSMPTimer<64> t1; sSMPTimer<192> t1;
sSMPTimer< 8> t2; sSMPTimer< 24> t2;
alwaysinline void add_clocks(unsigned clocks); alwaysinline void add_clocks(unsigned clocks);
alwaysinline void cycle_edge(unsigned speed); alwaysinline void cycle_edge();