diff options
Diffstat (limited to 'src/devices/cpu/i960/i960.cpp')
-rw-r--r-- | src/devices/cpu/i960/i960.cpp | 116 |
1 files changed, 72 insertions, 44 deletions
diff --git a/src/devices/cpu/i960/i960.cpp b/src/devices/cpu/i960/i960.cpp index ae17f211aba..9d9e5293a67 100644 --- a/src/devices/cpu/i960/i960.cpp +++ b/src/devices/cpu/i960/i960.cpp @@ -3,7 +3,6 @@ #include "emu.h" #include "i960.h" #include "i960dis.h" -#include "debugger.h" #ifdef _MSC_VER /* logb prototype is different for MS Visual C */ @@ -18,7 +17,7 @@ DEFINE_DEVICE_TYPE(I960, i960_cpu_device, "i960kb", "Intel i960KB") i960_cpu_device::i960_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : cpu_device(mconfig, I960, tag, owner, clock) , m_stalled(false), m_program_config("program", ENDIANNESS_LITTLE, 32, 32, 0) - , m_rcache_pos(0), m_SAT(0), m_PRCB(0), m_PC(0), m_AC(0), m_IP(0), m_PIP(0), m_ICR(0), m_bursting(0), m_immediate_irq(0) + , m_rcache_pos(0), m_SAT(0), m_PRCB(0), m_PC(0), m_AC(0), m_IP(0), m_PIP(0), m_ICR(0), m_immediate_irq(0) , m_immediate_vector(0), m_immediate_pri(0), m_icount(0) { std::fill(std::begin(m_r), std::end(m_r), 0); @@ -46,6 +45,15 @@ uint32_t i960_cpu_device::i960_read_dword_unaligned(uint32_t address) return m_program.read_dword(address); } +std::pair<uint32_t, uint16_t> i960_cpu_device::i960_read_dword_unaligned_flags(uint32_t address) +{ + if (!DWORD_ALIGNED(address)) { + auto v = m_program.read_byte_flags(address); + return std::pair<uint32_t, uint16_t>(v.first | m_program.read_byte(address+1)<<8 | m_program.read_byte(address+2)<<16 | m_program.read_byte(address+3)<<24, v.second); + } else + return m_program.read_dword_flags(address); +} + uint16_t i960_cpu_device::i960_read_word_unaligned(uint32_t address) { if (!WORD_ALIGNED(address)) @@ -69,6 +77,22 @@ void i960_cpu_device::i960_write_dword_unaligned(uint32_t address, uint32_t data } } +uint16_t i960_cpu_device::i960_write_dword_unaligned_flags(uint32_t address, uint32_t data) +{ + if (!DWORD_ALIGNED(address)) + { + uint16_t flags = m_program.write_byte_flags(address, data & 0xff); + m_program.write_byte(address+1, (data>>8)&0xff); + m_program.write_byte(address+2, (data>>16)&0xff); + m_program.write_byte(address+3, (data>>24)&0xff); + return flags; + } + else + { + return m_program.write_dword_flags(address, data); + } +} + void i960_cpu_device::i960_write_word_unaligned(uint32_t address, uint16_t data) { if (!WORD_ALIGNED(address)) @@ -333,20 +357,12 @@ uint32_t i960_cpu_device::get_2_ci(uint32_t opcode) uint32_t i960_cpu_device::get_disp(uint32_t opcode) { - uint32_t disp; - disp = opcode & 0xffffff; - if(disp & 0x00800000) - disp |= 0xff000000; - return disp-4; + return util::sext(opcode, 24) - 4; } uint32_t i960_cpu_device::get_disp_s(uint32_t opcode) { - uint32_t disp; - disp = opcode & 0x1fff; - if(disp & 0x00001000) - disp |= 0xffffe000; - return disp-4; + return util::sext(opcode, 13) - 4; } void i960_cpu_device::cmp_s(int32_t v1, int32_t v2) @@ -1094,14 +1110,16 @@ void i960_cpu_device::execute_op(uint32_t opcode) m_icount--; t1 = get_1_ri(opcode); t2 = get_2_ri(opcode); - set_ri(opcode, t2>>t1); + set_ri(opcode, t1 >= 32 ? 0 : t2>>t1); break; case 0xa: // shrdi m_icount--; t1 = get_1_ri(opcode); t2 = get_2_ri(opcode); - if(((int32_t)t2) < 0) { + if(t1 >= 32) + set_ri(opcode, 0); + else if(((int32_t)t2) < 0) { if(t2 & ((1<<t1)-1)) set_ri(opcode, (((int32_t)t2)>>t1)+1); else @@ -1114,21 +1132,24 @@ void i960_cpu_device::execute_op(uint32_t opcode) m_icount--; t1 = get_1_ri(opcode); t2 = get_2_ri(opcode); - set_ri(opcode, ((int32_t)t2)>>t1); + if(t1 >= 32) + set_ri(opcode, (int32_t)t2 < 0 ? -1 : 0); + else + set_ri(opcode, ((int32_t)t2)>>t1); break; case 0xc: // shlo m_icount--; t1 = get_1_ri(opcode); t2 = get_2_ri(opcode); - set_ri(opcode, t2<<t1); + set_ri(opcode, t1 >= 32 ? 0 : t2<<t1); break; case 0xd: // rotate m_icount--; t1 = get_1_ri(opcode) & 0x1f; t2 = get_2_ri(opcode); - set_ri(opcode, (t2<<t1)|(t2>>(32-t1))); + set_ri(opcode, rotl_32(t2, t1)); break; case 0xe: // shli @@ -1136,7 +1157,7 @@ void i960_cpu_device::execute_op(uint32_t opcode) m_icount--; t1 = get_1_ri(opcode); t2 = get_2_ri(opcode); - set_ri(opcode, t2<<t1); + set_ri(opcode, (t2 & 0x80000000) | (t1 >= 32 ? 0 : (t2<<t1) & 0x7fffffff)); // sign is preserved break; default: @@ -1430,6 +1451,23 @@ void i960_cpu_device::execute_op(uint32_t opcode) } break; + case 0x4: // dmovt + /* + The dmovt instruction moves a 32-bit word from one register to another + and tests the least-significant byte of the operand to determine if it is a + valid ASCII-coded decimal digit (001100002 through 001110012, + corresponding to the decimal digits 0 through 9). For valid digits, the + condition code (CC) is set to 000; otherwise the condition code is set to + 010. + */ + m_icount -= 7; + t1 = get_1_ri(opcode); + set_ri(opcode, t1); + m_AC &= 0xfff8; + if ((t1 & 0xff) < 0x30 || (t1 & 0xff) > 0x39) + m_AC |= 2; + break; + case 0x5: // modac m_icount -= 10; t1 = get_1_ri(opcode); @@ -2004,16 +2042,15 @@ void i960_cpu_device::execute_op(uint32_t opcode) m_icount -= 5; t1 = get_ea(opcode); t2 = (opcode>>19)&0x1e; - m_bursting = 1; for(i=0; i<2; i++) { - u32 v = i960_read_dword_unaligned(t1); + auto pack = i960_read_dword_unaligned_flags(t1); if(m_stalled) { burst_stall_save(t1,t2,i,2,false); return; } - m_r[t2+i] = v; - if(m_bursting) + m_r[t2+i] = pack.first; + if(pack.second & BURST) t1 += 4; } break; @@ -2024,15 +2061,14 @@ void i960_cpu_device::execute_op(uint32_t opcode) m_icount -= 3; t1 = get_ea(opcode); t2 = (opcode>>19)&0x1e; - m_bursting = 1; for(i=0; i<2; i++) { - i960_write_dword_unaligned(t1, m_r[t2+i]); + auto flags = i960_write_dword_unaligned_flags(t1, m_r[t2+i]); if(m_stalled) { burst_stall_save(t1,t2,i,2,true); return; } - if(m_bursting) + if(flags & BURST) t1 += 4; } break; @@ -2043,16 +2079,15 @@ void i960_cpu_device::execute_op(uint32_t opcode) m_icount -= 6; t1 = get_ea(opcode); t2 = (opcode>>19)&0x1c; - m_bursting = 1; for(i=0; i<3; i++) { - u32 v = i960_read_dword_unaligned(t1); + auto pack = i960_read_dword_unaligned_flags(t1); if(m_stalled) { burst_stall_save(t1,t2,i,3,false); return; } - m_r[t2+i] = v; - if(m_bursting) + m_r[t2+i] = pack.first; + if(pack.second & BURST) t1 += 4; } break; @@ -2063,15 +2098,14 @@ void i960_cpu_device::execute_op(uint32_t opcode) m_icount -= 4; t1 = get_ea(opcode); t2 = (opcode>>19)&0x1c; - m_bursting = 1; for(i=0; i<3; i++) { - i960_write_dword_unaligned(t1, m_r[t2+i]); + auto flags = i960_write_dword_unaligned_flags(t1, m_r[t2+i]); if(m_stalled) { burst_stall_save(t1,t2,i,3,true); return; } - if(m_bursting) + if(flags & BURST) t1 += 4; } break; @@ -2082,16 +2116,15 @@ void i960_cpu_device::execute_op(uint32_t opcode) m_icount -= 7; t1 = get_ea(opcode); t2 = (opcode>>19)&0x1c; - m_bursting = 1; for(i=0; i<4; i++) { - u32 v = i960_read_dword_unaligned(t1); + auto pack = i960_read_dword_unaligned_flags(t1); if(m_stalled) { burst_stall_save(t1,t2,i,4,false); return; } - m_r[t2+i] = v; - if(m_bursting) + m_r[t2+i] = pack.first; + if(pack.second & BURST) t1 += 4; } break; @@ -2102,15 +2135,14 @@ void i960_cpu_device::execute_op(uint32_t opcode) m_icount -= 5; t1 = get_ea(opcode); t2 = (opcode>>19)&0x1c; - m_bursting = 1; for(i=0; i<4; i++) { - i960_write_dword_unaligned(t1, m_r[t2+i]); + auto flags = i960_write_dword_unaligned_flags(t1, m_r[t2+i]); if(m_stalled) { burst_stall_save(t1,t2,i,4,true); return; } - if(m_bursting) + if(flags & BURST) t1 += 4; } break; @@ -2160,8 +2192,6 @@ void i960_cpu_device::execute_run() m_PIP = m_IP; debugger_instruction_hook(m_IP); - m_bursting = 0; - opcode = m_cache.read_dword(m_IP); m_IP += 4; @@ -2238,7 +2268,7 @@ void i960_cpu_device::execute_set_input(int irqline, int state) } // and ack it to the core now that it's queued - standard_irq_callback(irqline); + standard_irq_callback(irqline, m_IP); } } @@ -2263,7 +2293,6 @@ void i960_cpu_device::device_start() save_item(NAME(m_immediate_irq)); save_item(NAME(m_immediate_vector)); save_item(NAME(m_immediate_pri)); - save_item(NAME(m_bursting)); save_item(NAME(m_stalled)); save_item(NAME(m_stall_state.index)); save_item(NAME(m_stall_state.size)); @@ -2347,7 +2376,6 @@ void i960_cpu_device::device_reset() m_PC = 0x001f2002; m_AC = 0; m_ICR = 0xff000000; - m_bursting = 0; m_immediate_irq = 0; memset(m_r, 0, sizeof(m_r)); |