summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2026-02-16 01:54:57 +1100
committer Vas Crabb <vas@vastheman.com>2026-02-16 02:01:18 +1100
commit173fa81d13fbe1f9f862437af43ac348b4d3f84f (patch)
treeaeca68830eaa711098827f5c33db18d628ff0d87
parent6ba2355b51568bfa8d43b68f8be3b73528cf718a (diff)
cpu/sharc: Overhauled PC stack implementation:
* Always access top-of-stack through the pseudo-register value. * Better behaviour when PC stack is empty. * Implemented effects of writing to PCSTKP. * Mask PC stack values to 24 bits. * Try to get PC stack into a consistent state after loading a saved state. * Also fixed loops with initial counter value of zero (should iterate 2^32 times).
-rw-r--r--src/devices/cpu/sharc/sharc.cpp36
-rw-r--r--src/devices/cpu/sharc/sharc.h2
-rw-r--r--src/devices/cpu/sharc/sharcdrc.cpp191
-rw-r--r--src/devices/cpu/sharc/sharcinternal.ipp2
-rw-r--r--src/devices/cpu/sharc/sharcops.hxx161
5 files changed, 275 insertions, 117 deletions
diff --git a/src/devices/cpu/sharc/sharc.cpp b/src/devices/cpu/sharc/sharc.cpp
index cd3bddc4ca4..3cef9566f49 100644
--- a/src/devices/cpu/sharc/sharc.cpp
+++ b/src/devices/cpu/sharc/sharc.cpp
@@ -709,7 +709,6 @@ void adsp21062_device::device_start()
save_item(NAME(m_core->faddr));
save_item(NAME(m_core->daddr));
- save_item(NAME(m_core->pcstk));
save_item(NAME(m_core->pcstkp));
save_item(NAME(m_core->laddr.addr));
save_item(NAME(m_core->laddr.code));
@@ -808,8 +807,8 @@ void adsp21062_device::device_start()
save_item(NAME(m_core->astat_old_old_old));
state_add( SHARC_PC, "PC", m_core->pc).mask(0x00ffffff).formatstr("%06X");
- state_add( SHARC_PCSTK, "PCSTK", m_core->pcstk).formatstr("%08X");
- state_add( SHARC_PCSTKP, "PCSTKP", m_core->pcstkp).formatstr("%08X");
+ 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_FADDR, "FADDR", m_core->faddr).formatstr("%08X");
state_add( SHARC_DADDR, "DADDR", m_core->daddr).formatstr("%08X");
@@ -970,8 +969,9 @@ void adsp21062_device::device_reset()
m_core->ustat1 = 0x0000;
m_core->ustat2 = 0x0000;
- m_core->lstkp = 0;
m_core->pcstkp = 0;
+ m_core->lstkp = 0;
+ m_core->pcstk = 0x00ffffff;
m_core->status_stkp = 0;
m_core->interrupt_active = 0;
@@ -993,6 +993,9 @@ void adsp21062_device::device_pre_save()
{
cpu_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_enable_drc)
{
m_core->astat = m_core->astat_drc.pack();
@@ -1005,6 +1008,26 @@ void adsp21062_device::device_post_load()
{
cpu_device::device_post_load();
+ for (auto &pcstk : m_core->pcstack)
+ pcstk &= 0x00ffffff;
+
+ m_core->pcstkp &= 0x1f;
+
+ 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->pcstkp > 0)
+ m_core->stky &= ~PCEM;
+ else
+ m_core->stky |= PCEM;
+
+ if (m_core->pcstkp >= 30)
+ m_core->stky |= PCFL;
+ else
+ m_core->stky &= ~PCFL;
+
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);
@@ -1072,10 +1095,11 @@ void adsp21062_device::check_interrupts()
which++;
}
+ PUSH_PC();
if (m_core->idle)
- PUSH_PC(m_core->pc+1);
+ m_core->pcstk = m_core->pc + 1;
else
- PUSH_PC(m_core->daddr);
+ m_core->pcstk = m_core->daddr;
m_core->irptl |= 1 << which;
diff --git a/src/devices/cpu/sharc/sharc.h b/src/devices/cpu/sharc/sharc.h
index 1033f60ec7b..5e88a1a8347 100644
--- a/src/devices/cpu/sharc/sharc.h
+++ b/src/devices/cpu/sharc/sharc.h
@@ -321,7 +321,7 @@ private:
void SHIFT_OPERATION_IMM(int shiftop, int data, int rn, int rx);
void COMPUTE(uint32_t opcode);
void check_interrupts();
- void PUSH_PC(uint32_t pc);
+ 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);
diff --git a/src/devices/cpu/sharc/sharcdrc.cpp b/src/devices/cpu/sharc/sharcdrc.cpp
index 953d0fd3f1c..98f753c8d6e 100644
--- a/src/devices/cpu/sharc/sharcdrc.cpp
+++ b/src/devices/cpu/sharc/sharcdrc.cpp
@@ -441,38 +441,44 @@ void adsp21062_device::static_generate_memory_accessors()
void adsp21062_device::static_generate_push_pc()
{
- // Push contents of I0 to PC stack
+ // Push the PC stack
// Trashes I1
+ // Caller's responsibility to update PCSTK
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_pc, "push_pc");
- UML_HANDLE(block, *m_push_pc); // handle *m_push_pc
-
- UML_ADD(block, I1, PCSTKP, 1); // add i1,PCSTKP,1
- UML_CMP(block, I1, 32); // cmp i1,32
- UML_JMPc(block, COND_L, no_overflow); // jl no_overflow
- UML_CALLC(block, cfunc_pcstack_overflow, this); // callc cfunc_pcstack_overflow
-
- UML_LABEL(block, no_overflow); // no_overflow:
- UML_CMP(block, I1, 0); // cmp i1,0
- UML_JMPc(block, COND_E, empty); // je empty
- UML_AND(block, STKY, STKY, ~PCEM); // and STKY,~0x400000
- UML_JMP(block, do_store); // jmp do_store
- UML_LABEL(block, empty); // empty:
- UML_OR(block, STKY, STKY, PCEM); // or STKY,0x400000
+ UML_HANDLE(block, *m_push_pc);
- UML_LABEL(block, do_store); // do_store:
- UML_MOV(block, PCSTK, I0); // mov PCSTK,pc
- UML_STORE(block, &m_core->pcstack, I1, I0, SIZE_DWORD, SCALE_x4); // store [m_core->pcstack],i1,i0,dword,scale_x4
- UML_MOV(block, PCSTKP, I1); // mov PCSTKP,i1
+ // check for stack overflow
+ UML_MOV(block, I1, PCSTKP);
+ UML_CMP(block, I1, 30);
+ UML_JMPc(block, COND_B, no_overflow);
+ UML_CALLC(block, cfunc_pcstack_overflow, this);
+ UML_LABEL(block, no_overflow);
+ // store the top-of-stack pseudo-register if the stack isn't empty
+ UML_TEST(block, I1, I1);
+ UML_JMPc(block, COND_Z, empty);
+ UML_STORE(block, m_core->pcstack - 1, I1, PCSTK, SIZE_DWORD, SCALE_x4);
+ UML_LABEL(block, empty);
+
+ // increment stack pointer and update sticky flags
+ UML_ADD(block, I1, I1, 1);
+ UML_MOV(block, PCSTKP, I1);
+ UML_CMP(block, I1, 30);
+ UML_JMPc(block, COND_AE, full);
+ UML_AND(block, STKY, STKY, ~PCEM);
+ UML_RET(block);
+ UML_LABEL(block, full);
+ UML_AND(block, I1, STKY, ~PCEM);
+ UML_OR(block, STKY, I1, PCFL);
UML_RET(block);
block.end();
@@ -484,31 +490,32 @@ void adsp21062_device::static_generate_pop_pc()
// Trashes I1
uml::code_label label = 1;
+ uml::code_label const no_underflow = label++;
+ uml::code_label const empty = label++;
+
drcuml_block &block(m_drcuml->begin_invariant_block(32));
// add a global entry for this
alloc_handle(m_pop_pc, "pop_pc");
- UML_HANDLE(block, *m_pop_pc); // handle *m_pop_pc
-
- UML_MOV(block, I1, PCSTKP); // mov i0,PCSTKP
- UML_LOAD(block, I0, &m_core->pcstack, I1, SIZE_DWORD, SCALE_x4); // load i1,[m_core->pcstack],i0,dword,scale_x4
- UML_CMP(block, I1, 0); // cmp i1,0
- UML_JMPc(block, COND_NE, label); // jne label1
- UML_CALLC(block, cfunc_pcstack_underflow, this); // callc cfunc_pcstack_underflow
-
- UML_LABEL(block, label++); // label1:
- UML_SUB(block, I1, I1, 1); // sub i1,i1,1
- UML_CMP(block, I1, 0); // cmp i1,0
- UML_JMPc(block, COND_E, label); // je label2
- UML_AND(block, STKY, STKY, ~PCEM); // and STKY,~0x400000
- UML_JMP(block, label + 1); // jmp label3
- UML_LABEL(block, label++); // label2:
- UML_OR(block, STKY, STKY, PCEM); // or STKY,0x400000
+ UML_HANDLE(block, *m_pop_pc);
- UML_LABEL(block, label++); // label3:
- UML_MOV(block, PCSTKP, I1); // mov PCSTKP,i1
- UML_MOV(block, PCSTK, I0); // mov PCSTK,i0
+ // check for stack underflow
+ UML_SUB(block, I1, PCSTKP, 1);
+ UML_MOV(block, I0, PCSTK);
+ UML_JMPc(block, COND_AE, no_underflow);
+ UML_CALLC(block, cfunc_pcstack_underflow, this);
+ UML_LABEL(block, no_underflow);
+ UML_MOV(block, PCSTKP, I1);
+ // update the top-of-stack pseudo-register and sticky flags
+ UML_JMPc(block, COND_Z, empty);
+ UML_LOAD(block, PCSTK, m_core->pcstack - 1, I1, SIZE_DWORD, SCALE_x4);
+ UML_AND(block, STKY, STKY, ~PCFL);
+ UML_RET(block);
+ UML_LABEL(block, empty);
+ UML_MOV(block, PCSTK, 0x00ffffff);
+ UML_AND(block, I1, STKY, ~PCFL);
+ UML_OR(block, STKY, I1, PCEM);
UML_RET(block);
block.end();
@@ -841,7 +848,7 @@ void adsp21062_device::static_generate_loop_check_body(drcuml_block &block, bool
// update cycles and hash jump
UML_LABEL(block, loop);
- UML_LOAD(block, I2, m_core->pcstack, PCSTKP, SIZE_DWORD, SCALE_x4);
+ UML_MOV(block, I2, PCSTK);
if (is_call)
{
UML_MOV(block, mem(&m_core->temp_return), I2);
@@ -905,6 +912,7 @@ void adsp21062_device::static_generate_exception(uint8_t exception, const char *
UML_MOV(block, mem(&m_core->interrupt_active), 1); // mov [interrupt_active],1
UML_CALLH(block, *m_push_pc); // callh m_push_pc
+ UML_MOV(block, PCSTK, I0); // mov PCSTK,i0
// TODO: timer and VIRPT interrupts also push status
UML_CMP(block, I3, 6); // cmp i3,6
@@ -1730,6 +1738,7 @@ void adsp21062_device::generate_call(drcuml_block &block, compiler_state &compil
UML_MOV(block, I0, desc->pc + 1);
}
UML_CALLH(block, *m_push_pc);
+ UML_MOV(block, PCSTK, I0);
// update cycles and hash jump
if (desc->targetpc != BRANCH_TARGET_DYNAMIC)
@@ -1870,8 +1879,12 @@ void adsp21062_device::generate_read_ureg(drcuml_block &block, compiler_state &c
break;
case 0x64: // PCSTK
- UML_LOAD(block, I0, &m_core->pcstack, PCSTKP, SIZE_DWORD, SCALE_x4);
+ UML_MOV(block, I0, PCSTK);
break;
+ case 0x65: // PCSTKP
+ UML_MOV(block, I0, PCSTKP);
+ break;
+
case 0x70: // USTAT1
UML_MOV(block, I0, mem(&m_core->ustat1));
break;
@@ -2052,11 +2065,79 @@ void adsp21062_device::generate_write_ureg(drcuml_block &block, compiler_state &
break;
case 0x64: // PCSTK
- fatalerror("generate_write_ureg: PCSTK");
+ {
+ uml::code_label const skip = compiler.labelnum++;
+
+ UML_OR(block, I1, PCSTKP, 0);
+ UML_JMPc(block, COND_Z, skip);
+ UML_CMP(block, I1, 31);
+ if (imm)
+ {
+ UML_MOVc(block, COND_B, PCSTK, data & 0x00ffffff);
+ }
+ else
+ {
+ UML_JMPc(block, COND_AE, skip);
+ UML_AND(block, PCSTK, I0, 0x00ffffff);
+ }
+ UML_LABEL(block, skip);
break;
+ }
case 0x65: // PCSTKP
- UML_MOV(block, PCSTKP, imm ? data : I0);
+ {
+ // TODO: this should take effect after a one-cycle delay
+ uml::code_label const empty = compiler.labelnum++;
+ uml::code_label const no_overflow = compiler.labelnum++;
+ uml::code_label const pop = compiler.labelnum++;
+ uml::code_label const do_load = compiler.labelnum++;
+ uml::code_label const set_stky = compiler.labelnum++;
+ uml::code_label const done = compiler.labelnum++;
+
+ UML_MOV(block, I1, PCSTKP);
+ UML_CMP(block, I1, 31);
+ UML_JMPc(block, COND_AE, done);
+
+ UML_TEST(block, I1, I1);
+ UML_JMPc(block, COND_Z, empty);
+ UML_STORE(block, m_core->pcstack - 1, I1, PCSTK, SIZE_DWORD, SCALE_x4);
+ UML_LABEL(block, empty);
+
+ if (imm)
+ UML_MOV(block, I0, data & 0x1f);
+ else
+ UML_AND(block, I0, I0, 0x1f);
+ UML_CMP(block, I0, 31);
+ UML_JMPc(block, COND_B, no_overflow);
+ UML_CALLC(block, cfunc_pcstack_overflow, this);
+ UML_LABEL(block, no_overflow);
+ UML_CMP(block, I1, I0);
+ UML_JMPc(block, COND_E, done);
+ UML_MOV(block, I1, STKY);
+ UML_MOV(block, PCSTKP, I0);
+ UML_JMPc(block, COND_A, pop);
+
+ UML_AND(block, I1, I1, ~PCEM);
+ UML_CMP(block, I0, 30);
+ UML_JMPc(block, COND_B, do_load);
+ UML_OR(block, I1, I1, PCFL);
+ UML_JMP(block, do_load);
+
+ UML_LABEL(block, pop);
+ UML_AND(block, I1, I1, ~PCFL);
+ UML_TEST(block, I0, I0);
+ UML_JMPc(block, COND_NZ, do_load);
+
+ UML_MOV(block, PCSTK, 0x00ffffff);
+ UML_OR(block, I1, I1, PCEM);
+ UML_JMP(block, set_stky);
+
+ UML_LABEL(block, do_load);
+ UML_LOAD(block, PCSTK, m_core->pcstack - 1, I0, SIZE_DWORD, SCALE_x4);
+ UML_LABEL(block, set_stky);
+ UML_MOV(block, STKY, I1);
+ UML_LABEL(block, done);
break;
+ }
case 0x67: // CURLCNTR
UML_MOV(block, CURLCNTR, imm ? data : I0);
break;
@@ -2540,17 +2621,15 @@ bool adsp21062_device::generate_opcode(drcuml_block &block, compiler_state &comp
uint32_t address = desc->pc + offset;
UML_MOV(block, LCNTR, data);
- if (data > 0)
- {
- // push pc
- UML_MOV(block, I0, desc->pc + 1);
- UML_CALLH(block, *m_push_pc);
- // push loop
- UML_MOV(block, I0, data);
- UML_MOV(block, I1, 0xcf000000 | address);
- UML_CALLH(block, *m_push_loop);
- }
+ // push pc
+ UML_CALLH(block, *m_push_pc);
+ 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);
return true;
}
@@ -2566,8 +2645,8 @@ bool adsp21062_device::generate_opcode(drcuml_block &block, compiler_state &comp
UML_MOV(block, LCNTR, I3);
// push pc
- UML_MOV(block, I0, desc->pc + 1);
UML_CALLH(block, *m_push_pc);
+ UML_MOV(block, PCSTK, desc->pc + 1);
// push loop
UML_MOV(block, I0, I3);
@@ -2583,8 +2662,8 @@ bool adsp21062_device::generate_opcode(drcuml_block &block, compiler_state &comp
uint32_t address = desc->pc + offset;
// push pc
- UML_MOV(block, I0, desc->pc + 1);
UML_CALLH(block, *m_push_pc);
+ UML_MOV(block, PCSTK, desc->pc + 1);
// push loop
UML_MOV(block, I0, 0);
@@ -2972,7 +3051,7 @@ bool adsp21062_device::generate_opcode(drcuml_block &block, compiler_state &comp
}
if (opcode & 0x000800000000U)
{
- UML_MOV(block, I0, PCSTK);
+ // TODO: what should the top-of-stack value be after this?
UML_CALLH(block, *m_push_pc);
}
if (opcode & 0x000400000000U)
diff --git a/src/devices/cpu/sharc/sharcinternal.ipp b/src/devices/cpu/sharc/sharcinternal.ipp
index 04ef61433c7..0db1ea6a5d7 100644
--- a/src/devices/cpu/sharc/sharcinternal.ipp
+++ b/src/devices/cpu/sharc/sharcinternal.ipp
@@ -132,7 +132,7 @@ struct alignas(16) adsp21062_device::sharc_internal_state
uint64_t mrf;
uint64_t mrb;
- uint32_t pcstack[32];
+ uint32_t pcstack[30];
uint32_t lcstack[6];
uint32_t lastack[6];
uint32_t lstkp;
diff --git a/src/devices/cpu/sharc/sharcops.hxx b/src/devices/cpu/sharc/sharcops.hxx
index a5729172e2a..946b15b8c1f 100644
--- a/src/devices/cpu/sharc/sharcops.hxx
+++ b/src/devices/cpu/sharc/sharcops.hxx
@@ -267,7 +267,8 @@ uint32_t adsp21062_device::GET_UREG(int ureg)
{
switch(reg)
{
- case 0x4: return m_core->pcstack[m_core->pcstkp]; /* PCSTK */
+ case 0x4: return m_core->pcstk; /* PCSTK */
+ case 0x5: return m_core->pcstkp; /* PCSTKP */
default: fatalerror("SHARC: GET_UREG: unknown register %08X at %08X\n", ureg, m_core->pc);
}
break;
@@ -375,7 +376,47 @@ void adsp21062_device::SET_UREG(int ureg, uint32_t data)
case 0x6:
switch (reg)
{
- case 0x5: m_core->pcstkp = data; break; /* PCSTKP */
+ case 0x4: /* PCSTK */
+ if ((m_core->pcstkp > 0) && (m_core->pcstkp < 31))
+ m_core->pcstk = data & 0x00ffffff;
+ break;
+
+ case 0x5: /* PCSTKP */
+ if (m_core->pcstkp < 31)
+ {
+ // TODO: this should take effect with a one-cycle delay
+ uint32_t const prev = std::exchange(m_core->pcstkp, data & 0x1f);
+
+ if (prev > 0)
+ m_core->pcstack[prev - 1] = m_core->pcstk;
+
+ if (prev < m_core->pcstkp)
+ {
+ if (m_core->pcstkp >= 31)
+ fatalerror("SHARC: PC Stack overflow!\n");
+
+ m_core->pcstk = m_core->pcstack[m_core->pcstkp - 1];
+
+ m_core->stky &= ~PCEM;
+ if (m_core->pcstkp >= 30)
+ m_core->stky |= PCFL;
+ }
+ else if (prev > m_core->pcstkp)
+ {
+ if (m_core->pcstkp > 0)
+ {
+ m_core->pcstk = m_core->pcstack[m_core->pcstkp - 1];
+ }
+ else
+ {
+ m_core->pcstk = 0x00ffffff;
+ m_core->stky |= PCEM;
+ }
+ m_core->stky &= ~PCFL;
+ }
+ }
+ break;
+
case 0x7: m_core->curlcntr = data; break; /* CURLCNTR (Zero Gunner 2B) */
case 0x8: m_core->lcntr = data; break; /* LCNTR */
default: fatalerror("SHARC: SET_UREG: unknown register %08X at %08X\n", ureg, m_core->pc);
@@ -1017,41 +1058,51 @@ void adsp21062_device::COMPUTE(uint32_t opcode)
}
}
-inline void adsp21062_device::PUSH_PC(uint32_t pc)
+inline void adsp21062_device::PUSH_PC()
{
- m_core->pcstkp++;
- if (m_core->pcstkp >= 32)
+ if (m_core->pcstkp >= 30)
fatalerror("SHARC: PC Stack overflow!\n");
- if (m_core->pcstkp == 0)
- m_core->stky |= PCEM;
- else
- m_core->stky &= ~PCEM;
+ if (m_core->pcstkp > 0)
+ m_core->pcstack[m_core->pcstkp - 1] = m_core->pcstk;
+
+ m_core->pcstkp++;
- m_core->pcstk = pc;
- m_core->pcstack[m_core->pcstkp] = pc;
+ m_core->stky &= ~PCEM;
+ if (m_core->pcstkp >= 30)
+ m_core->stky |= PCFL;
}
inline uint32_t adsp21062_device::POP_PC()
{
- m_core->pcstk = m_core->pcstack[m_core->pcstkp];
-
if (m_core->pcstkp == 0)
fatalerror("SHARC: PC Stack underflow!\n");
+ uint32_t const result = m_core->pcstk;
+
m_core->pcstkp--;
- if (m_core->pcstkp == 0)
- m_core->stky |= PCEM;
- else
- m_core->stky &= ~PCEM;
+ if (m_core->pcstkp < 30)
+ {
+ m_core->pcstack[m_core->pcstkp] = m_core->pcstk;
+ if (m_core->pcstkp > 0)
+ {
+ m_core->pcstk = m_core->pcstack[m_core->pcstkp - 1];
+ }
+ else
+ {
+ m_core->pcstk = 0x00ffffff;
+ m_core->stky |= PCEM;
+ }
+ m_core->stky &= ~PCFL;
+ }
- return m_core->pcstk;
+ return result;
}
inline uint32_t adsp21062_device::TOP_PC()
{
- return m_core->pcstack[m_core->pcstkp];
+ return m_core->pcstk;
}
inline void adsp21062_device::PUSH_LOOP(uint32_t addr, uint32_t code, uint32_t type, uint32_t count)
@@ -1639,16 +1690,17 @@ void adsp21062_device::sharcop_direct_call()
if (IF_CONDITION_CODE(cond))
{
+ PUSH_PC();
if (j)
{
- //PUSH_PC(m_core->pc+3); /* 1 instruction + 2 delayed instructions */
- PUSH_PC(m_core->nfaddr); /* 1 instruction + 2 delayed instructions */
+ //m_core->pcstk = m_core->pc + 3; /* 1 instruction + 2 delayed instructions */
+ m_core->pcstk = m_core->nfaddr; /* 1 instruction + 2 delayed instructions */
CHANGE_PC_DELAYED(address);
}
else
{
- //PUSH_PC(m_core->pc+1);
- PUSH_PC(m_core->daddr);
+ //m_core->pcstk = m_core->pc + 1;
+ m_core->pcstk = m_core->daddr;
CHANGE_PC(address);
}
}
@@ -1701,14 +1753,15 @@ void adsp21062_device::sharcop_relative_call()
if (IF_CONDITION_CODE(cond))
{
+ PUSH_PC();
if (j)
{
- PUSH_PC(m_core->pc+3); /* 1 instruction + 2 delayed instructions */
+ m_core->pcstk = m_core->pc + 3; /* 1 instruction + 2 delayed instructions */
CHANGE_PC_DELAYED(m_core->pc + util::sext(address, 24));
}
else
{
- PUSH_PC(m_core->pc+1);
+ m_core->pcstk = m_core->pc + 1;
CHANGE_PC(m_core->pc + util::sext(address, 24));
}
}
@@ -1831,16 +1884,17 @@ void adsp21062_device::sharcop_indirect_call()
{
if (IF_CONDITION_CODE(cond))
{
+ PUSH_PC();
if (j)
{
- //PUSH_PC(m_core->pc+3); /* 1 instruction + 2 delayed instructions */
- PUSH_PC(m_core->nfaddr); /* 1 instruction + 2 delayed instructions */
+ //m_core->pcstk = m_core->pc + 3; /* 1 instruction + 2 delayed instructions */
+ m_core->pcstk = m_core->nfaddr; /* 1 instruction + 2 delayed instructions */
CHANGE_PC_DELAYED(PM_REG_I(pmi) + PM_REG_M(pmm));
}
else
{
- //PUSH_PC(m_core->pc+1);
- PUSH_PC(m_core->daddr);
+ //m_core->pcstk = m_core->pc + 1;
+ m_core->pcstk = m_core->daddr;
CHANGE_PC(PM_REG_I(pmi) + PM_REG_M(pmm));
}
}
@@ -1857,16 +1911,17 @@ void adsp21062_device::sharcop_indirect_call()
if (compute)
COMPUTE(compute);
+ PUSH_PC();
if (j)
{
- //PUSH_PC(m_core->pc+3); /* 1 instruction + 2 delayed instructions */
- PUSH_PC(m_core->nfaddr); /* 1 instruction + 2 delayed instructions */
+ //m_core->pcstk = m_core->pc + 3; /* 1 instruction + 2 delayed instructions */
+ m_core->pcstk = m_core->nfaddr; /* 1 instruction + 2 delayed instructions */
CHANGE_PC_DELAYED(PM_REG_I(pmi) + PM_REG_M(pmm));
}
else
{
- //PUSH_PC(m_core->pc+1);
- PUSH_PC(m_core->daddr);
+ //m_core->pcstk = m_core->pc + 1;
+ m_core->pcstk = m_core->daddr;
CHANGE_PC(PM_REG_I(pmi) + PM_REG_M(pmm));
}
}
@@ -1951,16 +2006,17 @@ void adsp21062_device::sharcop_relative_call_compute()
{
if (IF_CONDITION_CODE(cond))
{
+ PUSH_PC();
if (j)
{
- //PUSH_PC(m_core->pc+3); /* 1 instruction + 2 delayed instructions */
- PUSH_PC(m_core->nfaddr); /* 1 instruction + 2 delayed instructions */
+ //m_core->pcstk = m_core->pc + 3; /* 1 instruction + 2 delayed instructions */
+ m_core->pcstk = m_core->nfaddr; /* 1 instruction + 2 delayed instructions */
CHANGE_PC_DELAYED(m_core->pc + op_get_reladdr(m_core->opcode));
}
else
{
- //PUSH_PC(m_core->pc+1);
- PUSH_PC(m_core->daddr);
+ //m_core->pcstk = m_core->pc + 1;
+ m_core->pcstk = m_core->daddr;
CHANGE_PC(m_core->pc + op_get_reladdr(m_core->opcode));
}
}
@@ -1977,16 +2033,17 @@ void adsp21062_device::sharcop_relative_call_compute()
if (compute)
COMPUTE(compute);
+ PUSH_PC();
if (j)
{
- //PUSH_PC(m_core->pc+3); /* 1 instruction + 2 delayed instructions */
- PUSH_PC(m_core->nfaddr); /* 1 instruction + 2 delayed instructions */
+ //m_core->pcstk = m_core->pc + 3; /* 1 instruction + 2 delayed instructions */
+ m_core->pcstk = m_core->nfaddr; /* 1 instruction + 2 delayed instructions */
CHANGE_PC_DELAYED(m_core->pc + op_get_reladdr(m_core->opcode));
}
else
{
- //PUSH_PC(m_core->pc+1);
- PUSH_PC(m_core->daddr);
+ //m_core->pcstk = m_core->pc + 1;
+ m_core->pcstk = m_core->daddr;
CHANGE_PC(m_core->pc + op_get_reladdr(m_core->opcode));
}
}
@@ -2193,11 +2250,9 @@ void adsp21062_device::sharcop_do_until_counter_imm()
type = 3;
m_core->lcntr = data;
- if (m_core->lcntr > 0)
- {
- PUSH_PC(m_core->pc+1);
- PUSH_LOOP(address, cond, type, m_core->lcntr);
- }
+ PUSH_PC();
+ m_core->pcstk = m_core->pc + 1;
+ PUSH_LOOP(address, cond, type, m_core->lcntr);
}
/*****************************************************************************/
@@ -2221,11 +2276,9 @@ void adsp21062_device::sharcop_do_until_counter_ureg()
type = 3;
m_core->lcntr = GET_UREG(ureg);
- if (m_core->lcntr > 0)
- {
- PUSH_PC(m_core->pc+1);
- PUSH_LOOP(address, cond, type, m_core->lcntr);
- }
+ PUSH_PC();
+ m_core->pcstk = m_core->pc + 1;
+ PUSH_LOOP(address, cond, type, m_core->lcntr);
}
/*****************************************************************************/
@@ -2238,7 +2291,8 @@ void adsp21062_device::sharcop_do_until()
int const offset = util::sext(m_core->opcode & 0xffffff, 24);
uint32_t const address = (m_core->pc + offset);
- PUSH_PC(m_core->pc+1);
+ PUSH_PC();
+ m_core->pcstk = m_core->pc + 1;
PUSH_LOOP(address, cond, 0, 0);
}
@@ -2485,7 +2539,8 @@ void adsp21062_device::sharcop_push_pop_stacks()
}
if (m_core->opcode & 0x000800000000U)
{
- PUSH_PC(m_core->pcstk);
+ // TODO: what should the top-of-stack value be after this?
+ PUSH_PC();
}
if (m_core->opcode & 0x000400000000U)
{