mirror of
https://github.com/holub/mame
synced 2025-04-22 08:22:15 +03:00
romp: new device
This commit is contained in:
parent
def2bf867c
commit
52d1a412fa
@ -3162,3 +3162,20 @@ if (CPUS["UPD78K"]~=null or _OPTIONS["with-tools"]) then
|
||||
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/upd78k/upd78k3d.cpp")
|
||||
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/upd78k/upd78k3d.h")
|
||||
end
|
||||
|
||||
--------------------------------------------------
|
||||
-- IBM ROMP
|
||||
--@src/devices/cpu/romp/romp.h,CPUS["ROMP"] = true
|
||||
--------------------------------------------------
|
||||
|
||||
if (CPUS["ROMP"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/cpu/romp/romp.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/romp/romp.h",
|
||||
}
|
||||
end
|
||||
|
||||
if (CPUS["ROMP"]~=null or _OPTIONS["with-tools"]) then
|
||||
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/romp/rompdasm.cpp")
|
||||
table.insert(disasm_files , MAME_DIR .. "src/devices/cpu/romp/rompdasm.h")
|
||||
end
|
||||
|
685
src/devices/cpu/romp/romp.cpp
Normal file
685
src/devices/cpu/romp/romp.cpp
Normal file
@ -0,0 +1,685 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Patrick Mackinlay
|
||||
|
||||
/*
|
||||
* IBM Research and Office Products Division Microprocessor (ROMP).
|
||||
*
|
||||
* Sources:
|
||||
* - http://bitsavers.org/pdf/ibm/pc/rt/6489893_RT_PC_Technical_Reference_Volume_1_Nov85.pdf
|
||||
*
|
||||
* TODO:
|
||||
* - unimplemented instructions
|
||||
* - condition codes
|
||||
* - memory management unit
|
||||
* - interrupts and exceptions
|
||||
* - timer/counter
|
||||
* - assembler syntax
|
||||
* - instruction clocks
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "romp.h"
|
||||
#include "rompdasm.h"
|
||||
#include "debugger.h"
|
||||
|
||||
#define LOG_GENERAL (1U << 0)
|
||||
//#define VERBOSE (LOG_GENERAL)
|
||||
#include "logmacro.h"
|
||||
|
||||
// instruction decode helpers
|
||||
#define R2 ((op >> 4) & 15)
|
||||
#define R3 (op & 15)
|
||||
|
||||
DEFINE_DEVICE_TYPE(ROMP, romp_device, "romp", "IBM ROMP")
|
||||
|
||||
ALLOW_SAVE_TYPE(romp_device::branch_state);
|
||||
|
||||
romp_device::romp_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
|
||||
: cpu_device(mconfig, ROMP, tag, owner, clock)
|
||||
, m_mem_config("memory", ENDIANNESS_BIG, 32, 32)
|
||||
, m_io_config("io", ENDIANNESS_BIG, 32, 24, -2)
|
||||
, m_icount(0)
|
||||
{
|
||||
}
|
||||
|
||||
void romp_device::device_start()
|
||||
{
|
||||
// set instruction counter
|
||||
set_icountptr(m_icount);
|
||||
|
||||
// register state for the debugger
|
||||
state_add(STATE_GENPC, "GENPC", m_scr[IAR]).noshow();
|
||||
state_add(STATE_GENPCBASE, "CURPC", m_scr[IAR]).noshow();
|
||||
|
||||
state_add(ROMP_SCR + IAR, "IAR", m_scr[IAR]);
|
||||
state_add(ROMP_SCR + COS, "COS", m_scr[COS]);
|
||||
state_add(ROMP_SCR + COU, "COU", m_scr[COU]);
|
||||
state_add(ROMP_SCR + TS, "TS", m_scr[TS]);
|
||||
state_add(ROMP_SCR + MQ, "MQ", m_scr[MQ]);
|
||||
state_add(ROMP_SCR + MCS, "MCS", m_scr[MCS]);
|
||||
state_add(ROMP_SCR + IRB, "IRB", m_scr[IRB]);
|
||||
state_add(ROMP_SCR + ICS, "ICS", m_scr[ICS]);
|
||||
state_add(ROMP_SCR + CS, "CS", m_scr[CS]);
|
||||
|
||||
for (unsigned i = 0; i < ARRAY_LENGTH(m_gpr); i++)
|
||||
state_add(ROMP_GPR + i, util::string_format("R%d", i).c_str(), m_gpr[i]);
|
||||
|
||||
// register state for saving
|
||||
save_item(NAME(m_scr));
|
||||
save_item(NAME(m_gpr));
|
||||
save_item(NAME(m_branch_state));
|
||||
save_item(NAME(m_branch_target));
|
||||
}
|
||||
|
||||
void romp_device::device_reset()
|
||||
{
|
||||
// initialize the state
|
||||
// FIXME: should fetch initial address from 0
|
||||
m_scr[IAR] = space(AS_PROGRAM).read_dword(0x80'0000);
|
||||
m_branch_state = NONE;
|
||||
}
|
||||
|
||||
void romp_device::execute_run()
|
||||
{
|
||||
// core execution loop
|
||||
while (m_icount-- > 0)
|
||||
{
|
||||
// debugging
|
||||
debugger_instruction_hook(m_scr[IAR]);
|
||||
|
||||
// TODO: interrupts/exceptions
|
||||
|
||||
// fetch instruction
|
||||
u16 const op = space(AS_PROGRAM).read_word(m_scr[IAR]);
|
||||
m_scr[IAR] += 2;
|
||||
|
||||
// TODO: program check for illegal branch subject instructions
|
||||
|
||||
switch (op >> 12)
|
||||
{
|
||||
case 0x0: // jb/jnb: jump on [not] condition bit
|
||||
if (BIT(m_scr[CS], ((op >> 8) & 7) ^ 7) == BIT(op, 11))
|
||||
m_scr[IAR] = m_scr[IAR] - 2 + ji(op);
|
||||
break;
|
||||
case 0x1: // stcs: store character short
|
||||
space(AS_PROGRAM).write_byte(r3_0(R3) + ((op >> 8) & 15), m_gpr[R2]);
|
||||
break;
|
||||
case 0x2: // sths: store half short
|
||||
space(AS_PROGRAM).write_word(r3_0(R3) + ((op >> 7) & 30), m_gpr[R2]);
|
||||
break;
|
||||
case 0x3: // sts: store short
|
||||
space(AS_PROGRAM).write_dword(r3_0(R3) + ((op >> 6) & 60), m_gpr[R2]);
|
||||
break;
|
||||
case 0x4: // lcs: load character short
|
||||
m_gpr[R2] = space(AS_PROGRAM).read_byte(r3_0(R3) + ((op >> 8) & 15));
|
||||
break;
|
||||
case 0x5: // lhas: load half algebraic short
|
||||
m_gpr[R2] = s32(s16(space(AS_PROGRAM).read_word(r3_0(R3) + ((op >> 7) & 30))));
|
||||
break;
|
||||
case 0x6: // cas: compute address short
|
||||
m_gpr[(op >> 8) & 15] = m_gpr[R2] + r3_0(R3);
|
||||
break;
|
||||
case 0x7: // ls: load short
|
||||
m_gpr[R2] = space(AS_PROGRAM).read_dword(r3_0(R3) + ((op >> 6) & 60));
|
||||
break;
|
||||
case 0x8: // BI, BA format
|
||||
{
|
||||
u16 const b = space(AS_PROGRAM).read_word(m_scr[IAR]);
|
||||
m_scr[IAR] += 2;
|
||||
|
||||
switch (op >> 8)
|
||||
{
|
||||
case 0x88: // bnb: branch on not condition bit immediate
|
||||
if (!BIT(m_scr[CS], R2 ^ 15))
|
||||
m_scr[IAR] = m_scr[IAR] - 4 + bi(op, b);
|
||||
break;
|
||||
case 0x89: // bnbx: branch on not condition bit immediate with execute
|
||||
if (!BIT(m_scr[CS], R2 ^ 15))
|
||||
{
|
||||
m_branch_target = m_scr[IAR] - 4 + bi(op, b);
|
||||
m_branch_state = BRANCH;
|
||||
}
|
||||
break;
|
||||
case 0x8a: // bala: branch and link absolute
|
||||
m_gpr[15] = m_scr[IAR];
|
||||
m_scr[IAR] = ba(op, b);
|
||||
break;
|
||||
case 0x8b: // balax: branch and link absolute with execute
|
||||
m_gpr[15] = m_scr[IAR] + 4;
|
||||
m_branch_target = ba(op, b);
|
||||
m_branch_state = BRANCH;
|
||||
break;
|
||||
case 0x8c: // bali: branch and link immediate
|
||||
m_gpr[R2] = m_scr[IAR];
|
||||
m_scr[IAR] = m_scr[IAR] - 4 + bi(op, b);
|
||||
break;
|
||||
case 0x8d: // balix: branch and link immediate with execute
|
||||
m_gpr[R2] = m_scr[IAR] + 4;
|
||||
m_branch_target = m_scr[IAR] - 4 + bi(op, b);
|
||||
m_branch_state = BRANCH;
|
||||
break;
|
||||
case 0x8e: // bb: branch on condition bit immediate
|
||||
if (BIT(m_scr[CS], R2 ^ 15))
|
||||
m_scr[IAR] = m_scr[IAR] - 4 + bi(op, b);
|
||||
break;
|
||||
case 0x8f: // bbx: branch on condition bit immediate with execute
|
||||
if (BIT(m_scr[CS], R2 ^ 15))
|
||||
{
|
||||
m_branch_target = m_scr[IAR] - 4 + bi(op, b);
|
||||
m_branch_state = BRANCH;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xc:
|
||||
case 0xd: // D format
|
||||
{
|
||||
u16 const i = space(AS_PROGRAM).read_word(m_scr[IAR]);
|
||||
m_scr[IAR] += 2;
|
||||
|
||||
u32 const r3 = R3 ? m_gpr[R3] : 0;
|
||||
|
||||
switch (op >> 8)
|
||||
{
|
||||
//case 0xc0: // svc: supervisor call
|
||||
case 0xc1: // ai: add immediate
|
||||
m_gpr[R2] = m_gpr[R3] + s16(i);
|
||||
// TODO: LT, EQ, GT, C0, OV
|
||||
break;
|
||||
case 0xc2: // cal16: compute address lower half 16-bit
|
||||
m_gpr[R2] = (r3 & 0xffff'0000U) | u16(r3 + i);
|
||||
break;
|
||||
case 0xc3: // oiu: or immediate upper half
|
||||
m_gpr[R2] = (u32(i) << 16) | m_gpr[R3];
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xc4: // oil: or immediate lower half
|
||||
m_gpr[R2] = u32(i) | m_gpr[R3];
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xc5: // nilz: and immediate lower half extended zeroes
|
||||
m_gpr[R2] = u32(i) & m_gpr[R3];
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xc6: // nilo: and immediate lower half extended ones
|
||||
m_gpr[R2] = (i | 0xffff'0000U) & m_gpr[R3];
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xc7: // xil: exclusive or immediate lower half
|
||||
m_gpr[R2] = u32(i) ^ m_gpr[R3];
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xc8: // cal: compute address lower half
|
||||
m_gpr[R2] = r3 + s16(i);
|
||||
break;
|
||||
case 0xc9: // lm: load multiple
|
||||
for (unsigned reg = R2, offset = 0; reg < 16; reg++, offset += 4)
|
||||
m_gpr[reg] = space(AS_PROGRAM).read_dword(r3 + s16(i) + offset);
|
||||
break;
|
||||
case 0xca: // lha: load half algebraic
|
||||
m_gpr[R2] = s32(s16(space(AS_PROGRAM).read_word(r3 + s16(i))));
|
||||
break;
|
||||
case 0xcb: // ior: input/output read
|
||||
m_gpr[R2] = space(2).read_dword(r3 + i);
|
||||
break;
|
||||
//case 0xcc: // ti: trap on condition immediate
|
||||
case 0xcd: // l: load
|
||||
m_gpr[R2] = space(AS_PROGRAM).read_dword(r3 + s16(i));
|
||||
break;
|
||||
case 0xce: // lc: load character
|
||||
m_gpr[R2] = space(AS_PROGRAM).read_byte(r3 + s16(i));
|
||||
break;
|
||||
case 0xcf: // tsh: test and set half
|
||||
m_gpr[R2] = space(AS_PROGRAM).read_word(r3 + s16(i));
|
||||
space(AS_PROGRAM).write_byte(r3 + s16(i), 0xff);
|
||||
break;
|
||||
|
||||
case 0xd0: // lps: load program status
|
||||
m_scr[IAR] = space(AS_PROGRAM).read_dword(r3 + s16(i) + 0);
|
||||
m_scr[ICS] = space(AS_PROGRAM).read_word(r3 + s16(i) + 4);
|
||||
m_scr[CS] = space(AS_PROGRAM).read_word(r3 + s16(i) + 6);
|
||||
// TODO: clear MCS/PCS
|
||||
// TODO: defer interrupt enable
|
||||
break;
|
||||
case 0xd1: // aei: add extended immediate
|
||||
m_gpr[R2] = s32(s16(i)) + m_gpr[R3] + BIT(m_scr[CS], C0);
|
||||
// TODO: LT, EQ, GT, C0, OV
|
||||
break;
|
||||
case 0xd2: // sfi: subtract from immediate
|
||||
m_gpr[R2] = s32(s16(i)) - m_gpr[R3];
|
||||
// TODO: LT, EQ, GT, C0, OV
|
||||
break;
|
||||
case 0xd3: // cli: compare logical immediate
|
||||
{
|
||||
// LT, EQ, GT
|
||||
m_scr[CS] &= ~(7U << GT);
|
||||
|
||||
if (m_gpr[R2] == u32(s32(s16(i))))
|
||||
m_scr[CS] |= (1U << EQ);
|
||||
else
|
||||
if (m_gpr[R2] < u32(s32(s16(i))))
|
||||
m_scr[CS] |= (1U << LT);
|
||||
else
|
||||
m_scr[CS] |= (1U << GT);
|
||||
}
|
||||
break;
|
||||
case 0xd4: // ci: compare immediate
|
||||
{
|
||||
// LT, EQ, GT
|
||||
m_scr[CS] &= ~(7U << GT);
|
||||
|
||||
if (m_gpr[R2] == s32(s16(i)))
|
||||
m_scr[CS] |= (1U << EQ);
|
||||
else
|
||||
if (s32(m_gpr[R2]) < s16(i))
|
||||
m_scr[CS] |= (1U << LT);
|
||||
else
|
||||
m_scr[CS] |= (1U << GT);
|
||||
}
|
||||
break;
|
||||
case 0xd5: // niuz: and immediate upper half extended zeroes
|
||||
m_gpr[R2] = (u32(i) << 16) & m_gpr[R3];
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xd6: // niuo: and immediate upper half extended ones
|
||||
m_gpr[R2] = ((u32(i) << 16) | 0x0000'ffffU) & m_gpr[R3];
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xd7: // xiu: exclusive or immediate upper half
|
||||
m_gpr[R2] = (u32(i) << 16) ^ m_gpr[R3];
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xd8: // cau: compute address upper half
|
||||
m_gpr[R2] = r3 + (u32(i) << 16);
|
||||
break;
|
||||
case 0xd9: // stm: store multiple
|
||||
for (unsigned reg = R2, offset = 0; reg < 16; reg++, offset += 4)
|
||||
space(AS_PROGRAM).write_dword(r3 + s16(i) + offset, m_gpr[reg]);
|
||||
break;
|
||||
case 0xda: // lh: load half
|
||||
m_gpr[R2] = space(AS_PROGRAM).read_word(r3 + s16(i));
|
||||
break;
|
||||
case 0xdb: // iow: input/output write
|
||||
// TODO: program check on upper address byte set
|
||||
space(2).write_dword(r3 + i, m_gpr[R2]);
|
||||
break;
|
||||
case 0xdc: // sth: store half
|
||||
space(AS_PROGRAM).write_word(r3 + s16(i), m_gpr[R2]);
|
||||
break;
|
||||
case 0xdd: // st: store
|
||||
space(AS_PROGRAM).write_dword(r3 + s16(i), m_gpr[R2]);
|
||||
break;
|
||||
case 0xde: // stc: store character
|
||||
space(AS_PROGRAM).write_byte(r3 + s16(i), m_gpr[R2]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x9:
|
||||
case 0xa:
|
||||
case 0xb:
|
||||
case 0xe:
|
||||
case 0xf: // R format
|
||||
switch (op >> 8)
|
||||
{
|
||||
case 0x90: // ais: add immediate short
|
||||
m_gpr[R2] += R3;
|
||||
// TODO: LT, EQ, GT, C0, OV
|
||||
break;
|
||||
case 0x91: // inc: increment
|
||||
m_gpr[R2] += R3;
|
||||
break;
|
||||
case 0x92: // sis: subtract immediate short
|
||||
m_gpr[R2] -= R3;
|
||||
// TODO: LT, EQ, GT, C0, OV
|
||||
break;
|
||||
case 0x93: // dec: decrement
|
||||
m_gpr[R2] -= R3;
|
||||
break;
|
||||
case 0x94: // cis: compare immediate short
|
||||
{
|
||||
// LT, EQ, GT
|
||||
m_scr[CS] &= ~(7U << GT);
|
||||
|
||||
if (m_gpr[R2] == R3)
|
||||
m_scr[CS] |= (1U << EQ);
|
||||
else
|
||||
if (s32(m_gpr[R2]) < R3)
|
||||
m_scr[CS] |= (1U << LT);
|
||||
else
|
||||
m_scr[CS] |= (1U << GT);
|
||||
}
|
||||
break;
|
||||
case 0x95: // clrsb: clear scr bit
|
||||
m_scr[R2] &= ~(0x0000'8000U >> R3);
|
||||
// TODO: side effects?
|
||||
break;
|
||||
case 0x96: // mfs: move from scr
|
||||
m_gpr[R3] = m_scr[R2];
|
||||
break;
|
||||
case 0x97: // setsb: set scr bit
|
||||
m_scr[R2] |= (0x0000'8000U >> R3);
|
||||
// TODO: side effects, reserved bits
|
||||
break;
|
||||
case 0x98: // clrbu: clear bit upper half
|
||||
m_gpr[R2] &= ~(0x8000'0000U >> R3);
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0x99: // clrbl: clear bit lower half
|
||||
m_gpr[R2] &= ~(0x0000'8000U >> R3);
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0x9a: // setbu: set bit upper half
|
||||
m_gpr[R2] |= (0x8000'0000U >> R3);
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0x9b: // setbl: set bit lower half
|
||||
m_gpr[R2] |= (0x0000'8000U >> R3);
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0x9c: // mftbiu: move from test bit immediate upper half
|
||||
if (BIT(m_scr[CS], TB))
|
||||
m_gpr[R2] |= (0x8000'0000U >> R3);
|
||||
else
|
||||
m_gpr[R2] &= ~(0x8000'0000U >> R3);
|
||||
break;
|
||||
case 0x9d: // mftbil: move from test bit immediate lower half
|
||||
if (BIT(m_scr[CS], TB))
|
||||
m_gpr[R2] |= (0x0000'8000U >> R3);
|
||||
else
|
||||
m_gpr[R2] &= ~(0x0000'8000U >> R3);
|
||||
break;
|
||||
case 0x9e: // mttbiu: move to test bit immediate upper half
|
||||
if (m_gpr[R2] & (0x8000'0000U >> R3))
|
||||
m_scr[CS] |= (1U << TB);
|
||||
else
|
||||
m_scr[CS] &= ~(1U << TB);
|
||||
break;
|
||||
case 0x9f: // mttbil: move to test bit immediate lower half
|
||||
if (m_gpr[R2] & (0x0000'8000U >> R3))
|
||||
m_scr[CS] |= (1U << TB);
|
||||
else
|
||||
m_scr[CS] &= ~(1U << TB);
|
||||
break;
|
||||
|
||||
case 0xa0: // sari: shift algebraic right immediate
|
||||
m_gpr[R2] = s32(m_gpr[R2]) >> R3;
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xa1: // sari16: shift algebraic right immediate plus sixteen
|
||||
m_gpr[R2] = s32(m_gpr[R2]) >> (R3 + 16);
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
|
||||
case 0xa4: // lis: load immediate short
|
||||
m_gpr[R2] = R3;
|
||||
break;
|
||||
|
||||
case 0xa8: // sri: shift right immediate
|
||||
m_gpr[R2] >>= R3;
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xa9: // sri16: shift right immediate plus sixteen
|
||||
m_gpr[R2] >>= (R3 + 16);
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xaa: // sli: shift left immediate
|
||||
m_gpr[R2] <<= R3;
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xab: // sli16: shift left immediate plus sixteen
|
||||
m_gpr[R2] <<= (R3 + 16);
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xac: // srpi: shift right paired immediate
|
||||
m_gpr[R2 ^ 1] = m_gpr[R2] >> R3;
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xad: // srpi16: shift right paired immediate plus sixteen
|
||||
m_gpr[R2 ^ 1] = m_gpr[R2] >> (R3 + 16);
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xae: // slpi: shift left paired immediate
|
||||
m_gpr[R2 ^ 1] = m_gpr[R2] << R3;
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xaf: // slpi16: shift left paired immediate plus sixteen
|
||||
m_gpr[R2 ^ 1] = m_gpr[R2] << (R3 + 16);
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
|
||||
case 0xb0: // sar: shift algebraic right
|
||||
m_gpr[R2] = s32(m_gpr[R2]) >> (m_gpr[R3] & 63);
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xb1: // exts: extend sign
|
||||
m_gpr[R2] = s16(m_gpr[R3]);
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xb2: // sf: subtract from
|
||||
m_gpr[R2] = m_gpr[R3] - m_gpr[R2];
|
||||
// TODO: LT, EQ, GT, C0, OV
|
||||
break;
|
||||
case 0xb3: // cl: compare logical
|
||||
{
|
||||
// LT, EQ, GT
|
||||
m_scr[CS] &= ~(7U << GT);
|
||||
|
||||
if (m_gpr[R2] == m_gpr[R3])
|
||||
m_scr[CS] |= (1U << EQ);
|
||||
else
|
||||
if (m_gpr[R2] < m_gpr[R3])
|
||||
m_scr[CS] |= (1U << LT);
|
||||
else
|
||||
m_scr[CS] |= (1U << GT);
|
||||
}
|
||||
break;
|
||||
case 0xb4: // c: compare
|
||||
{
|
||||
// LT, EQ, GT
|
||||
m_scr[CS] &= ~(7U << GT);
|
||||
|
||||
if (m_gpr[R2] == m_gpr[R3])
|
||||
m_scr[CS] |= (1U << EQ);
|
||||
else
|
||||
if (s32(m_gpr[R2]) < s32(m_gpr[R3]))
|
||||
m_scr[CS] |= (1U << LT);
|
||||
else
|
||||
m_scr[CS] |= (1U << GT);
|
||||
}
|
||||
break;
|
||||
case 0xb5: // mts: move to scr
|
||||
m_scr[R2] = m_gpr[R3];
|
||||
break;
|
||||
//case 0xb6: // d: divide step
|
||||
|
||||
case 0xb8: // sr: shift right
|
||||
m_gpr[R2] >>= (m_gpr[R3] & 63);
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xb9: // srp: shift right paired
|
||||
m_gpr[R2 ^ 1] = m_gpr[R2] >> (m_gpr[R3] & 63);
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xba: // sl: shift left
|
||||
m_gpr[R2] <<= (m_gpr[R3] & 63);
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xbb: // slp: shift left paired
|
||||
m_gpr[R2 ^ 1] = m_gpr[R2] << (m_gpr[R3] & 63);
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xbc: // mftb: move from test bit
|
||||
if (BIT(m_scr[CS], TB))
|
||||
m_gpr[R2] |= (0x8000'0000U >> (m_gpr[R3] & 31));
|
||||
else
|
||||
m_gpr[R2] &= ~(0x8000'0000U >> (m_gpr[R3] & 31));
|
||||
break;
|
||||
//case 0xbd: // tgte: trap if register greater than or equal
|
||||
//case 0xbe: // tlt: trap if register less than
|
||||
case 0xbf: // mttb: move to test bit
|
||||
if (m_gpr[R2] & (0x8000'0000U >> (m_gpr[R3] & 31)))
|
||||
m_scr[CS] |= (1U << TB);
|
||||
else
|
||||
m_scr[CS] &= ~(1U << TB);
|
||||
break;
|
||||
|
||||
case 0xe0: // abs: absolute
|
||||
if (s32(m_gpr[R3]) < 0)
|
||||
m_gpr[R2] = -s32(m_gpr[R3]);
|
||||
else
|
||||
m_gpr[R2] = m_gpr[R3];
|
||||
// TODO: test for maximum negative
|
||||
// TODO: LT, EQ, GT, C0, OV
|
||||
break;
|
||||
case 0xe1: // a: add
|
||||
m_gpr[R2] += m_gpr[R3];
|
||||
// TODO: LT, EQ, GT, C0, OV
|
||||
break;
|
||||
case 0xe2: // s: subtract
|
||||
m_gpr[R2] -= m_gpr[R3];
|
||||
// TODO: LT, EQ, GT, C0, OV
|
||||
break;
|
||||
case 0xe3: // o: or
|
||||
m_gpr[R2] |= m_gpr[R3];
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xe4: // twoc: twos complement
|
||||
m_gpr[R2] = -m_gpr[R3];
|
||||
// TODO: LT, EQ, GT, C0, OV
|
||||
break;
|
||||
case 0xe5: // n: and
|
||||
m_gpr[R2] &= m_gpr[R3];
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
//case 0xe6: // m: multiply step
|
||||
case 0xe7: // x: exclusive or
|
||||
m_gpr[R2] ^= m_gpr[R3];
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xe8: // bnbr: branch on not condition bit
|
||||
if (!BIT(m_scr[CS], R2 ^ 15))
|
||||
m_scr[IAR] = m_gpr[R3] & ~1;
|
||||
break;
|
||||
case 0xe9: // bnbrx: branch on not condition bit with execute
|
||||
if (!BIT(m_scr[CS], R2 ^ 15))
|
||||
{
|
||||
m_branch_target = m_gpr[R3] & ~1;
|
||||
m_branch_state = BRANCH;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xeb: // lhs: load half short
|
||||
m_gpr[R2] = space(AS_PROGRAM).read_word(m_gpr[R3]);
|
||||
break;
|
||||
case 0xec: // balr: branch and link
|
||||
m_gpr[R2] = m_scr[IAR];
|
||||
m_scr[IAR] = m_gpr[R3] & ~1;
|
||||
break;
|
||||
case 0xed: // balrx: branch and link with execute
|
||||
m_gpr[R2] = m_scr[IAR] + 4;
|
||||
m_branch_target = m_gpr[R3] & ~1;
|
||||
m_branch_state = BRANCH;
|
||||
break;
|
||||
case 0xee: // bbr: branch on condition bit
|
||||
if (BIT(m_scr[CS], R2 ^ 15))
|
||||
m_scr[IAR] = m_gpr[R3] & ~1;
|
||||
break;
|
||||
case 0xef: // bbrx: branch on condition bit with execute
|
||||
if (BIT(m_scr[CS], R2 ^ 15))
|
||||
{
|
||||
m_branch_target = m_gpr[R3] & ~1;
|
||||
m_branch_state = BRANCH;
|
||||
}
|
||||
break;
|
||||
|
||||
//case 0xf0: // wait: wait
|
||||
case 0xf1: // ae: add extended
|
||||
m_gpr[R2] += m_gpr[R3] + BIT(m_scr[CS], C0);
|
||||
// TODO: LT, EQ, GT, C0, OV
|
||||
break;
|
||||
case 0xf2: // se: subtract extended
|
||||
m_gpr[R2] -= m_gpr[R3] + BIT(m_scr[CS], C0);
|
||||
// TODO: LT, EQ, GT, C0, OV
|
||||
break;
|
||||
case 0xf3: // ca16: compute address 16-bit
|
||||
m_gpr[R2] = (m_gpr[R3] & 0xffff'0000U) | (u16(m_gpr[R2]) + u16(m_gpr[R3]));
|
||||
break;
|
||||
case 0xf4: // onec: ones complement
|
||||
m_gpr[R2] = ~m_gpr[R3];
|
||||
// TODO: LT, EQ, GT
|
||||
break;
|
||||
case 0xf5: // clz: count leading zeros
|
||||
m_gpr[R2] = count_leading_zeros(u16(m_gpr[R3])) - 16;
|
||||
break;
|
||||
|
||||
case 0xf9: // mc03: move character zero from three
|
||||
m_gpr[R2] = (m_gpr[R2] & 0x00ff'ffffU) | ((m_gpr[R3] & 0x0000'000ffU) << 24);
|
||||
break;
|
||||
case 0xfa: // mc13: move character one from three
|
||||
m_gpr[R2] = (m_gpr[R2] & 0xff00'ffffU) | ((m_gpr[R3] & 0x0000'000ffU) << 16);
|
||||
break;
|
||||
case 0xfb: // mc23: move character two from three
|
||||
m_gpr[R2] = (m_gpr[R2] & 0xffff'00ffU) | ((m_gpr[R3] & 0x0000'000ffU) << 8);
|
||||
break;
|
||||
case 0xfc: // mc33: move character three from three
|
||||
m_gpr[R2] = (m_gpr[R2] & 0xffff'ff00U) | ((m_gpr[R3] & 0x0000'000ffU) << 0);
|
||||
break;
|
||||
case 0xfd: // mc30: move character three from zero
|
||||
m_gpr[R2] = (m_gpr[R2] & 0xffff'ff00U) | u8(m_gpr[R3] >> 24);
|
||||
break;
|
||||
case 0xfe: // mc31: move character three from one
|
||||
m_gpr[R2] = (m_gpr[R2] & 0xffff'ff00U) | u8(m_gpr[R3] >> 16);
|
||||
break;
|
||||
case 0xff: // mc32: move character three from two
|
||||
m_gpr[R2] = (m_gpr[R2] & 0xffff'ff00U) | u8(m_gpr[R3] >> 8);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// update iar and branch state
|
||||
switch (m_branch_state)
|
||||
{
|
||||
case SUBJECT:
|
||||
m_scr[IAR] = m_branch_target;
|
||||
m_branch_state = NONE;
|
||||
break;
|
||||
|
||||
case BRANCH:
|
||||
m_branch_state = SUBJECT;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void romp_device::execute_set_input(int irqline, int state)
|
||||
{
|
||||
// enable debugger interrupt breakpoints
|
||||
if (state)
|
||||
standard_irq_callback(irqline);
|
||||
}
|
||||
|
||||
device_memory_interface::space_config_vector romp_device::memory_space_config() const
|
||||
{
|
||||
return space_config_vector {
|
||||
std::make_pair(AS_PROGRAM, &m_mem_config),
|
||||
std::make_pair(AS_IO, &m_io_config)
|
||||
};
|
||||
}
|
||||
|
||||
bool romp_device::memory_translate(int spacenum, int intention, offs_t &address)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<util::disasm_interface> romp_device::create_disassembler()
|
||||
{
|
||||
return std::make_unique<romp_disassembler>();
|
||||
}
|
96
src/devices/cpu/romp/romp.h
Normal file
96
src/devices/cpu/romp/romp.h
Normal file
@ -0,0 +1,96 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Patrick Mackinlay
|
||||
|
||||
#ifndef MAME_CPU_ROMP_ROMP_H
|
||||
#define MAME_CPU_ROMP_ROMP_H
|
||||
|
||||
#pragma once
|
||||
|
||||
class romp_device : public cpu_device
|
||||
{
|
||||
public:
|
||||
romp_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
|
||||
|
||||
protected:
|
||||
enum registers : unsigned
|
||||
{
|
||||
ROMP_SCR = 0,
|
||||
ROMP_GPR = 16,
|
||||
};
|
||||
|
||||
enum scr : unsigned
|
||||
{
|
||||
COS = 6, // counter source
|
||||
COU = 7, // counter
|
||||
TS = 8, // timer status
|
||||
MQ = 10, // multiplier quotient
|
||||
MCS = 11, // machine check status
|
||||
PCS = 11, // program check status
|
||||
IRB = 12, // interrupt request buffer
|
||||
IAR = 13, // instruction address register
|
||||
ICS = 14, // interrupt control status
|
||||
CS = 15, // condition status
|
||||
};
|
||||
|
||||
enum cs : unsigned
|
||||
{
|
||||
TB = 0, // test bit
|
||||
OV = 1, // overflow
|
||||
// reserved
|
||||
C0 = 3, // carry zero
|
||||
GT = 4, // greater than
|
||||
EQ = 5, // equal
|
||||
LT = 6, // less than
|
||||
PZ = 7, // permanent zero
|
||||
};
|
||||
|
||||
// device_t overrides
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
// device_execute_interface overrides
|
||||
virtual u32 execute_min_cycles() const noexcept override { return 1; }
|
||||
virtual u32 execute_max_cycles() const noexcept override { return 40; }
|
||||
virtual u32 execute_input_lines() const noexcept override { return 6; }
|
||||
virtual void execute_run() override;
|
||||
virtual void execute_set_input(int inputnum, int state) override;
|
||||
|
||||
// device_memory_interface overrides
|
||||
virtual space_config_vector memory_space_config() const override;
|
||||
virtual bool memory_translate(int spacenum, int intention, offs_t &address) override;
|
||||
|
||||
// device_disasm_interface overrides
|
||||
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
|
||||
|
||||
private:
|
||||
// insruction decode helpers
|
||||
u32 r3_0(unsigned reg) const { return reg ? m_gpr[reg] : 0; }
|
||||
s32 ji(u16 op) const { return s32(s8(op)) << 1; }
|
||||
u32 ba(u16 hi, u16 lo) const { return ((u32(hi) << 16) | lo) & 0x00ff'fffeU; }
|
||||
s32 bi(u16 hi, u16 lo) const { return s32((u32(hi) << 16 | lo) << 12) >> 11; }
|
||||
|
||||
// address spaces
|
||||
address_space_config const m_mem_config;
|
||||
address_space_config const m_io_config;
|
||||
|
||||
// mame state
|
||||
int m_icount;
|
||||
|
||||
// core registers
|
||||
u32 m_scr[16];
|
||||
u32 m_gpr[16];
|
||||
|
||||
// internal state
|
||||
enum branch_state : unsigned
|
||||
{
|
||||
NONE = 0,
|
||||
SUBJECT = 1, // branch subject instruction active
|
||||
BRANCH = 2, // branch instruction active
|
||||
}
|
||||
m_branch_state;
|
||||
u32 m_branch_target;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(ROMP, romp_device)
|
||||
|
||||
#endif // MAME_CPU_ROMP_ROMP_H
|
220
src/devices/cpu/romp/rompdasm.cpp
Normal file
220
src/devices/cpu/romp/rompdasm.cpp
Normal file
@ -0,0 +1,220 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Patrick Mackinlay
|
||||
|
||||
#include "emu.h"
|
||||
#include "rompdasm.h"
|
||||
|
||||
#define R2 ((op >> 4) & 15)
|
||||
#define R3 (op & 15)
|
||||
#define R3_0(i, r3) (r3 ? util::string_format("0x%x(%s)", i, gpr[r3]) : util::string_format("0x%x", i))
|
||||
#define R3_X(r2, r3) (r3 ? util::string_format("%s(%s)", gpr[r2], gpr[r3]) : util::string_format("%s", gpr[r2]))
|
||||
|
||||
static char const *const gpr[16] =
|
||||
{
|
||||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
||||
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
|
||||
};
|
||||
|
||||
static char const *const scr[16] =
|
||||
{
|
||||
"SCR0", "SCR1", "SCR2", "SCR3", "SCR4", "SCR5", "CNT", "COU",
|
||||
"TS", "SCR9", "MQ", "MCS", "IRB", "IAR", "ICS", "CS",
|
||||
};
|
||||
|
||||
static char const *const cc3[8] =
|
||||
{
|
||||
"pz", "lt", "eq", "gt", "c0", "?", "ov", "tb",
|
||||
};
|
||||
|
||||
static char const *const cc4[16] =
|
||||
{
|
||||
"?", "?", "?", "?", "?", "?", "?", "?",
|
||||
"pz", "lt", "eq", "gt", "c0", "?", "ov", "tb"
|
||||
};
|
||||
|
||||
offs_t romp_disassembler::disassemble(std::ostream &stream, offs_t pc, data_buffer const &opcodes, data_buffer const ¶ms)
|
||||
{
|
||||
u16 const op = opcodes.r16(pc);
|
||||
unsigned bytes = 2;
|
||||
u32 flags = 0;
|
||||
|
||||
switch (op >> 12)
|
||||
{
|
||||
case 0x0:
|
||||
// JI format
|
||||
if (op & 0x0800)
|
||||
util::stream_format(stream, "jb %s,0x%x", cc3[(op >> 8) & 7], pc + (s32(s8(op)) << 1)); // jump on condition bit
|
||||
else
|
||||
util::stream_format(stream, "jnb %s,0x%x", cc3[(op >> 8) & 7], pc + (s32(s8(op)) << 1)); // jump on not condition bit
|
||||
break;
|
||||
|
||||
// DS format
|
||||
case 0x1: util::stream_format(stream, "stcs %s,%s", gpr[R2], R3_0((op >> 8) & 15, R3)); break; // store character short
|
||||
case 0x2: util::stream_format(stream, "sths %s,%s", gpr[R2], R3_0((op >> 7) & 30, R3)); break; // store half short
|
||||
case 0x3: util::stream_format(stream, "sts %s,%s", gpr[R2], R3_0((op >> 6) & 60, R3)); break; // store short
|
||||
case 0x4: util::stream_format(stream, "lcs %s,%s", gpr[R2], R3_0((op >> 8) & 15, R3)); break; // load character short
|
||||
case 0x5: util::stream_format(stream, "lhas %s,%s", gpr[R2], R3_0((op >> 7) & 30, R3)); break; // load half algebraic short
|
||||
case 0x6: util::stream_format(stream, "cas %s,%s", (op >> 8) & 15, R3_X(R2, R3)); break; // compute address short (X format)
|
||||
case 0x7: util::stream_format(stream, "ls %s,%s", gpr[R2], R3_0((op >> 6) & 60, R3)); break; // load short
|
||||
|
||||
case 0x8:
|
||||
// BI, BA format
|
||||
{
|
||||
u32 const b = opcodes.r32(pc);
|
||||
bytes = 4;
|
||||
|
||||
switch (op >> 8)
|
||||
{
|
||||
// 80-87
|
||||
case 0x88: util::stream_format(stream, "bnb %s,0x%x", cc4[R2], pc + (s32(b << 12) >> 11)); break; // branch on not condition bit immediate
|
||||
case 0x89: util::stream_format(stream, "bnbx %s,0x%x", cc4[R2], pc + (s32(b << 12) >> 11)); break; // branch on not condition bit immediate with execute
|
||||
case 0x8a: util::stream_format(stream, "bala 0x%x", b & 0x00ffffffU); flags |= STEP_OVER; break; // branch and link absolute
|
||||
case 0x8b: util::stream_format(stream, "balax 0x%x", b & 0x00ffffffU); flags |= STEP_OVER | step_over_extra(1); break; // branch and link absolute with execute
|
||||
case 0x8c: util::stream_format(stream, "bali %s,0x%x", gpr[R2], pc + (s32(b << 12) >> 11)); flags |= STEP_OVER; break; // branch and link immediate
|
||||
case 0x8d: util::stream_format(stream, "balix %s,0x%x", gpr[R2], pc + (s32(b << 12) >> 11)); flags |= STEP_OVER | step_over_extra(1); break; // branch and link immediate with execute
|
||||
case 0x8e: util::stream_format(stream, "bb %s,0x%x", cc4[R2], pc + (s32(b << 12) >> 11)); break; // branch on condition bit immediate
|
||||
case 0x8f: util::stream_format(stream, "bbx %s,0x%x", cc4[R2], pc + (s32(b << 12) >> 11)); break; // branch on condition bit immediate with execute
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xc:
|
||||
case 0xd:
|
||||
// D format
|
||||
{
|
||||
u16 const i = opcodes.r16(pc + 2);
|
||||
bytes = 4;
|
||||
|
||||
switch (op >> 8)
|
||||
{
|
||||
case 0xc0: util::stream_format(stream, "svc %s", R3_0(i, R3)); flags |= STEP_OVER; break; // supervisor call
|
||||
case 0xc1: util::stream_format(stream, "ai %s,%s,#0x%x", gpr[R2], gpr[R3], s16(i)); break; // add immediate
|
||||
case 0xc2: util::stream_format(stream, "cal16 %s,%s", gpr[R2], R3_0(i, R3)); break; // compute address lower half 16-bit
|
||||
case 0xc3: util::stream_format(stream, "oiu %s,%s,#0x%x", gpr[R2], gpr[R3], i); break; // or immediate upper half
|
||||
case 0xc4: util::stream_format(stream, "oil %s,%s,#0x%x", gpr[R2], gpr[R3], i); break; // or immediate lower half
|
||||
case 0xc5: util::stream_format(stream, "nilz %s,%s,#0x%x", gpr[R2], gpr[R3], i); break; // and immediate lower half extended zeroes
|
||||
case 0xc6: util::stream_format(stream, "nilo %s,%s,#0x%x", gpr[R2], gpr[R3], i); break; // and immediate lower half extended ones
|
||||
case 0xc7: util::stream_format(stream, "xil %s,%s,#0x%x", gpr[R2], gpr[R3], i); break; // exclusive or immediate lower half
|
||||
case 0xc8: util::stream_format(stream, "cal %s,%s", gpr[R2], R3_0(i, R3)); break; // compute address lower half
|
||||
case 0xc9: util::stream_format(stream, "lm %s,%s", gpr[R2], R3_0(i, R3)); break; // load multiple
|
||||
case 0xca: util::stream_format(stream, "lha %s,%s", gpr[R2], R3_0(i, R3)); break; // load half algebraic
|
||||
case 0xcb: util::stream_format(stream, "ior %s,%s", gpr[R2], R3_0(i, R3)); break; // input/output read
|
||||
case 0xcc: util::stream_format(stream, "ti %s%s%s,%s,#0x%x",
|
||||
BIT(op, 6) ? "l":"", BIT(op, 5) ? "e" : "", BIT(op, 6) ? "g" : "", gpr[R3], i); break; // trap on condition immediate
|
||||
case 0xcd: util::stream_format(stream, "l %s,%s", gpr[R2], R3_0(i, R3)); break; // load
|
||||
case 0xce: util::stream_format(stream, "lc %s,%s", gpr[R2], R3_0(i, R3)); break; // load character
|
||||
case 0xcf: util::stream_format(stream, "tsh %s,%s", gpr[R2], R3_0(i, R3)); break; // test and set half
|
||||
|
||||
case 0xd0: util::stream_format(stream, "lps %s", R3_0(i, R3)); flags |= STEP_OUT; break; // load program status
|
||||
case 0xd1: util::stream_format(stream, "aei %s,%s,#0x%x", gpr[R2], gpr[R3], s16(i)); break; // add extended immediate
|
||||
case 0xd2: util::stream_format(stream, "sfi %s,%s,#0x%x", gpr[R2], gpr[R3], s16(i)); break; // subtract from immediate
|
||||
case 0xd3: util::stream_format(stream, "cli %s,#0x%x", gpr[R3], s16(i)); break; // compare logical immediate
|
||||
case 0xd4: util::stream_format(stream, "ci %s,#0x%x", gpr[R3], s16(i)); break; // compare immediate
|
||||
case 0xd5: util::stream_format(stream, "niuz %s,%s,#0x%x", gpr[R2], gpr[R3], i); break; // and immediate upper half extended zeroes
|
||||
case 0xd6: util::stream_format(stream, "niuo %s,%s,#0x%x", gpr[R2], gpr[R3], i); break; // and immediate upper half extended ones
|
||||
case 0xd7: util::stream_format(stream, "xiu %s,%s,#0x%x", gpr[R2], gpr[R3], i); break; // exclusive or immediate upper half
|
||||
case 0xd8: util::stream_format(stream, "cau %s,%s", gpr[R2], R3_0(i, R3)); break; // compute address upper half
|
||||
case 0xd9: util::stream_format(stream, "stm %s,%s", gpr[R2], R3_0(i, R3)); break; // store multiple
|
||||
case 0xda: util::stream_format(stream, "lh %s,%s", gpr[R2], R3_0(i, R3)); break; // load half
|
||||
case 0xdb: util::stream_format(stream, "iow %s,%s", gpr[R2], R3_0(i, R3)); break; // input/output write
|
||||
case 0xdc: util::stream_format(stream, "sth %s,%s", gpr[R2], R3_0(i, R3)); break; // store half
|
||||
case 0xdd: util::stream_format(stream, "st %s,%s", gpr[R2], R3_0(i, R3)); break; // store
|
||||
case 0xde: util::stream_format(stream, "stc %s,%s", gpr[R2], R3_0(i, R3)); break; // store character
|
||||
// df
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x9:
|
||||
case 0xa:
|
||||
case 0xb:
|
||||
case 0xe:
|
||||
case 0xf:
|
||||
// R format
|
||||
switch (op >> 8)
|
||||
{
|
||||
case 0x90: util::stream_format(stream, "ais %s,#0x%x", gpr[R2], R3); break; // add immediate short
|
||||
case 0x91: util::stream_format(stream, "inc %s,#0x%x", gpr[R2], R3); break; // increment
|
||||
case 0x92: util::stream_format(stream, "sis %s,#0x%x", gpr[R2], R3); break; // subtract immediate short
|
||||
case 0x93: util::stream_format(stream, "dec %s,#0x%x", gpr[R2], R3); break; // decrement
|
||||
case 0x94: util::stream_format(stream, "cis %s,#0x%x", gpr[R2], R3); break; // compare immediate short
|
||||
case 0x95: util::stream_format(stream, "clrsb %s,#%d", scr[R2], R3); break; // clear scr bit
|
||||
case 0x96: util::stream_format(stream, "mfs %s,%s", scr[R2], gpr[R3]); break; // move from scr
|
||||
case 0x97: util::stream_format(stream, "setsb %s,#%d", scr[R2], R3); break; // set scr bit
|
||||
case 0x98: util::stream_format(stream, "clrbu %s,#%d", gpr[R2], R3); break; // clear bit upper half
|
||||
case 0x99: util::stream_format(stream, "clrbl %s,#%d", gpr[R2], R3); break; // clear bit lower half
|
||||
case 0x9a: util::stream_format(stream, "setbu %s,#%d", gpr[R2], R3); break; // set bit upper half
|
||||
case 0x9b: util::stream_format(stream, "setbl %s,#%d", gpr[R2], R3); break; // set bit lower half
|
||||
case 0x9c: util::stream_format(stream, "mftbiu %s,#%d", gpr[R2], R3); break; // move from test bit immediate upper half
|
||||
case 0x9d: util::stream_format(stream, "mftbil %s,#%d", gpr[R2], R3); break; // move from test bit immediate lower half
|
||||
case 0x9e: util::stream_format(stream, "mttbiu %s,#%d", gpr[R2], R3); break; // move to test bit immediate upper half
|
||||
case 0x9f: util::stream_format(stream, "mttbil %s,#%d", gpr[R2], R3); break; // move to test bit immediate lower half
|
||||
|
||||
case 0xa0: util::stream_format(stream, "sari %s,#%d", gpr[R2], R3); break; // shift algebraic right immediate
|
||||
case 0xa1: util::stream_format(stream, "sari16 %s,#%d", gpr[R2], R3); break; // shift algebraic right immediate plus sixteen
|
||||
// a2, a3
|
||||
case 0xa4: util::stream_format(stream, "lis %s,#%x", gpr[R2], R3); break; // load immediate short
|
||||
// a5, a6, a7
|
||||
case 0xa8: util::stream_format(stream, "sri %s,#%d", gpr[R2], R3); break; // shift right immediate
|
||||
case 0xa9: util::stream_format(stream, "sri16 %s,#%d", gpr[R2], R3); break; // shift right immediate plus sixteen
|
||||
case 0xaa: util::stream_format(stream, "sli %s,#%d", gpr[R2], R3); break; // shift left immediate
|
||||
case 0xab: util::stream_format(stream, "sli16 %s,#%d", gpr[R2], R3); break; // shift left immediate plus sixteen
|
||||
case 0xac: util::stream_format(stream, "srpi %s,#%d", gpr[R2], R3); break; // shift right paired immediate
|
||||
case 0xad: util::stream_format(stream, "srpi16 %s,#%d", gpr[R2], R3); break; // shift right paired immediate plus sixteen
|
||||
case 0xae: util::stream_format(stream, "slpi %s,#%d", gpr[R2], R3); break; // shift left paired immediate
|
||||
case 0xaf: util::stream_format(stream, "slpi16 %s,#%d", gpr[R2], R3); break; // shift left paired immediate plus sixteen
|
||||
|
||||
case 0xb0: util::stream_format(stream, "sar %s,%s", gpr[R2], gpr[R3]); break; // shift algebraic right
|
||||
case 0xb1: util::stream_format(stream, "exts %s,%s", gpr[R2], gpr[R3]); break; // extend sign
|
||||
case 0xb2: util::stream_format(stream, "sf %s,%s", gpr[R2], gpr[R3]); break; // subtract from
|
||||
case 0xb3: util::stream_format(stream, "cl %s,%s", gpr[R2], gpr[R3]); break; // compare logical
|
||||
case 0xb4: util::stream_format(stream, "c %s,%s", gpr[R2], gpr[R3]); break; // compare
|
||||
case 0xb5: util::stream_format(stream, "mts %s,%s", scr[R2], gpr[R3]); break; // move to scr
|
||||
case 0xb6: util::stream_format(stream, "d %s,%s", gpr[R2], gpr[R3]); break; // divide step
|
||||
// b7
|
||||
case 0xb8: util::stream_format(stream, "sr %s,%s", gpr[R2], gpr[R3]); break; // shift right
|
||||
case 0xb9: util::stream_format(stream, "srp %s,%s", gpr[R2], gpr[R3]); break; // shift right paired
|
||||
case 0xba: util::stream_format(stream, "sl %s,%s", gpr[R2], gpr[R3]); break; // shift left
|
||||
case 0xbb: util::stream_format(stream, "slp %s,%s", gpr[R2], gpr[R3]); break; // shift left paired
|
||||
case 0xbc: util::stream_format(stream, "mftb %s,%s", gpr[R2], gpr[R3]); break; // move from test bit
|
||||
case 0xbd: util::stream_format(stream, "tgte %s,%s", gpr[R2], gpr[R3]); break; // trap if register greater than or equal
|
||||
case 0xbe: util::stream_format(stream, "tlt %s,%s", gpr[R2], gpr[R3]); break; // trap if register less than
|
||||
case 0xbf: util::stream_format(stream, "mttb %s,%s", gpr[R2], gpr[R3]); break; // move to test bit
|
||||
|
||||
case 0xe0: util::stream_format(stream, "abs %s,%s", gpr[R2], gpr[R3]); break; // absolute
|
||||
case 0xe1: util::stream_format(stream, "a %s,%s", gpr[R2], gpr[R3]); break; // add
|
||||
case 0xe2: util::stream_format(stream, "s %s,%s", gpr[R2], gpr[R3]); break; // subtract
|
||||
case 0xe3: util::stream_format(stream, "o %s,%s", gpr[R2], gpr[R3]); break; // or
|
||||
case 0xe4: util::stream_format(stream, "twoc %s,%s", gpr[R2], gpr[R3]); break; // twos complement
|
||||
case 0xe5: util::stream_format(stream, "n %s,%s", gpr[R2], gpr[R3]); break; // and
|
||||
case 0xe6: util::stream_format(stream, "m %s,%s", gpr[R2], gpr[R3]); break; // multiply step
|
||||
case 0xe7: util::stream_format(stream, "x %s,%s", gpr[R2], gpr[R3]); break; // exclusive or
|
||||
case 0xe8: util::stream_format(stream, "bnbr %s,%s", cc4[R2], gpr[R3]); break; // branch on not condition bit
|
||||
case 0xe9: util::stream_format(stream, "bnbrx %s,%s", cc4[R2], gpr[R3]); break; // branch on not condition bit with execute
|
||||
// ea
|
||||
case 0xeb: util::stream_format(stream, "lhs %s,(%s)", gpr[R2], gpr[R3]); break; // load half short
|
||||
case 0xec: util::stream_format(stream, "balr %s,%s", gpr[R2], gpr[R3]); flags |= STEP_OVER; break; // branch and link
|
||||
case 0xed: util::stream_format(stream, "balrx %s,%s", gpr[R2], gpr[R3]); flags |= STEP_OVER | step_over_extra(1); break; // branch and link with execute
|
||||
case 0xee: util::stream_format(stream, "bbr %s,%s", cc4[R2], gpr[R3]); break; // branch on condition bit
|
||||
case 0xef: util::stream_format(stream, "bbrx %s,%s", cc4[R2], gpr[R3]); break; // branch on condition bit with execute
|
||||
|
||||
case 0xf0: util::stream_format(stream, "wait"); break; // wait
|
||||
case 0xf1: util::stream_format(stream, "ae %s,%s", gpr[R2], gpr[R3]); break; // add extended
|
||||
case 0xf2: util::stream_format(stream, "se %s,%s", gpr[R2], gpr[R3]); break; // subtract extended
|
||||
case 0xf3: util::stream_format(stream, "ca16 %s,%s", gpr[R2], gpr[R3]); break; // compute address 16-bit
|
||||
case 0xf4: util::stream_format(stream, "onec %s,%s", gpr[R2], gpr[R3]); break; // ones complement
|
||||
case 0xf5: util::stream_format(stream, "clz %s,%s", gpr[R2], gpr[R3]); break; // count leading zeros
|
||||
// f6, f7, f8
|
||||
case 0xf9: util::stream_format(stream, "mc03 %s,%s", gpr[R2], gpr[R3]); break; // move character zero from three
|
||||
case 0xfa: util::stream_format(stream, "mc13 %s,%s", gpr[R2], gpr[R3]); break; // move character one from three
|
||||
case 0xfb: util::stream_format(stream, "mc23 %s,%s", gpr[R2], gpr[R3]); break; // move character two from three
|
||||
case 0xfc: util::stream_format(stream, "mc33 %s,%s", gpr[R2], gpr[R3]); break; // move character three from three
|
||||
case 0xfd: util::stream_format(stream, "mc30 %s,%s", gpr[R2], gpr[R3]); break; // move character three from zero
|
||||
case 0xfe: util::stream_format(stream, "mc31 %s,%s", gpr[R2], gpr[R3]); break; // move character three from one
|
||||
case 0xff: util::stream_format(stream, "mc32 %s,%s", gpr[R2], gpr[R3]); break; // move character three from two
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return bytes | flags | SUPPORTED;
|
||||
}
|
19
src/devices/cpu/romp/rompdasm.h
Normal file
19
src/devices/cpu/romp/rompdasm.h
Normal file
@ -0,0 +1,19 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:Patrick Mackinlay
|
||||
|
||||
#ifndef MAME_CPU_ROMP_ROMPDASM_H
|
||||
#define MAME_CPU_ROMP_ROMPDASM_H
|
||||
|
||||
#pragma once
|
||||
|
||||
class romp_disassembler : public util::disasm_interface
|
||||
{
|
||||
public:
|
||||
romp_disassembler() = default;
|
||||
virtual ~romp_disassembler() = default;
|
||||
|
||||
virtual offs_t disassemble(std::ostream &stream, offs_t pc, data_buffer const &opcodes, data_buffer const ¶ms) override;
|
||||
virtual u32 opcode_alignment() const override { return 2; }
|
||||
};
|
||||
|
||||
#endif // MAME_CPU_ROMP_ROMPDASM_H
|
@ -121,6 +121,7 @@ using util::BIT;
|
||||
#include "cpu/pps4/pps4dasm.h"
|
||||
#include "cpu/psx/psxdasm.h"
|
||||
#include "cpu/rii/riidasm.h"
|
||||
#include "cpu/romp/rompdasm.h"
|
||||
#include "cpu/rsp/rsp_dasm.h"
|
||||
#include "cpu/rx01/rx01dasm.h"
|
||||
#include "cpu/s2650/2650dasm.h"
|
||||
@ -471,6 +472,7 @@ static const dasm_table_entry dasm_table[] =
|
||||
{ "psxcpu", le, 0, []() -> util::disasm_interface * { return new psxcpu_disassembler; } },
|
||||
{ "r65c02", le, 0, []() -> util::disasm_interface * { return new r65c02_disassembler; } },
|
||||
{ "r65c19", le, 0, []() -> util::disasm_interface * { return new r65c19_disassembler; } },
|
||||
{ "romp", be, 0, []() -> util::disasm_interface * { return new romp_disassembler; } },
|
||||
{ "rsp", le, 0, []() -> util::disasm_interface * { return new rsp_disassembler; } },
|
||||
{ "rx01", le, 0, []() -> util::disasm_interface * { return new rx01_disassembler; } },
|
||||
{ "s2650", be, 0, []() -> util::disasm_interface * { return new s2650_disassembler(&s2650_unidasm); } },
|
||||
|
Loading…
Reference in New Issue
Block a user