From bbd5057a2a767a950cb5a7909721a7f560081d3e Mon Sep 17 00:00:00 2001 From: hap Date: Sat, 4 Dec 2021 18:52:55 +0100 Subject: [PATCH] sparc: SWAP/SWAPA on unaligned address causes a trap --- src/devices/cpu/sparc/sparc.cpp | 88 ++++++++++++++++--------------- src/devices/cpu/sparc/sparcdefs.h | 2 +- 2 files changed, 46 insertions(+), 44 deletions(-) diff --git a/src/devices/cpu/sparc/sparc.cpp b/src/devices/cpu/sparc/sparc.cpp index 68c711c9833..7a23dfffe48 100644 --- a/src/devices/cpu/sparc/sparc.cpp +++ b/src/devices/cpu/sparc/sparc.cpp @@ -3885,9 +3885,8 @@ inline void sparc_base_device::dispatch_instruction(uint32_t op) case OP2_BICC: // branch on integer condition codes execute_bicc(op); break; - case OP2_SETHI: // sethi - *m_regs[RD] = op << 10; - m_r[0] = 0; + case OP2_SETHI: // sethi or nop + if (RDBITS) RDREG = op << 10; PC = nPC; nPC = nPC + 4; break; @@ -4419,52 +4418,55 @@ void sparcv8_device::execute_swap(uint32_t op) } } + if (address & 3) + { + m_trap = 1; + m_mem_address_not_aligned = 1; + m_stashed_icount = m_icount; + m_icount = 0; + return; + } + uint32_t word = 0; - uint32_t temp = 0; - if (!m_trap) + uint32_t data = RDREG; + + //while (m_pb_block_ldst_byte || m_pb_block_ldst_word) + //{ + // { wait for lock(s) to be lifted } + // { an implementation actually need only block when another SWAP is pending on + // the same word in memory as the one addressed by this SWAP, or a LDSTUB is + // pending on any byte of the word in memory addressed by this SWAP } + //} + + m_pb_block_ldst_word = 1; + + word = read_word(addr_space, address); + + if (MAE) { - temp = RDREG; - while (m_pb_block_ldst_byte || m_pb_block_ldst_word) - { - // { wait for lock(s) to be lifted } - // { an implementation actually need only block when another SWAP is pending on - // the same word in memory as the one addressed by this SWAP, or a LDSTUB is - // pending on any byte of the word in memory addressed by this SWAP } - } - - m_pb_block_ldst_word = 1; - - word = read_word(addr_space, address); - - if (MAE) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } + m_trap = 1; + m_data_access_exception = 1; + m_stashed_icount = m_icount; + m_icount = 0; + return; } - if (!m_trap) + + write_word(addr_space, address, data); + + m_pb_block_ldst_word = 0; + + if (MAE) { - write_word(addr_space, address, temp); - - m_pb_block_ldst_word = 0; - if (MAE) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - else - { - if (RDBITS) - RDREG = word; - } + m_trap = 1; + m_data_access_exception = 1; + m_stashed_icount = m_icount; + m_icount = 0; + return; } + if (RDBITS) + RDREG = word; + PC = nPC; nPC = nPC + 4; } diff --git a/src/devices/cpu/sparc/sparcdefs.h b/src/devices/cpu/sparc/sparcdefs.h index d7e291cbcdd..20a90b6a1d7 100644 --- a/src/devices/cpu/sparc/sparcdefs.h +++ b/src/devices/cpu/sparc/sparcdefs.h @@ -142,7 +142,7 @@ #define RDREG *m_regs[RD] #define RS1REG *m_regs[RS1] #define RS2REG *m_regs[RS2] -#define SET_RDREG(x) do { if(RD) { RDREG = (x); } } while (0) +#define SET_RDREG(x) do { if(RDBITS) { RDREG = (x); } } while (0) #define ADDRESS (USEIMM ? (RS1REG + SIMM13) : (RS1REG + RS2REG)) #define PC m_pc