summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2026-02-16 18:13:28 +1100
committer Vas Crabb <vas@vastheman.com>2026-02-16 18:13:28 +1100
commitda1361691f9ab95fa60a40c4c33a15abd134cc60 (patch)
tree4efbe710154bda3eba518215b69021998d01ca35
parenta00dffbfee978c9a3b88e9bd623973185285895e (diff)
cpu/sharc: Overhauled loop stack handling.
* Always access top-of-stack through pseudo-registers. * Better behaviour when stack is empty or full. * Implemented more read/write top-of-stack and explicit push/pop operations. * Try to get loop stack into a consistent state after loading a saved state.
-rw-r--r--src/devices/cpu/sharc/sharc.cpp55
-rw-r--r--src/devices/cpu/sharc/sharc.h2
-rw-r--r--src/devices/cpu/sharc/sharcdrc.cpp177
-rw-r--r--src/devices/cpu/sharc/sharcinternal.ipp12
-rw-r--r--src/devices/cpu/sharc/sharcops.hxx81
5 files changed, 214 insertions, 113 deletions
diff --git a/src/devices/cpu/sharc/sharc.cpp b/src/devices/cpu/sharc/sharc.cpp
index 9fb7a848236..e1997b02af0 100644
--- a/src/devices/cpu/sharc/sharc.cpp
+++ b/src/devices/cpu/sharc/sharc.cpp
@@ -709,11 +709,6 @@ void adsp21062_device::device_start()
save_item(NAME(m_core->faddr));
save_item(NAME(m_core->daddr));
save_item(NAME(m_core->pcstkp));
- save_item(NAME(m_core->laddr.addr));
- save_item(NAME(m_core->laddr.code));
- save_item(NAME(m_core->laddr.loop_type));
- save_item(NAME(m_core->curlcntr));
- save_item(NAME(m_core->lcntr));
save_item(NAME(m_core->iop_write_num));
save_item(NAME(m_core->iop_data));
@@ -808,7 +803,7 @@ void adsp21062_device::device_start()
state_add( SHARC_PC, "PC", m_core->pc).mask(0x00ffffff).formatstr("%06X");
state_add( SHARC_PCSTK, "PCSTK", m_core->pcstk).mask(0x00ffffff).formatstr("%06X");
state_add( SHARC_PCSTKP, "PCSTKP", m_core->pcstkp).mask(0x1f).formatstr("%02X");
- state_add( SHARC_LSTKP, "LSTKP", m_core->lstkp).formatstr("%08X");
+ state_add( SHARC_LSTKP, "LSTKP", m_core->lstkp).mask(0x07).formatstr("%01X");
state_add( SHARC_FADDR, "FADDR", m_core->faddr).formatstr("%08X");
state_add( SHARC_DADDR, "DADDR", m_core->daddr).formatstr("%08X");
state_add( SHARC_MODE1, "MODE1", m_core->mode1).formatstr("%08X");
@@ -971,6 +966,9 @@ void adsp21062_device::device_reset()
m_core->pcstkp = 0;
m_core->lstkp = 0;
m_core->pcstk = 0x00ffffff;
+ m_core->curlcntr = 0xffffffff;
+ m_core->lcntr = m_core->lcstack[0];
+ m_core->laddr.unpack(0xffffffff);
m_core->status_stkp = 0;
m_core->interrupt_active = 0;
@@ -995,6 +993,15 @@ void adsp21062_device::device_pre_save()
if ((m_core->pcstkp > 0) && (m_core->pcstkp < 31))
m_core->pcstack[m_core->pcstkp - 1] = m_core->pcstk;
+ if ((m_core->lstkp > 0) && (m_core->lstkp < 7))
+ {
+ m_core->lcstack[m_core->lstkp - 1] = m_core->curlcntr;
+ m_core->lastack[m_core->lstkp - 1] = m_core->laddr.pack();
+ }
+
+ if (m_core->lstkp < 6)
+ m_core->lcstack[m_core->lstkp] = m_core->lcntr;
+
if (m_enable_drc)
{
m_core->astat = m_core->astat_drc.pack();
@@ -1011,12 +1018,29 @@ void adsp21062_device::device_post_load()
pcstk &= 0x00ffffff;
m_core->pcstkp &= 0x1f;
+ m_core->lstkp &= 0x07;
if ((m_core->pcstkp > 0) && (m_core->pcstkp < 31))
m_core->pcstk = m_core->pcstack[m_core->pcstkp - 1];
else
m_core->pcstk = 0x00ffffff;
+ if ((m_core->lstkp > 0) && (m_core->lstkp < 7))
+ {
+ m_core->curlcntr = m_core->lcstack[m_core->lstkp - 1];
+ m_core->laddr.unpack(m_core->lastack[m_core->lstkp - 1]);
+ }
+ else
+ {
+ m_core->curlcntr = 0xffffffff;
+ m_core->laddr.unpack(0xffffffff);
+ }
+
+ if (m_core->lstkp < 6)
+ m_core->lcntr = m_core->lcstack[m_core->lstkp];
+ else
+ m_core->lcntr = 0xffffffff;
+
if (m_core->pcstkp > 0)
m_core->stky &= ~PCEM;
else
@@ -1027,6 +1051,11 @@ void adsp21062_device::device_post_load()
else
m_core->stky &= ~PCFL;
+ if (m_core->lstkp > 0)
+ m_core->stky &= ~LSEM;
+ else
+ m_core->stky |= LSEM;
+
m_core->astat_drc.unpack(m_core->astat);
m_core->astat_drc_copy.unpack(m_core->astat_old);
m_core->astat_delay_copy.unpack(m_core->astat_old_old);
@@ -1174,23 +1203,18 @@ void adsp21062_device::execute_run()
m_core->opcode = m_program.read_qword(m_core->pc);
// handle looping
- if (m_core->pc == m_core->laddr.addr)
+ if (!(m_core->stky & LSEM) && (m_core->pc == m_core->laddr.addr))
{
switch (m_core->laddr.loop_type)
{
case 0: // arithmetic condition-based
{
- int condition = m_core->laddr.code;
-
+ if ((m_core->pc - TOP_PC()) > 2)
{
- uint32_t looptop = TOP_PC();
- if (m_core->pc - looptop > 2)
- {
- m_core->astat = m_core->astat_old_old_old;
- }
+ m_core->astat = m_core->astat_old_old_old;
}
- if (DO_CONDITION_CODE(condition))
+ if (DO_CONDITION_CODE(m_core->laddr.code))
{
POP_LOOP();
POP_PC();
@@ -1215,7 +1239,6 @@ void adsp21062_device::execute_run()
}
case 3: // counter-based, length >2
{
- --m_core->lcstack[m_core->lstkp];
--m_core->curlcntr;
if (m_core->curlcntr == 0)
{
diff --git a/src/devices/cpu/sharc/sharc.h b/src/devices/cpu/sharc/sharc.h
index 5e88a1a8347..7f84c2470f7 100644
--- a/src/devices/cpu/sharc/sharc.h
+++ b/src/devices/cpu/sharc/sharc.h
@@ -324,7 +324,7 @@ private:
void PUSH_PC();
uint32_t POP_PC();
uint32_t TOP_PC();
- void PUSH_LOOP(uint32_t addr, uint32_t code, uint32_t type, uint32_t count);
+ void PUSH_LOOP();
void POP_LOOP();
void PUSH_STATUS_STACK();
void POP_STATUS_STACK();
diff --git a/src/devices/cpu/sharc/sharcdrc.cpp b/src/devices/cpu/sharc/sharcdrc.cpp
index 7362c074521..a1ee3901173 100644
--- a/src/devices/cpu/sharc/sharcdrc.cpp
+++ b/src/devices/cpu/sharc/sharcdrc.cpp
@@ -523,40 +523,50 @@ void adsp21062_device::static_generate_pop_pc()
void adsp21062_device::static_generate_push_loop()
{
- // I0 = counter
- // I1 = type/condition/addr
- // Trashes I2
+ // Trashes I1,I2
+ // Caller's responsibility to update laddr
uml::code_label label = 1;
uml::code_label const no_overflow = label++;
uml::code_label const empty = label++;
- uml::code_label const do_store = label++;
+ uml::code_label const full = label++;
drcuml_block &block(m_drcuml->begin_invariant_block(32));
// add a global entry for this
alloc_handle(m_push_loop, "push_loop");
- UML_HANDLE(block, *m_push_loop); // handle *m_push_loop
-
- UML_ADD(block, I2, LSTKP, 1); // add i2,LSTKP,1
- UML_CMP(block, I2, 6); // cmp i2,6
- UML_JMPc(block, COND_L, no_overflow); // jl no_overflow
- UML_CALLC(block, cfunc_loopstack_overflow, this); // callc cfunc_loopstack_overflow
-
- UML_LABEL(block, no_overflow); // no_overflow:
- UML_CMP(block, I2, 0); // cmp i2,0
- UML_JMPc(block, COND_E, empty); // je empty
- UML_AND(block, STKY, STKY, ~LSEM); // and STKY,~0x4000000
- UML_JMP(block, do_store); // jmp do_store
- UML_LABEL(block, empty); // empty:
- UML_OR(block, STKY, STKY, LSEM); // or STKY,0x4000000
-
- UML_LABEL(block, do_store); // do_store:
- UML_STORE(block, m_core->lcstack, I2, I0, SIZE_DWORD, SCALE_x4); // store m_core->lcstack,i2,i0,dword,scale_x4
- UML_STORE(block, m_core->lastack, I2, I1, SIZE_DWORD, SCALE_x4); // store m_core->lastack,i2,i1,dword,scale_x4
- UML_MOV(block, CURLCNTR, I0); // mov CURLCNTR,i0
- UML_MOV(block, LSTKP, I2); // mov LSTKP,i2
+ UML_HANDLE(block, *m_push_loop);
+ // check for stack overflow
+ UML_MOV(block, I1, LSTKP);
+ UML_CMP(block, I1, 6);
+ UML_JMPc(block, COND_B, no_overflow);
+ UML_CALLC(block, cfunc_loopstack_overflow, this);
+ UML_LABEL(block, no_overflow);
+
+ // store the top-of-stack pseudo-registers if the stack isn't empty
+ UML_TEST(block, I1, I1);
+ UML_JMPc(block, COND_Z, empty);
+ UML_STORE(block, m_core->lcstack - 1, I1, CURLCNTR, SIZE_DWORD, SCALE_x4);
+ UML_MOV(block, I2, mem(&m_core->laddr.addr));
+ UML_ROLINS(block, I2, mem(&m_core->laddr.code), 24, 0x1f000000);
+ UML_ROLINS(block, I2, mem(&m_core->laddr.loop_type), 30, 0xc0000000);
+ UML_STORE(block, m_core->lastack - 1, I1, I2, SIZE_DWORD, SCALE_x4);
+ UML_LABEL(block, empty);
+
+ // increment stack pointer and update sticky flags
+ UML_ADD(block, I1, I1, 1);
+ UML_MOV(block, LSTKP, I1);
+ UML_AND(block, STKY, STKY, ~LSEM);
+
+ // update the top-of-stack pseudo-registers
+ UML_MOV(block, CURLCNTR, LCNTR);
+ UML_CMP(block, I1, 6);
+ UML_JMPc(block, COND_E, full);
+ UML_LOAD(block, LCNTR, m_core->lcstack, I1, SIZE_DWORD, SCALE_x4);
+ UML_RET(block);
+ UML_LABEL(block, full);
+ UML_MOV(block, LCNTR, 0xffffffff);
UML_RET(block);
block.end();
@@ -567,30 +577,42 @@ void adsp21062_device::static_generate_pop_loop()
// Trashes I0,I2
uml::code_label label = 1;
+ uml::code_label const no_underflow = label++;
+ uml::code_label const empty = label++;
+ uml::code_label const set_laddr = label++;
+
drcuml_block &block(m_drcuml->begin_invariant_block(32));
// add a global entry for this
alloc_handle(m_pop_loop, "pop_loop");
- UML_HANDLE(block, *m_pop_loop); // handle *m_pop_loop
-
- UML_MOV(block, I2, LSTKP); // mov i2,LSTKP
- UML_CMP(block, I2, 0); // cmp i2,0
- UML_JMPc(block, COND_NE, label); // jne label1
- UML_CALLC(block, cfunc_loopstack_underflow, this); // callc cfunc_loopstack_underflow
-
- UML_LABEL(block, label++); // label1:
- UML_SUB(block, I2, I2, 1); // sub i2,i2,1
- UML_JMPc(block, COND_Z, label); // jz label2
- UML_AND(block, STKY, STKY, ~LSEM); // and STKY,~0x4000000
- UML_JMP(block, label + 1); // jmp label3
- UML_LABEL(block, label++); // label2:
- UML_OR(block, STKY, STKY, LSEM); // or STKY,0x4000000
-
- UML_LABEL(block, label++); // label3:
- UML_LOAD(block, I0, m_core->lcstack, I2, SIZE_DWORD, SCALE_x4); // load i0,m_core->lcstack,i2,dword,scale_x4
- UML_MOV(block, CURLCNTR, I0); // mov CURLCNTR,i0
- UML_MOV(block, LSTKP, I2); // mov LSTKP,i2
+ UML_HANDLE(block, *m_pop_loop);
+ // check for stack underflow
+ UML_SUB(block, I0, LSTKP, 1);
+ UML_JMPc(block, COND_NS, no_underflow);
+ UML_CALLC(block, cfunc_loopstack_underflow, this);
+ UML_LABEL(block, no_underflow);
+ UML_MOV(block, LSTKP, I0);
+
+ // update the top-of-stack pseudo-registers and sticky flags
+ UML_MOV(block, LCNTR, CURLCNTR);
+ UML_MOV(block, I2, mem(&m_core->laddr.addr));
+ UML_ROLINS(block, I2, mem(&m_core->laddr.code), 24, 0x1f000000);
+ UML_ROLINS(block, I2, mem(&m_core->laddr.loop_type), 30, 0xc0000000);
+ UML_STORE(block, m_core->lastack, I0, I2, SIZE_DWORD, SCALE_x4);
+ UML_TEST(block, I0, I0);
+ UML_JMPc(block, COND_Z, empty);
+ UML_LOAD(block, CURLCNTR, m_core->lcstack - 1, I0, SIZE_DWORD, SCALE_x4);
+ UML_LOAD(block, I0, m_core->lastack - 1, I0, SIZE_DWORD, SCALE_x4);
+ UML_JMP(block, set_laddr);
+ UML_LABEL(block, empty);
+ UML_OR(block, STKY, STKY, LSEM);
+ UML_MOV(block, I0, 0xffffffff);
+ UML_MOV(block, CURLCNTR, I0);
+ UML_LABEL(block, set_laddr);
+ UML_BFXU(block, mem(&m_core->laddr.addr), I0, 0, 24);
+ UML_BFXU(block, mem(&m_core->laddr.code), I0, 24, 5);
+ UML_BFXU(block, mem(&m_core->laddr.loop_type), I0, 30, 2);
UML_RET(block);
block.end();
@@ -762,17 +784,16 @@ void adsp21062_device::static_generate_loop_check_body(drcuml_block &block, bool
// check that the loop stack isn't empty and this is the end of the loop
UML_TEST(block, STKY, LSEM);
UML_RETc(block, COND_NZ);
- UML_LOAD(block, I1, m_core->lastack, LSTKP, SIZE_DWORD, SCALE_x4);
- UML_AND(block, I2, I1, 0xffffff);
- UML_CMP(block, I0, I2);
+ UML_CMP(block, I0, mem(&m_core->laddr.addr));
UML_RETc(block, COND_NE);
// check for counter loop first
- UML_TEST(block, I1, 0xc0000000);
+ UML_TEST(block, mem(&m_core->laddr.loop_type), 0x3);
UML_JMPc(block, COND_NZ, counter);
// check condition
- UML_BFXU(block, I2, I1, 24, 4);
+ UML_MOV(block, I1, mem(&m_core->laddr.code));
+ UML_BFXU(block, I2, I1, 0, 4);
UML_CMP(block, I2, 0x01); // LT/GE
UML_JMPc(block, COND_E, lt_ge);
UML_CMP(block, I2, 0x02); // LE/GT
@@ -790,7 +811,7 @@ void adsp21062_device::static_generate_loop_check_body(drcuml_block &block, bool
// ASTAT flag tests
UML_LABEL(block, astat_flag);
UML_LOAD(block, I2, loop_cond_map, I2, SIZE_DWORD, SCALE_x4);
- UML_BFXU(block, I1, I1, 28, 1);
+ UML_BFXU(block, I1, I1, 4, 1);
UML_LOAD(block, I2, &m_core->astat_delay_copy, I2, SIZE_DWORD, SCALE_x4);
UML_XOR(block, I2, I2, I1);
UML_JMPc(block, COND_NZ, terminate);
@@ -801,7 +822,7 @@ void adsp21062_device::static_generate_loop_check_body(drcuml_block &block, bool
UML_LABEL(block, lt_ge);
UML_XOR(block, I2, mem(&m_core->astat_delay_copy.az), 1);
UML_AND(block, I2, I2, mem(&m_core->astat_delay_copy.an));
- UML_BFXU(block, I1, I1, 28, 1);
+ UML_BFXU(block, I1, I1, 4, 1);
UML_XOR(block, I2, I2, I1);
UML_JMPc(block, COND_NZ, terminate);
UML_JMP(block, loop);
@@ -810,7 +831,7 @@ void adsp21062_device::static_generate_loop_check_body(drcuml_block &block, bool
// TODO: should do different things depending on AF
UML_LABEL(block, le_gt);
UML_OR(block, I2, mem(&m_core->astat_delay_copy.az), mem(&m_core->astat_delay_copy.an));
- UML_BFXU(block, I1, I1, 28, 1);
+ UML_BFXU(block, I1, I1, 4, 1);
UML_XOR(block, I2, I2, I1);
UML_JMPc(block, COND_NZ, terminate);
UML_JMP(block, loop);
@@ -819,20 +840,20 @@ void adsp21062_device::static_generate_loop_check_body(drcuml_block &block, bool
UML_LABEL(block, flag_in);
UML_SUB(block, I2, I2, 0x09);
UML_LOAD(block, I2, m_core->flag, I2, SIZE_DWORD, SCALE_x4);
- UML_BFXU(block, I1, I1, 28, 1);
+ UML_BFXU(block, I1, I1, 4, 1);
UML_XOR(block, I2, I2, I1);
UML_JMPc(block, COND_NZ, terminate);
UML_JMP(block, loop);
// bus master (not implemented)
UML_LABEL(block, bm);
- UML_TEST(block, I1, 0x10000000);
+ UML_TEST(block, I1, 0x10);
UML_JMPc(block, COND_NZ, terminate);
UML_JMP(block, loop);
// LCE and FOREVER
UML_LABEL(block, lce);
- UML_TEST(block, I1, 0x10000000);
+ UML_TEST(block, I1, 0x10);
UML_JMPc(block, COND_NZ, loop);
UML_CMP(block, CURLCNTR, 1);
UML_JMPc(block, COND_E, terminate);
@@ -840,9 +861,6 @@ void adsp21062_device::static_generate_loop_check_body(drcuml_block &block, bool
// counter-based loop
UML_LABEL(block, counter);
- UML_LOAD(block, I1, m_core->lcstack, LSTKP, SIZE_DWORD, SCALE_x4);
- UML_SUB(block, I1, I1, 1);
- UML_STORE(block, m_core->lcstack, LSTKP, I1, SIZE_DWORD, SCALE_x4);
UML_SUB(block, CURLCNTR, CURLCNTR, 1);
UML_JMPc(block, COND_Z, terminate);
@@ -1885,6 +1903,12 @@ void adsp21062_device::generate_read_ureg(drcuml_block &block, compiler_state &c
case 0x65: // PCSTKP
UML_MOV(block, I0, PCSTKP);
break;
+ case 0x67: // CURLCNTR
+ UML_MOV(block, I0, CURLCNTR);
+ break;
+ case 0x68: // LCNTR
+ UML_MOV(block, I0, LCNTR);
+ break;
case 0x70: // USTAT1
UML_MOV(block, I0, mem(&m_core->ustat1));
@@ -2140,10 +2164,19 @@ void adsp21062_device::generate_write_ureg(drcuml_block &block, compiler_state &
break;
}
case 0x67: // CURLCNTR
- UML_MOV(block, CURLCNTR, imm ? data : I0);
+ {
+ uml::code_label const skip = compiler.labelnum++;
+
+ UML_OR(block, I1, LSTKP, 0);
+ UML_JMPc(block, COND_Z, skip);
+ UML_CMP(block, I1, 7);
+ UML_MOVc(block, COND_B, CURLCNTR, imm ? data : I0);
+ UML_LABEL(block, skip);
break;
+ }
case 0x68: // LCNTR
- UML_MOV(block, LCNTR, imm ? data : I0);
+ UML_CMP(block, LSTKP, 6);
+ UML_MOVc(block, COND_B, LCNTR, imm ? data : I0);
break;
case 0x70: // USTAT1
@@ -2628,9 +2661,10 @@ bool adsp21062_device::generate_opcode(drcuml_block &block, compiler_state &comp
UML_MOV(block, PCSTK, desc->pc + 1);
// push loop
- UML_MOV(block, I0, data);
- UML_MOV(block, I1, 0xcf000000 | address);
UML_CALLH(block, *m_push_loop);
+ UML_MOV(block, mem(&m_core->laddr.addr), address);
+ UML_MOV(block, mem(&m_core->laddr.code), 0x0f);
+ UML_MOV(block, mem(&m_core->laddr.loop_type), 0x3); // TODO: support small loops
return true;
}
@@ -2642,17 +2676,17 @@ bool adsp21062_device::generate_opcode(drcuml_block &block, compiler_state &comp
generate_read_ureg(block, compiler, desc, ureg, false);
- UML_MOV(block, I3, I0);
- UML_MOV(block, LCNTR, I3);
+ UML_MOV(block, LCNTR, I0);
// push pc
UML_CALLH(block, *m_push_pc);
UML_MOV(block, PCSTK, desc->pc + 1);
// push loop
- UML_MOV(block, I0, I3);
- UML_MOV(block, I1, 0xcf000000 | address);
UML_CALLH(block, *m_push_loop);
+ UML_MOV(block, mem(&m_core->laddr.addr), address);
+ UML_MOV(block, mem(&m_core->laddr.code), 0x0f);
+ UML_MOV(block, mem(&m_core->laddr.loop_type), 0x3); // TODO: support small loops
return true;
}
@@ -2667,9 +2701,10 @@ bool adsp21062_device::generate_opcode(drcuml_block &block, compiler_state &comp
UML_MOV(block, PCSTK, desc->pc + 1);
// push loop
- UML_MOV(block, I0, 0);
- UML_MOV(block, I1, (cond << 24) | address);
UML_CALLH(block, *m_push_loop);
+ UML_MOV(block, mem(&m_core->laddr.addr), address);
+ UML_MOV(block, mem(&m_core->laddr.code), cond);
+ UML_MOV(block, mem(&m_core->laddr.loop_type), 0x0);
return true;
}
@@ -3036,11 +3071,15 @@ bool adsp21062_device::generate_opcode(drcuml_block &block, compiler_state &comp
{
if (opcode & 0x008000000000U)
{
- fatalerror("sharcdrc: push/pop stacks: push loop not implemented\n");
+ UML_CALLH(block, *m_push_loop);
+ UML_LOAD(block, I0, m_core->lastack - 1, LSTKP, SIZE_DWORD, SCALE_x4);
+ UML_BFXU(block, mem(&m_core->laddr.addr), I0, 0, 24);
+ UML_BFXU(block, mem(&m_core->laddr.code), I0, 24, 5);
+ UML_BFXU(block, mem(&m_core->laddr.loop_type), I0, 30, 2);
}
if (opcode & 0x004000000000U)
{
- fatalerror("sharcdrc: push/pop stacks: pop loop not implemented\n");
+ UML_CALLH(block, *m_pop_loop);
}
if (opcode & 0x002000000000U)
{
diff --git a/src/devices/cpu/sharc/sharcinternal.ipp b/src/devices/cpu/sharc/sharcinternal.ipp
index 0db1ea6a5d7..8b57f0403a3 100644
--- a/src/devices/cpu/sharc/sharcinternal.ipp
+++ b/src/devices/cpu/sharc/sharcinternal.ipp
@@ -49,6 +49,18 @@ struct alignas(16) adsp21062_device::sharc_internal_state
uint32_t addr;
uint32_t code;
uint32_t loop_type;
+
+ uint32_t pack() const
+ {
+ return (loop_type << 30) | (code << 24) | addr;
+ }
+
+ void unpack(uint32_t in)
+ {
+ addr = BIT(in, 0, 24);
+ code = BIT(in, 24, 5);
+ loop_type = BIT(in, 30, 2);
+ }
};
struct ASTAT_DRC
diff --git a/src/devices/cpu/sharc/sharcops.hxx b/src/devices/cpu/sharc/sharcops.hxx
index 946b15b8c1f..a3415127615 100644
--- a/src/devices/cpu/sharc/sharcops.hxx
+++ b/src/devices/cpu/sharc/sharcops.hxx
@@ -269,6 +269,8 @@ uint32_t adsp21062_device::GET_UREG(int ureg)
{
case 0x4: return m_core->pcstk; /* PCSTK */
case 0x5: return m_core->pcstkp; /* PCSTKP */
+ case 0x7: return m_core->curlcntr; /* CURLCNTR */
+ case 0x8: return m_core->lcntr; /* LCNTR */
default: fatalerror("SHARC: GET_UREG: unknown register %08X at %08X\n", ureg, m_core->pc);
}
break;
@@ -417,8 +419,16 @@ void adsp21062_device::SET_UREG(int ureg, uint32_t data)
}
break;
- case 0x7: m_core->curlcntr = data; break; /* CURLCNTR (Zero Gunner 2B) */
- case 0x8: m_core->lcntr = data; break; /* LCNTR */
+ case 0x7: /* CURLCNTR */
+ if ((m_core->lstkp > 0) && (m_core->lstkp < 7))
+ m_core->curlcntr = data;
+ break;
+
+ case 0x8: /* LCNTR */
+ if (m_core->lstkp < 6)
+ m_core->lcntr = data;
+ break;
+
default: fatalerror("SHARC: SET_UREG: unknown register %08X at %08X\n", ureg, m_core->pc);
}
break;
@@ -1105,24 +1115,27 @@ inline uint32_t adsp21062_device::TOP_PC()
return m_core->pcstk;
}
-inline void adsp21062_device::PUSH_LOOP(uint32_t addr, uint32_t code, uint32_t type, uint32_t count)
+inline void adsp21062_device::PUSH_LOOP()
{
- m_core->lstkp++;
if (m_core->lstkp >= 6)
fatalerror("SHARC: Loop Stack overflow!\n");
- if (m_core->lstkp == 0)
- m_core->stky |= LSEM;
- else
- m_core->stky &= ~LSEM;
+ if (m_core->lstkp > 0)
+ {
+ m_core->lcstack[m_core->lstkp - 1] = m_core->curlcntr;
+ m_core->lastack[m_core->lstkp - 1] = m_core->laddr.pack();
+ }
+ m_core->curlcntr = m_core->lcntr;
+ m_core->laddr.unpack(m_core->lastack[m_core->lstkp]);
- m_core->lcstack[m_core->lstkp] = count;
- m_core->lastack[m_core->lstkp] = (type << 30) | (code << 24) | addr;
- m_core->curlcntr = count;
+ m_core->lstkp++;
- m_core->laddr.addr = addr;
- m_core->laddr.code = code;
- m_core->laddr.loop_type = type;
+ if (m_core->lstkp < 6)
+ m_core->lcntr = m_core->lcstack[m_core->lstkp];
+ else
+ m_core->lcntr = 0xffffffff;
+
+ m_core->stky &= ~LSEM;
}
inline void adsp21062_device::POP_LOOP()
@@ -1132,16 +1145,21 @@ inline void adsp21062_device::POP_LOOP()
m_core->lstkp--;
- if (m_core->lstkp == 0)
- m_core->stky |= LSEM;
- else
- m_core->stky &= ~LSEM;
+ m_core->lcntr = m_core->curlcntr;
+ m_core->lastack[m_core->lstkp] = m_core->laddr.pack();
- m_core->curlcntr = m_core->lcstack[m_core->lstkp];
+ if (m_core->lstkp > 0)
+ {
+ m_core->curlcntr = m_core->lcstack[m_core->lstkp - 1];
+ m_core->laddr.unpack(m_core->lastack[m_core->lstkp - 1]);
+ }
+ else
+ {
+ m_core->curlcntr = 0xffffffff;
+ m_core->laddr.unpack(0xffffffff);
- m_core->laddr.addr = m_core->lastack[m_core->lstkp] & 0xffffff;
- m_core->laddr.code = (m_core->lastack[m_core->lstkp] >> 24) & 0x1f;
- m_core->laddr.loop_type = (m_core->lastack[m_core->lstkp] >> 30) & 0x3;
+ m_core->stky |= LSEM;
+ }
}
inline void adsp21062_device::PUSH_STATUS_STACK()
@@ -2251,8 +2269,11 @@ void adsp21062_device::sharcop_do_until_counter_imm()
m_core->lcntr = data;
PUSH_PC();
+ PUSH_LOOP();
m_core->pcstk = m_core->pc + 1;
- PUSH_LOOP(address, cond, type, m_core->lcntr);
+ m_core->laddr.addr = address;
+ m_core->laddr.code = cond;
+ m_core->laddr.loop_type = type;
}
/*****************************************************************************/
@@ -2277,8 +2298,11 @@ void adsp21062_device::sharcop_do_until_counter_ureg()
m_core->lcntr = GET_UREG(ureg);
PUSH_PC();
+ PUSH_LOOP();
m_core->pcstk = m_core->pc + 1;
- PUSH_LOOP(address, cond, type, m_core->lcntr);
+ m_core->laddr.addr = address;
+ m_core->laddr.code = cond;
+ m_core->laddr.loop_type = type;
}
/*****************************************************************************/
@@ -2292,8 +2316,11 @@ void adsp21062_device::sharcop_do_until()
uint32_t const address = (m_core->pc + offset);
PUSH_PC();
+ PUSH_LOOP();
m_core->pcstk = m_core->pc + 1;
- PUSH_LOOP(address, cond, 0, 0);
+ m_core->laddr.addr = address;
+ m_core->laddr.code = cond;
+ m_core->laddr.loop_type = 0;
}
/*****************************************************************************/
@@ -2521,11 +2548,11 @@ void adsp21062_device::sharcop_push_pop_stacks()
{
if (m_core->opcode & 0x008000000000U)
{
- fatalerror("sharcop_push_pop_stacks: push loop not implemented\n");
+ PUSH_LOOP();
}
if (m_core->opcode & 0x004000000000U)
{
- fatalerror("sharcop_push_pop_stacks: pop loop not implemented\n");
+ POP_LOOP();
}
if (m_core->opcode & 0x002000000000U)
{