summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/i960/i960.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/i960/i960.cpp')
-rw-r--r--src/devices/cpu/i960/i960.cpp116
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));