diff options
| author | 2026-02-16 01:54:57 +1100 | |
|---|---|---|
| committer | 2026-02-16 02:01:18 +1100 | |
| commit | 173fa81d13fbe1f9f862437af43ac348b4d3f84f (patch) | |
| tree | aeca68830eaa711098827f5c33db18d628ff0d87 | |
| parent | 6ba2355b51568bfa8d43b68f8be3b73528cf718a (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.cpp | 36 | ||||
| -rw-r--r-- | src/devices/cpu/sharc/sharc.h | 2 | ||||
| -rw-r--r-- | src/devices/cpu/sharc/sharcdrc.cpp | 191 | ||||
| -rw-r--r-- | src/devices/cpu/sharc/sharcinternal.ipp | 2 | ||||
| -rw-r--r-- | src/devices/cpu/sharc/sharcops.hxx | 161 |
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) { |
