// license:BSD-3-Clause // copyright-holders:R. Belmont /***************************************************************************** * * sh4.c * Portable Hitachi SH-4 (SH7750 family) emulator * * By R. Belmont, based on sh2.c by Juergen Buchmueller, Mariusz Wojcieszek, * Olivier Galibert, Sylvain Glaize, and James Forshaw. * * * TODO: FPU * DMA * on-board peripherals * * DONE: boot/reset setup * 64-bit data bus * banked registers * additional registers for supervisor mode * FPU status and data registers * state save for the new registers * interrupts * store queues * *****************************************************************************/ #include "emu.h" #include "debugger.h" #include "sh4.h" #include "sh4regs.h" #include "sh4comn.h" #include "sh3comn.h" #include "sh4tmu.h" #if SH4_USE_FASTRAM_OPTIMIZATION void sh34_base_device::add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base) { if (m_fastram_select < ARRAY_LENGTH(m_fastram)) { m_fastram[m_fastram_select].start = start; m_fastram[m_fastram_select].end = end; m_fastram[m_fastram_select].readonly = readonly; m_fastram[m_fastram_select].base = base; m_fastram_select++; } } #else void sh34_base_device::add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base) { } #endif CPU_DISASSEMBLE( sh4 ); CPU_DISASSEMBLE( sh4be ); const device_type SH3LE = &device_creator; const device_type SH3BE = &device_creator; const device_type SH4LE = &device_creator; const device_type SH4BE = &device_creator; #if 0 /*When OC index mode is off (CCR.OIX = 0)*/ static ADDRESS_MAP_START( sh4_internal_map, AS_PROGRAM, 64, sh4_base_device ) AM_RANGE(0x1C000000, 0x1C000FFF) AM_RAM AM_MIRROR(0x03FFD000) AM_RANGE(0x1C002000, 0x1C002FFF) AM_RAM AM_MIRROR(0x03FFD000) AM_RANGE(0xE0000000, 0xE000003F) AM_RAM AM_MIRROR(0x03FFFFC0) ADDRESS_MAP_END #endif /*When OC index mode is on (CCR.OIX = 1)*/ static ADDRESS_MAP_START( sh4_internal_map, AS_PROGRAM, 64, sh4_base_device ) AM_RANGE(0x1C000000, 0x1C000FFF) AM_RAM AM_MIRROR(0x01FFF000) AM_RANGE(0x1E000000, 0x1E000FFF) AM_RAM AM_MIRROR(0x01FFF000) AM_RANGE(0xE0000000, 0xE000003F) AM_RAM AM_MIRROR(0x03FFFFC0) // todo: store queues should be write only on DC's SH4, executing PREFM shouldn't cause an actual memory read access! AM_RANGE(0xF6000000, 0xF7FFFFFF) AM_READWRITE(sh4_tlb_r,sh4_tlb_w) AM_RANGE(0xFE000000, 0xFFFFFFFF) AM_READWRITE32(sh4_internal_r, sh4_internal_w, U64(0xffffffffffffffff)) ADDRESS_MAP_END static ADDRESS_MAP_START( sh3_internal_map, AS_PROGRAM, 64, sh3_base_device ) AM_RANGE(SH3_LOWER_REGBASE, SH3_LOWER_REGEND) AM_READWRITE32(sh3_internal_r, sh3_internal_w, U64(0xffffffffffffffff)) AM_RANGE(SH3_UPPER_REGBASE, SH3_UPPER_REGEND) AM_READWRITE32(sh3_internal_high_r, sh3_internal_high_w, U64(0xffffffffffffffff)) ADDRESS_MAP_END sh34_base_device::sh34_base_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, endianness_t endianness, address_map_constructor internal) : cpu_device(mconfig, type, name, tag, owner, clock, shortname, __FILE__) , m_program_config("program", endianness, 64, 32, 0, internal) , m_io_config("io", endianness, 64, 8) , c_md2(0) , c_md1(0) , c_md0(0) , c_md6(0) , c_md4(0) , c_md3(0) , c_md5(0) , c_md7(0) , c_md8(0) , c_clock(0) #if SH4_USE_FASTRAM_OPTIMIZATION , m_bigendian(endianness == ENDIANNESS_BIG) , m_byte_xor(m_bigendian ? BYTE8_XOR_BE(0) : BYTE8_XOR_LE(0)) , m_word_xor(m_bigendian ? WORD2_XOR_BE(0) : WORD2_XOR_LE(0)) , m_dword_xor(m_bigendian ? DWORD_XOR_BE(0) : DWORD_XOR_LE(0)) , m_fastram_select(0) #endif { #if SH4_USE_FASTRAM_OPTIMIZATION memset(m_fastram, 0, sizeof(m_fastram)); #endif } sh3_base_device::sh3_base_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, endianness_t endianness) : sh34_base_device(mconfig, type, name, tag, owner, clock, shortname, endianness, ADDRESS_MAP_NAME(sh3_internal_map)) { m_cpu_type = CPU_TYPE_SH3; } sh4_base_device::sh4_base_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, uint32_t clock, const char *shortname, endianness_t endianness) : sh34_base_device(mconfig, type, name, tag, owner, clock, shortname, endianness, ADDRESS_MAP_NAME(sh4_internal_map)) { m_cpu_type = CPU_TYPE_SH4; } sh3_device::sh3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : sh3_base_device(mconfig, SH3LE, "SH-3 (little)", tag, owner, clock, "sh3", ENDIANNESS_LITTLE) { } sh3be_device::sh3be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : sh3_base_device(mconfig, SH3BE, "SH-3 (big)", tag, owner, clock, "sh3be", ENDIANNESS_BIG) { } sh4_device::sh4_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : sh4_base_device(mconfig, SH4LE, "SH-4 (little)", tag, owner, clock, "sh4", ENDIANNESS_LITTLE) { } sh4be_device::sh4be_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : sh4_base_device(mconfig, SH4BE, "SH-4 (big)", tag, owner, clock, "sh4be", ENDIANNESS_BIG) { } offs_t sh34_base_device::disasm_disassemble(char *buffer, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) { extern CPU_DISASSEMBLE( sh4 ); return CPU_DISASSEMBLE_NAME(sh4)(this, buffer, pc, oprom, opram, options); } offs_t sh3be_device::disasm_disassemble(char *buffer, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) { extern CPU_DISASSEMBLE( sh4be ); return CPU_DISASSEMBLE_NAME(sh4be)(this, buffer, pc, oprom, opram, options); } offs_t sh4be_device::disasm_disassemble(char *buffer, offs_t pc, const uint8_t *oprom, const uint8_t *opram, uint32_t options) { extern CPU_DISASSEMBLE( sh4be ); return CPU_DISASSEMBLE_NAME(sh4be)(this, buffer, pc, oprom, opram, options); } /* Called for unimplemented opcodes */ void sh34_base_device::TODO(const uint16_t opcode) { } #if 0 int sign_of(int n) { return(m_fr[n]>>31); } void zero(int n,int sign) { if (sign == 0) m_fr[n] = 0x00000000; else m_fr[n] = 0x80000000; if ((m_fpscr & PR) == 1) m_fr[n+1] = 0x00000000; } int data_type_of(int n) { uint32_t abs; abs = m_fr[n] & 0x7fffffff; if ((m_fpscr & PR) == 0) { /* Single-precision */ if (abs < 0x00800000) { if (((m_fpscr & DN) == 1) || (abs == 0x00000000)) { if (sign_of(n) == 0) { zero(n, 0); return(SH4_FPU_PZERO); } else { zero(n, 1); return(SH4_FPU_NZERO); } } else return(SH4_FPU_DENORM); } else if (abs < 0x7f800000) return(SH4_FPU_NORM); else if (abs == 0x7f800000) { if (sign_of(n) == 0) return(SH4_FPU_PINF); else return(SH4_FPU_NINF); } else if (abs < 0x7fc00000) return(SH4_FPU_qNaN); else return(SH4_FPU_sNaN); } else { /* Double-precision */ if (abs < 0x00100000) { if (((m_fpscr & DN) == 1) || ((abs == 0x00000000) && (m_fr[n+1] == 0x00000000))) { if(sign_of(n) == 0) { zero(n, 0); return(SH4_FPU_PZERO); } else { zero(n, 1); return(SH4_FPU_NZERO); } } else return(SH4_FPU_DENORM); } else if (abs < 0x7ff00000) return(SH4_FPU_NORM); else if ((abs == 0x7ff00000) && (m_fr[n+1] == 0x00000000)) { if (sign_of(n) == 0) return(SH4_FPU_PINF); else return(SH4_FPU_NINF); } else if (abs < 0x7ff80000) return(SH4_FPU_qNaN); else return(SH4_FPU_sNaN); } return(SH4_FPU_NORM); } #endif inline uint8_t sh34_base_device::RB(offs_t A) { if (A >= 0xe0000000) return m_program->read_byte(A); #if SH4_USE_FASTRAM_OPTIMIZATION const offs_t _A = A & AM; for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) { if (_A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) { continue; } uint8_t *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; return fastbase[_A ^ m_byte_xor]; } return m_program->read_byte(_A); #else return m_program->read_byte(A & AM); #endif } inline uint16_t sh34_base_device::RW(offs_t A) { if (A >= 0xe0000000) return m_program->read_word(A); #if SH4_USE_FASTRAM_OPTIMIZATION const offs_t _A = A & AM; for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) { if (_A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) { continue; } uint8_t *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; return ((uint16_t*)fastbase)[(_A ^ m_word_xor) >> 1]; } return m_program->read_word(_A); #else return m_program->read_word(A & AM); #endif } inline uint32_t sh34_base_device::RL(offs_t A) { if (A >= 0xe0000000) return m_program->read_dword(A); #if SH4_USE_FASTRAM_OPTIMIZATION const offs_t _A = A & AM; for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) { if (_A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) { continue; } uint8_t *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; return ((uint32_t*)fastbase)[(_A^m_dword_xor) >> 2]; } return m_program->read_dword(_A); #else return m_program->read_dword(A & AM); #endif } inline void sh34_base_device::WB(offs_t A, uint8_t V) { if (A >= 0xe0000000) { m_program->write_byte(A,V); return; } #if SH4_USE_FASTRAM_OPTIMIZATION const offs_t _A = A & AM; for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) { if (m_fastram[ramnum].readonly == true || _A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) { continue; } uint8_t *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; fastbase[_A ^ m_byte_xor] = V; return; } m_program->write_byte(_A,V); #else m_program->write_byte(A & AM,V); #endif } inline void sh34_base_device::WW(offs_t A, uint16_t V) { if (A >= 0xe0000000) { m_program->write_word(A,V); return; } #if SH4_USE_FASTRAM_OPTIMIZATION const offs_t _A = A & AM; for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) { if (m_fastram[ramnum].readonly == true || _A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) { continue; } void *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; ((uint16_t*)fastbase)[(_A ^ m_word_xor) >> 1] = V; return; } m_program->write_word(_A,V); #else m_program->write_word(A & AM,V); #endif } inline void sh34_base_device::WL(offs_t A, uint32_t V) { if (A >= 0xe0000000) { m_program->write_dword(A,V); return; } #if SH4_USE_FASTRAM_OPTIMIZATION const offs_t _A = A & AM; for (int ramnum = 0; ramnum < m_fastram_select; ramnum++) { if (m_fastram[ramnum].readonly == true || _A < m_fastram[ramnum].start || _A > m_fastram[ramnum].end) { continue; } void *fastbase = (uint8_t*)m_fastram[ramnum].base - m_fastram[ramnum].start; ((uint32_t*)fastbase)[(_A ^ m_dword_xor) >> 2] = V; return; } m_program->write_dword(_A,V); #else m_program->write_dword(A & AM,V); #endif } /* code cycles t-bit * 0011 nnnn mmmm 1100 1 - * ADD Rm,Rn */ inline void sh34_base_device::ADD(const uint16_t opcode) { m_r[Rn] += m_r[Rm]; } /* code cycles t-bit * 0111 nnnn iiii iiii 1 - * ADD #imm,Rn */ inline void sh34_base_device::ADDI(const uint16_t opcode) { m_r[Rn] += (int32_t)(int16_t)(int8_t)(opcode&0xff); } /* code cycles t-bit * 0011 nnnn mmmm 1110 1 carry * ADDC Rm,Rn */ inline void sh34_base_device::ADDC(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; uint32_t tmp0, tmp1; tmp1 = m_r[n] + m_r[m]; tmp0 = m_r[n]; m_r[n] = tmp1 + (m_sr & T); if (tmp0 > tmp1) m_sr |= T; else m_sr &= ~T; if (tmp1 > m_r[n]) m_sr |= T; } /* code cycles t-bit * 0011 nnnn mmmm 1111 1 overflow * ADDV Rm,Rn */ inline void sh34_base_device::ADDV(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; int32_t dest, src, ans; if ((int32_t) m_r[n] >= 0) dest = 0; else dest = 1; if ((int32_t) m_r[m] >= 0) src = 0; else src = 1; src += dest; m_r[n] += m_r[m]; if ((int32_t) m_r[n] >= 0) ans = 0; else ans = 1; ans += dest; if (src == 0 || src == 2) { if (ans == 1) m_sr |= T; else m_sr &= ~T; } else m_sr &= ~T; } /* code cycles t-bit * 0010 nnnn mmmm 1001 1 - * AND Rm,Rn */ inline void sh34_base_device::AND(const uint16_t opcode) { m_r[Rn] &= m_r[Rm]; } /* code cycles t-bit * 1100 1001 iiii iiii 1 - * AND #imm,R0 */ inline void sh34_base_device::ANDI(const uint16_t opcode) { m_r[0] &= (opcode&0xff); } /* code cycles t-bit * 1100 1101 iiii iiii 1 - * AND.B #imm,@(R0,GBR) */ inline void sh34_base_device::ANDM(const uint16_t opcode) { uint32_t temp; m_ea = m_gbr + m_r[0]; temp = (opcode&0xff) & RB( m_ea ); WB(m_ea, temp ); m_sh4_icount -= 2; } /* code cycles t-bit * 1000 1011 dddd dddd 3/1 - * BF disp8 */ inline void sh34_base_device::BF(const uint16_t opcode) { if ((m_sr & T) == 0) { int32_t disp = ((int32_t)(opcode&0xff) << 24) >> 24; m_pc = m_ea = m_pc + disp * 2 + 2; m_sh4_icount -= 2; } } /* code cycles t-bit * 1000 1111 dddd dddd 3/1 - * BFS disp8 */ inline void sh34_base_device::BFS(const uint16_t opcode) { if ((m_sr & T) == 0) { int32_t disp = ((int32_t)(opcode&0xff) << 24) >> 24; m_delay = m_ea = m_pc + disp * 2 + 2; m_sh4_icount--; } } /* code cycles t-bit * 1010 dddd dddd dddd 2 - * BRA disp12 */ inline void sh34_base_device::BRA(const uint16_t opcode) { int32_t disp = ((int32_t)(opcode&0xfff) << 20) >> 20; #if BUSY_LOOP_HACKS if (disp == -2) { uint32_t next_opcode = RW(m_pc & AM); /* BRA $ * NOP */ if (next_opcode == 0x0009) m_sh4_icount %= 3; /* cycles for BRA $ and NOP taken (3) */ } #endif m_delay = m_ea = m_pc + disp * 2 + 2; m_sh4_icount--; } /* code cycles t-bit * 0000 mmmm 0010 0011 2 - * BRAF Rm */ inline void sh34_base_device::BRAF(const uint16_t opcode) { m_delay = m_pc + m_r[Rn] + 2; m_sh4_icount--; } /* code cycles t-bit * 1011 dddd dddd dddd 2 - * BSR disp12 */ inline void sh34_base_device::BSR(const uint16_t opcode) { int32_t disp = ((int32_t)(opcode&0xfff) << 20) >> 20; m_pr = m_pc + 2; m_delay = m_ea = m_pc + disp * 2 + 2; m_sh4_icount--; } /* code cycles t-bit * 0000 mmmm 0000 0011 2 - * BSRF Rm */ inline void sh34_base_device::BSRF(const uint16_t opcode) { m_pr = m_pc + 2; m_delay = m_pc + m_r[Rn] + 2; m_sh4_icount--; } /* code cycles t-bit * 1000 1001 dddd dddd 3/1 - * BT disp8 */ inline void sh34_base_device::BT(const uint16_t opcode) { if ((m_sr & T) != 0) { int32_t disp = ((int32_t)(opcode&0xff) << 24) >> 24; m_pc = m_ea = m_pc + disp * 2 + 2; m_sh4_icount -= 2; } } /* code cycles t-bit * 1000 1101 dddd dddd 2/1 - * BTS disp8 */ inline void sh34_base_device::BTS(const uint16_t opcode) { if ((m_sr & T) != 0) { int32_t disp = ((int32_t)(opcode&0xff) << 24) >> 24; m_delay = m_ea = m_pc + disp * 2 + 2; m_sh4_icount--; } } /* code cycles t-bit * 0000 0000 0010 1000 1 - * CLRMAC */ inline void sh34_base_device::CLRMAC(const uint16_t opcode) { m_mach = 0; m_macl = 0; } /* code cycles t-bit * 0000 0000 0000 1000 1 - * CLRT */ inline void sh34_base_device::CLRT(const uint16_t opcode) { m_sr &= ~T; } /* code cycles t-bit * 0011 nnnn mmmm 0000 1 comparison result * CMP_EQ Rm,Rn */ inline void sh34_base_device::CMPEQ(const uint16_t opcode) { if (m_r[Rn] == m_r[Rm]) m_sr |= T; else m_sr &= ~T; } /* code cycles t-bit * 0011 nnnn mmmm 0011 1 comparison result * CMP_GE Rm,Rn */ inline void sh34_base_device::CMPGE(const uint16_t opcode) { if ((int32_t) m_r[Rn] >= (int32_t) m_r[Rm]) m_sr |= T; else m_sr &= ~T; } /* code cycles t-bit * 0011 nnnn mmmm 0111 1 comparison result * CMP_GT Rm,Rn */ inline void sh34_base_device::CMPGT(const uint16_t opcode) { if ((int32_t) m_r[Rn] > (int32_t) m_r[Rm]) m_sr |= T; else m_sr &= ~T; } /* code cycles t-bit * 0011 nnnn mmmm 0110 1 comparison result * CMP_HI Rm,Rn */ inline void sh34_base_device::CMPHI(const uint16_t opcode) { if ((uint32_t) m_r[Rn] > (uint32_t) m_r[Rm]) m_sr |= T; else m_sr &= ~T; } /* code cycles t-bit * 0011 nnnn mmmm 0010 1 comparison result * CMP_HS Rm,Rn */ inline void sh34_base_device::CMPHS(const uint16_t opcode) { if ((uint32_t) m_r[Rn] >= (uint32_t) m_r[Rm]) m_sr |= T; else m_sr &= ~T; } /* code cycles t-bit * 0100 nnnn 0001 0101 1 comparison result * CMP_PL Rn */ inline void sh34_base_device::CMPPL(const uint16_t opcode) { if ((int32_t) m_r[Rn] > 0) m_sr |= T; else m_sr &= ~T; } /* code cycles t-bit * 0100 nnnn 0001 0001 1 comparison result * CMP_PZ Rn */ inline void sh34_base_device::CMPPZ(const uint16_t opcode) { if ((int32_t) m_r[Rn] >= 0) m_sr |= T; else m_sr &= ~T; } /* code cycles t-bit * 0010 nnnn mmmm 1100 1 comparison result * CMP_STR Rm,Rn */ inline void sh34_base_device::CMPSTR(const uint16_t opcode) { uint32_t temp; int32_t HH, HL, LH, LL; temp = m_r[Rn] ^ m_r[Rm]; HH = (temp >> 24) & 0xff; HL = (temp >> 16) & 0xff; LH = (temp >> 8) & 0xff; LL = temp & 0xff; if (HH && HL && LH && LL) m_sr &= ~T; else m_sr |= T; } /* code cycles t-bit * 1000 1000 iiii iiii 1 comparison result * CMP/EQ #imm,R0 */ inline void sh34_base_device::CMPIM(const uint16_t opcode) { uint32_t imm = (uint32_t)(int32_t)(int16_t)(int8_t)(opcode&0xff); if (m_r[0] == imm) m_sr |= T; else m_sr &= ~T; } /* code cycles t-bit * 0010 nnnn mmmm 0111 1 calculation result * DIV0S Rm,Rn */ inline void sh34_base_device::DIV0S(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; if ((m_r[n] & 0x80000000) == 0) m_sr &= ~Q; else m_sr |= Q; if ((m_r[m] & 0x80000000) == 0) m_sr &= ~M; else m_sr |= M; if ((m_r[m] ^ m_r[n]) & 0x80000000) m_sr |= T; else m_sr &= ~T; } /* code cycles t-bit * 0000 0000 0001 1001 1 0 * DIV0U */ inline void sh34_base_device::DIV0U(const uint16_t opcode) { m_sr &= ~(M | Q | T); } /* code cycles t-bit * 0011 nnnn mmmm 0100 1 calculation result * DIV1 Rm,Rn */ inline void sh34_base_device::DIV1(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; uint32_t tmp0; uint32_t old_q; old_q = m_sr & Q; if (0x80000000 & m_r[n]) m_sr |= Q; else m_sr &= ~Q; m_r[n] = (m_r[n] << 1) | (m_sr & T); if (!old_q) { if (!(m_sr & M)) { tmp0 = m_r[n]; m_r[n] -= m_r[m]; if(!(m_sr & Q)) if(m_r[n] > tmp0) m_sr |= Q; else m_sr &= ~Q; else if(m_r[n] > tmp0) m_sr &= ~Q; else m_sr |= Q; } else { tmp0 = m_r[n]; m_r[n] += m_r[m]; if(!(m_sr & Q)) { if(m_r[n] < tmp0) m_sr &= ~Q; else m_sr |= Q; } else { if(m_r[n] < tmp0) m_sr |= Q; else m_sr &= ~Q; } } } else { if (!(m_sr & M)) { tmp0 = m_r[n]; m_r[n] += m_r[m]; if(!(m_sr & Q)) if(m_r[n] < tmp0) m_sr |= Q; else m_sr &= ~Q; else if(m_r[n] < tmp0) m_sr &= ~Q; else m_sr |= Q; } else { tmp0 = m_r[n]; m_r[n] -= m_r[m]; if(!(m_sr & Q)) if(m_r[n] > tmp0) m_sr &= ~Q; else m_sr |= Q; else if(m_r[n] > tmp0) m_sr |= Q; else m_sr &= ~Q; } } tmp0 = (m_sr & (Q | M)); if((!tmp0) || (tmp0 == 0x300)) /* if Q == M set T else clear T */ m_sr |= T; else m_sr &= ~T; } /* DMULS.L Rm,Rn */ inline void sh34_base_device::DMULS(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2; uint32_t temp0, temp1, temp2, temp3; int32_t tempm, tempn, fnLmL; tempn = (int32_t) m_r[n]; tempm = (int32_t) m_r[m]; if (tempn < 0) tempn = 0 - tempn; if (tempm < 0) tempm = 0 - tempm; if ((int32_t) (m_r[n] ^ m_r[m]) < 0) fnLmL = -1; else fnLmL = 0; temp1 = (uint32_t) tempn; temp2 = (uint32_t) tempm; RnL = temp1 & 0x0000ffff; RnH = (temp1 >> 16) & 0x0000ffff; RmL = temp2 & 0x0000ffff; RmH = (temp2 >> 16) & 0x0000ffff; temp0 = RmL * RnL; temp1 = RmH * RnL; temp2 = RmL * RnH; temp3 = RmH * RnH; Res2 = 0; Res1 = temp1 + temp2; if (Res1 < temp1) Res2 += 0x00010000; temp1 = (Res1 << 16) & 0xffff0000; Res0 = temp0 + temp1; if (Res0 < temp0) Res2++; Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; if (fnLmL < 0) { Res2 = ~Res2; if (Res0 == 0) Res2++; else Res0 = (~Res0) + 1; } m_mach = Res2; m_macl = Res0; m_sh4_icount--; } /* DMULU.L Rm,Rn */ inline void sh34_base_device::DMULU(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2; uint32_t temp0, temp1, temp2, temp3; RnL = m_r[n] & 0x0000ffff; RnH = (m_r[n] >> 16) & 0x0000ffff; RmL = m_r[m] & 0x0000ffff; RmH = (m_r[m] >> 16) & 0x0000ffff; temp0 = RmL * RnL; temp1 = RmH * RnL; temp2 = RmL * RnH; temp3 = RmH * RnH; Res2 = 0; Res1 = temp1 + temp2; if (Res1 < temp1) Res2 += 0x00010000; temp1 = (Res1 << 16) & 0xffff0000; Res0 = temp0 + temp1; if (Res0 < temp0) Res2++; Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; m_mach = Res2; m_macl = Res0; m_sh4_icount--; } /* DT Rn */ inline void sh34_base_device::DT(const uint16_t opcode) { uint32_t n = Rn; m_r[n]--; if (m_r[n] == 0) m_sr |= T; else m_sr &= ~T; #if BUSY_LOOP_HACKS { uint32_t next_opcode = RW(m_pc & AM); /* DT Rn * BF $-2 */ if (next_opcode == 0x8bfd) { while (m_r[n] > 1 && m_sh4_icount > 4) { m_r[n]--; m_sh4_icount -= 4; /* cycles for DT (1) and BF taken (3) */ } } } #endif } /* EXTS.B Rm,Rn */ inline void sh34_base_device::EXTSB(const uint16_t opcode) { m_r[Rn] = ((int32_t)m_r[Rm] << 24) >> 24; } /* EXTS.W Rm,Rn */ inline void sh34_base_device::EXTSW(const uint16_t opcode) { m_r[Rn] = ((int32_t)m_r[Rm] << 16) >> 16; } /* EXTU.B Rm,Rn */ inline void sh34_base_device::EXTUB(const uint16_t opcode) { m_r[Rn] = m_r[Rm] & 0x000000ff; } /* EXTU.W Rm,Rn */ inline void sh34_base_device::EXTUW(const uint16_t opcode) { m_r[Rn] = m_r[Rm] & 0x0000ffff; } /* JMP @Rm */ inline void sh34_base_device::JMP(const uint16_t opcode) { m_delay = m_ea = m_r[Rn]; } /* JSR @Rm */ inline void sh34_base_device::JSR(const uint16_t opcode) { m_pr = m_pc + 2; m_delay = m_ea = m_r[Rn]; m_sh4_icount--; } /* LDC Rm,SR */ inline void sh34_base_device::LDCSR(const uint16_t opcode) { uint32_t reg; reg = m_r[Rn]; if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) sh4_syncronize_register_bank((m_sr & sRB) >> 29); if ((m_r[Rn] & sRB) != (m_sr & sRB)) sh4_change_register_bank(m_r[Rn] & sRB ? 1 : 0); m_sr = reg & FLAGS; sh4_exception_recompute(); } /* LDC Rm,GBR */ inline void sh34_base_device::LDCGBR(const uint16_t opcode) { m_gbr = m_r[Rn]; } /* LDC Rm,VBR */ inline void sh34_base_device::LDCVBR(const uint16_t opcode) { m_vbr = m_r[Rn]; } /* LDC.L @Rm+,SR */ inline void sh34_base_device::LDCMSR(const uint16_t opcode) { uint32_t old; old = m_sr; m_ea = m_r[Rn]; m_sr = RL(m_ea ) & FLAGS; if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) sh4_syncronize_register_bank((old & sRB) >> 29); if ((old & sRB) != (m_sr & sRB)) sh4_change_register_bank(m_sr & sRB ? 1 : 0); m_r[Rn] += 4; m_sh4_icount -= 2; sh4_exception_recompute(); } /* LDC.L @Rm+,GBR */ inline void sh34_base_device::LDCMGBR(const uint16_t opcode) { m_ea = m_r[Rn]; m_gbr = RL(m_ea ); m_r[Rn] += 4; m_sh4_icount -= 2; } /* LDC.L @Rm+,VBR */ inline void sh34_base_device::LDCMVBR(const uint16_t opcode) { m_ea = m_r[Rn]; m_vbr = RL(m_ea ); m_r[Rn] += 4; m_sh4_icount -= 2; } /* LDS Rm,MACH */ inline void sh34_base_device::LDSMACH(const uint16_t opcode) { m_mach = m_r[Rn]; } /* LDS Rm,MACL */ inline void sh34_base_device::LDSMACL(const uint16_t opcode) { m_macl = m_r[Rn]; } /* LDS Rm,PR */ inline void sh34_base_device::LDSPR(const uint16_t opcode) { m_pr = m_r[Rn]; } /* LDS.L @Rm+,MACH */ inline void sh34_base_device::LDSMMACH(const uint16_t opcode) { m_ea = m_r[Rn]; m_mach = RL(m_ea ); m_r[Rn] += 4; } /* LDS.L @Rm+,MACL */ inline void sh34_base_device::LDSMMACL(const uint16_t opcode) { m_ea = m_r[Rn]; m_macl = RL(m_ea ); m_r[Rn] += 4; } /* LDS.L @Rm+,PR */ inline void sh34_base_device::LDSMPR(const uint16_t opcode) { m_ea = m_r[Rn]; m_pr = RL(m_ea ); m_r[Rn] += 4; } /* MAC.L @Rm+,@Rn+ */ inline void sh34_base_device::MAC_L(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; uint32_t RnL, RnH, RmL, RmH, Res0, Res1, Res2; uint32_t temp0, temp1, temp2, temp3; int32_t tempm, tempn, fnLmL; tempn = (int32_t) RL(m_r[n] ); m_r[n] += 4; tempm = (int32_t) RL(m_r[m] ); m_r[m] += 4; if ((int32_t) (tempn ^ tempm) < 0) fnLmL = -1; else fnLmL = 0; if (tempn < 0) tempn = 0 - tempn; if (tempm < 0) tempm = 0 - tempm; temp1 = (uint32_t) tempn; temp2 = (uint32_t) tempm; RnL = temp1 & 0x0000ffff; RnH = (temp1 >> 16) & 0x0000ffff; RmL = temp2 & 0x0000ffff; RmH = (temp2 >> 16) & 0x0000ffff; temp0 = RmL * RnL; temp1 = RmH * RnL; temp2 = RmL * RnH; temp3 = RmH * RnH; Res2 = 0; Res1 = temp1 + temp2; if (Res1 < temp1) Res2 += 0x00010000; temp1 = (Res1 << 16) & 0xffff0000; Res0 = temp0 + temp1; if (Res0 < temp0) Res2++; Res2 = Res2 + ((Res1 >> 16) & 0x0000ffff) + temp3; if (fnLmL < 0) { Res2 = ~Res2; if (Res0 == 0) Res2++; else Res0 = (~Res0) + 1; } if (m_sr & S) { Res0 = m_macl + Res0; if (m_macl > Res0) Res2++; Res2 += (m_mach & 0x0000ffff); if (((int32_t) Res2 < 0) && (Res2 < 0xffff8000)) { Res2 = 0x00008000; Res0 = 0x00000000; } else if (((int32_t) Res2 > 0) && (Res2 > 0x00007fff)) { Res2 = 0x00007fff; Res0 = 0xffffffff; } m_mach = Res2; m_macl = Res0; } else { Res0 = m_macl + Res0; if (m_macl > Res0) Res2++; Res2 += m_mach; m_mach = Res2; m_macl = Res0; } m_sh4_icount -= 2; } /* MAC.W @Rm+,@Rn+ */ inline void sh34_base_device::MAC_W(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; int32_t tempm, tempn, dest, src, ans; uint32_t templ; tempn = (int32_t) RW(m_r[n] ); m_r[n] += 2; tempm = (int32_t) RW(m_r[m] ); m_r[m] += 2; templ = m_macl; tempm = ((int32_t) (short) tempn * (int32_t) (short) tempm); if ((int32_t) m_macl >= 0) dest = 0; else dest = 1; if ((int32_t) tempm >= 0) { src = 0; tempn = 0; } else { src = 1; tempn = 0xffffffff; } src += dest; m_macl += tempm; if ((int32_t) m_macl >= 0) ans = 0; else ans = 1; ans += dest; if (m_sr & S) { if (ans == 1) { if (src == 0) m_macl = 0x7fffffff; if (src == 2) m_macl = 0x80000000; } } else { m_mach += tempn; if (templ > m_macl) m_mach += 1; } m_sh4_icount -= 2; } /* MOV Rm,Rn */ inline void sh34_base_device::MOV(const uint16_t opcode) { m_r[Rn] = m_r[Rm]; } /* MOV.B Rm,@Rn */ inline void sh34_base_device::MOVBS(const uint16_t opcode) { m_ea = m_r[Rn]; WB(m_ea, m_r[Rm] & 0x000000ff); } /* MOV.W Rm,@Rn */ inline void sh34_base_device::MOVWS(const uint16_t opcode) { m_ea = m_r[Rn]; WW(m_ea, m_r[Rm] & 0x0000ffff); } /* MOV.L Rm,@Rn */ inline void sh34_base_device::MOVLS(const uint16_t opcode) { m_ea = m_r[Rn]; WL(m_ea, m_r[Rm] ); } /* MOV.B @Rm,Rn */ inline void sh34_base_device::MOVBL(const uint16_t opcode) { m_ea = m_r[Rm]; m_r[Rn] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_ea ); } /* MOV.W @Rm,Rn */ inline void sh34_base_device::MOVWL(const uint16_t opcode) { m_ea = m_r[Rm]; m_r[Rn] = (uint32_t)(int32_t)(int16_t) RW(m_ea ); } /* MOV.L @Rm,Rn */ inline void sh34_base_device::MOVLL(const uint16_t opcode) { m_ea = m_r[Rm]; m_r[Rn] = RL(m_ea ); } /* MOV.B Rm,@-Rn */ inline void sh34_base_device::MOVBM(const uint16_t opcode) { uint32_t data = m_r[Rm] & 0x000000ff; m_r[Rn] -= 1; WB(m_r[Rn], data ); } /* MOV.W Rm,@-Rn */ inline void sh34_base_device::MOVWM(const uint16_t opcode) { uint32_t data = m_r[Rm] & 0x0000ffff; m_r[Rn] -= 2; WW(m_r[Rn], data ); } /* MOV.L Rm,@-Rn */ inline void sh34_base_device::MOVLM(const uint16_t opcode) { uint32_t data = m_r[Rm]; m_r[Rn] -= 4; WL(m_r[Rn], data ); } /* MOV.B @Rm+,Rn */ inline void sh34_base_device::MOVBP(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; m_r[n] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_r[m] ); if (n != m) m_r[m] += 1; } /* MOV.W @Rm+,Rn */ inline void sh34_base_device::MOVWP(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; m_r[n] = (uint32_t)(int32_t)(int16_t) RW(m_r[m] ); if (n != m) m_r[m] += 2; } /* MOV.L @Rm+,Rn */ inline void sh34_base_device::MOVLP(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; m_r[n] = RL(m_r[m] ); if (n != m) m_r[m] += 4; } /* MOV.B Rm,@(R0,Rn) */ inline void sh34_base_device::MOVBS0(const uint16_t opcode) { m_ea = m_r[Rn] + m_r[0]; WB(m_ea, m_r[Rm] & 0x000000ff ); } /* MOV.W Rm,@(R0,Rn) */ inline void sh34_base_device::MOVWS0(const uint16_t opcode) { m_ea = m_r[Rn] + m_r[0]; WW(m_ea, m_r[Rm] & 0x0000ffff ); } /* MOV.L Rm,@(R0,Rn) */ inline void sh34_base_device::MOVLS0(const uint16_t opcode) { m_ea = m_r[Rn] + m_r[0]; WL(m_ea, m_r[Rm] ); } /* MOV.B @(R0,Rm),Rn */ inline void sh34_base_device::MOVBL0(const uint16_t opcode) { m_ea = m_r[Rm] + m_r[0]; m_r[Rn] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_ea ); } /* MOV.W @(R0,Rm),Rn */ inline void sh34_base_device::MOVWL0(const uint16_t opcode) { m_ea = m_r[Rm] + m_r[0]; m_r[Rn] = (uint32_t)(int32_t)(int16_t) RW(m_ea ); } /* MOV.L @(R0,Rm),Rn */ inline void sh34_base_device::MOVLL0(const uint16_t opcode) { m_ea = m_r[Rm] + m_r[0]; m_r[Rn] = RL(m_ea ); } /* MOV #imm,Rn */ inline void sh34_base_device::MOVI(const uint16_t opcode) { m_r[Rn] = (uint32_t)(int32_t)(int16_t)(int8_t)(opcode&0xff); } /* MOV.W @(disp8,PC),Rn */ inline void sh34_base_device::MOVWI(const uint16_t opcode) { uint32_t disp = opcode & 0xff; m_ea = m_pc + disp * 2 + 2; m_r[Rn] = (uint32_t)(int32_t)(int16_t) RW(m_ea ); } /* MOV.L @(disp8,PC),Rn */ inline void sh34_base_device::MOVLI(const uint16_t opcode) { uint32_t disp = opcode & 0xff; m_ea = ((m_pc + 2) & ~3) + disp * 4; m_r[Rn] = RL(m_ea ); } /* MOV.B @(disp8,GBR),R0 */ inline void sh34_base_device::MOVBLG(const uint16_t opcode) { uint32_t disp = opcode & 0xff; m_ea = m_gbr + disp; m_r[0] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_ea ); } /* MOV.W @(disp8,GBR),R0 */ inline void sh34_base_device::MOVWLG(const uint16_t opcode) { uint32_t disp = opcode & 0xff; m_ea = m_gbr + disp * 2; m_r[0] = (int32_t)(int16_t) RW(m_ea ); } /* MOV.L @(disp8,GBR),R0 */ inline void sh34_base_device::MOVLLG(const uint16_t opcode) { uint32_t disp = opcode & 0xff; m_ea = m_gbr + disp * 4; m_r[0] = RL(m_ea ); } /* MOV.B R0,@(disp8,GBR) */ inline void sh34_base_device::MOVBSG(const uint16_t opcode) { uint32_t disp = opcode & 0xff; m_ea = m_gbr + disp; WB(m_ea, m_r[0] & 0x000000ff ); } /* MOV.W R0,@(disp8,GBR) */ inline void sh34_base_device::MOVWSG(const uint16_t opcode) { uint32_t disp = opcode & 0xff; m_ea = m_gbr + disp * 2; WW(m_ea, m_r[0] & 0x0000ffff ); } /* MOV.L R0,@(disp8,GBR) */ inline void sh34_base_device::MOVLSG(const uint16_t opcode) { uint32_t disp = opcode & 0xff; m_ea = m_gbr + disp * 4; WL(m_ea, m_r[0] ); } /* MOV.B R0,@(disp4,Rm) */ inline void sh34_base_device::MOVBS4(const uint16_t opcode) { uint32_t disp = opcode & 0x0f; m_ea = m_r[Rm] + disp; WB(m_ea, m_r[0] & 0x000000ff ); } /* MOV.W R0,@(disp4,Rm) */ inline void sh34_base_device::MOVWS4(const uint16_t opcode) { uint32_t disp = opcode & 0x0f; m_ea = m_r[Rm] + disp * 2; WW(m_ea, m_r[0] & 0x0000ffff ); } /* MOV.L Rm,@(disp4,Rn) */ inline void sh34_base_device::MOVLS4(const uint16_t opcode) { uint32_t disp = opcode & 0x0f; m_ea = m_r[Rn] + disp * 4; WL(m_ea, m_r[Rm] ); } /* MOV.B @(disp4,Rm),R0 */ inline void sh34_base_device::MOVBL4(const uint16_t opcode) { uint32_t disp = opcode & 0x0f; m_ea = m_r[Rm] + disp; m_r[0] = (uint32_t)(int32_t)(int16_t)(int8_t) RB( m_ea ); } /* MOV.W @(disp4,Rm),R0 */ inline void sh34_base_device::MOVWL4(const uint16_t opcode) { uint32_t disp = opcode & 0x0f; m_ea = m_r[Rm] + disp * 2; m_r[0] = (uint32_t)(int32_t)(int16_t) RW(m_ea ); } /* MOV.L @(disp4,Rm),Rn */ inline void sh34_base_device::MOVLL4(const uint16_t opcode) { uint32_t disp = opcode & 0x0f; m_ea = m_r[Rm] + disp * 4; m_r[Rn] = RL(m_ea ); } /* MOVA @(disp8,PC),R0 */ inline void sh34_base_device::MOVA(const uint16_t opcode) { uint32_t disp = opcode & 0xff; m_ea = ((m_pc + 2) & ~3) + disp * 4; m_r[0] = m_ea; } /* MOVT Rn */ void sh34_base_device::MOVT(const uint16_t opcode) { m_r[Rn] = m_sr & T; } /* MUL.L Rm,Rn */ inline void sh34_base_device::MULL(const uint16_t opcode) { m_macl = m_r[Rn] * m_r[Rm]; m_sh4_icount--; } /* MULS Rm,Rn */ inline void sh34_base_device::MULS(const uint16_t opcode) { m_macl = (int16_t) m_r[Rn] * (int16_t) m_r[Rm]; } /* MULU Rm,Rn */ inline void sh34_base_device::MULU(const uint16_t opcode) { m_macl = (uint16_t) m_r[Rn] * (uint16_t) m_r[Rm]; } /* NEG Rm,Rn */ inline void sh34_base_device::NEG(const uint16_t opcode) { m_r[Rn] = 0 - m_r[Rm]; } /* NEGC Rm,Rn */ inline void sh34_base_device::NEGC(const uint16_t opcode) { uint32_t temp; temp = m_r[Rm]; m_r[Rn] = -temp - (m_sr & T); if (temp || (m_sr & T)) m_sr |= T; else m_sr &= ~T; } /* NOP */ inline void sh34_base_device::NOP(const uint16_t opcode) { } /* NOT Rm,Rn */ inline void sh34_base_device::NOT(const uint16_t opcode) { m_r[Rn] = ~m_r[Rm]; } /* OR Rm,Rn */ inline void sh34_base_device::OR(const uint16_t opcode) { m_r[Rn] |= m_r[Rm]; } /* OR #imm,R0 */ inline void sh34_base_device::ORI(const uint16_t opcode) { m_r[0] |= (opcode&0xff); m_sh4_icount -= 2; } /* OR.B #imm,@(R0,GBR) */ inline void sh34_base_device::ORM(const uint16_t opcode) { uint32_t temp; m_ea = m_gbr + m_r[0]; temp = RB( m_ea ); temp |= (opcode&0xff); WB(m_ea, temp ); } /* ROTCL Rn */ inline void sh34_base_device::ROTCL(const uint16_t opcode) { uint32_t n = Rn; uint32_t temp; temp = (m_r[n] >> 31) & T; m_r[n] = (m_r[n] << 1) | (m_sr & T); m_sr = (m_sr & ~T) | temp; } /* ROTCR Rn */ inline void sh34_base_device::ROTCR(const uint16_t opcode) { uint32_t n = Rn; uint32_t temp; temp = (m_sr & T) << 31; if (m_r[n] & T) m_sr |= T; else m_sr &= ~T; m_r[n] = (m_r[n] >> 1) | temp; } /* ROTL Rn */ inline void sh34_base_device::ROTL(const uint16_t opcode) { uint32_t n = Rn; m_sr = (m_sr & ~T) | ((m_r[n] >> 31) & T); m_r[n] = (m_r[n] << 1) | (m_r[n] >> 31); } /* ROTR Rn */ inline void sh34_base_device::ROTR(const uint16_t opcode) { uint32_t n = Rn; m_sr = (m_sr & ~T) | (m_r[n] & T); m_r[n] = (m_r[n] >> 1) | (m_r[n] << 31); } /* RTE */ inline void sh34_base_device::RTE(const uint16_t opcode) { m_delay = m_ea = m_spc; if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) sh4_syncronize_register_bank((m_sr & sRB) >> 29); if ((m_ssr & sRB) != (m_sr & sRB)) sh4_change_register_bank(m_ssr & sRB ? 1 : 0); m_sr = m_ssr; m_sh4_icount--; sh4_exception_recompute(); } /* RTS */ inline void sh34_base_device::RTS(const uint16_t opcode) { m_delay = m_ea = m_pr; m_sh4_icount--; } /* SETT */ inline void sh34_base_device::SETT(const uint16_t opcode) { m_sr |= T; } /* SHAL Rn (same as SHLL) */ inline void sh34_base_device::SHAL(const uint16_t opcode) { uint32_t n = Rn; m_sr = (m_sr & ~T) | ((m_r[n] >> 31) & T); m_r[n] <<= 1; } /* SHAR Rn */ inline void sh34_base_device::SHAR(const uint16_t opcode) { uint32_t n = Rn; m_sr = (m_sr & ~T) | (m_r[n] & T); m_r[n] = (uint32_t)((int32_t)m_r[n] >> 1); } /* SHLL Rn (same as SHAL) */ inline void sh34_base_device::SHLL(const uint16_t opcode) { uint32_t n = Rn; m_sr = (m_sr & ~T) | ((m_r[n] >> 31) & T); m_r[n] <<= 1; } /* SHLL2 Rn */ inline void sh34_base_device::SHLL2(const uint16_t opcode) { m_r[Rn] <<= 2; } /* SHLL8 Rn */ inline void sh34_base_device::SHLL8(const uint16_t opcode) { m_r[Rn] <<= 8; } /* SHLL16 Rn */ inline void sh34_base_device::SHLL16(const uint16_t opcode) { m_r[Rn] <<= 16; } /* SHLR Rn */ inline void sh34_base_device::SHLR(const uint16_t opcode) { uint32_t n = Rn; m_sr = (m_sr & ~T) | (m_r[n] & T); m_r[n] >>= 1; } /* SHLR2 Rn */ inline void sh34_base_device::SHLR2(const uint16_t opcode) { m_r[Rn] >>= 2; } /* SHLR8 Rn */ inline void sh34_base_device::SHLR8(const uint16_t opcode) { m_r[Rn] >>= 8; } /* SHLR16 Rn */ inline void sh34_base_device::SHLR16(const uint16_t opcode) { m_r[Rn] >>= 16; } /* SLEEP */ inline void sh34_base_device::SLEEP(const uint16_t opcode) { /* 0 = normal mode */ /* 1 = enters into power-down mode */ /* 2 = go out the power-down mode after an exception */ if(m_sleep_mode != 2) m_pc -= 2; m_sh4_icount -= 2; /* Wait_for_exception; */ if(m_sleep_mode == 0) m_sleep_mode = 1; else if(m_sleep_mode == 2) m_sleep_mode = 0; } /* STC SR,Rn */ inline void sh34_base_device::STCSR(const uint16_t opcode) { m_r[Rn] = m_sr; } /* STC GBR,Rn */ inline void sh34_base_device::STCGBR(const uint16_t opcode) { m_r[Rn] = m_gbr; } /* STC VBR,Rn */ inline void sh34_base_device::STCVBR(const uint16_t opcode) { m_r[Rn] = m_vbr; } /* STC.L SR,@-Rn */ inline void sh34_base_device::STCMSR(const uint16_t opcode) { uint32_t n = Rn; m_r[n] -= 4; m_ea = m_r[n]; WL(m_ea, m_sr ); m_sh4_icount--; } /* STC.L GBR,@-Rn */ inline void sh34_base_device::STCMGBR(const uint16_t opcode) { uint32_t n = Rn; m_r[n] -= 4; m_ea = m_r[n]; WL(m_ea, m_gbr ); m_sh4_icount--; } /* STC.L VBR,@-Rn */ inline void sh34_base_device::STCMVBR(const uint16_t opcode) { uint32_t n = Rn; m_r[n] -= 4; m_ea = m_r[n]; WL(m_ea, m_vbr ); m_sh4_icount--; } /* STS MACH,Rn */ inline void sh34_base_device::STSMACH(const uint16_t opcode) { m_r[Rn] = m_mach; } /* STS MACL,Rn */ inline void sh34_base_device::STSMACL(const uint16_t opcode) { m_r[Rn] = m_macl; } /* STS PR,Rn */ inline void sh34_base_device::STSPR(const uint16_t opcode) { m_r[Rn] = m_pr; } /* STS.L MACH,@-Rn */ inline void sh34_base_device::STSMMACH(const uint16_t opcode) { uint32_t n = Rn; m_r[n] -= 4; m_ea = m_r[n]; WL(m_ea, m_mach ); } /* STS.L MACL,@-Rn */ inline void sh34_base_device::STSMMACL(const uint16_t opcode) { uint32_t n = Rn; m_r[n] -= 4; m_ea = m_r[n]; WL(m_ea, m_macl ); } /* STS.L PR,@-Rn */ inline void sh34_base_device::STSMPR(const uint16_t opcode) { uint32_t n = Rn; m_r[n] -= 4; m_ea = m_r[n]; WL(m_ea, m_pr ); } /* SUB Rm,Rn */ inline void sh34_base_device::SUB(const uint16_t opcode) { m_r[Rn] -= m_r[Rm]; } /* SUBC Rm,Rn */ inline void sh34_base_device::SUBC(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; uint32_t tmp0, tmp1; tmp1 = m_r[n] - m_r[m]; tmp0 = m_r[n]; m_r[n] = tmp1 - (m_sr & T); if (tmp0 < tmp1) m_sr |= T; else m_sr &= ~T; if (tmp1 < m_r[n]) m_sr |= T; } /* SUBV Rm,Rn */ inline void sh34_base_device::SUBV(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; int32_t dest, src, ans; if ((int32_t) m_r[n] >= 0) dest = 0; else dest = 1; if ((int32_t) m_r[m] >= 0) src = 0; else src = 1; src += dest; m_r[n] -= m_r[m]; if ((int32_t) m_r[n] >= 0) ans = 0; else ans = 1; ans += dest; if (src == 1) { if (ans == 1) m_sr |= T; else m_sr &= ~T; } else m_sr &= ~T; } /* SWAP.B Rm,Rn */ inline void sh34_base_device::SWAPB(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; uint32_t temp0, temp1; temp0 = m_r[m] & 0xffff0000; temp1 = (m_r[m] & 0x000000ff) << 8; m_r[n] = (m_r[m] >> 8) & 0x000000ff; m_r[n] = m_r[n] | temp1 | temp0; } /* SWAP.W Rm,Rn */ inline void sh34_base_device::SWAPW(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; uint32_t temp; temp = (m_r[m] >> 16) & 0x0000ffff; m_r[n] = (m_r[m] << 16) | temp; } /* TAS.B @Rn */ inline void sh34_base_device::TAS(const uint16_t opcode) { uint32_t n = Rn; uint32_t temp; m_ea = m_r[n]; /* Bus Lock enable */ temp = RB( m_ea ); if (temp == 0) m_sr |= T; else m_sr &= ~T; temp |= 0x80; /* Bus Lock disable */ WB(m_ea, temp ); m_sh4_icount -= 3; } /* TRAPA #imm */ inline void sh34_base_device::TRAPA(const uint16_t opcode) { uint32_t imm = opcode & 0xff; if (m_cpu_type == CPU_TYPE_SH4) { m_m[TRA] = imm << 2; } else /* SH3 */ { m_sh3internal_upper[SH3_TRA_ADDR] = imm << 2; } m_ssr = m_sr; m_spc = m_pc; m_sgr = m_r[15]; m_sr |= MD; if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) sh4_syncronize_register_bank((m_sr & sRB) >> 29); if (!(m_sr & sRB)) sh4_change_register_bank(1); m_sr |= sRB; m_sr |= BL; sh4_exception_recompute(); if (m_cpu_type == CPU_TYPE_SH4) { m_m[EXPEVT] = 0x00000160; } else /* SH3 */ { m_sh3internal_upper[SH3_EXPEVT_ADDR] = 0x00000160; } m_pc = m_vbr + 0x00000100; m_sh4_icount -= 7; } /* TST Rm,Rn */ inline void sh34_base_device::TST(const uint16_t opcode) { if ((m_r[Rn] & m_r[Rm]) == 0) m_sr |= T; else m_sr &= ~T; } /* TST #imm,R0 */ inline void sh34_base_device::TSTI(const uint16_t opcode) { uint32_t imm = opcode & 0xff; if ((imm & m_r[0]) == 0) m_sr |= T; else m_sr &= ~T; } /* TST.B #imm,@(R0,GBR) */ inline void sh34_base_device::TSTM(const uint16_t opcode) { uint32_t imm = opcode & 0xff; m_ea = m_gbr + m_r[0]; if ((imm & RB( m_ea )) == 0) m_sr |= T; else m_sr &= ~T; m_sh4_icount -= 2; } /* XOR Rm,Rn */ inline void sh34_base_device::XOR(const uint16_t opcode) { m_r[Rn] ^= m_r[Rm]; } /* XOR #imm,R0 */ inline void sh34_base_device::XORI(const uint16_t opcode) { uint32_t imm = opcode & 0xff; m_r[0] ^= imm; } /* XOR.B #imm,@(R0,GBR) */ inline void sh34_base_device::XORM(const uint16_t opcode) { uint32_t imm = opcode & 0xff; uint32_t temp; m_ea = m_gbr + m_r[0]; temp = RB( m_ea ); temp ^= imm; WB(m_ea, temp ); m_sh4_icount -= 2; } /* XTRCT Rm,Rn */ inline void sh34_base_device::XTRCT(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; uint32_t temp; temp = (m_r[m] << 16) & 0xffff0000; m_r[n] = (m_r[n] >> 16) & 0x0000ffff; m_r[n] |= temp; } /* STC SSR,Rn */ inline void sh34_base_device::STCSSR(const uint16_t opcode) { m_r[Rn] = m_ssr; } /* STC SPC,Rn */ inline void sh34_base_device::STCSPC(const uint16_t opcode) { m_r[Rn] = m_spc; } /* STC SGR,Rn */ inline void sh34_base_device::STCSGR(const uint16_t opcode) { m_r[Rn] = m_sgr; } /* STS FPUL,Rn */ inline void sh34_base_device::STSFPUL(const uint16_t opcode) { m_r[Rn] = m_fpul; } /* STS FPSCR,Rn */ inline void sh34_base_device::STSFPSCR(const uint16_t opcode) { m_r[Rn] = m_fpscr & 0x003FFFFF; } /* STC DBR,Rn */ inline void sh34_base_device::STCDBR(const uint16_t opcode) { m_r[Rn] = m_dbr; } /* STCRBANK Rm_BANK,Rn */ inline void sh34_base_device::STCRBANK(const uint16_t opcode) { uint32_t m = Rm; m_r[Rn] = m_rbnk[m_sr&sRB ? 0 : 1][m & 7]; } /* STCMRBANK Rm_BANK,@-Rn */ inline void sh34_base_device::STCMRBANK(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; m_r[n] -= 4; m_ea = m_r[n]; WL(m_ea, m_rbnk[m_sr&sRB ? 0 : 1][m & 7]); m_sh4_icount--; } /* MOVCA.L R0,@Rn */ inline void sh34_base_device::MOVCAL(const uint16_t opcode) { m_ea = m_r[Rn]; WL(m_ea, m_r[0] ); } inline void sh34_base_device::CLRS(const uint16_t opcode) { m_sr &= ~S; } inline void sh34_base_device::SETS(const uint16_t opcode) { m_sr |= S; } /* STS.L SGR,@-Rn */ inline void sh34_base_device::STCMSGR(const uint16_t opcode) { uint32_t n = Rn; m_r[n] -= 4; m_ea = m_r[n]; WL(m_ea, m_sgr ); } /* STS.L FPUL,@-Rn */ inline void sh34_base_device::STSMFPUL(const uint16_t opcode) { uint32_t n = Rn; m_r[n] -= 4; m_ea = m_r[n]; WL(m_ea, m_fpul ); } /* STS.L FPSCR,@-Rn */ inline void sh34_base_device::STSMFPSCR(const uint16_t opcode) { uint32_t n = Rn; m_r[n] -= 4; m_ea = m_r[n]; WL(m_ea, m_fpscr & 0x003FFFFF); } /* STC.L DBR,@-Rn */ inline void sh34_base_device::STCMDBR(const uint16_t opcode) { uint32_t n = Rn; m_r[n] -= 4; m_ea = m_r[n]; WL(m_ea, m_dbr ); } /* STC.L SSR,@-Rn */ inline void sh34_base_device::STCMSSR(const uint16_t opcode) { uint32_t n = Rn; m_r[n] -= 4; m_ea = m_r[n]; WL(m_ea, m_ssr ); } /* STC.L SPC,@-Rn */ inline void sh34_base_device::STCMSPC(const uint16_t opcode) { uint32_t n = Rn; m_r[n] -= 4; m_ea = m_r[n]; WL(m_ea, m_spc ); } /* LDS.L @Rm+,FPUL */ inline void sh34_base_device::LDSMFPUL(const uint16_t opcode) { m_ea = m_r[Rn]; m_fpul = RL(m_ea ); m_r[Rn] += 4; } /* LDS.L @Rm+,FPSCR */ inline void sh34_base_device::LDSMFPSCR(const uint16_t opcode) { uint32_t s; s = m_fpscr; m_ea = m_r[Rn]; m_fpscr = RL(m_ea ); m_fpscr &= 0x003FFFFF; m_r[Rn] += 4; if ((s & FR) != (m_fpscr & FR)) sh4_swap_fp_registers(); #ifdef LSB_FIRST if ((s & PR) != (m_fpscr & PR)) sh4_swap_fp_couples(); #endif m_fpu_sz = (m_fpscr & SZ) ? 1 : 0; m_fpu_pr = (m_fpscr & PR) ? 1 : 0; } /* LDC.L @Rm+,DBR */ inline void sh34_base_device::LDCMDBR(const uint16_t opcode) { m_ea = m_r[Rn]; m_dbr = RL(m_ea ); m_r[Rn] += 4; } /* LDC.L @Rn+,Rm_BANK */ inline void sh34_base_device::LDCMRBANK(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; m_ea = m_r[n]; m_rbnk[m_sr&sRB ? 0 : 1][m & 7] = RL(m_ea ); m_r[n] += 4; } /* LDC.L @Rm+,SSR */ inline void sh34_base_device::LDCMSSR(const uint16_t opcode) { m_ea = m_r[Rn]; m_ssr = RL(m_ea ); m_r[Rn] += 4; } /* LDC.L @Rm+,SPC */ inline void sh34_base_device::LDCMSPC(const uint16_t opcode) { m_ea = m_r[Rn]; m_spc = RL(m_ea ); m_r[Rn] += 4; } /* LDS Rm,FPUL */ inline void sh34_base_device::LDSFPUL(const uint16_t opcode) { m_fpul = m_r[Rn]; } /* LDS Rm,FPSCR */ inline void sh34_base_device::LDSFPSCR(const uint16_t opcode) { uint32_t s; s = m_fpscr; m_fpscr = m_r[Rn] & 0x003FFFFF; if ((s & FR) != (m_fpscr & FR)) sh4_swap_fp_registers(); #ifdef LSB_FIRST if ((s & PR) != (m_fpscr & PR)) sh4_swap_fp_couples(); #endif m_fpu_sz = (m_fpscr & SZ) ? 1 : 0; m_fpu_pr = (m_fpscr & PR) ? 1 : 0; } /* LDC Rm,DBR */ inline void sh34_base_device::LDCDBR(const uint16_t opcode) { m_dbr = m_r[Rn]; } /* SHAD Rm,Rn */ inline void sh34_base_device::SHAD(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; if ((m_r[m] & 0x80000000) == 0) m_r[n] = m_r[n] << (m_r[m] & 0x1F); else if ((m_r[m] & 0x1F) == 0) { if ((m_r[n] & 0x80000000) == 0) m_r[n] = 0; else m_r[n] = 0xFFFFFFFF; } else m_r[n]=(int32_t)m_r[n] >> ((~m_r[m] & 0x1F)+1); } /* SHLD Rm,Rn */ inline void sh34_base_device::SHLD(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; if ((m_r[m] & 0x80000000) == 0) m_r[n] = m_r[n] << (m_r[m] & 0x1F); else if ((m_r[m] & 0x1F) == 0) m_r[n] = 0; else m_r[n] = m_r[n] >> ((~m_r[m] & 0x1F)+1); } /* LDCRBANK Rn,Rm_BANK */ inline void sh34_base_device::LDCRBANK(const uint16_t opcode) { uint32_t m = Rm; m_rbnk[m_sr&sRB ? 0 : 1][m & 7] = m_r[Rn]; } /* LDC Rm,SSR */ inline void sh34_base_device::LDCSSR(const uint16_t opcode) { m_ssr = m_r[Rn]; } /* LDC Rm,SPC */ inline void sh34_base_device::LDCSPC(const uint16_t opcode) { m_spc = m_r[Rn]; } /* PREF @Rn */ inline void sh34_base_device::PREFM(const uint16_t opcode) { int a; uint32_t addr,dest,sq; addr = m_r[Rn]; // address if ((addr >= 0xE0000000) && (addr <= 0xE3FFFFFF)) { if (m_sh4_mmu_enabled) { addr = addr & 0xFFFFFFE0; dest = sh4_getsqremap(addr); // good enough for naomi-gd rom, probably not much else } else { sq = (addr & 0x20) >> 5; dest = addr & 0x03FFFFE0; if (sq == 0) { if (m_cpu_type == CPU_TYPE_SH4) { dest |= (m_m[QACR0] & 0x1C) << 24; } else { fatalerror("m_cpu_type != CPU_TYPE_SH4 but access internal regs\n"); } } else { if (m_cpu_type == CPU_TYPE_SH4) { dest |= (m_m[QACR1] & 0x1C) << 24; } else { fatalerror("m_cpu_type != CPU_TYPE_SH4 but access internal regs\n"); } } addr = addr & 0xFFFFFFE0; } for (a = 0;a < 4;a++) { // shouldn't be causing a memory read, should store sq writes in registers. m_program->write_qword(dest, m_program->read_qword(addr)); addr += 8; dest += 8; } } } /***************************************************************************** * OPCODE DISPATCHERS *****************************************************************************/ /* FMOV.S @Rm+,FRn PR=0 SZ=0 1111nnnnmmmm1001 */ /* FMOV @Rm+,DRn PR=0 SZ=1 1111nnn0mmmm1001 */ /* FMOV @Rm+,XDn PR=0 SZ=1 1111nnn1mmmm1001 */ /* FMOV @Rm+,XDn PR=1 1111nnn1mmmm1001 */ inline void sh34_base_device::FMOVMRIFR(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; if (m_fpu_pr) { /* PR = 1 */ n = n & 14; m_ea = m_r[m]; m_r[m] += 8; m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(m_ea ); m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(m_ea+4 ); } else { /* PR = 0 */ if (m_fpu_sz) { /* SZ = 1 */ if (n & 1) { n = n & 14; m_ea = m_r[m]; m_xf[n] = RL(m_ea ); m_r[m] += 4; m_xf[n+1] = RL(m_ea+4 ); m_r[m] += 4; } else { m_ea = m_r[m]; m_fr[n] = RL(m_ea ); m_r[m] += 4; m_fr[n+1] = RL(m_ea+4 ); m_r[m] += 4; } } else { /* SZ = 0 */ m_ea = m_r[m]; m_fr[n] = RL(m_ea ); m_r[m] += 4; } } } /* FMOV.S FRm,@Rn PR=0 SZ=0 1111nnnnmmmm1010 */ /* FMOV DRm,@Rn PR=0 SZ=1 1111nnnnmmm01010 */ /* FMOV XDm,@Rn PR=0 SZ=1 1111nnnnmmm11010 */ /* FMOV XDm,@Rn PR=1 1111nnnnmmm11010 */ inline void sh34_base_device::FMOVFRMR(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; if (m_fpu_pr) { /* PR = 1 */ m= m & 14; m_ea = m_r[n]; WL(m_ea,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] ); WL(m_ea+4,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] ); } else { /* PR = 0 */ if (m_fpu_sz) { /* SZ = 1 */ if (m & 1) { m= m & 14; m_ea = m_r[n]; WL(m_ea,m_xf[m] ); WL(m_ea+4,m_xf[m+1] ); } else { m_ea = m_r[n]; WL(m_ea,m_fr[m] ); WL(m_ea+4,m_fr[m+1] ); } } else { /* SZ = 0 */ m_ea = m_r[n]; WL(m_ea,m_fr[m] ); } } } /* FMOV.S FRm,@-Rn PR=0 SZ=0 1111nnnnmmmm1011 */ /* FMOV DRm,@-Rn PR=0 SZ=1 1111nnnnmmm01011 */ /* FMOV XDm,@-Rn PR=0 SZ=1 1111nnnnmmm11011 */ /* FMOV XDm,@-Rn PR=1 1111nnnnmmm11011 */ inline void sh34_base_device::FMOVFRMDR(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; if (m_fpu_pr) { /* PR = 1 */ m= m & 14; m_r[n] -= 8; m_ea = m_r[n]; WL(m_ea,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] ); WL(m_ea+4,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] ); } else { /* PR = 0 */ if (m_fpu_sz) { /* SZ = 1 */ if (m & 1) { m= m & 14; m_r[n] -= 8; m_ea = m_r[n]; WL(m_ea,m_xf[m] ); WL(m_ea+4,m_xf[m+1] ); } else { m_r[n] -= 8; m_ea = m_r[n]; WL(m_ea,m_fr[m] ); WL(m_ea+4,m_fr[m+1] ); } } else { /* SZ = 0 */ m_r[n] -= 4; m_ea = m_r[n]; WL(m_ea,m_fr[m] ); } } } /* FMOV.S FRm,@(R0,Rn) PR=0 SZ=0 1111nnnnmmmm0111 */ /* FMOV DRm,@(R0,Rn) PR=0 SZ=1 1111nnnnmmm00111 */ /* FMOV XDm,@(R0,Rn) PR=0 SZ=1 1111nnnnmmm10111 */ /* FMOV XDm,@(R0,Rn) PR=1 1111nnnnmmm10111 */ inline void sh34_base_device::FMOVFRS0(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; if (m_fpu_pr) { /* PR = 1 */ m= m & 14; m_ea = m_r[0] + m_r[n]; WL(m_ea,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] ); WL(m_ea+4,m_xf[m+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] ); } else { /* PR = 0 */ if (m_fpu_sz) { /* SZ = 1 */ if (m & 1) { m= m & 14; m_ea = m_r[0] + m_r[n]; WL(m_ea,m_xf[m] ); WL(m_ea+4,m_xf[m+1] ); } else { m_ea = m_r[0] + m_r[n]; WL(m_ea,m_fr[m] ); WL(m_ea+4,m_fr[m+1] ); } } else { /* SZ = 0 */ m_ea = m_r[0] + m_r[n]; WL(m_ea,m_fr[m] ); } } } /* FMOV.S @(R0,Rm),FRn PR=0 SZ=0 1111nnnnmmmm0110 */ /* FMOV @(R0,Rm),DRn PR=0 SZ=1 1111nnn0mmmm0110 */ /* FMOV @(R0,Rm),XDn PR=0 SZ=1 1111nnn1mmmm0110 */ /* FMOV @(R0,Rm),XDn PR=1 1111nnn1mmmm0110 */ inline void sh34_base_device::FMOVS0FR(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; if (m_fpu_pr) { /* PR = 1 */ n= n & 14; m_ea = m_r[0] + m_r[m]; m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(m_ea ); m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(m_ea+4 ); } else { /* PR = 0 */ if (m_fpu_sz) { /* SZ = 1 */ if (n & 1) { n= n & 14; m_ea = m_r[0] + m_r[m]; m_xf[n] = RL(m_ea ); m_xf[n+1] = RL(m_ea+4 ); } else { m_ea = m_r[0] + m_r[m]; m_fr[n] = RL(m_ea ); m_fr[n+1] = RL(m_ea+4 ); } } else { /* SZ = 0 */ m_ea = m_r[0] + m_r[m]; m_fr[n] = RL(m_ea ); } } } /* FMOV.S @Rm,FRn PR=0 SZ=0 1111nnnnmmmm1000 */ /* FMOV @Rm,DRn PR=0 SZ=1 1111nnn0mmmm1000 */ /* FMOV @Rm,XDn PR=0 SZ=1 1111nnn1mmmm1000 */ /* FMOV @Rm,XDn PR=1 1111nnn1mmmm1000 */ /* FMOV @Rm,DRn PR=1 1111nnn0mmmm1000 */ inline void sh34_base_device::FMOVMRFR(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; if (m_fpu_pr) { /* PR = 1 */ if (n & 1) { n= n & 14; m_ea = m_r[m]; m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(m_ea ); m_xf[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(m_ea+4 ); } else { n= n & 14; m_ea = m_r[m]; m_fr[n+NATIVE_ENDIAN_VALUE_LE_BE(1,0)] = RL(m_ea ); m_fr[n+NATIVE_ENDIAN_VALUE_LE_BE(0,1)] = RL(m_ea+4 ); } } else { /* PR = 0 */ if (m_fpu_sz) { /* SZ = 1 */ if (n & 1) { n= n & 14; m_ea = m_r[m]; m_xf[n] = RL(m_ea ); m_xf[n+1] = RL(m_ea+4 ); } else { n= n & 14; m_ea = m_r[m]; m_fr[n] = RL(m_ea ); m_fr[n+1] = RL(m_ea+4 ); } } else { /* SZ = 0 */ m_ea = m_r[m]; m_fr[n] = RL(m_ea ); } } } /* FMOV FRm,FRn PR=0 SZ=0 FRm -> FRn 1111nnnnmmmm1100 */ /* FMOV DRm,DRn PR=0 SZ=1 DRm -> DRn 1111nnn0mmm01100 */ /* FMOV XDm,DRn PR=1 XDm -> DRn 1111nnn0mmm11100 */ /* FMOV DRm,XDn PR=1 DRm -> XDn 1111nnn1mmm01100 */ /* FMOV XDm,XDn PR=1 XDm -> XDn 1111nnn1mmm11100 */ inline void sh34_base_device::FMOVFR(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; if ((m_fpu_sz == 0) && (m_fpu_pr == 0)) /* SZ = 0 */ m_fr[n] = m_fr[m]; else { /* SZ = 1 or PR = 1 */ if (m & 1) { if (n & 1) { m_xf[n & 14] = m_xf[m & 14]; m_xf[n | 1] = m_xf[m | 1]; } else { m_fr[n] = m_xf[m & 14]; m_fr[n | 1] = m_xf[m | 1]; } } else { if (n & 1) { m_xf[n & 14] = m_fr[m]; m_xf[n | 1] = m_fr[m | 1]; // (a&14)+1 -> a|1 } else { m_fr[n] = m_fr[m]; m_fr[n | 1] = m_fr[m | 1]; } } } } /* FLDI1 FRn 1111nnnn10011101 */ inline void sh34_base_device::FLDI1(const uint16_t opcode) { m_fr[Rn] = 0x3F800000; } /* FLDI0 FRn 1111nnnn10001101 */ inline void sh34_base_device::FLDI0(const uint16_t opcode) { m_fr[Rn] = 0; } /* FLDS FRm,FPUL 1111mmmm00011101 */ inline void sh34_base_device:: FLDS(const uint16_t opcode) { m_fpul = m_fr[Rn]; } /* FSTS FPUL,FRn 1111nnnn00001101 */ inline void sh34_base_device:: FSTS(const uint16_t opcode) { m_fr[Rn] = m_fpul; } /* FRCHG 1111101111111101 */ void sh34_base_device::FRCHG() { m_fpscr ^= FR; sh4_swap_fp_registers(); } /* FSCHG 1111001111111101 */ void sh34_base_device::FSCHG() { m_fpscr ^= SZ; m_fpu_sz = (m_fpscr & SZ) ? 1 : 0; } /* FTRC FRm,FPUL PR=0 1111mmmm00111101 */ /* FTRC DRm,FPUL PR=1 1111mmm000111101 */ inline void sh34_base_device::FTRC(const uint16_t opcode) { uint32_t n = Rn; if (m_fpu_pr) { /* PR = 1 */ if(n & 1) fatalerror("SH-4: FTRC opcode used with n %d",n); n = n & 14; *((int32_t *)&m_fpul) = (int32_t)FP_RFD(n); } else { /* PR = 0 */ /* read m_fr[n] as float -> truncate -> fpul(32) */ *((int32_t *)&m_fpul) = (int32_t)FP_RFS(n); } } /* FLOAT FPUL,FRn PR=0 1111nnnn00101101 */ /* FLOAT FPUL,DRn PR=1 1111nnn000101101 */ inline void sh34_base_device::FLOAT(const uint16_t opcode) { uint32_t n = Rn; if (m_fpu_pr) { /* PR = 1 */ if(n & 1) fatalerror("SH-4: FLOAT opcode used with n %d",n); n = n & 14; FP_RFD(n) = (double)*((int32_t *)&m_fpul); } else { /* PR = 0 */ FP_RFS(n) = (float)*((int32_t *)&m_fpul); } } /* FNEG FRn PR=0 1111nnnn01001101 */ /* FNEG DRn PR=1 1111nnn001001101 */ inline void sh34_base_device::FNEG(const uint16_t opcode) { uint32_t n = Rn; if (m_fpu_pr) { /* PR = 1 */ FP_RFD(n) = -FP_RFD(n); } else { /* PR = 0 */ FP_RFS(n) = -FP_RFS(n); } } /* FABS FRn PR=0 1111nnnn01011101 */ /* FABS DRn PR=1 1111nnn001011101 */ inline void sh34_base_device::FABS(const uint16_t opcode) { uint32_t n = Rn; if (m_fpu_pr) { /* PR = 1 */ #ifdef LSB_FIRST n = n | 1; // n & 14 + 1 m_fr[n] = m_fr[n] & 0x7fffffff; #else n = n & 14; m_fr[n] = m_fr[n] & 0x7fffffff; #endif } else { /* PR = 0 */ m_fr[n] = m_fr[n] & 0x7fffffff; } } /* FCMP/EQ FRm,FRn PR=0 1111nnnnmmmm0100 */ /* FCMP/EQ DRm,DRn PR=1 1111nnn0mmm00100 */ inline void sh34_base_device::FCMP_EQ(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; if (m_fpu_pr) { /* PR = 1 */ n = n & 14; m = m & 14; if (FP_RFD(n) == FP_RFD(m)) m_sr |= T; else m_sr &= ~T; } else { /* PR = 0 */ if (FP_RFS(n) == FP_RFS(m)) m_sr |= T; else m_sr &= ~T; } } /* FCMP/GT FRm,FRn PR=0 1111nnnnmmmm0101 */ /* FCMP/GT DRm,DRn PR=1 1111nnn0mmm00101 */ inline void sh34_base_device::FCMP_GT(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; if (m_fpu_pr) { /* PR = 1 */ n = n & 14; m = m & 14; if (FP_RFD(n) > FP_RFD(m)) m_sr |= T; else m_sr &= ~T; } else { /* PR = 0 */ if (FP_RFS(n) > FP_RFS(m)) m_sr |= T; else m_sr &= ~T; } } /* FCNVDS DRm,FPUL PR=1 1111mmm010111101 */ inline void sh34_base_device::FCNVDS(const uint16_t opcode) { uint32_t n = Rn; if (m_fpu_pr) { /* PR = 1 */ n = n & 14; if (m_fpscr & RM) m_fr[n | NATIVE_ENDIAN_VALUE_LE_BE(0,1)] &= 0xe0000000; /* round toward zero*/ *((float *)&m_fpul) = (float)FP_RFD(n); } } /* FCNVSD FPUL, DRn PR=1 1111nnn010101101 */ inline void sh34_base_device::FCNVSD(const uint16_t opcode) { uint32_t n = Rn; if (m_fpu_pr) { /* PR = 1 */ n = n & 14; FP_RFD(n) = (double)*((float *)&m_fpul); } } /* FADD FRm,FRn PR=0 1111nnnnmmmm0000 */ /* FADD DRm,DRn PR=1 1111nnn0mmm00000 */ inline void sh34_base_device::FADD(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; if (m_fpu_pr) { /* PR = 1 */ n = n & 14; m = m & 14; FP_RFD(n) = FP_RFD(n) + FP_RFD(m); } else { /* PR = 0 */ FP_RFS(n) = FP_RFS(n) + FP_RFS(m); } } /* FSUB FRm,FRn PR=0 1111nnnnmmmm0001 */ /* FSUB DRm,DRn PR=1 1111nnn0mmm00001 */ inline void sh34_base_device::FSUB(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; if (m_fpu_pr) { /* PR = 1 */ n = n & 14; m = m & 14; FP_RFD(n) = FP_RFD(n) - FP_RFD(m); } else { /* PR = 0 */ FP_RFS(n) = FP_RFS(n) - FP_RFS(m); } } /* FMUL FRm,FRn PR=0 1111nnnnmmmm0010 */ /* FMUL DRm,DRn PR=1 1111nnn0mmm00010 */ inline void sh34_base_device::FMUL(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; if (m_fpu_pr) { /* PR = 1 */ n = n & 14; m = m & 14; FP_RFD(n) = FP_RFD(n) * FP_RFD(m); } else { /* PR = 0 */ FP_RFS(n) = FP_RFS(n) * FP_RFS(m); } } /* FDIV FRm,FRn PR=0 1111nnnnmmmm0011 */ /* FDIV DRm,DRn PR=1 1111nnn0mmm00011 */ inline void sh34_base_device::FDIV(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; if (m_fpu_pr) { /* PR = 1 */ n = n & 14; m = m & 14; if (FP_RFD(m) == 0) return; FP_RFD(n) = FP_RFD(n) / FP_RFD(m); } else { /* PR = 0 */ if (FP_RFS(m) == 0) return; FP_RFS(n) = FP_RFS(n) / FP_RFS(m); } } /* FMAC FR0,FRm,FRn PR=0 1111nnnnmmmm1110 */ inline void sh34_base_device::FMAC(const uint16_t opcode) { uint32_t m = Rm; uint32_t n = Rn; if (m_fpu_pr == 0) { /* PR = 0 */ FP_RFS(n) = (FP_RFS(0) * FP_RFS(m)) + FP_RFS(n); } } /* FSQRT FRn PR=0 1111nnnn01101101 */ /* FSQRT DRn PR=1 1111nnnn01101101 */ inline void sh34_base_device::FSQRT(const uint16_t opcode) { uint32_t n = Rn; if (m_fpu_pr) { /* PR = 1 */ n = n & 14; if (FP_RFD(n) < 0) return; FP_RFD(n) = sqrtf(FP_RFD(n)); } else { /* PR = 0 */ if (FP_RFS(n) < 0) return; FP_RFS(n) = sqrtf(FP_RFS(n)); } } /* FSRRA FRn PR=0 1111nnnn01111101 */ inline void sh34_base_device::FSRRA(const uint16_t opcode) { uint32_t n = Rn; if (FP_RFS(n) < 0) return; FP_RFS(n) = 1.0f / sqrtf(FP_RFS(n)); } /* FSSCA FPUL,FRn PR=0 1111nnn011111101 */ void sh34_base_device::FSSCA(const uint16_t opcode) { uint32_t n = Rn; float angle; angle = (((float)(m_fpul & 0xFFFF)) / 65536.0f) * 2.0f * (float) M_PI; FP_RFS(n) = sinf(angle); FP_RFS(n+1) = cosf(angle); } /* FIPR FVm,FVn PR=0 1111nnmm11101101 */ inline void sh34_base_device::FIPR(const uint16_t opcode) { uint32_t n = Rn; uint32_t m; float ml[4]; int a; m = (n & 3) << 2; n = n & 12; for (a = 0;a < 4;a++) ml[a] = FP_RFS(n+a) * FP_RFS(m+a); FP_RFS(n+3) = ml[0] + ml[1] + ml[2] + ml[3]; } /* FTRV XMTRX,FVn PR=0 1111nn0111111101 */ void sh34_base_device::FTRV(const uint16_t opcode) { uint32_t n = Rn; int i,j; float sum[4]; n = n & 12; for (i = 0;i < 4;i++) { sum[i] = 0; for (j=0;j < 4;j++) sum[i] += FP_XFS((j << 2) + i)*FP_RFS(n + j); } for (i = 0;i < 4;i++) FP_RFS(n + i) = sum[i]; } inline void sh34_base_device::op1111_0xf13(const uint16_t opcode) { if (opcode & 0x100) { if (opcode & 0x200) { switch (opcode & 0xC00) { case 0x000: FSCHG(); break; case 0x800: FRCHG(); break; default: machine().debug_break(); break; } } else { FTRV(opcode); } } else { FSSCA(opcode); } } void sh34_base_device::dbreak(const uint16_t opcode) { machine().debug_break(); } inline void sh34_base_device::op1111_0x13(uint16_t opcode) { switch((opcode >> 4) & 0x0f) { case 0x00: FSTS(opcode); break; case 0x01: FLDS(opcode); break; case 0x02: FLOAT(opcode); break; case 0x03: FTRC(opcode); break; case 0x04: FNEG(opcode); break; case 0x05: FABS(opcode); break; case 0x06: FSQRT(opcode); break; case 0x07: FSRRA(opcode); break; case 0x08: FLDI0(opcode); break; case 0x09: FLDI1(opcode); break; case 0x0a: FCNVSD(opcode); break; case 0x0b: FCNVDS(opcode); break; case 0x0c: dbreak(opcode); break; case 0x0d: dbreak(opcode); break; case 0x0e: FIPR(opcode); break; case 0x0f: op1111_0xf13(opcode); break; } } /***************************************************************************** * MAME CPU INTERFACE *****************************************************************************/ void sh34_base_device::device_reset() { m_spc = 0; m_pr = 0; m_sr = 0; m_ssr = 0; m_gbr = 0; m_vbr = 0; m_mach = 0; m_macl = 0; memset(m_r, 0, sizeof(m_r)); memset(m_rbnk, 0, sizeof(m_rbnk)); m_sgr = 0; memset(m_fr, 0, sizeof(m_fr)); memset(m_xf, 0, sizeof(m_xf)); m_ea = 0; m_delay = 0; m_cpu_off = 0; m_pending_irq = 0; m_test_irq = 0; memset(m_exception_priority, 0, sizeof(m_exception_priority)); memset(m_exception_requesting, 0, sizeof(m_exception_requesting)); memset(m_m, 0, sizeof(m_m)); memset(m_sh3internal_upper, 0, sizeof(m_sh3internal_upper)); memset(m_sh3internal_lower, 0, sizeof(m_sh3internal_lower)); memset(m_irq_line_state, 0, sizeof(m_irq_line_state)); m_SH4_TSTR = 0; m_SH4_TCNT0 = 0; m_SH4_TCNT1 = 0; m_SH4_TCNT2 = 0; m_SH4_TCR0 = 0; m_SH4_TCR1 = 0; m_SH4_TCR2 = 0; m_SH4_TCOR0 = 0; m_SH4_TCOR1 = 0; m_SH4_TCOR2 = 0; m_SH4_TOCR = 0; m_SH4_TCPR2 = 0; m_SH4_IPRA = 0; m_SH4_IPRC = 0; m_SH4_SAR0 = 0; m_SH4_SAR1 = 0; m_SH4_SAR2 = 0; m_SH4_SAR3 = 0; m_SH4_DAR0 = 0; m_SH4_DAR1 = 0; m_SH4_DAR2 = 0; m_SH4_DAR3 = 0; m_SH4_CHCR0 = 0; m_SH4_CHCR1 = 0; m_SH4_CHCR2 = 0; m_SH4_CHCR3 = 0; m_SH4_DMATCR0 = 0; m_SH4_DMATCR1 = 0; m_SH4_DMATCR2 = 0; m_SH4_DMATCR3 = 0; m_SH4_DMAOR = 0; m_nmi_line_state = 0; m_frt_input = 0; m_internal_irq_vector = 0; m_refresh_timer_base = 0; memset(m_dma_timer_active, 0, sizeof(m_dma_timer_active)); memset(m_dma_source, 0, sizeof(m_dma_source)); memset(m_dma_destination, 0, sizeof(m_dma_destination)); memset(m_dma_count, 0, sizeof(m_dma_count)); memset(m_dma_wordsize, 0, sizeof(m_dma_wordsize)); memset(m_dma_source_increment, 0, sizeof(m_dma_source_increment)); memset(m_dma_destination_increment, 0, sizeof(m_dma_destination_increment)); memset(m_dma_mode, 0, sizeof(m_dma_mode)); m_ioport16_pullup = 0; m_ioport16_direction = 0; m_ioport4_pullup = 0; m_ioport4_direction = 0; sh4_default_exception_priorities(); m_rtc_timer->adjust(attotime::from_hz(128)); m_pc = 0xa0000000; m_ppc = m_pc & AM; m_r[15] = RL(4); m_sr = 0x700000f0; m_fpscr = 0x00040001; m_fpu_sz = (m_fpscr & SZ) ? 1 : 0; m_fpu_pr = (m_fpscr & PR) ? 1 : 0; m_fpul = 0; m_dbr = 0; m_internal_irq_level = -1; m_irln = 15; m_sleep_mode = 0; m_sh4_mmu_enabled = 0; } /*------------------------------------------------- sh3_reset - reset the processor -------------------------------------------------*/ void sh3_base_device::device_reset() { sh34_base_device::device_reset(); m_SH4_TCOR0 = 0xffffffff; m_SH4_TCNT0 = 0xffffffff; m_SH4_TCOR1 = 0xffffffff; m_SH4_TCNT1 = 0xffffffff; m_SH4_TCOR2 = 0xffffffff; m_SH4_TCNT2 = 0xffffffff; } void sh4_base_device::device_reset() { sh34_base_device::device_reset(); m_m[RCR2] = 0x09; m_SH4_TCOR0 = 0xffffffff; m_SH4_TCNT0 = 0xffffffff; m_SH4_TCOR1 = 0xffffffff; m_SH4_TCNT1 = 0xffffffff; m_SH4_TCOR2 = 0xffffffff; m_SH4_TCNT2 = 0xffffffff; } inline void sh34_base_device::execute_one_0000(const uint16_t opcode) { switch(opcode & 0xff) { // 0x00 case 0x00: NOP(opcode); break; case 0x10: NOP(opcode); break; case 0x20: NOP(opcode); break; case 0x30: NOP(opcode); break; case 0x40: NOP(opcode); break; case 0x50: NOP(opcode); break; case 0x60: NOP(opcode); break; case 0x70: NOP(opcode); break; case 0x80: NOP(opcode); break; case 0x90: NOP(opcode); break; case 0xa0: NOP(opcode); break; case 0xb0: NOP(opcode); break; case 0xc0: NOP(opcode); break; case 0xd0: NOP(opcode); break; case 0xe0: NOP(opcode); break; case 0xf0: NOP(opcode); break; // 0x10 case 0x01: NOP(opcode); break; case 0x11: NOP(opcode); break; case 0x21: NOP(opcode); break; case 0x31: NOP(opcode); break; case 0x41: NOP(opcode); break; case 0x51: NOP(opcode); break; case 0x61: NOP(opcode); break; case 0x71: NOP(opcode); break; case 0x81: NOP(opcode); break; case 0x91: NOP(opcode); break; case 0xa1: NOP(opcode); break; case 0xb1: NOP(opcode); break; case 0xc1: NOP(opcode); break; case 0xd1: NOP(opcode); break; case 0xe1: NOP(opcode); break; case 0xf1: NOP(opcode); break; // 0x20 case 0x02: STCSR(opcode); break; case 0x12: STCGBR(opcode); break; case 0x22: STCVBR(opcode); break; case 0x32: STCSSR(opcode); break; case 0x42: STCSPC(opcode); break; case 0x52: NOP(opcode); break; case 0x62: NOP(opcode); break; case 0x72: NOP(opcode); break; case 0x82: STCRBANK(opcode); break; case 0x92: STCRBANK(opcode); break; case 0xa2: STCRBANK(opcode); break; case 0xb2: STCRBANK(opcode); break; case 0xc2: STCRBANK(opcode); break; case 0xd2: STCRBANK(opcode); break; case 0xe2: STCRBANK(opcode); break; case 0xf2: STCRBANK(opcode); break; // 0x30 case 0x03: BSRF(opcode); break; case 0x13: NOP(opcode); break; case 0x23: BRAF(opcode); break; case 0x33: NOP(opcode); break; case 0x43: NOP(opcode); break; case 0x53: NOP(opcode); break; case 0x63: NOP(opcode); break; case 0x73: NOP(opcode); break; case 0x83: PREFM(opcode); break; case 0x93: TODO(opcode); break; case 0xa3: TODO(opcode); break; case 0xb3: TODO(opcode); break; case 0xc3: MOVCAL(opcode); break; case 0xd3: NOP(opcode); break; case 0xe3: NOP(opcode); break; case 0xf3: NOP(opcode); break; // 0x40 case 0x04: MOVBS0(opcode); break; case 0x14: MOVBS0(opcode); break; case 0x24: MOVBS0(opcode); break; case 0x34: MOVBS0(opcode); break; case 0x44: MOVBS0(opcode); break; case 0x54: MOVBS0(opcode); break; case 0x64: MOVBS0(opcode); break; case 0x74: MOVBS0(opcode); break; case 0x84: MOVBS0(opcode); break; case 0x94: MOVBS0(opcode); break; case 0xa4: MOVBS0(opcode); break; case 0xb4: MOVBS0(opcode); break; case 0xc4: MOVBS0(opcode); break; case 0xd4: MOVBS0(opcode); break; case 0xe4: MOVBS0(opcode); break; case 0xf4: MOVBS0(opcode); break; // 0x50 case 0x05: MOVWS0(opcode); break; case 0x15: MOVWS0(opcode); break; case 0x25: MOVWS0(opcode); break; case 0x35: MOVWS0(opcode); break; case 0x45: MOVWS0(opcode); break; case 0x55: MOVWS0(opcode); break; case 0x65: MOVWS0(opcode); break; case 0x75: MOVWS0(opcode); break; case 0x85: MOVWS0(opcode); break; case 0x95: MOVWS0(opcode); break; case 0xa5: MOVWS0(opcode); break; case 0xb5: MOVWS0(opcode); break; case 0xc5: MOVWS0(opcode); break; case 0xd5: MOVWS0(opcode); break; case 0xe5: MOVWS0(opcode); break; case 0xf5: MOVWS0(opcode); break; // 0x60 case 0x06: MOVLS0(opcode); break; case 0x16: MOVLS0(opcode); break; case 0x26: MOVLS0(opcode); break; case 0x36: MOVLS0(opcode); break; case 0x46: MOVLS0(opcode); break; case 0x56: MOVLS0(opcode); break; case 0x66: MOVLS0(opcode); break; case 0x76: MOVLS0(opcode); break; case 0x86: MOVLS0(opcode); break; case 0x96: MOVLS0(opcode); break; case 0xa6: MOVLS0(opcode); break; case 0xb6: MOVLS0(opcode); break; case 0xc6: MOVLS0(opcode); break; case 0xd6: MOVLS0(opcode); break; case 0xe6: MOVLS0(opcode); break; case 0xf6: MOVLS0(opcode); break; // 0x70 case 0x07: MULL(opcode); break; case 0x17: MULL(opcode); break; case 0x27: MULL(opcode); break; case 0x37: MULL(opcode); break; case 0x47: MULL(opcode); break; case 0x57: MULL(opcode); break; case 0x67: MULL(opcode); break; case 0x77: MULL(opcode); break; case 0x87: MULL(opcode); break; case 0x97: MULL(opcode); break; case 0xa7: MULL(opcode); break; case 0xb7: MULL(opcode); break; case 0xc7: MULL(opcode); break; case 0xd7: MULL(opcode); break; case 0xe7: MULL(opcode); break; case 0xf7: MULL(opcode); break; // 0x80 case 0x08: CLRT(opcode); break; case 0x18: SETT(opcode); break; case 0x28: CLRMAC(opcode); break; case 0x38: TODO(opcode); break; case 0x48: CLRS(opcode); break; case 0x58: SETS(opcode); break; case 0x68: NOP(opcode); break; case 0x78: NOP(opcode); break; case 0x88: CLRT(opcode); break; case 0x98: SETT(opcode); break; case 0xa8: CLRMAC(opcode); break; case 0xb8: TODO(opcode); break; case 0xc8: CLRS(opcode); break; case 0xd8: SETS(opcode); break; case 0xe8: NOP(opcode); break; case 0xf8: NOP(opcode); break; // 0x90 case 0x09: NOP(opcode); break; case 0x19: DIV0U(opcode); break; case 0x29: MOVT(opcode); break; case 0x39: NOP(opcode); break; case 0x49: NOP(opcode); break; case 0x59: DIV0U(opcode); break; case 0x69: MOVT(opcode); break; case 0x79: NOP(opcode); break; case 0x89: NOP(opcode); break; case 0x99: DIV0U(opcode); break; case 0xa9: MOVT(opcode); break; case 0xb9: NOP(opcode); break; case 0xc9: NOP(opcode); break; case 0xd9: DIV0U(opcode); break; case 0xe9: MOVT(opcode); break; case 0xf9: NOP(opcode); break; // 0xa0 case 0x0a: STSMACH(opcode); break; case 0x1a: STSMACL(opcode); break; case 0x2a: STSPR(opcode); break; case 0x3a: STCSGR(opcode); break; case 0x4a: NOP(opcode); break; case 0x5a: STSFPUL(opcode); break; case 0x6a: STSFPSCR(opcode); break; case 0x7a: STCDBR(opcode); break; case 0x8a: STSMACH(opcode); break; case 0x9a: STSMACL(opcode); break; case 0xaa: STSPR(opcode); break; case 0xba: STCSGR(opcode); break; case 0xca: NOP(opcode); break; case 0xda: STSFPUL(opcode); break; case 0xea: STSFPSCR(opcode); break; case 0xfa: STCDBR(opcode); break; // 0xb0 case 0x0b: RTS(opcode); break; case 0x1b: SLEEP(opcode); break; case 0x2b: RTE(opcode); break; case 0x3b: NOP(opcode); break; case 0x4b: RTS(opcode); break; case 0x5b: SLEEP(opcode); break; case 0x6b: RTE(opcode); break; case 0x7b: NOP(opcode); break; case 0x8b: RTS(opcode); break; case 0x9b: SLEEP(opcode); break; case 0xab: RTE(opcode); break; case 0xbb: NOP(opcode); break; case 0xcb: RTS(opcode); break; case 0xdb: SLEEP(opcode); break; case 0xeb: RTE(opcode); break; case 0xfb: NOP(opcode); break; // 0xc0 case 0x0c: MOVBL0(opcode); break; case 0x1c: MOVBL0(opcode); break; case 0x2c: MOVBL0(opcode); break; case 0x3c: MOVBL0(opcode); break; case 0x4c: MOVBL0(opcode); break; case 0x5c: MOVBL0(opcode); break; case 0x6c: MOVBL0(opcode); break; case 0x7c: MOVBL0(opcode); break; case 0x8c: MOVBL0(opcode); break; case 0x9c: MOVBL0(opcode); break; case 0xac: MOVBL0(opcode); break; case 0xbc: MOVBL0(opcode); break; case 0xcc: MOVBL0(opcode); break; case 0xdc: MOVBL0(opcode); break; case 0xec: MOVBL0(opcode); break; case 0xfc: MOVBL0(opcode); break; // 0xd0 case 0x0d: MOVWL0(opcode); break; case 0x1d: MOVWL0(opcode); break; case 0x2d: MOVWL0(opcode); break; case 0x3d: MOVWL0(opcode); break; case 0x4d: MOVWL0(opcode); break; case 0x5d: MOVWL0(opcode); break; case 0x6d: MOVWL0(opcode); break; case 0x7d: MOVWL0(opcode); break; case 0x8d: MOVWL0(opcode); break; case 0x9d: MOVWL0(opcode); break; case 0xad: MOVWL0(opcode); break; case 0xbd: MOVWL0(opcode); break; case 0xcd: MOVWL0(opcode); break; case 0xdd: MOVWL0(opcode); break; case 0xed: MOVWL0(opcode); break; case 0xfd: MOVWL0(opcode); break; // 0xe0 case 0x0e: MOVLL0(opcode); break; case 0x1e: MOVLL0(opcode); break; case 0x2e: MOVLL0(opcode); break; case 0x3e: MOVLL0(opcode); break; case 0x4e: MOVLL0(opcode); break; case 0x5e: MOVLL0(opcode); break; case 0x6e: MOVLL0(opcode); break; case 0x7e: MOVLL0(opcode); break; case 0x8e: MOVLL0(opcode); break; case 0x9e: MOVLL0(opcode); break; case 0xae: MOVLL0(opcode); break; case 0xbe: MOVLL0(opcode); break; case 0xce: MOVLL0(opcode); break; case 0xde: MOVLL0(opcode); break; case 0xee: MOVLL0(opcode); break; case 0xfe: MOVLL0(opcode); break; // 0xf0 case 0x0f: MAC_L(opcode); break; case 0x1f: MAC_L(opcode); break; case 0x2f: MAC_L(opcode); break; case 0x3f: MAC_L(opcode); break; case 0x4f: MAC_L(opcode); break; case 0x5f: MAC_L(opcode); break; case 0x6f: MAC_L(opcode); break; case 0x7f: MAC_L(opcode); break; case 0x8f: MAC_L(opcode); break; case 0x9f: MAC_L(opcode); break; case 0xaf: MAC_L(opcode); break; case 0xbf: MAC_L(opcode); break; case 0xcf: MAC_L(opcode); break; case 0xdf: MAC_L(opcode); break; case 0xef: MAC_L(opcode); break; case 0xff: MAC_L(opcode); break; } } inline void sh34_base_device::execute_one_4000(const uint16_t opcode) { switch(opcode & 0xff) { // 0x00 case 0x00: SHLL(opcode); break; case 0x10: DT(opcode); break; case 0x20: SHAL(opcode); break; case 0x30: NOP(opcode); break; case 0x40: SHLL(opcode); break; case 0x50: DT(opcode); break; case 0x60: SHAL(opcode); break; case 0x70: NOP(opcode); break; case 0x80: SHLL(opcode); break; case 0x90: DT(opcode); break; case 0xa0: SHAL(opcode); break; case 0xb0: NOP(opcode); break; case 0xc0: SHLL(opcode); break; case 0xd0: DT(opcode); break; case 0xe0: SHAL(opcode); break; case 0xf0: NOP(opcode); break; // 0x10 case 0x01: SHLR(opcode); break; case 0x11: CMPPZ(opcode); break; case 0x21: SHAR(opcode); break; case 0x31: NOP(opcode); break; case 0x41: SHLR(opcode); break; case 0x51: CMPPZ(opcode); break; case 0x61: SHAR(opcode); break; case 0x71: NOP(opcode); break; case 0x81: SHLR(opcode); break; case 0x91: CMPPZ(opcode); break; case 0xa1: SHAR(opcode); break; case 0xb1: NOP(opcode); break; case 0xc1: SHLR(opcode); break; case 0xd1: CMPPZ(opcode); break; case 0xe1: SHAR(opcode); break; case 0xf1: NOP(opcode); break; // 0x20 case 0x02: STSMMACH(opcode); break; case 0x12: STSMMACL(opcode); break; case 0x22: STSMPR(opcode); break; case 0x32: STCMSGR(opcode); break; case 0x42: NOP(opcode); break; case 0x52: STSMFPUL(opcode); break; case 0x62: STSMFPSCR(opcode); break; case 0x72: NOP(opcode); break; case 0x82: NOP(opcode); break; case 0x92: NOP(opcode); break; case 0xa2: NOP(opcode); break; case 0xb2: NOP(opcode); break; case 0xc2: NOP(opcode); break; case 0xd2: NOP(opcode); break; case 0xe2: NOP(opcode); break; case 0xf2: STCMDBR(opcode); break; // 0x30 case 0x03: STCMSR(opcode); break; case 0x13: STCMGBR(opcode); break; case 0x23: STCMVBR(opcode); break; case 0x33: STCMSSR(opcode); break; case 0x43: STCMSPC(opcode); break; case 0x53: NOP(opcode); break; case 0x63: NOP(opcode); break; case 0x73: NOP(opcode); break; case 0x83: STCMRBANK(opcode); break; case 0x93: STCMRBANK(opcode); break; case 0xa3: STCMRBANK(opcode); break; case 0xb3: STCMRBANK(opcode); break; case 0xc3: STCMRBANK(opcode); break; case 0xd3: STCMRBANK(opcode); break; case 0xe3: STCMRBANK(opcode); break; case 0xf3: STCMRBANK(opcode); break; // 0x40 case 0x04: ROTL(opcode); break; case 0x14: NOP(opcode); break; case 0x24: ROTCL(opcode); break; case 0x34: NOP(opcode); break; case 0x44: ROTL(opcode); break; case 0x54: NOP(opcode); break; case 0x64: ROTCL(opcode); break; case 0x74: NOP(opcode); break; case 0x84: ROTL(opcode); break; case 0x94: NOP(opcode); break; case 0xa4: ROTCL(opcode); break; case 0xb4: NOP(opcode); break; case 0xc4: ROTL(opcode); break; case 0xd4: NOP(opcode); break; case 0xe4: ROTCL(opcode); break; case 0xf4: NOP(opcode); break; // 0x50 case 0x05: ROTR(opcode); break; case 0x15: CMPPL(opcode); break; case 0x25: ROTCR(opcode); break; case 0x35: NOP(opcode); break; case 0x45: ROTR(opcode); break; case 0x55: CMPPL(opcode); break; case 0x65: ROTCR(opcode); break; case 0x75: NOP(opcode); break; case 0x85: ROTR(opcode); break; case 0x95: CMPPL(opcode); break; case 0xa5: ROTCR(opcode); break; case 0xb5: NOP(opcode); break; case 0xc5: ROTR(opcode); break; case 0xd5: CMPPL(opcode); break; case 0xe5: ROTCR(opcode); break; case 0xf5: NOP(opcode); break; // 0x60 case 0x06: LDSMMACH(opcode); break; case 0x16: LDSMMACL(opcode); break; case 0x26: LDSMPR(opcode); break; case 0x36: NOP(opcode); break; case 0x46: NOP(opcode); break; case 0x56: LDSMFPUL(opcode); break; case 0x66: LDSMFPSCR(opcode); break; case 0x76: NOP(opcode); break; case 0x86: NOP(opcode); break; case 0x96: NOP(opcode); break; case 0xa6: NOP(opcode); break; case 0xb6: NOP(opcode); break; case 0xc6: NOP(opcode); break; case 0xd6: NOP(opcode); break; case 0xe6: NOP(opcode); break; case 0xf6: LDCMDBR(opcode); break; // 0x70 case 0x07: LDCMSR(opcode); break; case 0x17: LDCMGBR(opcode); break; case 0x27: LDCMVBR(opcode); break; case 0x37: LDCMSSR(opcode); break; case 0x47: LDCMSPC(opcode); break; case 0x57: NOP(opcode); break; case 0x67: NOP(opcode); break; case 0x77: NOP(opcode); break; case 0x87: LDCMRBANK(opcode); break; case 0x97: LDCMRBANK(opcode); break; case 0xa7: LDCMRBANK(opcode); break; case 0xb7: LDCMRBANK(opcode); break; case 0xc7: LDCMRBANK(opcode); break; case 0xd7: LDCMRBANK(opcode); break; case 0xe7: LDCMRBANK(opcode); break; case 0xf7: LDCMRBANK(opcode); break; // 0x80 case 0x08: SHLL2(opcode); break; case 0x18: SHLL8(opcode); break; case 0x28: SHLL16(opcode); break; case 0x38: NOP(opcode); break; case 0x48: SHLL2(opcode); break; case 0x58: SHLL8(opcode); break; case 0x68: SHLL16(opcode); break; case 0x78: NOP(opcode); break; case 0x88: SHLL2(opcode); break; case 0x98: SHLL8(opcode); break; case 0xa8: SHLL16(opcode); break; case 0xb8: NOP(opcode); break; case 0xc8: SHLL2(opcode); break; case 0xd8: SHLL8(opcode); break; case 0xe8: SHLL16(opcode); break; case 0xf8: NOP(opcode); break; // 0x90 case 0x09: SHLR2(opcode); break; case 0x19: SHLR8(opcode); break; case 0x29: SHLR16(opcode); break; case 0x39: NOP(opcode); break; case 0x49: SHLR2(opcode); break; case 0x59: SHLR8(opcode); break; case 0x69: SHLR16(opcode); break; case 0x79: NOP(opcode); break; case 0x89: SHLR2(opcode); break; case 0x99: SHLR8(opcode); break; case 0xa9: SHLR16(opcode); break; case 0xb9: NOP(opcode); break; case 0xc9: SHLR2(opcode); break; case 0xd9: SHLR8(opcode); break; case 0xe9: SHLR16(opcode); break; case 0xf9: NOP(opcode); break; // 0xa0 case 0x0a: LDSMACH(opcode); break; case 0x1a: LDSMACL(opcode); break; case 0x2a: LDSPR(opcode); break; case 0x3a: NOP(opcode); break; case 0x4a: NOP(opcode); break; case 0x5a: LDSFPUL(opcode); break; case 0x6a: LDSFPSCR(opcode); break; case 0x7a: NOP(opcode); break; case 0x8a: NOP(opcode); break; case 0x9a: NOP(opcode); break; case 0xaa: NOP(opcode); break; case 0xba: NOP(opcode); break; case 0xca: NOP(opcode); break; case 0xda: NOP(opcode); break; case 0xea: NOP(opcode); break; case 0xfa: LDCDBR(opcode); break; // 0xb0 case 0x0b: JSR(opcode); break; case 0x1b: TAS(opcode); break; case 0x2b: JMP(opcode); break; case 0x3b: NOP(opcode); break; case 0x4b: JSR(opcode); break; case 0x5b: TAS(opcode); break; case 0x6b: JMP(opcode); break; case 0x7b: NOP(opcode); break; case 0x8b: JSR(opcode); break; case 0x9b: TAS(opcode); break; case 0xab: JMP(opcode); break; case 0xbb: NOP(opcode); break; case 0xcb: JSR(opcode); break; case 0xdb: TAS(opcode); break; case 0xeb: JMP(opcode); break; case 0xfb: NOP(opcode); break; // 0xc0 case 0x0c: SHAD(opcode); break; case 0x1c: SHAD(opcode); break; case 0x2c: SHAD(opcode); break; case 0x3c: SHAD(opcode); break; case 0x4c: SHAD(opcode); break; case 0x5c: SHAD(opcode); break; case 0x6c: SHAD(opcode); break; case 0x7c: SHAD(opcode); break; case 0x8c: SHAD(opcode); break; case 0x9c: SHAD(opcode); break; case 0xac: SHAD(opcode); break; case 0xbc: SHAD(opcode); break; case 0xcc: SHAD(opcode); break; case 0xdc: SHAD(opcode); break; case 0xec: SHAD(opcode); break; case 0xfc: SHAD(opcode); break; // 0xd0 case 0x0d: SHLD(opcode); break; case 0x1d: SHLD(opcode); break; case 0x2d: SHLD(opcode); break; case 0x3d: SHLD(opcode); break; case 0x4d: SHLD(opcode); break; case 0x5d: SHLD(opcode); break; case 0x6d: SHLD(opcode); break; case 0x7d: SHLD(opcode); break; case 0x8d: SHLD(opcode); break; case 0x9d: SHLD(opcode); break; case 0xad: SHLD(opcode); break; case 0xbd: SHLD(opcode); break; case 0xcd: SHLD(opcode); break; case 0xdd: SHLD(opcode); break; case 0xed: SHLD(opcode); break; case 0xfd: SHLD(opcode); break; // 0xe0 case 0x0e: LDCSR(opcode); break; case 0x1e: LDCGBR(opcode); break; case 0x2e: LDCVBR(opcode); break; case 0x3e: LDCSSR(opcode); break; case 0x4e: LDCSPC(opcode); break; case 0x5e: NOP(opcode); break; case 0x6e: NOP(opcode); break; case 0x7e: NOP(opcode); break; case 0x8e: LDCRBANK(opcode); break; case 0x9e: LDCRBANK(opcode); break; case 0xae: LDCRBANK(opcode); break; case 0xbe: LDCRBANK(opcode); break; case 0xce: LDCRBANK(opcode); break; case 0xde: LDCRBANK(opcode); break; case 0xee: LDCRBANK(opcode); break; case 0xfe: LDCRBANK(opcode); break; // 0xf0 case 0x0f: MAC_W(opcode); break; case 0x1f: MAC_W(opcode); break; case 0x2f: MAC_W(opcode); break; case 0x3f: MAC_W(opcode); break; case 0x4f: MAC_W(opcode); break; case 0x5f: MAC_W(opcode); break; case 0x6f: MAC_W(opcode); break; case 0x7f: MAC_W(opcode); break; case 0x8f: MAC_W(opcode); break; case 0x9f: MAC_W(opcode); break; case 0xaf: MAC_W(opcode); break; case 0xbf: MAC_W(opcode); break; case 0xcf: MAC_W(opcode); break; case 0xdf: MAC_W(opcode); break; case 0xef: MAC_W(opcode); break; case 0xff: MAC_W(opcode); break; } } inline void sh34_base_device::execute_one(const uint16_t opcode) { switch(opcode & 0xf000) { case 0x0000: execute_one_0000(opcode); break; case 0x1000: MOVLS4(opcode); break; case 0x2000: switch(opcode & 0x0f) { case 0x00: MOVBS(opcode); break; case 0x01: MOVWS(opcode); break; case 0x02: MOVLS(opcode); break; case 0x03: NOP(opcode); break; case 0x04: MOVBM(opcode); break; case 0x05: MOVWM(opcode); break; case 0x06: MOVLM(opcode); break; case 0x07: DIV0S(opcode); break; case 0x08: TST(opcode); break; case 0x09: AND(opcode); break; case 0x0a: XOR(opcode); break; case 0x0b: OR(opcode); break; case 0x0c: CMPSTR(opcode); break; case 0x0d: XTRCT(opcode); break; case 0x0e: MULU(opcode); break; case 0x0f: MULS(opcode); break; } break; case 0x3000: switch(opcode & 0x0f) { case 0x00: CMPEQ(opcode); break; case 0x01: NOP(opcode); break; case 0x02: CMPHS(opcode); break; case 0x03: CMPGE(opcode); break; case 0x04: DIV1(opcode); break; case 0x05: DMULU(opcode); break; case 0x06: CMPHI(opcode); break; case 0x07: CMPGT(opcode); break; case 0x08: SUB(opcode); break; case 0x09: NOP(opcode); break; case 0x0a: SUBC(opcode); break; case 0x0b: SUBV(opcode); break; case 0x0c: ADD(opcode); break; case 0x0d: DMULS(opcode); break; case 0x0e: ADDC(opcode); break; case 0x0f: ADDV(opcode); break; } break; case 0x4000: execute_one_4000(opcode); break; case 0x5000: MOVLL4(opcode); break; case 0x6000: switch(opcode & 0x0f) { case 0x00: MOVBL(opcode); break; case 0x01: MOVWL(opcode); break; case 0x02: MOVLL(opcode); break; case 0x03: MOV(opcode); break; case 0x04: MOVBP(opcode); break; case 0x05: MOVWP(opcode); break; case 0x06: MOVLP(opcode); break; case 0x07: NOT(opcode); break; case 0x08: SWAPB(opcode); break; case 0x09: SWAPW(opcode); break; case 0x0a: NEGC(opcode); break; case 0x0b: NEG(opcode); break; case 0x0c: EXTUB(opcode); break; case 0x0d: EXTUW(opcode); break; case 0x0e: EXTSB(opcode); break; case 0x0f: EXTSW(opcode); break; } break; case 0x7000: ADDI(opcode); break; case 0x8000: switch((opcode >> 8) & 0x0f) { case 0x00: MOVBS4(opcode); break; case 0x01: MOVWS4(opcode); break; case 0x02: NOP(opcode); break; case 0x03: NOP(opcode); break; case 0x04: MOVBL4(opcode); break; case 0x05: MOVWL4(opcode); break; case 0x06: NOP(opcode); break; case 0x07: NOP(opcode); break; case 0x08: CMPIM(opcode); break; case 0x09: BT(opcode); break; case 0x0a: NOP(opcode); break; case 0x0b: BF(opcode); break; case 0x0c: NOP(opcode); break; case 0x0d: BTS(opcode); break; case 0x0e: NOP(opcode); break; case 0x0f: BFS(opcode); break; } break; case 0x9000: MOVWI(opcode); break; case 0xa000: BRA(opcode); break; case 0xb000: BSR(opcode); break; case 0xc000: switch((opcode >> 8) & 0x0f) { case 0x00: MOVBSG(opcode); break; case 0x01: MOVWSG(opcode); break; case 0x02: MOVLSG(opcode); break; case 0x03: TRAPA(opcode); break; case 0x04: MOVBLG(opcode); break; case 0x05: MOVWLG(opcode); break; case 0x06: MOVLLG(opcode); break; case 0x07: MOVA(opcode); break; case 0x08: TSTI(opcode); break; case 0x09: ANDI(opcode); break; case 0x0a: XORI(opcode); break; case 0x0b: ORI(opcode); break; case 0x0c: TSTM(opcode); break; case 0x0d: ANDM(opcode); break; case 0x0e: XORM(opcode); break; case 0x0f: ORM(opcode); break; } break; case 0xd000: MOVLI(opcode); break; case 0xe000: MOVI(opcode); break; case 0xf000: switch(opcode & 0x0f) { case 0x00: FADD(opcode); break; case 0x01: FSUB(opcode); break; case 0x02: FMUL(opcode); break; case 0x03: FDIV(opcode); break; case 0x04: FCMP_EQ(opcode); break; case 0x05: FCMP_GT(opcode); break; case 0x06: FMOVS0FR(opcode); break; case 0x07: FMOVFRS0(opcode); break; case 0x08: FMOVMRFR(opcode); break; case 0x09: FMOVMRIFR(opcode); break; case 0x0a: FMOVFRMR(opcode); break; case 0x0b: FMOVFRMDR(opcode); break; case 0x0c: FMOVFR(opcode); break; case 0x0d: op1111_0x13(opcode); break; case 0x0e: FMAC(opcode); break; case 0x0f: dbreak(opcode); break; } break; } } /* Execute cycles - returns number of cycles actually run */ void sh34_base_device::execute_run() { if (m_cpu_off) { m_sh4_icount = 0; return; } do { m_ppc = m_pc & AM; debugger_instruction_hook(this, m_pc & AM); const uint16_t opcode = m_direct->read_word(m_pc & AM, WORD2_XOR_LE(0)); if (m_delay) { m_pc = m_delay; m_delay = 0; } else m_pc += 2; execute_one(opcode); if (m_test_irq && !m_delay) { sh4_check_pending_irq("mame_sh4_execute"); } m_sh4_icount--; } while( m_sh4_icount > 0 ); } void sh3be_device::execute_run() { if (m_cpu_off) { m_sh4_icount = 0; return; } do { m_ppc = m_pc & AM; debugger_instruction_hook(this, m_pc & AM); const uint16_t opcode = m_direct->read_word(m_pc & AM, WORD_XOR_LE(6)); if (m_delay) { m_pc = m_delay; m_delay = 0; } else m_pc += 2; execute_one(opcode); if (m_test_irq && !m_delay) { sh4_check_pending_irq("mame_sh4_execute"); } m_sh4_icount--; } while( m_sh4_icount > 0 ); } void sh4be_device::execute_run() { if (m_cpu_off) { m_sh4_icount = 0; return; } do { m_ppc = m_pc & AM; debugger_instruction_hook(this, m_pc & AM); const uint16_t opcode = m_direct->read_word(m_pc & AM, WORD_XOR_LE(6)); if (m_delay) { m_pc = m_delay; m_delay = 0; } else m_pc += 2; execute_one(opcode); if (m_test_irq && !m_delay) { sh4_check_pending_irq("mame_sh4_execute"); } m_sh4_icount--; } while( m_sh4_icount > 0 ); } void sh34_base_device::device_start() { for (int i=0; i<3; i++) { m_timer[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh34_base_device::sh4_timer_callback), this)); m_timer[i]->adjust(attotime::never, i); } for (int i=0; i<4; i++) { m_dma_timer[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh34_base_device::sh4_dmac_callback), this)); m_dma_timer[i]->adjust(attotime::never, i); } m_refresh_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh34_base_device::sh4_refresh_timer_callback), this)); m_refresh_timer->adjust(attotime::never); m_refresh_timer_base = 0; m_rtc_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(sh34_base_device::sh4_rtc_timer_callback), this)); m_rtc_timer->adjust(attotime::never); sh4_parse_configuration(); m_internal = &space(AS_PROGRAM); m_program = &space(AS_PROGRAM); m_io = &space(AS_IO); m_direct = &m_program->direct(); sh4_default_exception_priorities(); m_irln = 15; m_test_irq = 0; save_item(NAME(m_pc)); save_item(NAME(m_r)); save_item(NAME(m_sr)); save_item(NAME(m_pr)); save_item(NAME(m_gbr)); save_item(NAME(m_vbr)); save_item(NAME(m_mach)); save_item(NAME(m_macl)); save_item(NAME(m_spc)); save_item(NAME(m_ssr)); save_item(NAME(m_sgr)); save_item(NAME(m_fpscr)); save_item(NAME(m_rbnk)); save_item(NAME(m_fr)); save_item(NAME(m_xf)); save_item(NAME(m_ea)); save_item(NAME(m_delay)); save_item(NAME(m_cpu_off)); save_item(NAME(m_pending_irq)); save_item(NAME(m_test_irq)); save_item(NAME(m_fpul)); save_item(NAME(m_dbr)); save_item(NAME(m_exception_priority)); save_item(NAME(m_exception_requesting)); save_item(NAME(m_irq_line_state)); save_item(NAME(m_m)); save_item(NAME(m_SH4_TSTR)); save_item(NAME(m_SH4_TCNT0)); save_item(NAME(m_SH4_TCNT1)); save_item(NAME(m_SH4_TCNT2)); save_item(NAME(m_SH4_TCR0)); save_item(NAME(m_SH4_TCR1)); save_item(NAME(m_SH4_TCR2)); save_item(NAME(m_SH4_TCOR0)); save_item(NAME(m_SH4_TCOR1)); save_item(NAME(m_SH4_TCOR2)); save_item(NAME(m_SH4_TOCR)); save_item(NAME(m_SH4_TCPR2)); save_item(NAME(m_SH4_IPRA)); save_item(NAME(m_SH4_IPRC)); save_item(NAME(m_SH4_DAR0)); save_item(NAME(m_SH4_DAR1)); save_item(NAME(m_SH4_DAR2)); save_item(NAME(m_SH4_DAR3)); save_item(NAME(m_SH4_CHCR0)); save_item(NAME(m_SH4_CHCR1)); save_item(NAME(m_SH4_CHCR2)); save_item(NAME(m_SH4_CHCR3)); save_item(NAME(m_SH4_DMATCR0)); save_item(NAME(m_SH4_DMATCR1)); save_item(NAME(m_SH4_DMATCR2)); save_item(NAME(m_SH4_DMATCR3)); save_item(NAME(m_SH4_DMAOR)); save_item(NAME(m_nmi_line_state)); save_item(NAME(m_sleep_mode)); save_item(NAME(m_frt_input)); save_item(NAME(m_irln)); save_item(NAME(m_internal_irq_level)); save_item(NAME(m_internal_irq_vector)); save_item(NAME(m_refresh_timer_base)); save_item(NAME(m_dma_timer_active)); save_item(NAME(m_dma_source)); save_item(NAME(m_dma_destination)); save_item(NAME(m_dma_count)); save_item(NAME(m_dma_wordsize)); save_item(NAME(m_dma_source_increment)); save_item(NAME(m_dma_destination_increment)); save_item(NAME(m_dma_mode)); save_item(NAME(m_sh4_icount)); save_item(NAME(m_fpu_sz)); save_item(NAME(m_fpu_pr)); save_item(NAME(m_ioport16_pullup)); save_item(NAME( m_ioport16_direction)); save_item(NAME(m_ioport4_pullup)); save_item(NAME(m_ioport4_direction)); save_item(NAME(m_sh4_tlb_address)); save_item(NAME(m_sh4_tlb_data)); save_item(NAME(m_sh4_mmu_enabled)); save_item(NAME(m_sh3internal_upper)); save_item(NAME(m_sh3internal_lower)); // Debugger state state_add(SH4_PC, "PC", m_pc).formatstr("%08X").callimport(); state_add(SH4_SR, "SR", m_sr).formatstr("%08X").callimport(); state_add(SH4_PR, "PR", m_pr).formatstr("%08X"); state_add(SH4_GBR, "GBR", m_gbr).formatstr("%08X"); state_add(SH4_VBR, "VBR", m_vbr).formatstr("%08X"); state_add(SH4_DBR, "DBR", m_dbr).formatstr("%08X"); state_add(SH4_MACH, "MACH", m_mach).formatstr("%08X"); state_add(SH4_MACL, "MACL", m_macl).formatstr("%08X"); state_add(SH4_R0, "R0", m_r[ 0]).formatstr("%08X"); state_add(SH4_R1, "R1", m_r[ 1]).formatstr("%08X"); state_add(SH4_R2, "R2", m_r[ 2]).formatstr("%08X"); state_add(SH4_R3, "R3", m_r[ 3]).formatstr("%08X"); state_add(SH4_R4, "R4", m_r[ 4]).formatstr("%08X"); state_add(SH4_R5, "R5", m_r[ 5]).formatstr("%08X"); state_add(SH4_R6, "R6", m_r[ 6]).formatstr("%08X"); state_add(SH4_R7, "R7", m_r[ 7]).formatstr("%08X"); state_add(SH4_R8, "R8", m_r[ 8]).formatstr("%08X"); state_add(SH4_R9, "R9", m_r[ 9]).formatstr("%08X"); state_add(SH4_R10, "R10", m_r[10]).formatstr("%08X"); state_add(SH4_R11, "R11", m_r[11]).formatstr("%08X"); state_add(SH4_R12, "R12", m_r[12]).formatstr("%08X"); state_add(SH4_R13, "R13", m_r[13]).formatstr("%08X"); state_add(SH4_R14, "R14", m_r[14]).formatstr("%08X"); state_add(SH4_R15, "R15", m_r[15]).formatstr("%08X"); state_add(SH4_EA, "EA", m_ea).formatstr("%08X"); state_add(SH4_R0_BK0, "R0 BK 0", m_rbnk[0][0]).formatstr("%08X"); state_add(SH4_R1_BK0, "R1 BK 0", m_rbnk[0][1]).formatstr("%08X"); state_add(SH4_R2_BK0, "R2 BK 0", m_rbnk[0][2]).formatstr("%08X"); state_add(SH4_R3_BK0, "R3 BK 0", m_rbnk[0][3]).formatstr("%08X"); state_add(SH4_R4_BK0, "R4 BK 0", m_rbnk[0][4]).formatstr("%08X"); state_add(SH4_R5_BK0, "R5 BK 0", m_rbnk[0][5]).formatstr("%08X"); state_add(SH4_R6_BK0, "R6 BK 0", m_rbnk[0][6]).formatstr("%08X"); state_add(SH4_R7_BK0, "R7 BK 0", m_rbnk[0][7]).formatstr("%08X"); state_add(SH4_R0_BK1, "R0 BK 1", m_rbnk[1][0]).formatstr("%08X"); state_add(SH4_R1_BK1, "R1 BK 1", m_rbnk[1][1]).formatstr("%08X"); state_add(SH4_R2_BK1, "R2 BK 1", m_rbnk[1][2]).formatstr("%08X"); state_add(SH4_R3_BK1, "R3 BK 1", m_rbnk[1][3]).formatstr("%08X"); state_add(SH4_R4_BK1, "R4 BK 1", m_rbnk[1][4]).formatstr("%08X"); state_add(SH4_R5_BK1, "R5 BK 1", m_rbnk[1][5]).formatstr("%08X"); state_add(SH4_R6_BK1, "R6 BK 1", m_rbnk[1][6]).formatstr("%08X"); state_add(SH4_R7_BK1, "R7 BK 1", m_rbnk[1][7]).formatstr("%08X"); state_add(SH4_SPC, "SPC", m_spc).formatstr("%08X"); state_add(SH4_SSR, "SSR", m_ssr).formatstr("%08X"); state_add(SH4_SGR, "SGR", m_sgr).formatstr("%08X"); state_add(SH4_FPSCR, "FPSCR", m_fpscr).formatstr("%08X"); state_add(SH4_FPUL, "FPUL", m_fpul).formatstr("%08X"); state_add(SH4_FR0, "FR0", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_FR1, "FR1", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_FR2, "FR2", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_FR3, "FR3", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_FR4, "FR4", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_FR5, "FR5", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_FR6, "FR6", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_FR7, "FR7", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_FR8, "FR8", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_FR9, "FR9", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_FR10, "FR10", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_FR11, "FR11", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_FR12, "FR12", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_FR13, "FR13", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_FR14, "FR14", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_FR15, "FR15", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_XF0, "XF0", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_XF1, "XF1", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_XF2, "XF2", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_XF3, "XF3", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_XF4, "XF4", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_XF5, "XF5", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_XF6, "XF6", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_XF7, "XF7", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_XF8, "XF8", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_XF9, "XF9", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_XF10, "XF10", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_XF11, "XF11", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_XF12, "XF12", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_XF13, "XF13", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_XF14, "XF14", m_debugger_temp).callimport().formatstr("%25s"); state_add(SH4_XF15, "XF15", m_debugger_temp).callimport().formatstr("%25s"); state_add(STATE_GENPC, "GENPC", m_debugger_temp).callimport().callexport().noshow(); state_add(STATE_GENPCBASE, "CURPC", m_ppc).noshow(); state_add(STATE_GENSP, "GENSP", m_r[15]).noshow(); state_add(STATE_GENFLAGS, "GENFLAGS", m_sr).formatstr("%20s").noshow(); m_icountptr = &m_sh4_icount; } void sh34_base_device::state_import(const device_state_entry &entry) { #ifdef LSB_FIRST uint8_t fpu_xor = m_fpu_pr; #else uint8_t fpu_xor = 0; #endif switch (entry.index()) { case STATE_GENPC: m_pc = m_debugger_temp; case SH4_PC: m_delay = 0; break; case SH4_SR: sh4_exception_recompute(); sh4_check_pending_irq("sh4_set_info"); break; case SH4_FR0: m_fr[0 ^ fpu_xor] = m_debugger_temp; break; case SH4_FR1: m_fr[1 ^ fpu_xor] = m_debugger_temp; break; case SH4_FR2: m_fr[2 ^ fpu_xor] = m_debugger_temp; break; case SH4_FR3: m_fr[3 ^ fpu_xor] = m_debugger_temp; break; case SH4_FR4: m_fr[4 ^ fpu_xor] = m_debugger_temp; break; case SH4_FR5: m_fr[5 ^ fpu_xor] = m_debugger_temp; break; case SH4_FR6: m_fr[6 ^ fpu_xor] = m_debugger_temp; break; case SH4_FR7: m_fr[7 ^ fpu_xor] = m_debugger_temp; break; case SH4_FR8: m_fr[8 ^ fpu_xor] = m_debugger_temp; break; case SH4_FR9: m_fr[9 ^ fpu_xor] = m_debugger_temp; break; case SH4_FR10: m_fr[10 ^ fpu_xor] = m_debugger_temp; break; case SH4_FR11: m_fr[11 ^ fpu_xor] = m_debugger_temp; break; case SH4_FR12: m_fr[12 ^ fpu_xor] = m_debugger_temp; break; case SH4_FR13: m_fr[13 ^ fpu_xor] = m_debugger_temp; break; case SH4_FR14: m_fr[14 ^ fpu_xor] = m_debugger_temp; break; case SH4_FR15: m_fr[15 ^ fpu_xor] = m_debugger_temp; break; case SH4_XF0: m_xf[0 ^ fpu_xor] = m_debugger_temp; break; case SH4_XF1: m_xf[1 ^ fpu_xor] = m_debugger_temp; break; case SH4_XF2: m_xf[2 ^ fpu_xor] = m_debugger_temp; break; case SH4_XF3: m_xf[3 ^ fpu_xor] = m_debugger_temp; break; case SH4_XF4: m_xf[4 ^ fpu_xor] = m_debugger_temp; break; case SH4_XF5: m_xf[5 ^ fpu_xor] = m_debugger_temp; break; case SH4_XF6: m_xf[6 ^ fpu_xor] = m_debugger_temp; break; case SH4_XF7: m_xf[7 ^ fpu_xor] = m_debugger_temp; break; case SH4_XF8: m_xf[8 ^ fpu_xor] = m_debugger_temp; break; case SH4_XF9: m_xf[9 ^ fpu_xor] = m_debugger_temp; break; case SH4_XF10: m_xf[10 ^ fpu_xor] = m_debugger_temp; break; case SH4_XF11: m_xf[11 ^ fpu_xor] = m_debugger_temp; break; case SH4_XF12: m_xf[12 ^ fpu_xor] = m_debugger_temp; break; case SH4_XF13: m_xf[13 ^ fpu_xor] = m_debugger_temp; break; case SH4_XF14: m_xf[14 ^ fpu_xor] = m_debugger_temp; break; case SH4_XF15: m_xf[15 ^ fpu_xor] = m_debugger_temp; break; } } void sh34_base_device::state_export(const device_state_entry &entry) { switch (entry.index()) { case STATE_GENPC: m_debugger_temp = (m_pc & AM); break; } } void sh34_base_device::state_string_export(const device_state_entry &entry, std::string &str) const { #ifdef LSB_FIRST uint8_t fpu_xor = m_fpu_pr; #else uint8_t fpu_xor = 0; #endif switch (entry.index()) { case STATE_GENFLAGS: str = string_format("%s%s%s%s%c%c%d%c%c", m_sr & MD ? "MD ":" ", m_sr & sRB ? "RB ":" ", m_sr & BL ? "BL ":" ", m_sr & FD ? "FD ":" ", m_sr & M ? 'M':'.', m_sr & Q ? 'Q':'.', (m_sr & I) >> 4, m_sr & S ? 'S':'.', m_sr & T ? 'T':'.'); break; case SH4_FR0: str = string_format("%08X %f", m_fr[0 ^ fpu_xor], (double)FP_RFS(0 ^ fpu_xor)); break; case SH4_FR1: str = string_format("%08X %f", m_fr[1 ^ fpu_xor], (double)FP_RFS(1 ^ fpu_xor)); break; case SH4_FR2: str = string_format("%08X %f", m_fr[2 ^ fpu_xor], (double)FP_RFS(2 ^ fpu_xor)); break; case SH4_FR3: str = string_format("%08X %f", m_fr[3 ^ fpu_xor], (double)FP_RFS(3 ^ fpu_xor)); break; case SH4_FR4: str = string_format("%08X %f", m_fr[4 ^ fpu_xor], (double)FP_RFS(4 ^ fpu_xor)); break; case SH4_FR5: str = string_format("%08X %f", m_fr[5 ^ fpu_xor], (double)FP_RFS(5 ^ fpu_xor)); break; case SH4_FR6: str = string_format("%08X %f", m_fr[6 ^ fpu_xor], (double)FP_RFS(6 ^ fpu_xor)); break; case SH4_FR7: str = string_format("%08X %f", m_fr[7 ^ fpu_xor], (double)FP_RFS(7 ^ fpu_xor)); break; case SH4_FR8: str = string_format("%08X %f", m_fr[8 ^ fpu_xor], (double)FP_RFS(8 ^ fpu_xor)); break; case SH4_FR9: str = string_format("%08X %f", m_fr[9 ^ fpu_xor], (double)FP_RFS(9 ^ fpu_xor)); break; case SH4_FR10: str = string_format("%08X %f", m_fr[10 ^ fpu_xor], (double)FP_RFS(10 ^ fpu_xor)); break; case SH4_FR11: str = string_format("%08X %f", m_fr[11 ^ fpu_xor], (double)FP_RFS(11 ^ fpu_xor)); break; case SH4_FR12: str = string_format("%08X %f", m_fr[12 ^ fpu_xor], (double)FP_RFS(12 ^ fpu_xor)); break; case SH4_FR13: str = string_format("%08X %f", m_fr[13 ^ fpu_xor], (double)FP_RFS(13 ^ fpu_xor)); break; case SH4_FR14: str = string_format("%08X %f", m_fr[14 ^ fpu_xor], (double)FP_RFS(14 ^ fpu_xor)); break; case SH4_FR15: str = string_format("%08X %f", m_fr[15 ^ fpu_xor], (double)FP_RFS(15 ^ fpu_xor)); break; case SH4_XF0: str = string_format("%08X %f", m_xf[0 ^ fpu_xor], (double)FP_XFS(0 ^ fpu_xor)); break; case SH4_XF1: str = string_format("%08X %f", m_xf[1 ^ fpu_xor], (double)FP_XFS(1 ^ fpu_xor)); break; case SH4_XF2: str = string_format("%08X %f", m_xf[2 ^ fpu_xor], (double)FP_XFS(2 ^ fpu_xor)); break; case SH4_XF3: str = string_format("%08X %f", m_xf[3 ^ fpu_xor], (double)FP_XFS(3 ^ fpu_xor)); break; case SH4_XF4: str = string_format("%08X %f", m_xf[4 ^ fpu_xor], (double)FP_XFS(4 ^ fpu_xor)); break; case SH4_XF5: str = string_format("%08X %f", m_xf[5 ^ fpu_xor], (double)FP_XFS(5 ^ fpu_xor)); break; case SH4_XF6: str = string_format("%08X %f", m_xf[6 ^ fpu_xor], (double)FP_XFS(6 ^ fpu_xor)); break; case SH4_XF7: str = string_format("%08X %f", m_xf[7 ^ fpu_xor], (double)FP_XFS(7 ^ fpu_xor)); break; case SH4_XF8: str = string_format("%08X %f", m_xf[8 ^ fpu_xor], (double)FP_XFS(8 ^ fpu_xor)); break; case SH4_XF9: str = string_format("%08X %f", m_xf[9 ^ fpu_xor], (double)FP_XFS(9 ^ fpu_xor)); break; case SH4_XF10: str = string_format("%08X %f", m_xf[10 ^ fpu_xor], (double)FP_XFS(10 ^ fpu_xor)); break; case SH4_XF11: str = string_format("%08X %f", m_xf[11 ^ fpu_xor], (double)FP_XFS(11 ^ fpu_xor)); break; case SH4_XF12: str = string_format("%08X %f", m_xf[12 ^ fpu_xor], (double)FP_XFS(12 ^ fpu_xor)); break; case SH4_XF13: str = string_format("%08X %f", m_xf[13 ^ fpu_xor], (double)FP_XFS(13 ^ fpu_xor)); break; case SH4_XF14: str = string_format("%08X %f", m_xf[14 ^ fpu_xor], (double)FP_XFS(14 ^ fpu_xor)); break; case SH4_XF15: str = string_format("%08X %f", m_xf[15 ^ fpu_xor], (double)FP_XFS(15 ^ fpu_xor)); break; } } void sh34_base_device::sh4_set_ftcsr_callback(sh4_ftcsr_callback callback) { m_ftcsr_read_callback = callback; }