New clones marked as NOT_WORKING

--------------------------------
TX-0 upgraded system (8 kWords of RAM, old order code)

* tx0_64kw: Swap LR and MBR when MLR and LMB are specified together
* tx0_8kw: Recognize a few more composite OPRs in disassembly
This commit is contained in:
AJR 2021-09-25 13:06:32 -04:00
parent 51a053d396
commit 34225baaab
9 changed files with 401 additions and 24 deletions

View File

@ -13,9 +13,10 @@ license:CC0
<description>Munching Squares</description>
<year>196?</year>
<publisher>MIT</publisher>
<info name="usage" value="Press read in switch, then restart after loader halts at 17777. Use TAC switches to vary display."/>
<info name="usage" value="Press read in switch, then restart after loader halts at 17777. Use TAC switches to vary display pattern."/>
<sharedfeat name="compatibility" value="NEWCODE"/>
<part name="ptp" interface="tx0_ptp">
<feature name="blocks_used" value="20-52, 17756-17777"/>
<dataarea name="ptap" size="327">
<rom name="bin_munchingSquares.bin" size="327" crc="54afd9a3" sha1="a7fc6d62ea1cef21f1563cb8b86a5e63198af0ae"/>
</dataarea>

View File

@ -16,7 +16,7 @@
#include "debugger.h"
#define LOG_RIM (1 << 1U)
//#define VERBOSE (LOG_RIM)
#define VERBOSE (LOG_RIM)
#include "logmacro.h"
@ -42,8 +42,9 @@
#define INCREMENT_PC_8KW (PC = (PC+1) & ADDRESS_MASK_8KW)
DEFINE_DEVICE_TYPE(TX0_8KW, tx0_8kw_device, "tx0_8kw_cpu", "MIT Lincoln Laboratory TX-0 8KW")
DEFINE_DEVICE_TYPE(TX0_64KW, tx0_64kw_device, "tx0_64kw_cpu", "MIT Lincoln Laboratory TX-0 64KW")
DEFINE_DEVICE_TYPE(TX0_8KW, tx0_8kw_device, "tx0_8kw_cpu", "MIT Lincoln Laboratory TX-0 8KW (new)")
DEFINE_DEVICE_TYPE(TX0_8KW_OLD, tx0_8kwo_device, "tx0_8kwo_cpu", "MIT Lincoln Laboratory TX-0 8KW (old)")
DEFINE_DEVICE_TYPE(TX0_64KW, tx0_64kw_device, "tx0_64kw_cpu", "MIT Lincoln Laboratory TX-0 64KW")
tx0_device::tx0_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int addr_bits, int address_mask, int ir_mask)
@ -66,8 +67,18 @@ tx0_device::tx0_device(const machine_config &mconfig, device_type type, const ch
m_program_config.m_is_octal = true;
}
tx0_8kw_device::tx0_8kw_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: tx0_device(mconfig, type, tag, owner, clock, 13, ADDRESS_MASK_8KW, 037)
{
}
tx0_8kw_device::tx0_8kw_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: tx0_device(mconfig, TX0_8KW, tag, owner, clock, 13, ADDRESS_MASK_8KW, 037)
: tx0_8kw_device(mconfig, TX0_8KW, tag, owner, clock)
{
}
tx0_8kwo_device::tx0_8kwo_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: tx0_8kw_device(mconfig, TX0_8KW_OLD, tag, owner, clock)
{
}
@ -583,11 +594,13 @@ void tx0_64kw_device::execute_instruction_64kw()
/* (1.2) TBR = Store the contents of the TBR in the MBR. */
MBR |= m_tbr;
if ((MAR & 0000003) == 2)
if ((MAR & 0000003) == 2 && ((MAR & 0000600) >> 7) == 1)
/* LMB and MBL used simultaneously interchange LR and MBR */
std::swap(LR, MBR);
else if ((MAR & 0000003) == 2)
/* (1.3) LMB = Store the contents of the LR in the MBR. */
MBR = LR;
if (((MAR & 0000600) >> 7) == 1)
else if (((MAR & 0000600) >> 7) == 1)
/* (1.3) MLR = Store the contents of the MBR (memory buffer
register) in the live reg. */
LR = MBR;
@ -638,6 +651,227 @@ void tx0_64kw_device::execute_instruction_64kw()
}
}
/* execute one instruction */
void tx0_8kwo_device::execute_instruction_8kw()
{
if (! m_cycle)
{
m_cycle = 1; /* most frequent case */
switch (IR)
{
case 0: /* STOre */
case 4: /* Store LR */
case 8: /* ADD */
case 12: /* Load LR */
break;
case 16: /* TRansfer on Negative */
if (AC & 0400000)
{
PC = MAR & 0017777;
m_cycle = 0; /* instruction only takes one cycle if branch
is taken */
}
break;
case 20: /* TRAnsfer */
PC = MAR & 0017777;
m_cycle = 0; /* instruction only takes one cycle if branch
is taken */
break;
case 24: /* OPeRate */
case 25:
case 26:
case 27:
case 28:
case 29:
case 30:
case 31:
if (IR & 004)
/* (0.8) CLL = Clear the left nine digital positions of the AC */
AC &= 0000777;
if (IR & 002)
/* (0.8) CLR = Clear the right nine digital positions of the AC */
AC &= 0777000;
if (((IR & 001) == 01) && ((MAR & 010000) == 000000))
{
/* (0.8) IOS In-Out Stop = Stop machine so that an In-Out command
(specified by digits 6 7 8 of MAR) may be executed */
/* ((MAR & 0007000) >> 9) is device ID */
/* 7: */
/* (0.8) P7H = Punch holes 1-6 in flexo tape specified by AC
digital positions 2, 5, 8, 11, 14, and 17. Also punches a 7th
hole on tape. */
/* 6: */
/* (0.8) P6H = Same as P7H but no seventh hole */
/* 4: */
/* (0.8) PNT = Print one flexowriter character specified by AC
digits 2, 5, 8, 11, 14, and 17. */
/* 1: */
/* (0.8) R1C = Read one line of flexo tape so that tape positions
1, 2, 3, 4, 5, and 6 will be put in the AC digital positions 0,
3, 6, 9, 12 and 15. */
/* 3: */
/* (0.8) R3C = Read one line of flexo tape into AC digits 0, 3, 6,
9, 12 and 15. Then cycle the AC one digital position; read the
next line on tape into AC digits 0, 3, 6, 9, 12 and 15, cycle
the AC right one digital position and read the third and last
line into AC digits 0, 3, 6, 9, 12 and 15. (This command is
equal to a triple CYR-R1C.) */
/* 2: */
/* (0.8) DIS = Intensify a point on the scope with x and y
coordinates where x is specified by AC digits 0-8 with digit 0
being used as the sign and y is specified by AC digits 9-17
with digit 9 being used as the sign for y. The complement
system is in effect when the signs are negative. */
/* (5 is undefined) */
int index = (MAR & 0007000) >> 9;
m_ios = 0;
call_io_handler(index);
m_ioh = 1;
}
if (((IR & 001) == 00) && ((MAR & 010000) == 010000))
{ /* (IOS) EX0 through EX7 = operate user's EXternal equipment. */
switch ((MAR & 0007000) >> 9)
{
/* ... */
}
}
break;
}
}
else
{
m_cycle = 0; /* always true */
switch (IR)
{
case 0: /* STOre */
tx0_write(MAR, (MBR = AC));
break;
case 4: /* Store LR */
tx0_write(MAR, (MBR = LR));
break;
case 8: /* ADD */
MBR = tx0_read(MAR);
AC = AC + MBR;
AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
break;
case 12: /* Load LR */
LR = MBR = tx0_read(MAR);
break;
case 16: /* TRansfer on Negative */
case 20: /* TRAnsfer */
break;
case 24: /* OPeRate */
case 25:
case 26:
case 27:
case 28:
case 29:
case 30:
case 31:
MBR = 0;
if ((MAR & 0000104) == 0000100)
/* (1.1) PEN = Read the light pen flip-flops 1 and 2 into AC(0) and
AC(1). */
/*...*/{ }
if ((MAR & 0000104) == 0000004)
/* (1.1) TAC = Insert a one in each digital position of the AC
wherever there is a one in the corresponding digital position
of the TAC. */
AC |= m_tac;
if ((MAR & 0000003) == 1)
/* (1.2) AMB = Store the contents of the AC in the MBR. */
MBR = AC;
if (MAR & 0000040)
/* (1.2) COM = Complement every digit in the accumulator */
AC ^= 0777777;
if ((MAR & 0000003) == 3)
/* (1.2) TBR = Store the contents of the TBR in the MBR. */
MBR |= m_tbr;
uint32_t tmp = MBR;
if ((MAR & 0000003) == 2)
/* (1.3) LMB = Store the contents of the LR in the MBR. */
MBR = LR;
if (((MAR & 0000600) >> 7) == 1)
/* (1.3) MLR = Store the contents of the MBR (memory buffer
register) in the live reg. */
LR = tmp;
if ((MAR & 0000704) == 0000104)
/* (1.3) ORL = Inclusive or MBR into LR. */
LR |= tmp;
if ((MAR & 0000704) == 0000304)
/* (1.3) ANL = And MBR into LR. */
LR &= tmp;
if (((MAR & 0000600) >> 7) == 2)
/* (1.4) SHR = Shift the AC right one place, i.e. multiply the AC
by 2^-1 */
AC >>= 1;
if (((MAR & 0000600) >> 7) == 3)
/* (1.4) CYR = Cycle the AC right one digital position (AC(17) will
become AC(0)) */
AC = (AC >> 1) | ((AC & 1) << 17);
if (MAR & 0000020)
/* (1.4) PAD = Partial add AC to MBR, that is, for every digital
position of the MBR that contains a one, complement the digit
in the corresponding digital position of the AC. This is also
called a half add. */
AC ^= MBR;
if (MAR & 0000010)
{ /* (1.7) CRY = Partial add the 18 digits of the AC to the
corresponding 18 digits of the carry.
To determine what the 18 digits of the carry are, use the
following rule:
"Grouping the AC and MBR digits into pairs and proceeding from
right to left, assign the carry digit of the next pair to a one
if in the present pair MBR = 1 and AC = 0 or if in the present
pair AC = 1 and carry 1.
(Note: the 0th digit pair determines the 17th pair's carry
digit)" */
AC ^= MBR;
AC = AC + MBR;
AC = (AC + (AC >> 18)) & 0777777; /* propagate carry around */
}
if (((IR & 001) == 01) && ((MAR & 017000) == 010000))
/* (1.8) Hlt = Halt the computer */
m_run = 0;
break;
}
}
}
void tx0_device::indexed_address_eval()
{
MAR = MAR + XR;
@ -969,11 +1203,8 @@ void tx0_8kw_device::execute_instruction_8kw()
}
if (((! (MAR & 0000400)) && (MAR & 0000200)) && ((! (MAR & 0000004)) && (MAR & 0000002)))
{ /* LMB and MBL used simultaneously interchange LR and MBR */
int tmp = MBR;
MBR = LR;
LR = tmp;
}
/* LMB and MBL used simultaneously interchange LR and MBR */
std::swap(LR, MBR);
else if ((! (MAR & 0000400)) && (MAR & 0000200))
/* (1.4) MBL = Transfer MBR contents to LR */
LR = MBR;
@ -1073,6 +1304,11 @@ std::unique_ptr<util::disasm_interface> tx0_8kw_device::create_disassembler()
return std::make_unique<tx0_8kw_disassembler>();
}
std::unique_ptr<util::disasm_interface> tx0_8kwo_device::create_disassembler()
{
return std::make_unique<tx0_8kwo_disassembler>();
}
std::unique_ptr<util::disasm_interface> tx0_64kw_device::create_disassembler()
{
return std::make_unique<tx0_64kw_disassembler>();

View File

@ -133,11 +133,27 @@ public:
tx0_8kw_device(const machine_config &mconfig, const char *_tag, device_t *_owner, uint32_t _clock);
protected:
tx0_8kw_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
virtual void execute_run() override;
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
private:
void execute_instruction_8kw();
virtual void execute_instruction_8kw();
};
class tx0_8kwo_device : public tx0_8kw_device
{
public:
// construction/destruction
tx0_8kwo_device(const machine_config &mconfig, const char *_tag, device_t *_owner, uint32_t _clock);
protected:
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
private:
virtual void execute_instruction_8kw() override;
};
@ -156,7 +172,8 @@ private:
};
DECLARE_DEVICE_TYPE(TX0_64KW, tx0_64kw_device)
DECLARE_DEVICE_TYPE(TX0_8KW, tx0_8kw_device)
DECLARE_DEVICE_TYPE(TX0_64KW, tx0_64kw_device)
DECLARE_DEVICE_TYPE(TX0_8KW_OLD, tx0_8kwo_device)
DECLARE_DEVICE_TYPE(TX0_8KW, tx0_8kw_device)
#endif // MAME_CPU_TX0_TX0_H

View File

@ -38,7 +38,7 @@
1.4 | 600020 (PAD) Partial add (exclusive or) MBR to AC
1.4 | 600400 (SHR) Shift AC right once
1.4 | 600600 (CYR) Cycle AC right once
1.7 | 600010 (CRY) Add carry digits to AC (according to LR)
1.7 | 600010 (CRY) Add carry digits to AC (according to MBR)
1.8 | 603000 (HLT) Halt computer
ANL and ORL were added in the first half of 1959 (M-5001-6).
@ -72,7 +72,7 @@
1.6 | 600400 (SHR) Shift AC right once
1.6 | 600600 (CYR) Cycle AC right once
1.6 | 607000 (SPF) Set PFR from MBR
1.7 | 600010 (CRY) Add carry digits to AC (according to LR)
1.7 | 600010 (CRY) Add carry digits to AC (according to MBR)
1.8 | 600001 (MBX) Transfer MBR to XR
1.8 | 603000 (HLT) Halt computer
@ -119,7 +119,15 @@ offs_t tx0_64kw_disassembler::disassemble(std::ostream &stream, offs_t pc, const
// Addressable instructions (only 3 in this version)
util::stream_format(stream, "%s %06o", s_addressable_insts[(inst & 0600000) >> 13], inst & 0177777);
}
else switch (inst)
else
dasm_opr(stream, inst);
return 1 | SUPPORTED;
}
void tx0_64kw_disassembler::dasm_opr(std::ostream &stream, u32 inst)
{
switch (inst)
{
case 0600012:
stream << "cry";
@ -245,6 +253,10 @@ offs_t tx0_64kw_disassembler::disassemble(std::ostream &stream, offs_t pc, const
stream << "clc";
break;
case 0740062:
stream << "lcc";
break;
case 0740200:
stream << "cal";
break;
@ -276,6 +288,46 @@ offs_t tx0_64kw_disassembler::disassemble(std::ostream &stream, offs_t pc, const
util::stream_format(stream, "opr %o", inst & 0177777);
break;
}
}
offs_t tx0_8kwo_disassembler::disassemble(std::ostream &stream, offs_t pc, const tx0_8kwo_disassembler::data_buffer &opcodes, const tx0_8kwo_disassembler::data_buffer &params)
{
u32 inst = opcodes.r32(pc) & 0777777;
if (inst < 0600000)
{
// Addressable instructions (only 6 in this version)
if ((inst & 060000) != 0)
util::stream_format(stream, "%06o", inst);
else
util::stream_format(stream, "%s %05o", s_addressable_insts[(inst & 0700000) >> 13], inst & 017777);
}
else switch (inst)
{
case 0600105:
stream << "orl";
break;
case 0600125:
stream << "ora";
break;
case 0600305:
stream << "anl";
break;
case 0600325:
stream << "ana";
break;
case 0610000: case 0611000: case 0612000: case 0613000: case 0614000: case 0615000: case 0616000: case 0617000:
util::stream_format(stream, "ex%d", BIT(inst, 9, 3));
break;
default:
dasm_opr(stream, inst);
break;
}
return 1 | SUPPORTED;
}
@ -309,10 +361,10 @@ offs_t tx0_8kw_disassembler::disassemble(std::ostream &stream, offs_t pc, const
}
else
{
if ((inst & 037000) == 02000)
if ((inst & 0137020) == 0102020)
{
stream << "tbr";
if ((inst & 0100757) == 0)
if ((inst & 000757) == 0)
return 1 | SUPPORTED;
stream << 'U';
}
@ -642,6 +694,10 @@ offs_t tx0_8kw_disassembler::disassemble(std::ostream &stream, offs_t pc, const
stream << "alo";
break;
case 040227:
stream << "anl 20"; // no consistent mnemonic used in program macros
break;
case 040230:
stream << "all";
break;
@ -662,6 +718,10 @@ offs_t tx0_8kw_disassembler::disassemble(std::ostream &stream, offs_t pc, const
stream << "anlUcom";
break;
case 040250:
stream << "alrUamz";
break;
case 040260:
stream << "alc";
break;
@ -694,6 +754,10 @@ offs_t tx0_8kw_disassembler::disassemble(std::ostream &stream, offs_t pc, const
stream << "clc";
break;
case 0100041:
stream << "clcUxro";
break;
case 0100062:
stream << "lcc";
break;
@ -718,6 +782,18 @@ offs_t tx0_8kw_disassembler::disassemble(std::ostream &stream, offs_t pc, const
stream << "cal";
break;
case 0100201:
stream << "calUxro";
break;
case 0100212:
stream << "lalUlro";
break;
case 0100222:
stream << "lacUlro";
break;
case 0100240:
stream << "calUcom";
break;

View File

@ -12,8 +12,20 @@ public:
tx0_64kw_disassembler() = default;
virtual ~tx0_64kw_disassembler() = default;
protected:
virtual u32 opcode_alignment() const override;
virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
void dasm_opr(std::ostream &stream, u32 inst);
};
class tx0_8kwo_disassembler : public tx0_64kw_disassembler
{
public:
tx0_8kwo_disassembler() = default;
protected:
virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
};
class tx0_8kw_disassembler : public util::disasm_interface
@ -22,6 +34,7 @@ public:
tx0_8kw_disassembler() = default;
virtual ~tx0_8kw_disassembler() = default;
protected:
virtual u32 opcode_alignment() const override;
virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
};

View File

@ -1612,6 +1612,31 @@ void tx0_state::tx0_64kw(machine_config &config)
SOFTWARE_LIST(config, "ptp_list").set_original("tx0_ptp").set_filter("64,OLDCODE");
}
void tx0_state::tx0_8kwo(machine_config &config)
{
tx0_64kw(config);
/* basic machine hardware */
/* TX0 CPU @ approx. 167 kHz (no master clock, but the memory cycle time is
approximately 6usec) */
TX0_8KW_OLD(config.replace(), m_maincpu, 166667);
m_maincpu->cpy().set(FUNC(tx0_state::tx0_io_cpy));
m_maincpu->r1l().set(FUNC(tx0_state::tx0_io_r1l));
m_maincpu->dis().set(FUNC(tx0_state::tx0_io_dis));
m_maincpu->r3l().set(FUNC(tx0_state::tx0_io_r3l));
m_maincpu->prt().set(FUNC(tx0_state::tx0_io_prt));
m_maincpu->rsv().set_nop();
m_maincpu->p6h().set(FUNC(tx0_state::tx0_io_p6h));
m_maincpu->p7h().set(FUNC(tx0_state::tx0_io_p7h));
m_maincpu->sel().set(FUNC(tx0_state::tx0_sel));
m_maincpu->res().set(FUNC(tx0_state::tx0_io_reset_callback));
m_maincpu->set_addrmap(AS_PROGRAM, &tx0_state::tx0_8kw_map);
/* dummy interrupt: handles input */
m_maincpu->set_vblank_int("screen", FUNC(tx0_state::tx0_interrupt));
SOFTWARE_LIST(config.replace(), "ptp_list").set_original("tx0_ptp").set_filter("8,OLDCODE");
}
void tx0_state::tx0_8kw(machine_config &config)
{
tx0_64kw(config);
@ -1642,6 +1667,11 @@ ROM_START(tx0_64kw)
/* space filled with our font */
ROM_END
ROM_START(tx0_8kwo)
ROM_REGION(tx0_fontdata_size, "gfx1", ROMREGION_ERASEFF)
/* space filled with our font */
ROM_END
ROM_START(tx0_8kw)
ROM_REGION(tx0_fontdata_size, "gfx1", ROMREGION_ERASEFF)
/* space filled with our font */
@ -1653,6 +1683,7 @@ ROM_END
***************************************************************************/
// YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS
COMP( 1956, tx0_64kw, 0, 0, tx0_64kw, tx0, tx0_state, init_tx0, "MIT", "TX-0 original demonstrator (64 kWords of RAM)", MACHINE_NO_SOUND_HW | MACHINE_NOT_WORKING)
COMP( 1962, tx0_8kw, tx0_64kw, 0, tx0_8kw, tx0, tx0_state, init_tx0, "MIT", "TX-0 upgraded system (8 kWords of RAM)", MACHINE_NO_SOUND_HW | MACHINE_NOT_WORKING)
// YEAR NAME PARENT COMPAT MACHINE INPUT STATE INIT COMPANY FULLNAME FLAGS
COMP( 1956, tx0_64kw, tx0_8kw, 0, tx0_64kw, tx0, tx0_state, init_tx0, "MIT", "TX-0 original demonstrator (64 kWords of RAM)", MACHINE_NO_SOUND_HW | MACHINE_NOT_WORKING)
COMP( 1959, tx0_8kwo, tx0_8kw, 0, tx0_8kwo, tx0, tx0_state, init_tx0, "MIT", "TX-0 upgraded system (8 kWords of RAM, old order code)", MACHINE_NO_SOUND_HW | MACHINE_NOT_WORKING)
COMP( 1962, tx0_8kw, 0, 0, tx0_8kw, tx0, tx0_state, init_tx0, "MIT", "TX-0 upgraded system (8 kWords of RAM, new order code)", MACHINE_NO_SOUND_HW | MACHINE_NOT_WORKING)

View File

@ -145,6 +145,7 @@ public:
{ }
void tx0_64kw(machine_config &config);
void tx0_8kwo(machine_config &config);
void tx0_8kw(machine_config &config);
void init_tx0();

View File

@ -41737,6 +41737,7 @@ twinsed2 // (c) 1994 Electronic Devices
@source:tx0.cpp
tx0_64kw // April 1956 MIT TX-0 (64kw RAM)
tx0_8kwo // 1959 MIT TX-0 (8kw RAM)
tx0_8kw // 1962 MIT TX-0 (8kw RAM)
@source:tx1.cpp

View File

@ -596,6 +596,7 @@ static const dasm_table_entry dasm_table[] =
{ "tp0320", be, 0, []() -> util::disasm_interface * { return new tp0320_disassembler; } },
{ "tx0_64kw", be, -2, []() -> util::disasm_interface * { return new tx0_64kw_disassembler; } },
{ "tx0_8kw", be, -2, []() -> util::disasm_interface * { return new tx0_8kw_disassembler; } },
{ "tx0_8kwo", be, -2, []() -> util::disasm_interface * { return new tx0_8kwo_disassembler; } },
{ "ucom4", le, 0, []() -> util::disasm_interface * { return new ucom4_disassembler; } },
{ "unsp10", be, -1, []() -> util::disasm_interface * { return new unsp_disassembler; } },
{ "unsp12", be, -1, []() -> util::disasm_interface * { return new unsp_12_disassembler; } },