smc1102: add opcode placeholders and microinstructions

This commit is contained in:
hap 2023-04-10 19:41:35 +02:00
parent 96789c582b
commit 962f44a5fa
8 changed files with 219 additions and 81 deletions

View File

@ -7,7 +7,7 @@
SMC1102 is a CMOS MCU based on TMS1100, keeping the same ALU and opcode mnemonics.
They added a timer, interrupts, and a built-in LCD controller.
In the USA, it was marketed by S-MOS Systems, an affiliate of the Seiko Group.
In the USA, it was marketed by S-MOS Systems, an affiliate of Seiko Group.
SMC1112 die notes (SMC1102 is assumed to be the same):
- 128x4 RAM array at top-left
@ -18,7 +18,10 @@ SMC1112 die notes (SMC1102 is assumed to be the same):
- no output PLA
TODO:
- x
- row(pc) order is unknown
- each opcode is 4 cycles instead of 6
- does it have CL (call latch)
- everything else
*/
@ -60,10 +63,111 @@ void smc1102_cpu_device::device_start()
u32 smc1102_cpu_device::decode_micro(offs_t offset)
{
return 0;
// TCY, YNEC, TCMIY
static const u16 micro1[3] = { 0x0402, 0x1204, 0x1032 };
// 0x20, 0x30, 0x00, 0x70
static const u16 micro2[0x40] =
{
0x0102, 0x0801, 0x0802, 0x1001, 0x306a, 0x303a, 0x2021, 0x2020,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0e04, 0x0e04, 0x0e04, 0x0e04, 0x0899, 0x0099, 0x0819, 0x0804,
0x0904, 0x0898, 0x1104, 0x2821, 0x104a, 0x101a, 0x0909, 0x0849,
0x0401, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0404, 0x0000,
0x0519, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0519,
0x0000, 0x0519, 0x0519, 0x0000, 0x0000, 0x0000, 0x0519, 0x0419,
};
u16 mask = 0;
if (offset >= 0x40 && offset < 0x70)
mask = micro1[offset >> 4 & 3];
else if (offset < 0x80 && (offset & 0xf0) != 0x10)
mask = micro2[((offset ^ 0x20) | (offset >> 1 & 0x20)) & 0x3f];
// does not have M_MTN or M_STSL
const u32 md[14] = { M_AUTA, M_AUTY, M_NE, M_C8, M_CIN, M_CKM, M_15TN, M_NATN, M_ATN, M_CKN, M_CKP, M_MTP, M_YTP, M_STO };
u32 decode = 0;
for (int bit = 0; bit < 14; bit++)
if (mask & (1 << bit))
decode |= md[bit];
return decode;
}
void smc1102_cpu_device::device_reset()
{
tms1100_cpu_device::device_reset();
// changed/added fixed instructions (mostly handled in op_extra)
m_fixed_decode[0x0a] = F_EXTRA;
m_fixed_decode[0x71] = F_EXTRA;
m_fixed_decode[0x74] = F_EXTRA;
m_fixed_decode[0x75] = F_EXTRA;
m_fixed_decode[0x76] = F_RETN;
m_fixed_decode[0x78] = F_EXTRA;
m_fixed_decode[0x7b] = F_EXTRA;
m_fixed_decode[0x72] = m_fixed_decode[0x73] = F_EXTRA;
m_fixed_decode[0x7c] = m_fixed_decode[0x7d] = F_EXTRA;
}
// opcode deviations
void smc1102_cpu_device::op_tasr()
{
// TASR: transfer A to LCD S/R
}
void smc1102_cpu_device::op_tsg()
{
// TSG: transfer LCD S/R to RAM
}
void smc1102_cpu_device::op_intdis()
{
// INTDIS: disable interrupt
}
void smc1102_cpu_device::op_inten()
{
// INTEN: enable interrupt after next instruction
}
void smc1102_cpu_device::op_selin()
{
// SELIN: select interrupt
}
void smc1102_cpu_device::op_tmset()
{
// TMSET: transfer A to timer latch
}
void smc1102_cpu_device::op_halt()
{
// HALT: stop CPU
}
void smc1102_cpu_device::op_extra()
{
switch (m_opcode)
{
case 0x0a: op_tasr(); break;
case 0x71: op_halt(); break;
case 0x74: op_inten(); break;
case 0x75: op_intdis(); break;
case 0x78: op_selin(); break;
case 0x7b: op_tmset(); break;
case 0x72: case 0x73: case 0x7c: case 0x7d:
op_tsg(); break;
default: break;
}
}

View File

@ -53,6 +53,20 @@ protected:
virtual u32 decode_micro(offs_t offset) override;
virtual void write_o_reg(u8 index) override { } // no O pins
virtual void op_setr() override { tms1k_base_device::op_setr(); } // no anomaly with MSB of X register
virtual void op_rstr() override { tms1k_base_device::op_rstr(); } // "
virtual void op_extra() override;
private:
void op_halt();
void op_intdis();
void op_inten();
void op_selin();
void op_tasr();
void op_tmset();
void op_tsg();
};
class smc1112_cpu_device : public smc1102_cpu_device

View File

@ -696,10 +696,12 @@ void tms1k_base_device::execute_one()
if (m_fixed & F_LDP) op_ldp();
if (m_fixed & F_COMC) op_comc();
if (m_fixed & F_TPC) op_tpc();
if (m_fixed & F_TAX) op_tax();
if (m_fixed & F_TAC) op_tac();
if (m_fixed & F_TADM) op_tadm();
if (m_fixed & F_TMA) op_tma();
if (m_fixed & F_OFF) op_off();
if (m_fixed & F_SEAC) op_seac();
if (m_fixed & F_REAC) op_reac();
@ -707,6 +709,8 @@ void tms1k_base_device::execute_one()
if (m_fixed & F_SBL) op_sbl();
if (m_fixed & F_XDA) op_xda();
if (m_fixed & F_EXTRA) op_extra();
// after fixed opcode handling: store status, write ram
m_status = status;
if (m_ram_out != -1)

View File

@ -73,67 +73,69 @@ protected:
// microinstructions
enum
{
M_15TN = (1U << 0), // 15 to -ALU
M_ATN = (1U << 1), // ACC to -ALU
M_AUTA = (1U << 2), // ALU to ACC
M_AUTY = (1U << 3), // ALU to Y
M_C8 = (1U << 4), // CARRY8 to STATUS
M_CIN = (1U << 5), // Carry In to ALU
M_CKM = (1U << 6), // CKB to MEM
M_CKN = (1U << 7), // CKB to -ALU
M_CKP = (1U << 8), // CKB to +ALU
M_MTN = (1U << 9), // MEM to -ALU
M_MTP = (1U << 10), // MEM to +ALU
M_NATN = (1U << 11), // ~ACC to -ALU
M_NE = (1U << 12), // COMP to STATUS
M_STO = (1U << 13), // ACC to MEM
M_STSL = (1U << 14), // STATUS to Status Latch
M_YTP = (1U << 15), // Y to +ALU
M_15TN = (1U << 0), // 15 to -ALU
M_ATN = (1U << 1), // ACC to -ALU
M_AUTA = (1U << 2), // ALU to ACC
M_AUTY = (1U << 3), // ALU to Y
M_C8 = (1U << 4), // CARRY8 to STATUS
M_CIN = (1U << 5), // Carry In to ALU
M_CKM = (1U << 6), // CKB to MEM
M_CKN = (1U << 7), // CKB to -ALU
M_CKP = (1U << 8), // CKB to +ALU
M_MTN = (1U << 9), // MEM to -ALU
M_MTP = (1U << 10), // MEM to +ALU
M_NATN = (1U << 11), // ~ACC to -ALU
M_NE = (1U << 12), // COMP to STATUS
M_STO = (1U << 13), // ACC to MEM
M_STSL = (1U << 14), // STATUS to Status Latch
M_YTP = (1U << 15), // Y to +ALU
M_CME = (1U << 16), // Conditional Memory Enable
M_DMTP = (1U << 17), // DAM to +ALU
M_NDMTP = (1U << 18), // ~DAM to +ALU
M_SSE = (1U << 19), // Special Status Enable
M_SSS = (1U << 20), // Special Status Sample
M_CME = (1U << 16), // Conditional Memory Enable
M_DMTP = (1U << 17), // DAM to +ALU
M_NDMTP = (1U << 18), // ~DAM to +ALU
M_SSE = (1U << 19), // Special Status Enable
M_SSS = (1U << 20), // Special Status Sample
M_SETR = (1U << 21), // -> line #0d, F_SETR (TP0320 custom)
M_RSTR = (1U << 22), // -> line #36, F_RSTR (TMS02x0 custom)
M_UNK1 = (1U << 23) // -> line #37, F_???? (TMS0270 custom)
M_SETR = (1U << 21), // -> line #0d, F_SETR (TP0320 custom)
M_RSTR = (1U << 22), // -> line #36, F_RSTR (TMS02x0 custom)
M_UNK1 = (1U << 23) // -> line #37, F_???? (TMS0270 custom)
};
// standard/fixed instructions - these are documented more in their specific handlers
enum
{
F_BR = (1ULL << 0),
F_CALL = (1ULL << 1),
F_CLO = (1ULL << 2),
F_COMC = (1ULL << 3),
F_COMX = (1ULL << 4),
F_COMX8 = (1ULL << 5),
F_LDP = (1ULL << 6),
F_LDX = (1ULL << 7),
F_RBIT = (1ULL << 8),
F_RETN = (1ULL << 9),
F_RSTR = (1ULL << 10),
F_SBIT = (1ULL << 11),
F_SETR = (1ULL << 12),
F_TDO = (1ULL << 13),
F_TPC = (1ULL << 14),
F_BR = (1ULL << 0),
F_CALL = (1ULL << 1),
F_CLO = (1ULL << 2),
F_COMC = (1ULL << 3),
F_COMX = (1ULL << 4),
F_COMX8 = (1ULL << 5),
F_LDP = (1ULL << 6),
F_LDX = (1ULL << 7),
F_RBIT = (1ULL << 8),
F_RETN = (1ULL << 9),
F_RSTR = (1ULL << 10),
F_SBIT = (1ULL << 11),
F_SETR = (1ULL << 12),
F_TDO = (1ULL << 13),
F_TPC = (1ULL << 14),
F_TAX = (1ULL << 15),
F_TXA = (1ULL << 16),
F_TRA = (1ULL << 17),
F_TAC = (1ULL << 18),
F_TCA = (1ULL << 19),
F_TADM = (1ULL << 20),
F_TMA = (1ULL << 21),
F_TAX = (1ULL << 15),
F_TXA = (1ULL << 16),
F_TRA = (1ULL << 17),
F_TAC = (1ULL << 18),
F_TCA = (1ULL << 19),
F_TADM = (1ULL << 20),
F_TMA = (1ULL << 21),
F_OFF = (1ULL << 22),
F_REAC = (1ULL << 23),
F_SAL = (1ULL << 24),
F_SBL = (1ULL << 25),
F_SEAC = (1ULL << 26),
F_XDA = (1ULL << 27)
F_OFF = (1ULL << 22),
F_REAC = (1ULL << 23),
F_SAL = (1ULL << 24),
F_SBL = (1ULL << 25),
F_SEAC = (1ULL << 26),
F_XDA = (1ULL << 27),
F_EXTRA = (1ULL << 28), // custom opcodes
};
void rom_10bit(address_map &map);
@ -152,6 +154,7 @@ protected:
virtual void set_cki_bus();
virtual void dynamic_output() { } // not used by default
virtual void read_opcode();
virtual void op_extra() { }
virtual void op_br();
virtual void op_call();

View File

@ -40,13 +40,13 @@ tms1000_base_disassembler::tms1000_base_disassembler(const u8 *lut_mnemonic, boo
}
}
tms1000_disassembler::tms1000_disassembler() : tms1000_base_disassembler(tms1000_mnemonic, false, 6)
{ }
tms1100_disassembler::tms1100_disassembler(const u8 *lut_mnemonic, bool opcode_9bits, int pc_bits) :
tms1000_base_disassembler(lut_mnemonic, opcode_9bits, pc_bits)
{ }
tms1000_disassembler::tms1000_disassembler() : tms1000_base_disassembler(tms1000_mnemonic, false, 6)
{ }
tms1100_disassembler::tms1100_disassembler() : tms1100_disassembler(tms1100_mnemonic, false, 6)
{ }

View File

@ -1,16 +1,28 @@
// license:BSD-3-Clause
// copyright-holders:hap
/******************************************************************************
/*******************************************************************************
Coleco Talking Wrinkles, a plushie dog handpuppet toy
Talking Wrinkles, a plushie dog handpuppet toy
Hardware is a P80C31BH @ 11MHz and a 32KB ROM, RAM is in the MCU.
It also has a cartridge slot, but no known cartridges were released.
The speech technology is by Electronic Speech Systems.
Published by Lakeside (a Coleco subsidiary at that time, after Coleco purchased
Leisure Dynamics in 1985). Programming by Steve Beck. The speech technology is
by Electronic Speech Systems. The plushie itself is licensed from Ganz Bros.
Hardware notes:
PCB 1:
- PCB label: REV 4.1 DIGITAL, 201239C, (C) COLECO 1986
- P80C31BH, 11MHz XTAL
- 32KB EPROM
- cartridge slot (no known cartridges were released)
PCB 2:
- PCB label: ANALOG REV 6.2, 201238D, (C) COLECO 1986
- button, motion sensor, microphone
Known sensors:
- 0x02: bellybutton, literally a button
- 0x04: detect violent motion (Wrinkles will cry)
- 0x04: detect violent motion (drop Wrinkles and he will cry)
- 0x10: detect light motion
- 0x40: detect open mouth (use as handpuppet to make it 'talk')
- 0x80: detect magnet in mouth (the toy came with a 'bone' that has a magnet in it)
@ -19,7 +31,7 @@ TODO:
- where is the microphone? or are they the same inputs as the motion sensors?
- power-on by pressing button
******************************************************************************/
*******************************************************************************/
#include "emu.h"
@ -49,9 +61,9 @@ private:
/******************************************************************************
/*******************************************************************************
Address Maps
******************************************************************************/
*******************************************************************************/
void wrinkles_state::main_map(address_map &map)
{
@ -61,15 +73,15 @@ void wrinkles_state::main_map(address_map &map)
/******************************************************************************
/*******************************************************************************
Input Ports
******************************************************************************/
*******************************************************************************/
static INPUT_PORTS_START( wrinkles )
PORT_START("INPUTS")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_CODE(KEYCODE_1) PORT_NAME("Tickle Button")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_CODE(KEYCODE_5) PORT_NAME("Shake Sensor")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_CODE(KEYCODE_5) PORT_NAME("Impact Sensor")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_UNKNOWN )
PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_OTHER ) PORT_CODE(KEYCODE_4) PORT_NAME("Motion Sensor")
PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_UNKNOWN )
@ -79,28 +91,28 @@ INPUT_PORTS_END
/******************************************************************************
/*******************************************************************************
Machine Configs
******************************************************************************/
*******************************************************************************/
void wrinkles_state::wrinkles(machine_config &config)
{
/* basic machine hardware */
// basic machine hardware
I80C31(config, m_maincpu, 11_MHz_XTAL);
m_maincpu->set_addrmap(AS_PROGRAM, &wrinkles_state::main_map);
m_maincpu->port_in_cb<1>().set_ioport("INPUTS");
m_maincpu->port_out_cb<3>().set("dac", FUNC(dac_8bit_r2r_device::write));
/* sound hardware */
// sound hardware
SPEAKER(config, "speaker").front_center();
DAC_8BIT_R2R(config, "dac").add_route(ALL_OUTPUTS, "speaker", 0.5);
}
/******************************************************************************
/*******************************************************************************
ROM Definitions
******************************************************************************/
*******************************************************************************/
ROM_START( wrinkles )
ROM_REGION( 0x8000, "maincpu", 0 )
@ -111,9 +123,9 @@ ROM_END
/******************************************************************************
/*******************************************************************************
Drivers
******************************************************************************/
*******************************************************************************/
// YEAR NAME PARENT CMP MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS
CONS( 1986, wrinkles, 0, 0, wrinkles, wrinkles, wrinkles_state, empty_init, "Coleco / Ganz", "Talking Wrinkles", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_CONTROLS | MACHINE_NOT_WORKING )
// YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY, FULLNAME, FLAGS
CONS( 1986, wrinkles, 0, 0, wrinkles, wrinkles, wrinkles_state, empty_init, "Lakeside / Coleco / Ganz Bros", "Talking Wrinkles", MACHINE_SUPPORTS_SAVE | MACHINE_IMPERFECT_CONTROLS | MACHINE_NOT_WORKING )

View File

@ -173,6 +173,7 @@ on Joerg Woerner's datamath.org: http://www.datamath.org/IC_List.htm
*M34014 TMS1100 1981, Coleco Bowlatronic
M34017 TMS1100 1981, Microvision cartridge: Cosmic Hunter
@M34018 TMS1100 1981, Coleco Head to Head: Electronic Boxing
*M34033 TMS1100 1982, Spartus Electronic Talking Clock (1411-61)
@M34038 TMS1100 1982, Parker Brothers Lost Treasure
M34047 TMS1100 1982, Microvision cartridge: Super Blockbuster
@M34078A TMS1100 1983, Milton Bradley Electronic Arcade Mania

View File

@ -160,7 +160,7 @@ u32 microvision_state::tms1100_micro_pla(offs_t offset)
// default TMS1100 microinstructions PLA - this should work for all games
// verified for: blckbstr, bowling, pinball, vegasslt
// TCY, YNEC, TMCIY, AxAAC
// TCY, YNEC, TCMIY, AxAAC
static const u16 micro1[4] = { 0x0108, 0x9080, 0x8068, 0x0136 };
// 0x20, 0x30, 0x00