diff options
| author | 2026-02-16 18:13:28 +1100 | |
|---|---|---|
| committer | 2026-02-16 18:13:28 +1100 | |
| commit | da1361691f9ab95fa60a40c4c33a15abd134cc60 (patch) | |
| tree | 4efbe710154bda3eba518215b69021998d01ca35 | |
| parent | a00dffbfee978c9a3b88e9bd623973185285895e (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.cpp | 55 | ||||
| -rw-r--r-- | src/devices/cpu/sharc/sharc.h | 2 | ||||
| -rw-r--r-- | src/devices/cpu/sharc/sharcdrc.cpp | 177 | ||||
| -rw-r--r-- | src/devices/cpu/sharc/sharcinternal.ipp | 12 | ||||
| -rw-r--r-- | src/devices/cpu/sharc/sharcops.hxx | 81 |
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) { |
