diff options
author | R. Belmont <rb6502@users.noreply.github.com> | 2017-11-17 09:15:00 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-11-17 09:15:00 -0500 |
commit | e8e9cbe6c2b5a73053bb327405c41cb42717e289 (patch) | |
tree | bd8da767b74229330de606620e19c078e2f5da9c | |
parent | c5028af1e5e1784e5b892c9042a2d2daa84fc243 (diff) | |
parent | 3873ba65ad3728038115de7ddd476fc971644035 (diff) |
Merge pull request #2815 from pmackinlay/interpro
interpro: clipper floating point improvements and use new 28f010 flash memory
-rw-r--r-- | src/devices/cpu/clipper/clipper.cpp | 454 | ||||
-rw-r--r-- | src/devices/cpu/clipper/clipper.h | 54 | ||||
-rw-r--r-- | src/mame/drivers/interpro.cpp | 54 | ||||
-rw-r--r-- | src/mame/includes/interpro.h | 30 |
4 files changed, 399 insertions, 193 deletions
diff --git a/src/devices/cpu/clipper/clipper.cpp b/src/devices/cpu/clipper/clipper.cpp index c2d057d8d35..d7498beb6f2 100644 --- a/src/devices/cpu/clipper/clipper.cpp +++ b/src/devices/cpu/clipper/clipper.cpp @@ -4,12 +4,11 @@ /* * An implementation of the Fairchild/Intergraph CLIPPER CPU family. * - * Primary source: http://bitsavers.trailing-edge.com/pdf/fairchild/clipper/Clipper_Instruction_Set_Oct85.pdf + * Primary source: http://bitsavers.org/pdf/fairchild/clipper/Clipper_Instruction_Set_Oct85.pdf * * TODO: * - save/restore state - * - unimplemented instructions - * - C100, C300, C400 variants + * - unimplemented C400 instructions * - correct boot logic * - condition codes for multiply instructions * - most cpu traps/faults @@ -119,6 +118,8 @@ void clipper_device::device_start() save_item(NAME(m_ru)); save_item(NAME(m_rs)); save_item(NAME(m_f)); + save_item(NAME(m_fp_pc)); + save_item(NAME(m_fp_dst)); save_item(NAME(m_nmi)); save_item(NAME(m_irq)); @@ -181,14 +182,14 @@ void clipper_device::device_reset() * ssw: EI, TP, M, U, K, KU, UU, P cleared, ID set from hardware, others undefined */ m_psw = 0; + float_rounding_mode = float_round_nearest_even; + + // clear the ssw set_ssw(0); + // select the register file according to the ssw m_r = SSW(U) ? m_ru : m_rs; - // we'll opt to clear the integer and floating point registers too - memset(m_r, 0, sizeof(s32)*16); - memset(m_f, 0, sizeof(m_f)); - // FIXME: figure out how to branch to the boot code properly m_pc = 0x7f100000; m_irq = CLEAR_LINE; @@ -248,9 +249,16 @@ void clipper_device::execute_run() // decode instruction decode_instruction(insn); + // clear floating point exceptions + float_exception_flags = 0; + // execute instruction, return next pc m_pc = execute_instruction(); + // handle floating point exceptions + if (float_exception_flags) + fp_exception(); + // FIXME: some instructions take longer (significantly) than one cycle // and also the timings are often slower for the C100 and C300 m_icount--; @@ -321,8 +329,8 @@ void clipper_device::decode_instruction (u16 insn) } else { - // fetch 32 bit immediate and sign extend - m_info.imm = (s32)m_insn->read_dword_unaligned(m_pc + 2); + // fetch 32 bit immediate + m_info.imm = m_insn->read_dword_unaligned(m_pc + 2); m_info.size = 6; } } @@ -337,7 +345,7 @@ void clipper_device::decode_instruction (u16 insn) switch (insn & 0x00f0) { case ADDR_MODE_PC32: - m_info.address = m_pc + (s32)m_insn->read_dword_unaligned(m_pc + 2); + m_info.address = m_pc + m_insn->read_dword_unaligned(m_pc + 2); m_info.size = 6; break; @@ -348,7 +356,7 @@ void clipper_device::decode_instruction (u16 insn) case ADDR_MODE_REL32: m_info.r2 = m_insn->read_word(m_pc + 2) & 0xf; - m_info.address = m_r[insn & 0xf] + (s32)m_insn->read_dword_unaligned(m_pc + 4); + m_info.address = m_r[insn & 0xf] + m_insn->read_dword_unaligned(m_pc + 4); m_info.size = 8; break; @@ -429,7 +437,10 @@ int clipper_device::execute_instruction () // treated as a noop if target ssw in user mode // R1 == 3 means "fast" mode - avoids pipeline flush if (R1 == 0) + { m_psw = m_r[R2]; + fp_rounding(); + } else if (!SSW(U) && (R1 == 1 || R1 == 3)) { set_ssw(m_r[R2]); @@ -471,229 +482,242 @@ int clipper_device::execute_instruction () case 0x20: // adds: add single floating - *((float *)&m_f[R2]) += *((float *)&m_f[R1]); + set_fp32(R2, float32_add(get_fp32(R2), get_fp32(R1))); // TRAPS: F_IVUX + float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_underflow | float_flag_inexact); break; case 0x21: // subs: subtract single floating - *((float *)&m_f[R2]) -= *((float *)&m_f[R1]); + set_fp32(R2, float32_sub(get_fp32(R2), get_fp32(R1))); // TRAPS: F_IVUX + float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_underflow | float_flag_inexact); break; case 0x22: // addd: add double floating - m_f[R2] += m_f[R1]; + set_fp64(R2, float64_add(get_fp64(R2), get_fp64(R1))); // TRAPS: F_IVUX + float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_underflow | float_flag_inexact); break; case 0x23: // subd: subtract double floating - m_f[R2] -= m_f[R1]; + set_fp64(R2, float64_sub(get_fp64(R2), get_fp64(R1))); // TRAPS: F_IVUX + float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_underflow | float_flag_inexact); break; case 0x24: // movs: move single floating - *((float *)&m_f[R2]) = *((float *)&m_f[R1]); + set_fp32(R2, get_fp32(R1)); break; case 0x25: // cmps: compare single floating - FLAGS(0, 0, *((float *)&m_f[R2]) == *((float *)&m_f[R1]), *((float *)&m_f[R2]) < *((float *)&m_f[R1])) + FLAGS(0, 0, float32_eq(get_fp32(R2), get_fp32(R1)), float32_lt(get_fp32(R2), get_fp32(R1))) + if (float_exception_flags & float_flag_invalid) + m_psw |= PSW_Z | PSW_N; + float_exception_flags &= (0); break; case 0x26: // movd: move double floating - m_f[R2] = m_f[R1]; + set_fp64(R2, get_fp64(R1)); break; case 0x27: // cmpd: compare double floating - FLAGS(0, 0, m_f[R2] == m_f[R1], m_f[R2] < m_f[R1]) - // FLAGS: 00ZN + FLAGS(0, 0, float64_eq(get_fp64(R2), get_fp64(R1)), float64_lt(get_fp64(R2), get_fp64(R1))) + if (float_exception_flags & float_flag_invalid) + m_psw |= PSW_Z | PSW_N; + float_exception_flags &= (0); break; case 0x28: // muls: multiply single floating - *((float *)&m_f[R2]) *= *((float *)&m_f[R1]); + set_fp32(R2, float32_mul(get_fp32(R2), get_fp32(R1))); // TRAPS: F_IVUX + float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_underflow | float_flag_inexact); break; case 0x29: // divs: divide single floating - *((float *)&m_f[R2]) /= *((float *)&m_f[R1]); + set_fp32(R2, float32_div(get_fp32(R2), get_fp32(R1))); // TRAPS: F_IVDUX + float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_divbyzero | float_flag_underflow | float_flag_inexact); break; case 0x2a: // muld: multiply double floating - m_f[R2] *= m_f[R1]; + set_fp64(R2, float64_mul(get_fp64(R2), get_fp64(R1))); // TRAPS: F_IVUX + float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_underflow | float_flag_inexact); break; case 0x2b: // divd: divide double floating - m_f[R2] /= m_f[R1]; + set_fp64(R2, float64_div(get_fp64(R2), get_fp64(R1))); // TRAPS: F_IVDUX + float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_divbyzero | float_flag_underflow | float_flag_inexact); break; case 0x2c: // movsw: move single floating to word - m_r[R2] = *((s32 *)&m_f[R1]); + m_r[R2] = get_fp32(R1); break; case 0x2d: // movws: move word to single floating - *((s32 *)&m_f[R2]) = m_r[R1]; + set_fp32(R2, m_r[R1]); break; case 0x2e: // movdl: move double floating to longword - ((double *)m_r)[R2 >> 1] = m_f[R1]; + ((u64 *)m_r)[R2 >> 1] = get_fp64(R1); break; case 0x2f: // movld: move longword to double floating - m_f[R2] = ((double *)m_r)[R1 >> 1]; + set_fp64(R2, ((u64 *)m_r)[R1 >> 1]); break; case 0x30: // shaw: shift arithmetic word - if (m_r[R1] > 0) + if ((s32)m_r[R1] > 0) { // save the bits that will be shifted out plus new sign bit - s32 v = m_r[R2] >> (31 - m_r[R1]); + s32 v = (s32)m_r[R2] >> (31 - m_r[R1]); m_r[R2] <<= m_r[R1]; // overflow is set if sign changes during shift - FLAGS(0, v != 0 && v != -1, m_r[R2] == 0, m_r[R2] < 0) + FLAGS(0, v != 0 && v != -1, m_r[R2] == 0, (s32)m_r[R2] < 0) } else { - m_r[R2] >>= -m_r[R1]; - FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0) + ((s32 *)m_r)[R2] >>= -m_r[R1]; + FLAGS(0, 0, m_r[R2] == 0, (s32)m_r[R2] < 0) } // FLAGS: 0VZN break; case 0x31: // shal: shift arithmetic longword - if (m_r[R1] > 0) + if ((s32)m_r[R1] > 0) { // save the bits that will be shifted out plus new sign bit s64 v = ((s64 *)m_r)[R2 >> 1] >> (63 - m_r[R1]); - ((s64 *)m_r)[R2 >> 1] <<= m_r[R1]; + ((u64 *)m_r)[R2 >> 1] <<= m_r[R1]; // overflow is set if sign changes during shift - FLAGS(0, v != 0 && v != -1, ((s64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0) + FLAGS(0, v != 0 && v != -1, ((u64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0) } else { ((s64 *)m_r)[R2 >> 1] >>= -m_r[R1]; - FLAGS(0, 0, ((s64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0) + FLAGS(0, 0, ((u64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0) } // FLAGS: 0VZN break; case 0x32: // shlw: shift logical word - if (m_r[R1] > 0) + if ((s32)m_r[R1] > 0) m_r[R2] <<= m_r[R1]; else - ((u32 *)m_r)[R2] >>= -m_r[R1]; + m_r[R2] >>= -m_r[R1]; // FLAGS: 00ZN - FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0); + FLAGS(0, 0, m_r[R2] == 0, (s32)m_r[R2] < 0); break; case 0x33: // shll: shift logical longword - if (m_r[R1] > 0) + if ((s32)m_r[R1] > 0) ((u64 *)m_r)[R2 >> 1] <<= m_r[R1]; else ((u64 *)m_r)[R2 >> 1] >>= -m_r[R1]; // FLAGS: 00ZN - FLAGS(0, 0, ((s64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0); + FLAGS(0, 0, ((u64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0); break; case 0x34: // rotw: rotate word - if (m_r[R1] > 0) + if ((s32)m_r[R1] > 0) m_r[R2] = rotl32(m_r[R2], m_r[R1]); else m_r[R2] = rotr32(m_r[R2], -m_r[R1]); // FLAGS: 00ZN - FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0); + FLAGS(0, 0, m_r[R2] == 0, (s32)m_r[R2] < 0); break; case 0x35: // rotl: rotate longword - if (m_r[R1] > 0) + if ((s32)m_r[R1] > 0) ((u64 *)m_r)[R2 >> 1] = rotl64(((u64 *)m_r)[R2 >> 1], m_r[R1]); else ((u64 *)m_r)[R2 >> 1] = rotr64(((u64 *)m_r)[R2 >> 1], -m_r[R1]); // FLAGS: 00ZN - FLAGS(0, 0, ((s64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0); + FLAGS(0, 0, ((u64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0); break; case 0x38: // shai: shift arithmetic immediate - if (m_info.imm > 0) + if ((s32)m_info.imm > 0) { // save the bits that will be shifted out plus new sign bit - s32 v = m_r[R2] >> (31 - m_info.imm); + s32 v = (s32)m_r[R2] >> (31 - m_info.imm); m_r[R2] <<= m_info.imm; // overflow is set if sign changes during shift - FLAGS(0, v != 0 && v != -1, m_r[R2] == 0, m_r[R2] < 0) + FLAGS(0, v != 0 && v != -1, m_r[R2] == 0, (s32)m_r[R2] < 0) } else { - m_r[R2] >>= -m_info.imm; - FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0) + ((s32 *)m_r)[R2] >>= -m_info.imm; + FLAGS(0, 0, m_r[R2] == 0, (s32)m_r[R2] < 0) } // FLAGS: 0VZN // TRAPS: I break; case 0x39: // shali: shift arithmetic longword immediate - if (m_info.imm > 0) + if ((s32)m_info.imm > 0) { // save the bits that will be shifted out plus new sign bit s64 v = ((s64 *)m_r)[R2 >> 1] >> (63 - m_info.imm); - ((s64 *)m_r)[R2 >> 1] <<= m_info.imm; + ((u64 *)m_r)[R2 >> 1] <<= m_info.imm; // overflow is set if sign changes during shift - FLAGS(0, v != 0 && v != -1, ((s64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0) + FLAGS(0, v != 0 && v != -1, ((u64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0) } else { ((s64 *)m_r)[R2 >> 1] >>= -m_info.imm; - FLAGS(0, 0, ((s64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0) + FLAGS(0, 0, ((u64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0) } // FLAGS: 0VZN // TRAPS: I break; case 0x3a: // shli: shift logical immediate - if (m_info.imm > 0) + if ((s32)m_info.imm > 0) m_r[R2] <<= m_info.imm; else - ((u32 *)m_r)[R2] >>= -m_info.imm; - FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0); + m_r[R2] >>= -m_info.imm; + FLAGS(0, 0, m_r[R2] == 0, (s32)m_r[R2] < 0); // FLAGS: 00ZN // TRAPS: I break; case 0x3b: // shlli: shift logical longword immediate - if (m_info.imm > 0) + if ((s32)m_info.imm > 0) ((u64 *)m_r)[R2 >> 1] <<= m_info.imm; else ((u64 *)m_r)[R2 >> 1] >>= -m_info.imm; - FLAGS(0, 0, ((s64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0); + FLAGS(0, 0, ((u64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0); // FLAGS: 00ZN // TRAPS: I break; case 0x3c: // roti: rotate immediate - if (m_info.imm > 0) + if ((s32)m_info.imm > 0) m_r[R2] = rotl32(m_r[R2], m_info.imm); else m_r[R2] = rotr32(m_r[R2], -m_info.imm); - FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0); + FLAGS(0, 0, m_r[R2] == 0, (s32)m_r[R2] < 0); // FLAGS: 00ZN // TRAPS: I break; case 0x3d: // rotli: rotate longword immediate - if (m_info.imm > 0) + if ((s32)m_info.imm > 0) ((u64 *)m_r)[R2 >> 1] = rotl64(((u64 *)m_r)[R2 >> 1], m_info.imm); else ((u64 *)m_r)[R2 >> 1] = rotr64(((u64 *)m_r)[R2 >> 1], -m_info.imm); - FLAGS(0, 0, ((s64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0); + FLAGS(0, 0, ((u64 *)m_r)[R2 >> 1] == 0, ((s64 *)m_r)[R2 >> 1] < 0); // FLAGS: 00ZN // TRAPS: I break; @@ -759,13 +783,13 @@ int clipper_device::execute_instruction () case 0x64: case 0x65: // loads: load single floating - ((u64 *)&m_f)[R2] = m_data->read_dword(m_info.address); + set_fp32(R2, m_data->read_dword(m_info.address)); // TRAPS: C,U,A,P,R,I break; case 0x66: case 0x67: // loadd: load double floating - ((u64 *)&m_f)[R2] = m_data->read_qword(m_info.address); + set_fp64(R2, m_data->read_qword(m_info.address)); // TRAPS: C,U,A,P,R,I break; case 0x68: @@ -808,13 +832,13 @@ int clipper_device::execute_instruction () case 0x74: case 0x75: // stors: store single floating - m_data->write_dword(m_info.address, *((u32 *)&m_f[R2])); + m_data->write_dword(m_info.address, get_fp32(R2)); // TRAPS: A,P,W,I break; case 0x76: case 0x77: // stord: store double floating - m_data->write_qword(m_info.address, *((u64 *)&m_f[R2])); + m_data->write_qword(m_info.address, get_fp64(R2)); // TRAPS: A,P,W,I break; case 0x78: @@ -835,7 +859,7 @@ int clipper_device::execute_instruction () // addw: add word FLAGS_CV(C_ADD(m_r[R2], m_r[R1]), V_ADD(m_r[R2], m_r[R1])) m_r[R2] += m_r[R1]; - FLAGS_ZN(m_r[R2] == 0, m_r[R2] < 0) + FLAGS_ZN(m_r[R2] == 0, (s32)m_r[R2] < 0) // FLAGS: CVZN break; @@ -843,21 +867,21 @@ int clipper_device::execute_instruction () // addq: add quick FLAGS_CV(C_ADD(m_r[R2], R1), V_ADD(m_r[R2], R1)) m_r[R2] += R1; - FLAGS_ZN(m_r[R2] == 0, m_r[R2] < 0) + FLAGS_ZN(m_r[R2] == 0, (s32)m_r[R2] < 0) // FLAGS: CVZN break; case 0x83: // addi: add immediate FLAGS_CV(C_ADD(m_r[R2], m_info.imm), V_ADD(m_r[R2], m_info.imm)) m_r[R2] += m_info.imm; - FLAGS_ZN(m_r[R2] == 0, m_r[R2] < 0) + FLAGS_ZN(m_r[R2] == 0, (s32)m_r[R2] < 0) // FLAGS: CVZN // TRAPS: I break; case 0x84: // movw: move word m_r[R2] = m_r[R1]; - FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0) + FLAGS(0, 0, m_r[R2] == 0, (s32)m_r[R2] < 0) // FLAGS: 00ZN break; @@ -870,35 +894,35 @@ int clipper_device::execute_instruction () case 0x87: // loadi: load immediate m_r[R2] = m_info.imm; - FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0) + FLAGS(0, 0, m_r[R2] == 0, (s32)m_r[R2] < 0) // FLAGS: 00ZN // TRAPS: I break; case 0x88: // andw: and word m_r[R2] &= m_r[R1]; - FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0) + FLAGS(0, 0, m_r[R2] == 0, (s32)m_r[R2] < 0) // FLAGS: 00ZN break; case 0x8b: // andi: and immediate m_r[R2] &= m_info.imm; - FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0) + FLAGS(0, 0, m_r[R2] == 0, (s32)m_r[R2] < 0) // FLAGS: 00ZN // TRAPS: I break; case 0x8c: // orw: or word m_r[R2] |= m_r[R1]; - FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0) + FLAGS(0, 0, m_r[R2] == 0, (s32)m_r[R2] < 0) // FLAGS: 00ZN break; case 0x8f: // ori: or immediate m_r[R2] |= m_info.imm; - FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0) + FLAGS(0, 0, m_r[R2] == 0, (s32)m_r[R2] < 0) // FLAGS: 00ZN // TRAPS: I break; @@ -906,14 +930,14 @@ int clipper_device::execute_instruction () // addwc: add word with carry FLAGS_CV(C_ADD(m_r[R2], (m_r[R1] + (PSW(C) ? 1 : 0))), V_ADD(m_r[R2], (m_r[R1] + (PSW(C) ? 1 : 0)))) m_r[R2] += m_r[R1] + (PSW(C) ? 1 : 0); - FLAGS_ZN(m_r[R2] == 0, m_r[R2] < 0) + FLAGS_ZN(m_r[R2] == 0, (s32)m_r[R2] < 0) // FLAGS: CVZN break; case 0x91: // subwc: subtract word with carry FLAGS_CV(C_SUB(m_r[R2], (m_r[R1] + (PSW(C) ? 1 : 0))), V_SUB(m_r[R2], (m_r[R1] + (PSW(C) ? 1 : 0)))) m_r[R2] -= m_r[R1] + (PSW(C) ? 1 : 0); - FLAGS_ZN(m_r[R2] == 0, m_r[R2] < 0) + FLAGS_ZN(m_r[R2] == 0, (s32)m_r[R2] < 0) // FLAGS: CVZN break; @@ -921,13 +945,13 @@ int clipper_device::execute_instruction () // negw: negate word FLAGS_CV(m_r[R1] != 0, m_r[R1] == INT32_MIN) m_r[R2] = -m_r[R1]; - FLAGS_ZN(m_r[R2] == 0, m_r[R2] < 0) + FLAGS_ZN(m_r[R2] == 0, (s32)m_r[R2] < 0) // FLAGS: CVZN break; case 0x98: // mulw: multiply word - m_r[R2] = m_r[R2] * m_r[R1]; + m_r[R2] = (s32)m_r[R2] * (s32)m_r[R1]; // FLAGS: 0V00 break; case 0x99: @@ -937,7 +961,7 @@ int clipper_device::execute_instruction () break; case 0x9a: // mulwu: multiply word unsigned - m_r[R2] = (u32)m_r[R2] * (u32)m_r[R1]; + m_r[R2] = m_r[R2] * m_r[R1]; // FLAGS: 0V00 break; case 0x9b: @@ -950,7 +974,7 @@ int clipper_device::execute_instruction () if (m_r[R1] != 0) { FLAGS(0, m_r[R2] == INT32_MIN && m_r[R1] == -1, 0, 0) - m_r[R2] = m_r[R2] / m_r[R1]; + m_r[R2] = (s32)m_r[R2] / (s32)m_r[R1]; } else next_pc = intrap(EXCEPTION_INTEGER_DIVIDE_BY_ZERO, next_pc, CTS_DIVIDE_BY_ZERO); @@ -962,7 +986,7 @@ int clipper_device::execute_instruction () if (m_r[R1] != 0) { FLAGS(0, m_r[R2] == INT32_MIN && m_r[R1] == -1, 0, 0) - m_r[R2] = m_r[R2] % m_r[R1]; + m_r[R2] = (s32)m_r[R2] % (s32)m_r[R1]; } else next_pc = intrap(EXCEPTION_INTEGER_DIVIDE_BY_ZERO, next_pc, CTS_DIVIDE_BY_ZERO); @@ -971,8 +995,8 @@ int clipper_device::execute_instruction () break; case 0x9e: // divwu: divide word unsigned - if ((u32)m_r[R1] != 0) - m_r[R2] = (u32)m_r[R2] / (u32)m_r[R1]; + if (m_r[R1] != 0) + m_r[R2] = m_r[R2] / m_r[R1]; else next_pc = intrap(EXCEPTION_INTEGER_DIVIDE_BY_ZERO, next_pc, CTS_DIVIDE_BY_ZERO); FLAGS(0, 0, 0, 0) @@ -981,8 +1005,8 @@ int clipper_device::execute_instruction () break; case 0x9f: // modwu: modulus word unsigned - if ((u32)m_r[R1] != 0) - m_r[R2] = (u32)m_r[R2] % (u32)m_r[R1]; + if (m_r[R1] != 0) + m_r[R2] = m_r[R2] % m_r[R1]; else next_pc = intrap(EXCEPTION_INTEGER_DIVIDE_BY_ZERO, next_pc, CTS_DIVIDE_BY_ZERO); FLAGS(0, 0, 0, 0) @@ -993,7 +1017,7 @@ int clipper_device::execute_instruction () // subw: subtract word FLAGS_CV(C_SUB(m_r[R2], m_r[R1]), V_SUB(m_r[R2], m_r[R1])) m_r[R2] -= m_r[R1]; - FLAGS_ZN(m_r[R2] == 0, m_r[R2] < 0) + FLAGS_ZN(m_r[R2] == 0, (s32)m_r[R2] < 0) // FLAGS: CVZN break; @@ -1001,52 +1025,52 @@ int clipper_device::execute_instruction () // subq: subtract quick FLAGS_CV(C_SUB(m_r[R2], R1), V_SUB(m_r[R2], R1)) m_r[R2] -= R1; - FLAGS_ZN(m_r[R2] == 0, m_r[R2] < 0) + FLAGS_ZN(m_r[R2] == 0, (s32)m_r[R2] < 0) // FLAGS: CVZN break; case 0xa3: // subi: subtract immediate FLAGS_CV(C_SUB(m_r[R2], m_info.imm), V_SUB(m_r[R2], m_info.imm)) m_r[R2] -= m_info.imm; - FLAGS_ZN(m_r[R2] == 0, m_r[R2] < 0) + FLAGS_ZN(m_r[R2] == 0, (s32)m_r[R2] < 0) // FLAGS: CVZN // TRAPS: I break; case 0xa4: // cmpw: compare word - FLAGS(C_SUB(m_r[R2], m_r[R1]), V_SUB(m_r[R2], m_r[R1]), m_r[R2] == m_r[R1], m_r[R2] < m_r[R1]) + FLAGS(C_SUB(m_r[R2], m_r[R1]), V_SUB(m_r[R2], m_r[R1]), m_r[R2] == m_r[R1], (s32)m_r[R2] < (s32)m_r[R1]) // FLAGS: CVZN break; case 0xa6: // cmpq: compare quick - FLAGS(C_SUB(m_r[R2], R1), V_SUB(m_r[R2], R1), m_r[R2] == (s32)R1, m_r[R2] < (s32)R1) + FLAGS(C_SUB(m_r[R2], R1), V_SUB(m_r[R2], R1), m_r[R2] == R1, (s32)m_r[R2] < (s32)R1) // FLAGS: CVZN break; case 0xa7: // cmpi: compare immediate - FLAGS(C_SUB(m_r[R2], m_info.imm), V_SUB(m_r[R2], m_info.imm), m_r[R2] == m_info.imm, m_r[R2] < m_info.imm) + FLAGS(C_SUB(m_r[R2], m_info.imm), V_SUB(m_r[R2], m_info.imm), m_r[R2] == m_info.imm, (s32)m_r[R2] < (s32)m_info.imm) // FLAGS: CVZN // TRAPS: I break; case 0xa8: // xorw: exclusive or word m_r[R2] ^= m_r[R1]; - FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0) + FLAGS(0, 0, m_r[R2] == 0, (s32)m_r[R2] < 0) // FLAGS: 00ZN break; case 0xab: // xori: exclusive or immediate m_r[R2] ^= m_info.imm; - FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0) + FLAGS(0, 0, m_r[R2] == 0, (s32)m_r[R2] < 0) // FLAGS: 00ZN // TRAPS: I break; case 0xac: // notw: not word m_r[R2] = ~m_r[R1]; - FLAGS(0, 0, m_r[R2] == 0, m_r[R2] < 0) + FLAGS(0, 0, m_r[R2] == 0, (s32)m_r[R2] < 0) // FLAGS: 00ZN break; @@ -1158,7 +1182,7 @@ int clipper_device::execute_instruction () // store fi at sp - 8 * (8 - i) for (int i = R2; i < 8; i++) - m_data->write_qword(m_r[15] - 8 * (8 - i), m_f[i]); + m_data->write_qword(m_r[15] - 8 * (8 - i), get_fp64(i)); // decrement sp after push to allow restart on exceptions m_r[15] -= 8 * (8 - R2); @@ -1170,71 +1194,148 @@ int clipper_device::execute_instruction () // load fi from sp + 8 * (i - N) for (int i = R2; i < 8; i++) - m_f[i] = m_data->read_qword(m_r[15] + 8 * (i - R2)); + set_fp64(i, m_data->read_qword(m_r[15] + 8 * (i - R2))); // increment sp after pop to allow restart on exceptions m_r[15] += 8 * (8 - R2); // TRAPS: C,U,A,P,R break; -#ifdef UNIMPLEMENTED case 0x30: - // cnvsw + // cnvsw: convert single floating to word + m_fp_pc = m_pc; + + m_r[m_info.macro & 0xf] = float32_to_int32(get_fp32((m_info.macro >> 4) & 0xf)); + // TRAPS: F_IX + float_exception_flags &= (float_flag_invalid | float_flag_inexact); + break; case 0x31: - // cnvrsw + // cnvrsw: convert rounding single floating to word (non-IEEE +0.5/-0.5 rounding) + m_fp_pc = m_pc; + + if (float32_lt(get_fp32((m_info.macro >> 4) & 0xf), 0)) + m_r[m_info.macro & 0xf] = float32_to_int32_round_to_zero(float32_sub(get_fp32((m_info.macro >> 4) & 0xf), + float32_div(int32_to_float32(1), int32_to_float32(2)))); + else + m_r[m_info.macro & 0xf] = float32_to_int32_round_to_zero(float32_add(get_fp32((m_info.macro >> 4) & 0xf), + float32_div(int32_to_float32(1), int32_to_float32(2)))); // TRAPS: F_IX + float_exception_flags &= (float_flag_invalid | float_flag_inexact); + break; case 0x32: - // cnvtsw + // cnvtsw: convert truncating single floating to word + m_fp_pc = m_pc; + + m_r[m_info.macro & 0xf] = float32_to_int32_round_to_zero(get_fp32((m_info.macro >> 4) & 0xf)); // TRAPS: F_IX + float_exception_flags &= (float_flag_invalid | float_flag_inexact); + break; case 0x33: - // cnvws + // cnvws: convert word to single floating + set_fp32(m_info.macro & 0xf, int32_to_float32(m_r[(m_info.macro >> 4) & 0xf])); // TRAPS: F_X + float_exception_flags &= (float_flag_inexact); + break; case 0x34: - // cnvdw + // cnvdw: convert double floating to word + m_fp_pc = m_pc; + + m_r[m_info.macro & 0xf] = float64_to_int32(get_fp64((m_info.macro >> 4) & 0xf)); // TRAPS: F_IX + float_exception_flags &= (float_flag_invalid | float_flag_inexact); + break; case 0x35: - // cnvrdw + // cnvrdw: convert rounding double floating to word (non-IEEE +0.5/-0.5 rounding) + m_fp_pc = m_pc; + + if (float64_lt(get_fp64((m_info.macro >> 4) & 0xf), 0)) + m_r[m_info.macro & 0xf] = float64_to_int32_round_to_zero(float64_sub(get_fp64((m_info.macro >> 4) & 0xf), + float64_div(int32_to_float64(1), int32_to_float64(2)))); + else + m_r[m_info.macro & 0xf] = float64_to_int32_round_to_zero(float64_add(get_fp64((m_info.macro >> 4) & 0xf), + float64_div(int32_to_float64(1), int32_to_float64(2)))); // TRAPS: F_IX + float_exception_flags &= (float_flag_invalid | float_flag_inexact); break; -#endif - case 0x36: // cnvtdw - m_r[m_info.macro & 0xf] = (s32)m_f[(m_info.macro >> 4) & 0xf]; + case 0x36: + // cnvtdw: convert truncating double floating to word + m_fp_pc = m_pc; + + m_r[m_info.macro & 0xf] = float64_to_int32_round_to_zero(get_fp64((m_info.macro >> 4) & 0xf)); // TRAPS: F_IX + float_exception_flags &= (float_flag_invalid | float_flag_inexact); break; - case 0x37: // cnvwd - m_f[m_info.macro & 0xf] = (double)m_r[(m_info.macro >> 4) & 0xf]; + case 0x37: + // cnvwd: convert word to double floating + set_fp64(m_info.macro & 0xf, int32_to_float64(m_r[(m_info.macro >> 4) & 0xf])); + float_exception_flags &= (0); break; -#ifdef UNIMPLEMENTED case 0x38: - // cnvsd + // cnvsd: convert single to double floating + set_fp64(m_info.macro & 0xf, float32_to_float64(get_fp32((m_info.macro >> 4) & 0xf))); // TRAPS: F_I + float_exception_flags &= (float_flag_invalid); + break; case 0x39: - // cnvds + // cnvds: convert double to single floating + set_fp32(m_info.macro & 0xf, float64_to_float32(get_fp64((m_info.macro >> 4) & 0xf))); // TRAPS: F_IVUX + float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_underflow | float_flag_inexact); + break; case 0x3a: - // negs + // negs: negate single floating + set_fp32(m_info.macro & 0xf, float32_mul(get_fp32((m_info.macro >> 4) & 0xf), int32_to_float32(-1))); + float_exception_flags &= (0); + break; case 0x3b: - // negds + // negd: negate double floating + set_fp64(m_info.macro & 0xf, float64_mul(get_fp64((m_info.macro >> 4) & 0xf), int32_to_float64(-1))); + float_exception_flags &= (0); + break; case 0x3c: - // scalbs + /* + * This implementation for scalbd and scalbs is a bit opaque, but + * essentially we check if the integer value is within range, and + * directly create a floating constant representing 2^n or NaN + * respectively, which is used as an input to a multiply, producing + * the desired result. While doing an actual multiply is both + * inefficient and unnecessary, it's a tidy way to ensure the + * correct exception flags are set. + */ + // scalbs: scale by, single floating + set_fp32(m_info.macro & 0xf, float32_mul(get_fp32(m_info.macro & 0xf), + (((s32)m_r[(m_info.macro >> 4) & 0xf] > -127 && (s32)m_r[(m_info.macro >> 4) & 0xf] < 128) + ? (float32)(((s32)m_r[(m_info.macro >> 4) & 0xf] + 127) << 23) + : (float32)~u32(0)))); // TRAPS: F_IVUX + float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_underflow | float_flag_inexact); + break; case 0x3d: - // scalbd - // FLAGS: N + // scalbd: scale by, double floating + set_fp64(m_info.macro & 0xf, float64_mul(get_fp64(m_info.macro & 0xf), + ((s32)m_r[(m_info.macro >> 4) & 0xf] > -1023 && (s32)m_r[(m_info.macro >> 4) & 0xf] < 1024) + ? (float64)((u64)((s32)m_r[(m_info.macro >> 4) & 0xf] + 1023) << 52) + : (float64)~u64(0))); // TRAPS: F_IVUX + float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_underflow | float_flag_inexact); + break; case 0x3e: - // trapfn + // trapfn: trap floating unordered + if (PSW(Z) && PSW(N)) + next_pc = intrap(EXCEPTION_ILLEGAL_OPERATION, next_pc, CTS_ILLEGAL_OPERATION); // TRAPS: I case 0x3f: - // loadfs + // loadfs: load floating status + m_r[(m_info.macro >> 4) & 0xf] = m_fp_pc; + m_f[m_info.macro & 0xf] = m_fp_dst; + m_ssw |= SSW_FRD; break; -#endif + default: LOG("illegal unprivileged macro opcode at 0x%08x\n", m_pc); next_pc = intrap(EXCEPTION_ILLEGAL_OPERATION, next_pc, CTS_ILLEGAL_OPERATION); machine().debug_break(); break; } - break; case 0xb6: @@ -1246,14 +1347,14 @@ int clipper_device::execute_instruction () case 0x00: // movus: move user to supervisor m_rs[m_info.macro & 0xf] = m_ru[(m_info.macro >> 4) & 0xf]; - FLAGS(0, 0, m_rs[m_info.macro & 0xf] == 0, m_rs[m_info.macro & 0xf] < 0) + FLAGS(0, 0, m_rs[m_info.macro & 0xf] == 0, (s32)m_rs[m_info.macro & 0xf] < 0) // FLAGS: 00ZN // TRAPS: S break; case 0x01: // movsu: move supervisor to user m_ru[m_info.macro & 0xf] = m_rs[(m_info.macro >> 4) & 0xf]; - FLAGS(0, 0, m_ru[m_info.macro & 0xf] == 0, m_ru[m_info.macro & 0xf] < 0) + FLAGS(0, 0, m_ru[m_info.macro & 0xf] == 0, (s32)m_ru[m_info.macro & 0xf] < 0) // FLAGS: 00ZN // TRAPS: S break; @@ -1285,6 +1386,9 @@ int clipper_device::execute_instruction () m_rs[(m_info.macro >> 4) & 0xf] += 12; m_r = SSW(U) ? m_ru : m_rs; + + fp_rounding(); + // TRAPS: S break; case 0x05: @@ -1330,15 +1434,17 @@ int clipper_device::execute_instruction () } /* -* Common entry point for transferring control in the event of an interrupt or exception. -*/ -u32 clipper_device::intrap(u32 vector, u32 pc, u32 cts, u32 mts) + * Common entry point for transferring control in the event of an interrupt or + * exception. Reading between the lines, it appears this logic was implemented + * using the macro instruction ROM and a special macro instruction (intrap). + */ +u32 clipper_device::intrap(u16 vector, u32 pc, u32 cts, u32 mts) { // fetch pc and ssw from interrupt vector u32 next_pc = m_data->read_dword(vector + 0); u32 next_ssw = m_data->read_dword(vector + 4); - LOGMASKED(LOG_INTERRUPT, "intrap vector 0x%08x pc 0x%08x next_pc 0x%08x ssp 0x%08x\n", vector, pc, next_pc, m_rs[15]); + LOGMASKED(LOG_INTERRUPT, "intrap vector 0x%04x pc 0x%08x next_pc 0x%08x ssp 0x%08x\n", vector, pc, next_pc, m_rs[15]); // set cts and mts to indicate source of exception m_psw = (m_psw & ~(PSW_CTS | PSW_MTS)) | mts | cts; @@ -1356,6 +1462,7 @@ u32 clipper_device::intrap(u32 vector, u32 pc, u32 cts, u32 mts) // clear psw m_psw = 0; + float_rounding_mode = float_round_nearest_even; m_r = SSW(U) ? m_ru : m_rs; @@ -1363,13 +1470,13 @@ u32 clipper_device::intrap(u32 vector, u32 pc, u32 cts, u32 mts) return next_pc; } -u32 clipper_c400_device::intrap(u32 vector, u32 pc, u32 cts, u32 mts) +u32 clipper_c400_device::intrap(u16 vector, u32 pc, u32 cts, u32 mts) { // C400 reverses order of pc and ssw in interrupt vector u32 next_pc = m_data->read_dword(vector + 4); u32 next_ssw = m_data->read_dword(vector + 0); - LOGMASKED(LOG_INTERRUPT, "intrap vector 0x%08x pc 0x%08x next_pc 0x%08x ssp 0x%08x\n", vector, pc, next_pc, m_rs[15]); + LOGMASKED(LOG_INTERRUPT, "intrap vector 0x%04x pc 0x%08x next_pc 0x%08x ssp 0x%08x\n", vector, pc, next_pc, m_rs[15]); // set cts and mts to indicate source of exception m_psw = (m_psw & ~(PSW_CTS | PSW_MTS)) | mts | cts; @@ -1393,6 +1500,7 @@ u32 clipper_c400_device::intrap(u32 vector, u32 pc, u32 cts, u32 mts) // clear psw m_psw = 0; + float_rounding_mode = float_round_nearest_even; m_r = SSW(U) ? m_ru : m_rs; @@ -1460,6 +1568,90 @@ bool clipper_device::evaluate_branch() const return false; } +void clipper_device::fp_rounding() +{ + // set the softfloat rounding mode based on the psw rounding mode + switch (PSW(FR)) + { + case FR_0: float_rounding_mode = float_round_nearest_even; break; + case FR_1: float_rounding_mode = float_round_up; break; + case FR_2: float_rounding_mode = float_round_down; break; + case FR_3: float_rounding_mode = float_round_to_zero; break; + } +} + +void clipper_device::fp_exception() +{ + u16 vector = 0; + + /* + * Set the psw floating exception flags, and identify any enabled + * exceptions. The order here is important, but since the documentation + * doesn't explicitly specify, this is a guess. Simply put, exceptions + * are considered in sequence with an increasing order of priority. + */ + if (float_exception_flags & float_flag_inexact) + { + m_psw |= PSW_FX; + if (PSW(EFX)) + vector = EXCEPTION_FLOATING_INEXACT; + } + if (float_exception_flags & float_flag_underflow) + { + m_psw |= PSW_FU; + if (PSW(EFU)) + vector = EXCEPTION_FLOATING_UNDERFLOW; + } + if (float_exception_flags & float_flag_overflow) + { + m_psw |= PSW_FV; + if (PSW(EFV)) + vector = EXCEPTION_FLOATING_OVERFLOW; + } + if (float_exception_flags & float_flag_divbyzero) + { + m_psw |= PSW_FD; + if (PSW(EFD)) + vector = EXCEPTION_FLOATING_DIVIDE_BY_ZERO; + } + if (float_exception_flags & float_flag_invalid) + { + m_psw |= PSW_FI; + if (PSW(EFI)) + vector = EXCEPTION_FLOATING_INVALID_OPERATION; + } + + // trigger a floating point exception + if (PSW(EFT) && vector) + m_pc = intrap(vector, m_pc); +} + +inline void clipper_device::set_fp32(const u8 reg, const float32 data) +{ + // save floating exception state + m_fp_pc = m_pc; + m_fp_dst = m_f[reg & 0xf]; + + // assign data + m_f[reg & 0xf] = data; + + // set floating dirty flag + m_ssw |= SSW_FRD; +} + +inline void clipper_device::set_fp64(const u8 reg, const float64 data) +{ + // save floating exception state + m_fp_pc = m_pc; + m_fp_dst = m_f[reg & 0xf]; + + // assign data + m_f[reg & 0xf] = data; + + // set floating dirty flag + m_ssw |= SSW_FRD; +} + offs_t clipper_device::disasm_disassemble(std::ostream &stream, offs_t pc, const u8 *oprom, const u8 *opram, u32 options) { return CPU_DISASSEMBLE_NAME(clipper)(this, stream, pc, oprom, opram, options); diff --git a/src/devices/cpu/clipper/clipper.h b/src/devices/cpu/clipper/clipper.h index 27624b4e05a..6a1d5dc0ba2 100644 --- a/src/devices/cpu/clipper/clipper.h +++ b/src/devices/cpu/clipper/clipper.h @@ -7,6 +7,8 @@ #pragma once #include <limits.h> +#include "softfloat/milieu.h" +#include "softfloat/softfloat.h" // convenience macros for dealing with the psw and ssw #define PSW(mask) (m_psw & PSW_##mask) @@ -91,13 +93,21 @@ protected: PSW_MTS = 0xf0000000, // memory trap status (4 bits) }; - enum clipper_ssw + enum psw_fr + { + FR_0 = 0x00000000, // round to nearest + FR_1 = 0x00008000, // round toward + infinity + FR_2 = 0x00010000, // round toward - infinity + FR_3 = 0x00018000 // round toward zero + }; + + enum ssw { SSW_IN = 0x0000000f, // interrupt number (4 bits) SSW_IL = 0x000000f0, // interrupt level (4 bits) SSW_EI = 0x00000100, // enable interrupts SSW_ID = 0x0001fe00, // cpu rev # and type (8 bits) - // unused (5 bits) + // unused (5 bits) SSW_FRD = 0x00400000, // floating registers dirty SSW_TP = 0x00800000, // trace trap pending SSW_ECM = 0x01000000, // enabled corrected memory error @@ -110,7 +120,7 @@ protected: SSW_P = 0x80000000, // previous mode }; - enum clipper_ssw_id + enum ssw_id { SSW_ID_C400R0 = 0x00000, SSW_ID_C400R1 = 0x04000, @@ -211,24 +221,32 @@ protected: virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; // device_disasm_interface overrides - virtual uint32_t disasm_min_opcode_bytes() const override { return 2; } // smallest instruction - virtual uint32_t disasm_max_opcode_bytes() const override { return 8; } // largest instruction + virtual u32 disasm_min_opcode_bytes() const override { return 2; } // smallest instruction + virtual u32 disasm_max_opcode_bytes() const override { return 8; } // largest instruction virtual offs_t disasm_disassemble(std::ostream &stream, offs_t pc, const u8 *oprom, const u8 *opram, u32 options) override; void set_ssw(u32 data) { m_ssw = (m_ssw & SSW(ID)) | (data & ~SSW(ID)); } + inline float32 get_fp32(const u8 reg) const { return m_f[reg & 0xf]; }; + inline float64 get_fp64(const u8 reg) const { return m_f[reg & 0xf]; }; + inline void set_fp32(const u8 reg, const float32 data); + inline void set_fp64(const u8 reg, const float64 data); + // core registers u32 m_pc; u32 m_psw; u32 m_ssw; // integer registers - s32 *m_r; // active registers - s32 m_ru[16]; // user registers - s32 m_rs[16]; // supervisor registers + u32 *m_r; // active registers + u32 m_ru[16]; // user registers + u32 m_rs[16]; // supervisor registers - // floating registers - double m_f[16]; + // floating point registers + u64 m_f[16]; + + u32 m_fp_pc; // address of floating point instruction causing exception + u64 m_fp_dst; // original value of destination register during fp exception address_space_config m_insn_config; address_space_config m_data_config; @@ -244,12 +262,12 @@ private: u8 m_ivec; // decoded instruction information - struct + struct decode { + // various decoded instruction fields u8 opcode, subopcode; u8 r1, r2; - - s32 imm; + u32 imm; u16 macro; // total size of instruction in bytes @@ -257,14 +275,18 @@ private: // computed effective address u32 address; - } m_info; + } + m_info; void decode_instruction(u16 insn); int execute_instruction(); bool evaluate_branch() const; + void fp_rounding(); + void fp_exception(); + protected: - virtual uint32_t intrap(u32 vector, u32 pc, u32 cts = CTS_NO_CPU_TRAP, u32 mts = MTS_NO_MEMORY_TRAP); + virtual u32 intrap(u16 vector, u32 pc, u32 cts = CTS_NO_CPU_TRAP, u32 mts = MTS_NO_MEMORY_TRAP); }; class clipper_c100_device : public clipper_device @@ -285,7 +307,7 @@ public: clipper_c400_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); protected: - virtual uint32_t intrap(u32 vector, u32 pc, u32 cts = CTS_NO_CPU_TRAP, u32 mts = MTS_NO_MEMORY_TRAP) override; + virtual u32 intrap(u16 vector, u32 pc, u32 cts = CTS_NO_CPU_TRAP, u32 mts = MTS_NO_MEMORY_TRAP) override; }; DECLARE_DEVICE_TYPE(CLIPPER_C100, clipper_c100_device) diff --git a/src/mame/drivers/interpro.cpp b/src/mame/drivers/interpro.cpp index 44bf7846b25..2445c9285b2 100644 --- a/src/mame/drivers/interpro.cpp +++ b/src/mame/drivers/interpro.cpp @@ -104,8 +104,10 @@ * U35 128 kB EPROM (MPRGW510B) Boot ROM * U43? (MPRGM610P) Bitstream for XC3020? * U44 Intel 82596SX Ethernet controller (20MHz) + * U67 Intel N28F010-200 128Kx8 flash memory (200ns) * U68 CYID21603 TC150G89AF * U71 LSI L1A6104 CICD 95801 Intergraph I/O gate array + * U76 Intel N28F010-200 128Kx8 flash memory (200ns) * U81 NCR 53C94 SCSI controller * U86 24.0 MHz crystal Clock source for 53C94? * U87 4.9152 MHz crystal Clock source for 8530s? @@ -129,7 +131,9 @@ * U43? (MPRGM610P) Bitstream for XC3020? * U44 Intel 82596SX? Ethernet controller * U68 CYID21603 TC150G89AF + * U67 Intel N28F010 128Kx8 flash memory * U71 LSI L1A7374 CIDC094A3 Intergraph I/O gate array + * U76 Intel N28F010 128Kx8 flash memory * U81 NCR 53C94 SCSI controller * U86 24.0 MHz crystal Clock source for 53C94? * U87 4.9152 MHz crystal Clock source for 8530s? @@ -155,14 +159,6 @@ #define VERBOSE 0 #include "logmacro.h" -// FIXME: eeprom/flash device embedded here until real device is known -DEFINE_DEVICE_TYPE(INTERPRO_EEPROM, interpro_eeprom_device, "interpro_eeprom", "InterPro Flash EEPROM"); - -interpro_eeprom_device::interpro_eeprom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : eeprom_base_device(mconfig, INTERPRO_EEPROM, tag, owner) -{ -} - void interpro_state::machine_start() { // FIXME: disabled for now to avoid cold start diagnostic errors @@ -242,7 +238,9 @@ WRITE16_MEMBER(sapphire_state::sreg_ctrl2_w) { interpro_state::sreg_ctrl2_w(space, offset, data, mem_mask); - m_eeprom->write_enable(data & CTRL2_FLASHEN ? ASSERT_LINE : CLEAR_LINE); + // enable/disable programming power on both flash devices + m_flash_lo->vpp(data & CTRL2_FLASHEN ? ASSERT_LINE : CLEAR_LINE); + m_flash_hi->vpp(data & CTRL2_FLASHEN ? ASSERT_LINE : CLEAR_LINE); } READ16_MEMBER(interpro_state::sreg_error_r) @@ -376,7 +374,8 @@ ADDRESS_MAP_END static ADDRESS_MAP_START(sapphire_main_map, 0, 32, sapphire_state) AM_RANGE(0x00000000, 0x00ffffff) AM_RAM AM_SHARE(RAM_TAG) AM_RANGE(0x7f100000, 0x7f11ffff) AM_ROM AM_REGION(INTERPRO_EPROM_TAG, 0) - AM_RANGE(0x7f180000, 0x7f1bffff) AM_DEVREADWRITE16(INTERPRO_EEPROM_TAG, interpro_eeprom_device, eeprom_r, eeprom_w, 0xffffffff) + AM_RANGE(0x7f180000, 0x7f1fffff) AM_DEVREADWRITE8(INTERPRO_FLASH_TAG "_lo", intel_28f010_device, read, write, 0x00ff00ff) AM_MASK(0x3ffff) + AM_RANGE(0x7f180000, 0x7f1fffff) AM_DEVREADWRITE8(INTERPRO_FLASH_TAG "_hi", intel_28f010_device, read, write, 0xff00ff00) AM_MASK(0x3ffff) AM_IMPORT_FROM(sapphire_base_map) ADDRESS_MAP_END @@ -635,10 +634,9 @@ static MACHINE_CONFIG_DERIVED(sapphire, interpro) MCFG_DEVICE_ADD(INTERPRO_IOGA_TAG, SAPPHIRE_IOGA, 0) MCFG_FRAGMENT_ADD(ioga) - // eeprom - MCFG_DEVICE_ADD(INTERPRO_EEPROM_TAG, INTERPRO_EEPROM, 0) - MCFG_EEPROM_SIZE(0x20000, 16) - MCFG_EEPROM_WRITE_TIME(attotime::from_usec(1000)) + // flash memory + MCFG_DEVICE_ADD(INTERPRO_FLASH_TAG "_lo", INTEL_28F010, 0) + MCFG_DEVICE_ADD(INTERPRO_FLASH_TAG "_hi", INTEL_28F010, 0) MACHINE_CONFIG_END MACHINE_CONFIG_DERIVED(ip2000, turquoise) @@ -684,8 +682,11 @@ ROM_START(ip2400) ROM_SYSTEM_BIOS(0, "ip2400", "InterPro 2400 EPROM") ROMX_LOAD("mprgw510b__05_16_92.u35", 0x00000, 0x20000, CRC(3b2c4545) SHA1(4e4c98d1cd1035a04be8527223f44d0b687ec3ef), ROM_BIOS(1)) - ROM_REGION16_LE(0x0040000, INTERPRO_EEPROM_TAG, 0) - ROM_LOAD_OPTIONAL("c4saph.bin", 0x00000, 0x40000, CRC(a0c0899f) SHA1(dda6fbca81f9885a1a76ca3c25e80463a83a0ef7)) + ROM_REGION(0x20000, INTERPRO_FLASH_TAG "_lo", 0) + ROM_LOAD_OPTIONAL("y225.u76", 0x00000, 0x20000, CRC(46c0b105) SHA1(7c4a104e4fb3d0e5e8db7c911cdfb3f5c4fb0218)) + + ROM_REGION(0x20000, INTERPRO_FLASH_TAG "_hi", 0) + ROM_LOAD_OPTIONAL("y226.u67", 0x00000, 0x20000, CRC(54d95730) SHA1(a4e114dee1567d8aa31eed770f7cc366588f395c)) ROM_END ROM_START(ip2500) @@ -696,8 +697,11 @@ ROM_START(ip2500) ROM_SYSTEM_BIOS(0, "ip2500", "InterPro 2500 EPROM") ROMX_LOAD("ip2500_eprom.bin", 0x00000, 0x20000, NO_DUMP, ROM_BIOS(1)) - ROM_REGION16_LE(0x0040000, INTERPRO_EEPROM_TAG, 0) - ROM_LOAD_OPTIONAL("c4saph.bin", 0x00000, 0x40000, CRC(a0c0899f) SHA1(dda6fbca81f9885a1a76ca3c25e80463a83a0ef7)) + ROM_REGION(0x20000, INTERPRO_FLASH_TAG "_lo", 0) + ROM_LOAD_OPTIONAL("y225.u76", 0x00000, 0x20000, CRC(46c0b105) SHA1(7c4a104e4fb3d0e5e8db7c911cdfb3f5c4fb0218)) + + ROM_REGION(0x20000, INTERPRO_FLASH_TAG "_hi", 0) + ROM_LOAD_OPTIONAL("y226.u67", 0x00000, 0x20000, CRC(54d95730) SHA1(a4e114dee1567d8aa31eed770f7cc366588f395c)) ROM_END ROM_START(ip2700) @@ -708,8 +712,11 @@ ROM_START(ip2700) ROM_SYSTEM_BIOS(0, "ip2700", "InterPro 2700 EPROM") ROMX_LOAD("mprgz530a__9405181.u35", 0x00000, 0x20000, CRC(467ce7bd) SHA1(53faee40d5df311f53b24c930e434cbf94a5c4aa), ROM_BIOS(1)) - ROM_REGION16_LE(0x0040000, INTERPRO_EEPROM_TAG, 0) - ROM_LOAD_OPTIONAL("c4saph.bin", 0x00000, 0x40000, CRC(a0c0899f) SHA1(dda6fbca81f9885a1a76ca3c25e80463a83a0ef7)) + ROM_REGION(0x20000, INTERPRO_FLASH_TAG "_lo", 0) + ROM_LOAD_OPTIONAL("y225.u76", 0x00000, 0x20000, CRC(46c0b105) SHA1(7c4a104e4fb3d0e5e8db7c911cdfb3f5c4fb0218)) + + ROM_REGION(0x20000, INTERPRO_FLASH_TAG "_hi", 0) + ROM_LOAD_OPTIONAL("y226.u67", 0x00000, 0x20000, CRC(54d95730) SHA1(a4e114dee1567d8aa31eed770f7cc366588f395c)) ROM_END ROM_START(ip2800) @@ -720,8 +727,11 @@ ROM_START(ip2800) ROM_SYSTEM_BIOS(0, "ip2800", "InterPro 2800 EPROM") ROMX_LOAD("ip2800_eprom.bin", 0x00000, 0x20000, CRC(467ce7bd) SHA1(53faee40d5df311f53b24c930e434cbf94a5c4aa), ROM_BIOS(1)) - ROM_REGION16_LE(0x0040000, INTERPRO_EEPROM_TAG, 0) - ROM_LOAD_OPTIONAL("c4saph.bin", 0x00000, 0x40000, CRC(a0c0899f) SHA1(dda6fbca81f9885a1a76ca3c25e80463a83a0ef7)) + ROM_REGION(0x20000, INTERPRO_FLASH_TAG "_lo", 0) + ROM_LOAD_OPTIONAL("y225.u76", 0x00000, 0x20000, CRC(46c0b105) SHA1(7c4a104e4fb3d0e5e8db7c911cdfb3f5c4fb0218)) + + ROM_REGION(0x20000, INTERPRO_FLASH_TAG "_hi", 0) + ROM_LOAD_OPTIONAL("y226.u67", 0x00000, 0x20000, CRC(54d95730) SHA1(a4e114dee1567d8aa31eed770f7cc366588f395c)) ROM_END /* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */ diff --git a/src/mame/includes/interpro.h b/src/mame/includes/interpro.h index d64884fe77d..f65bcbb0c1f 100644 --- a/src/mame/includes/interpro.h +++ b/src/mame/includes/interpro.h @@ -15,7 +15,7 @@ #include "machine/interpro_arbga.h" #include "machine/ram.h" -#include "machine/eeprom.h" +#include "machine/28fxxx.h" #include "machine/mc146818.h" #include "machine/z80scc.h" #include "machine/upd765.h" @@ -55,30 +55,10 @@ #define INTERPRO_IDPROM_TAG "idprom" #define INTERPRO_EPROM_TAG "eprom" -#define INTERPRO_EEPROM_TAG "eeprom" +#define INTERPRO_FLASH_TAG "flash" #define INTERPRO_SRBUS_TAG "sr" -class interpro_eeprom_device : public eeprom_base_device -{ -public: - interpro_eeprom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - DECLARE_READ16_MEMBER(eeprom_r) { return read(offset); } - DECLARE_WRITE16_MEMBER(eeprom_w) { if (m_write_enable) write(offset, data); } - - DECLARE_WRITE_LINE_MEMBER(write_enable) { m_write_enable = state; } - -protected: - virtual void device_start() override { eeprom_base_device::device_start(); } - virtual void device_reset() override { eeprom_base_device::device_reset(); } - -private: - int m_write_enable; -}; - -DECLARE_DEVICE_TYPE(INTERPRO_EEPROM, interpro_eeprom_device) - class interpro_state : public driver_device { public: @@ -210,10 +190,12 @@ class sapphire_state : public interpro_state public: sapphire_state(const machine_config &mconfig, device_type type, const char *tag) : interpro_state(mconfig, type, tag) - , m_eeprom(*this, INTERPRO_EEPROM_TAG) + , m_flash_lo(*this, INTERPRO_FLASH_TAG "_lo") + , m_flash_hi(*this, INTERPRO_FLASH_TAG "_hi") {} - required_device<interpro_eeprom_device> m_eeprom; + required_device<intel_28f010_device> m_flash_lo; + required_device<intel_28f010_device> m_flash_hi; virtual DECLARE_WRITE16_MEMBER(sreg_ctrl2_w) override; }; |