summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/devices/cpu/hphybrid/hphybrid.cpp33
-rw-r--r--src/devices/cpu/hphybrid/hphybrid.h3
-rw-r--r--src/devices/cpu/sparc/mb86901.cpp3281
-rw-r--r--src/devices/cpu/sparc/sparc.h110
-rw-r--r--src/devices/cpu/sparc/sparcdasm.cpp17
-rw-r--r--src/devices/cpu/sparc/sparcdasm.h25
-rw-r--r--src/devices/cpu/sparc/sparcdefs.h204
-rw-r--r--src/devices/machine/netlist.cpp2
-rw-r--r--src/devices/machine/netlist.h6
-rw-r--r--src/lib/netlist/build/makefile33
-rw-r--r--src/lib/netlist/devices/nld_74279.cpp4
-rw-r--r--src/lib/netlist/devices/nld_7493.cpp4
-rw-r--r--src/lib/netlist/devices/nld_9312.cpp2
-rw-r--r--src/lib/netlist/devices/nld_9316.cpp78
-rw-r--r--src/lib/netlist/devices/nld_truthtable.cpp31
-rw-r--r--src/lib/netlist/devices/nld_truthtable.h78
-rw-r--r--src/lib/netlist/macro/nlm_cd4xxx.cpp2
-rw-r--r--src/lib/netlist/macro/nlm_other.cpp2
-rw-r--r--src/lib/netlist/macro/nlm_ttl74xx.cpp54
-rw-r--r--src/lib/netlist/nl_base.cpp139
-rw-r--r--src/lib/netlist/nl_base.h76
-rw-r--r--src/lib/netlist/nl_config.h17
-rw-r--r--src/lib/netlist/nl_factory.h12
-rw-r--r--src/lib/netlist/nl_lists.h20
-rw-r--r--src/lib/netlist/nl_parser.cpp33
-rw-r--r--src/lib/netlist/nl_parser.h2
-rw-r--r--src/lib/netlist/nl_setup.cpp90
-rw-r--r--src/lib/netlist/nl_setup.h167
-rw-r--r--src/lib/netlist/nl_time.h22
-rw-r--r--src/lib/netlist/plib/pchrono.cpp55
-rw-r--r--src/lib/netlist/plib/pchrono.h213
-rw-r--r--src/lib/netlist/plib/pconfig.h43
-rw-r--r--src/lib/netlist/plib/poptions.cpp226
-rw-r--r--src/lib/netlist/plib/poptions.h176
-rw-r--r--src/lib/netlist/plib/pstring.cpp2
-rw-r--r--src/lib/netlist/prg/nltool.cpp73
-rw-r--r--src/lib/netlist/prg/nlwav.cpp60
-rw-r--r--src/lib/netlist/tools/nl_convert.cpp23
-rw-r--r--src/lib/netlist/tools/nl_convert.h8
-rw-r--r--src/mame/drivers/galpani3.cpp5
-rw-r--r--src/mame/drivers/goldnpkr.cpp124
-rw-r--r--src/mame/drivers/tomcat.cpp2
-rw-r--r--src/mame/machine/nl_breakout.cpp31
-rw-r--r--src/mame/machine/nl_pong.cpp43
-rw-r--r--src/mame/mame.lst1
-rw-r--r--src/mame/video/abc1600.cpp2
46 files changed, 4048 insertions, 1586 deletions
diff --git a/src/devices/cpu/hphybrid/hphybrid.cpp b/src/devices/cpu/hphybrid/hphybrid.cpp
index 18440c6e8d1..aa7421e5d15 100644
--- a/src/devices/cpu/hphybrid/hphybrid.cpp
+++ b/src/devices/cpu/hphybrid/hphybrid.cpp
@@ -1076,7 +1076,7 @@ void hp_hybrid_cpu_device::check_for_interrupts(void)
// Do a double-indirect JSM IV,I instruction
WM(AEC_CASE_C , ++m_reg_R , m_reg_P);
- m_reg_P = RM(AEC_CASE_I , m_reg_IV + CURRENT_PA);
+ m_reg_P = RM(AEC_CASE_C , m_reg_IV + CURRENT_PA);
m_reg_I = fetch();
}
@@ -1539,10 +1539,23 @@ UINT32 hp_5061_3001_cpu_device::add_mae(aec_cases_t aec_case , UINT16 addr)
bool top_half = BIT(addr , 15) != 0;
// Detect accesses to top half of base page
- if ((aec_case == AEC_CASE_C || aec_case == AEC_CASE_I) && (addr & 0xfe00) == 0xfe00) {
+ if (aec_case == AEC_CASE_C && (addr & 0xfe00) == 0xfe00) {
aec_case = AEC_CASE_B;
}
+ // **** IM == 0 ****
+ // Case | Top | Bottom
+ // A | R34 | R33
+ // B | R36 | R33
+ // C | R32 | R35
+ // D | R32 | R37
+ //
+ // **** IM == 1 ****
+ // Case | Top | Bottom
+ // A | R34 | 5
+ // B | 1 | 5
+ // C | 0 | R35
+ // D | R32 | R37
switch (aec_case) {
case AEC_CASE_A:
if (top_half) {
@@ -1564,22 +1577,18 @@ UINT32 hp_5061_3001_cpu_device::add_mae(aec_cases_t aec_case , UINT16 addr)
break;
case AEC_CASE_C:
- bsc_reg = top_half ? m_reg_aec[ HP_REG_R32_ADDR - HP_REG_R32_ADDR ] : m_reg_aec[ HP_REG_R35_ADDR - HP_REG_R32_ADDR ];
+ if (top_half) {
+ // Block 0 is used when IM bit overrides R32 value
+ bsc_reg = BIT(m_flags , HPHYBRID_IM_BIT) ? 0 : m_reg_aec[ HP_REG_R32_ADDR - HP_REG_R32_ADDR ];
+ } else {
+ bsc_reg = m_reg_aec[ HP_REG_R35_ADDR - HP_REG_R32_ADDR ];
+ }
break;
case AEC_CASE_D:
bsc_reg = top_half ? m_reg_aec[ HP_REG_R32_ADDR - HP_REG_R32_ADDR ] : m_reg_aec[ HP_REG_R37_ADDR - HP_REG_R32_ADDR ];
break;
- case AEC_CASE_I:
- // Behaviour of AEC during interrupt vector fetch is undocumented but it can be guessed from 9845B firmware.
- // Basically in this case the integrated AEC seems to do what the discrete implementation in 9845A does:
- // top half of memory is mapped to block 0 (fixed) and bottom half is mapped according to content of R35
- // (see pg 334 of patent).
- // I'm beginning to suspect that these values actually come from IM overriding case "C"
- bsc_reg = top_half ? 0 : m_reg_aec[ HP_REG_R35_ADDR - HP_REG_R32_ADDR ];
- break;
-
default:
logerror("hphybrid: aec_case=%d\n" , aec_case);
return 0;
diff --git a/src/devices/cpu/hphybrid/hphybrid.h b/src/devices/cpu/hphybrid/hphybrid.h
index c34d6f0b252..43ce4533694 100644
--- a/src/devices/cpu/hphybrid/hphybrid.h
+++ b/src/devices/cpu/hphybrid/hphybrid.h
@@ -127,8 +127,7 @@ protected:
AEC_CASE_A, // Instr. fetches, non-base page fetches of link pointers, BPC direct non-base page accesses
AEC_CASE_B, // Base page fetches of link pointers, BPC direct base page accesses
AEC_CASE_C, // IOC, EMC & BPC indirect final destination accesses
- AEC_CASE_D, // DMA accesses
- AEC_CASE_I // Interrupt vector fetches
+ AEC_CASE_D // DMA accesses
} aec_cases_t;
// do memory address extension
diff --git a/src/devices/cpu/sparc/mb86901.cpp b/src/devices/cpu/sparc/mb86901.cpp
index f2e737b7265..61dc5043530 100644
--- a/src/devices/cpu/sparc/mb86901.cpp
+++ b/src/devices/cpu/sparc/mb86901.cpp
@@ -26,7 +26,7 @@
const device_type MB86901 = &device_creator<mb86901_device>;
-const int mb86901_device::WINDOW_COUNT = 7;
+const int mb86901_device::NWINDOWS = 7;
//-------------------------------------------------
// mb86901_device - constructor
@@ -42,43 +42,120 @@ mb86901_device::mb86901_device(const machine_config &mconfig, const char *tag, d
void mb86901_device::device_start()
{
- m_trap_priorities[0] = 1;
- m_trap_priorities[1] = 2;
- m_trap_priorities[2] = 3;
- m_trap_priorities[3] = 4;
- m_trap_priorities[4] = 5;
- m_trap_priorities[5] = 6;
- m_trap_priorities[6] = 6;
- m_trap_priorities[7] = 7;
- m_trap_priorities[8] = 8;
- m_trap_priorities[9] = 10;
- m_trap_priorities[10] = 11;
- for (int i = 11; i <= 16; i++)
- m_trap_priorities[i] = 31;
- m_trap_priorities[17] = 27;
- m_trap_priorities[18] = 26;
- m_trap_priorities[19] = 25;
- m_trap_priorities[20] = 24;
- m_trap_priorities[21] = 23;
- m_trap_priorities[22] = 22;
- m_trap_priorities[23] = 21;
- m_trap_priorities[24] = 20;
- m_trap_priorities[25] = 19;
- m_trap_priorities[26] = 18;
- m_trap_priorities[27] = 17;
- m_trap_priorities[28] = 16;
- m_trap_priorities[29] = 15;
- m_trap_priorities[30] = 14;
- m_trap_priorities[31] = 13;
- for (int i = 32; i < 128; i++)
- m_trap_priorities[i] = 31;
- for (int i = 128; i < 256; i++)
- m_trap_priorities[i] = 12;
+ m_bp_reset_in = false;
+ m_bp_irl = 0;
+ m_bp_fpu_present = false;
+ m_bp_cp_present = false;
+ m_pb_error = false;
+ m_pb_block_ldst_byte = false;
+ m_pb_block_ldst_word = false;
memset(m_dbgregs, 0, 24 * sizeof(UINT32));
+ memset(m_illegal_instruction_asr, 0, 32 * sizeof(bool));
+ memset(m_privileged_asr, 1, 32 * sizeof(bool));
+ m_privileged_asr[0] = false;
+
+ memset(m_alu_op3_assigned, 0, 64 * sizeof(bool));
+ m_alu_op3_assigned[OP3_ADD] = true;
+ m_alu_op3_assigned[OP3_AND] = true;
+ m_alu_op3_assigned[OP3_OR] = true;
+ m_alu_op3_assigned[OP3_XOR] = true;
+ m_alu_op3_assigned[OP3_SUB] = true;
+ m_alu_op3_assigned[OP3_ANDN] = true;
+ m_alu_op3_assigned[OP3_ORN] = true;
+ m_alu_op3_assigned[OP3_XNOR] = true;
+ m_alu_op3_assigned[OP3_ADDX] = true;
+ m_alu_op3_assigned[OP3_SUBX] = true;
+ m_alu_op3_assigned[OP3_ADDCC] = true;
+ m_alu_op3_assigned[OP3_ANDCC] = true;
+ m_alu_op3_assigned[OP3_ORCC] = true;
+ m_alu_op3_assigned[OP3_XORCC] = true;
+ m_alu_op3_assigned[OP3_SUBCC] = true;
+ m_alu_op3_assigned[OP3_ANDNCC] = true;
+ m_alu_op3_assigned[OP3_ORNCC] = true;
+ m_alu_op3_assigned[OP3_XNORCC] = true;
+ m_alu_op3_assigned[OP3_ADDXCC] = true;
+ m_alu_op3_assigned[OP3_SUBXCC] = true;
+ m_alu_op3_assigned[OP3_TADDCC] = true;
+ m_alu_op3_assigned[OP3_TSUBCC] = true;
+ m_alu_op3_assigned[OP3_TADDCCTV] = true;
+ m_alu_op3_assigned[OP3_TSUBCCTV] = true;
+ m_alu_op3_assigned[OP3_MULSCC] = true;
+ m_alu_op3_assigned[OP3_SLL] = true;
+ m_alu_op3_assigned[OP3_SRL] = true;
+ m_alu_op3_assigned[OP3_SRA] = true;
+ m_alu_op3_assigned[OP3_RDASR] = true;
+ m_alu_op3_assigned[OP3_RDPSR] = true;
+ m_alu_op3_assigned[OP3_RDWIM] = true;
+ m_alu_op3_assigned[OP3_RDTBR] = true;
+ m_alu_op3_assigned[OP3_WRASR] = true;
+ m_alu_op3_assigned[OP3_WRPSR] = true;
+ m_alu_op3_assigned[OP3_WRWIM] = true;
+ m_alu_op3_assigned[OP3_WRTBR] = true;
+ m_alu_op3_assigned[OP3_FPOP1] = true;
+ m_alu_op3_assigned[OP3_FPOP2] = true;
+ m_alu_op3_assigned[OP3_JMPL] = true;
+ m_alu_op3_assigned[OP3_RETT] = true;
+ m_alu_op3_assigned[OP3_TICC] = true;
+ m_alu_op3_assigned[OP3_SAVE] = true;
+ m_alu_op3_assigned[OP3_RESTORE] = true;
+#if SPARCV8
+ m_alu_op3_assigned[OP3_UMUL] = true;
+ m_alu_op3_assigned[OP3_SMUL] = true;
+ m_alu_op3_assigned[OP3_UDIV] = true;
+ m_alu_op3_assigned[OP3_SDIV] = true;
+ m_alu_op3_assigned[OP3_UMULCC] = true;
+ m_alu_op3_assigned[OP3_SMULCC] = true;
+ m_alu_op3_assigned[OP3_UDIVCC] = true;
+ m_alu_op3_assigned[OP3_SDIVCC] = true;
+ m_alu_op3_assigned[OP3_CPOP1] = true;
+ m_alu_op3_assigned[OP3_CPOP2] = true;
+#endif
m_program = &space(AS_PROGRAM);
+ memset(m_ldst_op3_assigned, 0, 64 * sizeof(bool));
+ m_ldst_op3_assigned[OP3_LD] = true;
+ m_ldst_op3_assigned[OP3_LDUB] = true;
+ m_ldst_op3_assigned[OP3_LDUH] = true;
+ m_ldst_op3_assigned[OP3_LDD] = true;
+ m_ldst_op3_assigned[OP3_ST] = true;
+ m_ldst_op3_assigned[OP3_STB] = true;
+ m_ldst_op3_assigned[OP3_STH] = true;
+ m_ldst_op3_assigned[OP3_STD] = true;
+ m_ldst_op3_assigned[OP3_LDSB] = true;
+ m_ldst_op3_assigned[OP3_LDSH] = true;
+ m_ldst_op3_assigned[OP3_LDSTUB] = true;
+ m_ldst_op3_assigned[OP3_LDA] = true;
+ m_ldst_op3_assigned[OP3_LDUBA] = true;
+ m_ldst_op3_assigned[OP3_LDUHA] = true;
+ m_ldst_op3_assigned[OP3_LDDA] = true;
+ m_ldst_op3_assigned[OP3_STA] = true;
+ m_ldst_op3_assigned[OP3_STBA] = true;
+ m_ldst_op3_assigned[OP3_STHA] = true;
+ m_ldst_op3_assigned[OP3_STDA] = true;
+ m_ldst_op3_assigned[OP3_LDSBA] = true;
+ m_ldst_op3_assigned[OP3_LDSHA] = true;
+ m_ldst_op3_assigned[OP3_LDSTUBA] = true;
+ m_ldst_op3_assigned[OP3_LDFPR] = true;
+ m_ldst_op3_assigned[OP3_LDFSR] = true;
+ m_ldst_op3_assigned[OP3_LDDFPR] = true;
+ m_ldst_op3_assigned[OP3_STFPR] = true;
+ m_ldst_op3_assigned[OP3_STFSR] = true;
+ m_ldst_op3_assigned[OP3_STDFQ] = true;
+ m_ldst_op3_assigned[OP3_STDFPR] = true;
+#if SPARCV8
+ m_ldst_op3_assigned[OP3_SWAP] = true;
+ m_ldst_op3_assigned[OP3_SWAPA] = true;
+ m_ldst_op3_assigned[OP3_LDCPR] = true;
+ m_ldst_op3_assigned[OP3_LDCSR] = true;
+ m_ldst_op3_assigned[OP3_LDDCPR] = true;
+ m_ldst_op3_assigned[OP3_STCPR] = true;
+ m_ldst_op3_assigned[OP3_STCSR] = true;
+ m_ldst_op3_assigned[OP3_STDCQ] = true;
+ m_ldst_op3_assigned[OP3_STDCPR] = true;
+#endif
+
// register our state for the debugger
state_add(STATE_GENPC, "GENPC", m_pc).noshow();
state_add(STATE_GENFLAGS, "GENFLAGS", m_psr).callimport().callexport().formatstr("%6s").noshow();
@@ -130,14 +207,51 @@ void mb86901_device::device_start()
state_add(SPARC_R0 + i, rname, m_r[i]).formatstr("%08X");
}
- // register with the savestate system
save_item(NAME(m_r));
+ save_item(NAME(m_fpr));
+ save_item(NAME(m_fsr));
+ save_item(NAME(m_ftt));
save_item(NAME(m_pc));
save_item(NAME(m_npc));
save_item(NAME(m_psr));
save_item(NAME(m_wim));
save_item(NAME(m_tbr));
save_item(NAME(m_y));
+ save_item(NAME(m_bp_reset_in));
+ save_item(NAME(m_bp_irl));
+ save_item(NAME(m_bp_fpu_present));
+ save_item(NAME(m_bp_cp_present));
+ save_item(NAME(m_pb_block_ldst_byte));
+ save_item(NAME(m_pb_block_ldst_word));
+ save_item(NAME(m_trap));
+ save_item(NAME(m_tt));
+ save_item(NAME(m_ticc_trap_type));
+ save_item(NAME(m_interrupt_level));
+ save_item(NAME(m_privileged_instruction));
+ save_item(NAME(m_illegal_instruction));
+ save_item(NAME(m_mem_address_not_aligned));
+ save_item(NAME(m_fp_disabled));
+ save_item(NAME(m_fp_exception));
+ save_item(NAME(m_cp_disabled));
+ save_item(NAME(m_cp_exception));
+ save_item(NAME(m_unimplemented_FLUSH));
+ save_item(NAME(m_r_register_access_error));
+ save_item(NAME(m_instruction_access_error));
+ save_item(NAME(m_instruction_access_exception));
+ save_item(NAME(m_data_access_error));
+ save_item(NAME(m_data_store_error));
+ save_item(NAME(m_data_access_exception));
+ save_item(NAME(m_division_by_zero));
+ save_item(NAME(m_trap_instruction));
+ save_item(NAME(m_window_underflow));
+ save_item(NAME(m_window_overflow));
+ save_item(NAME(m_tag_overflow));
+ save_item(NAME(m_reset_mode));
+ save_item(NAME(m_reset_trap));
+ save_item(NAME(m_execute_mode));
+ save_item(NAME(m_error_mode));
+ save_item(NAME(m_fpu_sequence_err));
+ save_item(NAME(m_cp_sequence_err));
save_item(NAME(m_impl));
save_item(NAME(m_ver));
save_item(NAME(m_icc));
@@ -148,35 +262,56 @@ void mb86901_device::device_start()
save_item(NAME(m_ps));
save_item(NAME(m_et));
save_item(NAME(m_cwp));
- save_item(NAME(m_insn_asi));
- save_item(NAME(m_data_asi));
save_item(NAME(m_asi));
- save_item(NAME(m_queued_tt));
- save_item(NAME(m_queued_priority));
+ save_item(NAME(m_mae));
+ save_item(NAME(m_annul));
+ save_item(NAME(m_hold_bus));
// set our instruction counter
m_icountptr = &m_icount;
}
+
void mb86901_device::device_stop()
{
}
+
void mb86901_device::device_reset()
{
- m_queued_tt = 0;
- m_queued_priority = SPARC_NO_TRAP;
+ m_trap = 0;
+ m_tt = 0;
+ m_ticc_trap_type = 0;
+ m_privileged_instruction = 0;
+ m_illegal_instruction = 0;
+ m_mem_address_not_aligned = 0;
+ m_fp_disabled = 0;
+ m_cp_disabled = 0;
+ m_instruction_access_exception = 0;
+ m_trap_instruction = 0;
+ m_window_underflow = 0;
+ m_window_overflow = 0;
+ m_tag_overflow = 0;
+ m_reset_mode = 1;
+ m_reset_trap = 0;
+ m_execute_mode = 0;
+ m_error_mode = 0;
+ m_fpu_sequence_err = 0;
+ m_cp_sequence_err = 0;
+
m_asi = 0;
MAE = false;
HOLD_BUS = false;
+ m_annul = false;
PC = 0;
nPC = 4;
memset(m_r, 0, sizeof(UINT32) * 120);
+ memset(m_fpr, 0, sizeof(UINT32) * 32);
- m_wim = 0;
- m_tbr = 0;
- m_y = 0;
+ WIM = 0;
+ TBR = 0;
+ Y = 0;
m_impl = 0;
m_ver = 0;
@@ -189,9 +324,6 @@ void mb86901_device::device_reset()
m_et = false;
m_cwp = 0;
- m_insn_asi = 9;
- m_data_asi = 11;
-
MAKE_PSR;
for (int i = 0; i < 8; i++)
{
@@ -218,80 +350,56 @@ const address_space_config *mb86901_device::memory_space_config(address_spacenum
}
}
+
//-------------------------------------------------
-// read_byte - read an 8-bit value from a given
-// address space
+// read_sized_word - read a value from a given
+// address space and address, shifting the data
+// that is read into the appropriate location of
+// a 32-bit word in a big-endian system.
//-------------------------------------------------
-UINT32 mb86901_device::read_byte(UINT8 asi, UINT32 address)
-{
- m_asi = asi;
- // TODO: data_access_exception, data_access_error traps
- return m_program->read_byte(address);
-}
-
-INT32 mb86901_device::read_signed_byte(UINT8 asi, UINT32 address)
-{
- m_asi = asi;
- // TODO: data_access_exception, data_access_error traps
- return (((INT32)m_program->read_byte(address) << 24) >> 24);
-}
-
-UINT32 mb86901_device::read_half(UINT8 asi, UINT32 address)
-{
- m_asi = asi;
- // TODO: data_access_exception, data_access_error traps
- return m_program->read_word(address);
-}
-
-INT32 mb86901_device::read_signed_half(UINT8 asi, UINT32 address)
-{
- m_asi = asi;
- // TODO: data_access_exception, data_access_error traps
- return (((INT32)m_program->read_word(address) << 16) >> 16);
-}
-
-UINT32 mb86901_device::read_word(UINT8 asi, UINT32 address)
+UINT32 mb86901_device::read_sized_word(UINT8 asi, UINT32 address, int size)
{
m_asi = asi;
- // TODO: data_access_exception, data_access_error traps
- return m_program->read_dword(address);
-}
-
-UINT64 mb86901_device::read_doubleword(UINT8 asi, UINT32 address)
-{
- m_asi = asi;
- // TODO: data_access_exception, data_access_error traps
- return (((UINT64)m_program->read_dword(address) << 32) | m_program->read_dword(address+4));
-}
-
-void mb86901_device::write_byte(UINT8 asi, UINT32 address, UINT8 data)
-{
- m_asi = asi;
- // TODO: data_access_exception, data_access_error traps
- m_program->write_byte(address, data);
+ if (size == 1)
+ {
+ return m_program->read_byte(address) << ((3 - (address & 3)) * 8);
+ }
+ else if (size == 2)
+ {
+ return m_program->read_word(address) << ((1 - (address & 1)) * 16);
+ }
+ else
+ {
+ return m_program->read_dword(address);
+ }
}
-void mb86901_device::write_half(UINT8 asi, UINT32 address, UINT16 data)
-{
- m_asi = asi;
- // TODO: data_access_exception, data_access_error traps
- m_program->write_word(address, data);
-}
-void mb86901_device::write_word(UINT8 asi, UINT32 address, UINT32 data)
-{
- m_asi = asi;
- // TODO: data_access_exception, data_access_error traps
- m_program->write_dword(address, data);
-}
+//-------------------------------------------------
+// write_sized_word - write a value to a given
+// address space and address, shifting the data
+// that is written into the least significant
+// bits as appropriate in order to write the
+// value to a memory system with separate data
+// size handlers
+//-------------------------------------------------
-void mb86901_device::write_doubleword(UINT8 asi, UINT32 address, UINT64 data)
+void mb86901_device::write_sized_word(UINT8 asi, UINT32 address, UINT32 data, int size)
{
m_asi = asi;
- // TODO: data_access_exception, data_access_error traps
- m_program->write_dword(address, (UINT32)(data >> 32));
- m_program->write_dword(address+4, (UINT32)data);
+ if (size == 1)
+ {
+ m_program->write_byte(address, data >> ((3 - (address & 3)) * 8));
+ }
+ else if (size == 2)
+ {
+ m_program->write_word(address, data >> ((1 - (address & 1)) * 16));
+ }
+ else
+ {
+ m_program->write_dword(address, data);
+ }
}
@@ -403,83 +511,868 @@ void mb86901_device::execute_set_input(int inputnum, int state)
//-------------------------------------------------
-// save_restore_update_cwp - update cwp after
-// a save or restore opcode with no trap taken
+// execute_add - execute an add-type opcode
+//-------------------------------------------------
+
+void mb86901_device::execute_add(UINT32 op)
+{
+ /* The SPARC Instruction Manual: Version 8, page 173, "Appendix C - ISP Descriptions - Add Instructions" (SPARCv8.pdf, pg. 170)
+
+ operand2 := if (i = 0) then r[rs2] else sign_extend(simm13);
+
+ if (ADD or ADDcc) then
+ result <- r[rs1] + operand2;
+ else if (ADDX or ADDXcc) then
+ result <= r[rs1] + operand2 + C;
+ next;
+
+ if (rd != 0) then
+ r[rd] <- result;
+
+ if (ADDcc or ADDXcc) then (
+ N <- result<31>;
+ Z <- if (result = 0) then 1 else 0;
+ V <- (r[rs1]<31> and operand2<31> and (not result<31>)) or
+ ((not r[rs1]<31>) and (not operand2<31>) and result<31>);
+ C <- (r[rs1]<31> and operand2<31>) or
+ ((not result<31>) and (r[rs1]<31> or operand2<31>))
+ );
+ */
+ UINT32 operand2 = USEIMM ? SIMM13 : RS2REG;
+
+ UINT32 result = 0;
+ if (OP3 == 0 || OP3 == 16)
+ result = RS1REG + operand2;
+ else if (OP3 == 8 || OP3 == 24)
+ result = RS1REG + operand2 + ICC_C;
+
+
+ if (RD != 0)
+ RDREG = result;
+
+ if (OP3 & 16)
+ {
+ CLEAR_ICC;
+ PSR |= (BIT31(result)) ? PSR_N_MASK : 0;
+ PSR |= (result == 0) ? PSR_Z_MASK : 0;
+ PSR |= ((BIT31(RS1REG) && BIT31(operand2) && !BIT31(result)) ||
+ (!BIT31(RS1REG) && !BIT31(operand2) && BIT31(result))) ? PSR_V_MASK : 0;
+ PSR |= ((BIT31(RS1REG) && BIT31(operand2)) ||
+ (!BIT31(result) && (BIT31(RS1REG) || BIT31(operand2)))) ? PSR_C_MASK : 0;
+ }
+}
+
+
+//-------------------------------------------------
+// execute_taddcc - execute a tagged add-type
+// opcode
+//-------------------------------------------------
+
+void mb86901_device::execute_taddcc(UINT32 op)
+{
+ /* The SPARC Instruction Manual: Version 8, page 173, "Appendix C - ISP Descriptions - Tagged Add Instructions" (SPARCv8.pdf, pg. 170)
+
+ operand2 := if (i = 0) then r[rs2] else sign_extend(simm13);
+
+ result <- r[rs1] + operand2;
+ next;
+
+ temp_V <- (r[rs1]<31> and operand2<31> and (not result<31>)) or
+ ((not r[rs1]<31>) and (not operand2<31>) and result<31>) or
+ (r[rs1]<1:0> != 0 or operand2<1:0> != 0);
+ next;
+
+ if (TADDccTV and (temp_V = 1)) then (
+ trap <- 1;
+ tag_overflow <- 1
+ ) else (
+ N <- result<31>;
+ Z <- if (result = 0) then 1 else 0;
+ V <- temp_V;
+ C <- (r[rs1]<31> and operand2<31>) or
+ ((not result<31>) and (r[rs1]<31> or operand2<31>));
+ if (rd != 0) then
+ r[rd] <- result;
+ );
+ */
+ UINT32 operand2 = USEIMM ? SIMM13 : RS2REG;
+
+ UINT32 result = RS1REG + operand2;
+
+ bool temp_v = (BIT31(RS1REG) && BIT31(operand2) && !BIT31(result)) ||
+ (!BIT31(RS1REG) && !BIT31(operand2) && BIT31(result)) ||
+ ((RS1REG & 3) != 0 || (RS1REG & 3) != 0) ? true : false;
+
+ if (OP3 == 34 && temp_v)
+ {
+ m_trap = 1;
+ m_tag_overflow = true;
+ }
+ else
+ {
+ CLEAR_ICC;
+ PSR |= (BIT31(result)) ? PSR_N_MASK : 0;
+ PSR |= (result == 0) ? PSR_Z_MASK : 0;
+ PSR |= temp_v ? PSR_V_MASK : 0;
+ PSR |= ((BIT31(RS1REG) && BIT31(operand2)) ||
+ (!BIT31(result) && (BIT31(RS1REG) || BIT31(operand2)))) ? PSR_C_MASK : 0;
+
+ if (RD != 0)
+ RDREG = result;
+ }
+}
+
+
+//-------------------------------------------------
+// execute_sub - execute a subtraction-type
+// opcode
+//-------------------------------------------------
+
+void mb86901_device::execute_sub(UINT32 op)
+{
+ /* The SPARC Instruction Manual: Version 8, page 174, "Appendix C - ISP Descriptions - Subtract Instructions" (SPARCv8.pdf, pg. 171)
+
+ operand2 := if (i = 0) then r[rs2] else sign_extend(simm13);
+
+ if (SUB or SUBcc) then
+ result <- r[rs1] - operand2;
+ else if (SUBX or SUBXcc) then
+ result <= r[rs1] - operand2 - C;
+ next;
+
+ if (rd != 0) then
+ r[rd] <- result;
+
+ if (SUBcc or SUBXcc) then (
+ N <- result<31>;
+ Z <- if (result = 0) then 1 else 0;
+ V <- (r[rs1]<31> and (not operand2<31>) and (not result<31>)) or
+ ((not r[rs1]<31>) and operand2<31> and result<31>);
+ C <- ((not r[rs1]<31>) and operand2<31>) or
+ (result<31> and ((not r[rs1]<31>) or operand2<31>))
+ );
+ */
+ UINT32 operand2 = USEIMM ? SIMM13 : RS2REG;
+
+ UINT32 result = 0;
+ if (OP3 == 4 || OP3 == 20)
+ result = RS1REG - operand2;
+ else if (OP3 == 12 || OP3 == 28)
+ result = RS1REG - operand2 - ICC_C;
+
+ if (RD != 0)
+ RDREG = result;
+
+ if (OP3 & 16)
+ {
+ CLEAR_ICC;
+ PSR |= (BIT31(result)) ? PSR_N_MASK : 0;
+ PSR |= (result == 0) ? PSR_Z_MASK : 0;
+ PSR |= ((BIT31(RS1REG) && !BIT31(operand2) && !BIT31(result)) ||
+ (!BIT31(RS1REG) && BIT31(operand2) && BIT31(result))) ? PSR_V_MASK : 0;
+ PSR |= ((!BIT31(RS1REG) && BIT31(operand2)) ||
+ (BIT31(result) && (!BIT31(RS1REG) || BIT31(operand2)))) ? PSR_C_MASK : 0;
+ }
+}
+
+
+//--------------------------------------------------
+// execute_tsubcc - execute a tagged subtract-type
+// opcode
+//--------------------------------------------------
+
+void mb86901_device::execute_tsubcc(UINT32 op)
+{
+ /* The SPARC Instruction Manual: Version 8, page 174, "Appendix C - ISP Descriptions - Tagged Subtract Instructions" (SPARCv8.pdf, pg. 171)
+
+ operand2 := if (i = 0) then r[rs2] else sign_extend(simm13);
+
+ result <- r[rs1] - operand2;
+ next;
+
+ temp_V <- (r[rs1]<31> and (not operand2<31>) and (not result<31>)) or
+ ((not r[rs1]<31>) and operand2<31> and result<31>) or
+ (r[rs1]<1:0> != 0 or operand2<1:0> != 0);
+ next;
+
+ if (TSUBccTV and (temp_V = 1)) then (
+ trap <- 1;
+ tag_overflow <- 1
+ ) else (
+ N <- result<31>;
+ Z <- if (result = 0) then 1 else 0;
+ V <- temp_V;
+ C <- ((not r[rs1]<31>) and operand2<31>) or
+ (result<31> and ((not r[rs1]<31>) or operand2<31>));
+ if (rd != 0) then
+ r[rd] <- result;
+ );
+ */
+
+ UINT32 operand2 = USEIMM ? SIMM13 : RS2REG;
+
+ UINT32 result = RS1REG - operand2;
+
+ bool temp_v = (BIT31(RS1REG) && !BIT31(operand2) && !BIT31(result)) ||
+ (!BIT31(RS1REG) && BIT31(operand2) && BIT31(result)) ||
+ ((RS1REG & 3) != 0 || (RS1REG & 3) != 0) ? true : false;
+
+ if (OP3 == 35 && temp_v)
+ {
+ m_trap = 1;
+ m_tag_overflow = 1;
+ }
+ else
+ {
+ CLEAR_ICC;
+ PSR |= (BIT31(result)) ? PSR_N_MASK : 0;
+ PSR |= (result == 0) ? PSR_Z_MASK : 0;
+ PSR |= temp_v ? PSR_V_MASK : 0;
+ PSR |= ((!BIT31(RS1REG) && BIT31(operand2)) ||
+ (BIT31(result) && (!BIT31(RS1REG) || BIT31(operand2)))) ? PSR_C_MASK : 0;
+
+ if (RD != 0)
+ RDREG = result;
+ }
+}
+
+
+//-------------------------------------------------
+// execute_logical - execute a logical-type
+// opcode, and/or/xor/andn/orn/xnor
+//-------------------------------------------------
+
+void mb86901_device::execute_logical(UINT32 op)
+{
+ /* The SPARC Instruction Manual: Version 8, page 172, "Appendix C - ISP Descriptions - Logical Instructions" (SPARCv8.pdf, pg. 169)
+
+ operand2 := if (i = 0) then r[rs2] else sign_extend(simm13);
+
+ if ( AND or ANDcc) then result <- r[rs1] and operand2
+ if (ANDN or ANDNcc) then result <- r[rs1] and not operand2
+ if ( OR or ORcc) then result <- r[rs1] or operand2
+ if ( ORN or ORNcc) then result <- r[rs1] or not operand2
+ if ( XOR or XORcc) then result <- r[rs1] xor operand2
+ if (XNOR or XNORcc) then result <- r[rs1] xor not operand2;
+ next;
+
+ if (rd != 0) then r[rd] <- result;
+
+ if (ANDcccc or ANDNcc or ORcc or ORNcc or XORcc or XNORcc) then (
+ N <- result<31>;
+ Z <- if (result = 0) then 1 else 0;
+ V <- 0
+ C <- 0
+ );
+ */
+
+ UINT32 operand2 = USEIMM ? SIMM13 : RS2REG;
+
+ UINT32 result = 0;
+ switch (OP3)
+ {
+ case 1:
+ case 17:
+ result = RS1REG & operand2;
+ break;
+ case 5:
+ case 21:
+ result = RS1REG & ~operand2;
+ break;
+ case 2: case 18:
+ result = RS1REG | operand2;
+ break;
+ case 6: case 22:
+ result = RS1REG | ~operand2;
+ break;
+ case 3: case 19:
+ result = RS1REG ^ operand2;
+ break;
+ case 7: case 23:
+ result = RS1REG ^ ~operand2;
+ break;
+ }
+
+ if (RD != 0) RDREG = result;
+
+ if (OP3 & 16)
+ {
+ CLEAR_ICC;
+ PSR |= (BIT31(result)) ? PSR_N_MASK : 0;
+ PSR |= (result == 0) ? PSR_Z_MASK : 0;
+ }
+}
+
+
+//-------------------------------------------------
+// execute_shift - execute a shift-type opcode,
+// sll/srl/sra
+//-------------------------------------------------
+
+void mb86901_device::execute_shift(UINT32 op)
+{
+ /* The SPARC Instruction Manual: Version 8, page 172, "Appendix C - ISP Descriptions - Shift Instructions" (SPARCv8.pdf, pg. 169)
+
+ shift_count := if (i = 0) then r[rs2]<4:0> else shcnt;
+
+ if (SLL and (rd != 0) ) then
+ r[rd] <- shift_left_logical(r[rs1], shift_count)
+ else if (SRL and (rd != 0) ) then
+ r[rd] <- shift_right_logical(r[rs1], shift_count)
+ else if (SRA and (rd != 0) ) then
+ r[rd] <- shift_right_arithmetic(r[rs1], shift_count)
+ */
+ UINT32 shift_count = USEIMM ? (SIMM13 & 31) : (RS2REG & 31);
+
+ if (OP3 == 37 && RD != 0)
+ RDREG = RS1REG << shift_count;
+ else if (OP3 == 38 && RD != 0)
+ RDREG = UINT32(RS1REG) >> shift_count;
+ else if (OP3 == 39 && RD != 0)
+ RDREG = INT32(RS1REG) >> shift_count;
+}
+
+
+//--------------------------------------------------
+// execute_mulscc - execute a multiply step opcode
+//--------------------------------------------------
+
+void mb86901_device::execute_mulscc(UINT32 op)
+{
+ /* The SPARC Instruction Manual: Version 8, page 175, "Appendix C - ISP Descriptions - Multiply Step Instruction" (SPARCv8.pdf, pg. 172)
+
+ operand1 := (N xor V) [] (r[rs1]<31:1>);
+
+ operand2 := (
+ if (Y<0> = 0) then 0
+ else if (i = 0) then r[rs2] else sign_extend(simm13)
+ );
+
+ result <- operand1 + operand2;
+ Y <- r[rs1]<0> [] Y<31:1>;
+ next;
+
+ if (rd != 0) then (
+ r[rd] <- result;
+ )
+ N <- result<31>;
+ Z <- if (result = 0) then 1 else 0;
+ V <- (operand1<31> and operand2<31> and (not result<31>)) or
+ ((not operand1<31>) and (not operand2<31>) and result<31>);
+ C <- (operand1<31> and operand2<31>) or
+ ((not result<31>) and (operand1<31> or operand2<31>))
+ */
+ UINT32 operand1 = (ICC_N != ICC_V ? 0x80000000 : 0) | (RS1REG >> 1);
+
+ UINT32 operand2 = (Y & 1) ? 0 : (USEIMM ? SIMM13 : RS2REG);
+
+ UINT32 result = operand1 + operand2;
+ Y = ((RS1REG & 1) ? 0x80000000 : 0) | (Y >> 1);
+
+ if (RD != 0)
+ RDREG = result;
+
+ CLEAR_ICC;
+ PSR |= (BIT31(result)) ? PSR_N_MASK : 0;
+ PSR |= (result == 0) ? PSR_Z_MASK : 0;
+ PSR |= ((BIT31(operand1) && BIT31(operand2) && !BIT31(result)) ||
+ (!BIT31(operand1) && !BIT31(operand2) && BIT31(result))) ? PSR_V_MASK : 0;
+ PSR |= ((BIT31(operand1) && BIT31(operand2)) ||
+ (!BIT31(result) && (BIT31(operand1) || BIT31(operand2)))) ? PSR_C_MASK : 0;
+}
+
+
+//-------------------------------------------------
+// execute_rdsr - execute a status register read
+// opcode
+//-------------------------------------------------
+
+void mb86901_device::execute_rdsr(UINT32 op)
+{
+ /* The SPARC Instruction Manual: Version 8, page 182, "Appendix C - ISP Descriptions - Read State Register Instructions" (SPARCv8.pdf, pg. 179)
+
+ if ((RDPSR or RDWIM or RDBTR
+ or (RDASR and (privileged_ASR(rs1) = 1))) and (S = 0)) then (
+ trap <- 1;
+ privileged_instruction <- 1;
+ else if (illegal_instruction_ASR(rs1) = 1) then (
+ trap <- 1;
+ illegal_instruction <- 1
+ else if (rd != 0) then (
+ if (RDY) then r[rd] <- Y
+ else if (RDASR) then r[rd] <- ASR[rs1]
+ else if (RDPSR) then r[rd] <- PSR
+ else if (RDWIM) then r[rd] <- WIM
+ else if (RDTBR) then r[rd] <- TBR;
+ );
+ */
+
+ if (((OP3 == 41 || OP3 == 42 || OP3 == 43) || (OP3 == 40 && m_privileged_asr[RS1])) && IS_USER)
+ {
+ m_trap = 1;
+ m_privileged_instruction = 1;
+ }
+ else if (m_illegal_instruction_asr[RS1])
+ {
+ m_trap = 1;
+ m_illegal_instruction = 1;
+ }
+ else if (RD != 0)
+ {
+ switch (OP3)
+ {
+ case OP3_RDASR:
+ if (RS1 == 0) RDREG = Y; break;
+ case OP3_RDPSR: RDREG = PSR; break;
+ case OP3_RDWIM: RDREG = WIM; break;
+ case OP3_RDTBR: RDREG = TBR; break;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// execute_wrsr - execute a status register write
+// opcode
+//-------------------------------------------------
+
+void mb86901_device::execute_wrsr(UINT32 op)
+{
+ /* The SPARC Instruction Manual: Version 8, page 183, "Appendix C - ISP Descriptions - Write State Register Instructions" (SPARCv8.pdf, pg. 180)
+
+ operand2 := if (i = 0) then r[rs2] else sign_extend(simm13);
+ result := r[rs1] xor operand2;
+
+ if (WRY) then (
+ Y'''' <- result
+ ) else if (WRASR) then (
+ if ( (privileged_ASR(rd) = 1) and (S = 0) ) then (
+ trap <- 1;
+ privileged_instruction <- 1
+ ) else if (illegal_instruction_ASR(rd) = 1) then (
+ trap <- 1;
+ illegal_instruction <- 1
+ ) else (
+ ASR[rd]'''' <- result
+ )
+ ) else if (WRPSR) then (
+ if (S = 0) then (
+ trap <- 1;
+ privileged_instruction <- 1
+ ) else if (result<4:0> >= NWINDOWS) then (
+ trap <- 1;
+ illegal_instruction <- 1
+ ) else (
+ PSR'''' <- result
+ )
+ ) else if (WRWIM) then (
+ if (S = 0) then (
+ trap <- 1;
+ privileged_instruction <- 1
+ ) else (
+ WIM'''' <- result
+ )
+ ) else if (WRBTR) then (
+ if (S = 0) then (
+ trap <- 1;
+ privileged_instruction <- 1
+ ) else (
+ WIM'''' <- result
+ )
+ );
+ */
+ UINT32 operand2 = USEIMM ? SIMM13 : RS2REG;
+
+ UINT32 result = RS1REG ^ operand2;
+
+ if (OP3 == 48 && RD == 0)
+ {
+ Y = result;
+ }
+ else if (OP3 == 48)
+ {
+ if (m_privileged_asr[RD] && IS_USER)
+ {
+ m_trap = 1;
+ m_privileged_instruction = 1;
+ }
+ else if (m_illegal_instruction_asr[RD])
+ {
+ m_trap = 1;
+ m_illegal_instruction = 1;
+ }
+ else
+ {
+ // SPARCv8
+ }
+ }
+ else if (OP3 == 49)
+ {
+ if (IS_USER)
+ {
+ m_trap = 1;
+ m_privileged_instruction = 1;
+ }
+ else if ((result & 31) >= NWINDOWS)
+ {
+ m_trap = 1;
+ m_illegal_instruction = 1;
+ }
+ else
+ {
+ PSR = result &~ PSR_ZERO_MASK;
+ }
+ }
+ else if (OP3 == 50)
+ {
+ if (IS_USER)
+ {
+ m_trap = 1;
+ m_privileged_instruction = 1;
+ }
+ else
+ {
+ WIM = result & 0x7f;
+ }
+ }
+ else if (OP3 == 51)
+ {
+ if (IS_USER)
+ {
+ m_trap = 1;
+ m_privileged_instruction = 1;
+ }
+ else
+ {
+ TBR = result & 0xfffff000;
+ }
+ }
+}
+
+
+//-------------------------------------------------
+// execute_rett - execute a return-from-trap
+// opcode
+//-------------------------------------------------
+
+void mb86901_device::execute_rett(UINT32 op)
+{
+ /* The SPARC Instruction Manual: Version 8, page 181, "Appendix C - ISP Descriptions - Return from Trap Instructions" (SPARCv8.pdf, pg. 178)
+
+ new_cwp <- (CWP + 1) modulo NWINDOWS;
+ address <- r[rs1] + (if (i = 0) then r[rs2] else sign_extend(simm13));
+ next;
+ if (ET = 1) then (
+ trap <- 1;
+ if (S = 0) then privileged_instruction <- 1
+ else if (S != 0) then illegal_instruction <- 1
+ ) else if (S = 0) then (
+ trap <- 1;
+ privileged_instruction <- 1
+ tt <- 00000011; { trap type for privileged_instruction }
+ execute_mode <- 0;
+ error_mode = 1
+ ) else if ((WIM and (1 << new_cwp)) != 0) then (
+ trap <- 1;
+ window_underflow <- 1;
+ tt <- 00000110; { trap type for window_underflow }
+ execute_mode = 0;
+ error_mode = 1
+ ) else if (address<1:0> != 0) then (
+ trap = 1;
+ mem_address_not_aligned = 1;
+ tt = 7; { trap type for mem_address_not_aligned }
+ execute_mode = 0;
+ error_mode = 1
+ ) else (
+ ET <- 1;
+ PC <- nPC;
+ nPC <- address;
+ CWP <- new_cwp;
+ S <- PS
+ )
+ */
+
+ UINT8 new_cwp = (CWP + 1) % NWINDOWS;
+ UINT32 address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
+ if (ET)
+ {
+ m_trap = 1;
+ if (IS_USER) m_privileged_instruction = 1;
+ else m_illegal_instruction = 1;
+ }
+ else if (IS_USER)
+ {
+ m_trap = 1;
+ m_privileged_instruction = 1;
+ m_tt = 3;
+ m_execute_mode = 0;
+ m_error_mode = 1;
+ }
+ else if ((WIM & (1 << new_cwp)) != 0)
+ {
+ m_trap = 1;
+ m_window_underflow = 1;
+ m_tt = 6;
+ m_execute_mode = 0;
+ m_error_mode = 1;
+
+ }
+ else if (address & 3)
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ m_tt = 7;
+ m_execute_mode = 0;
+ m_error_mode = 1;
+ }
+ else
+ {
+ ET = 1;
+ PC = nPC;
+ nPC = address;
+ CWP = new_cwp;
+ S = PS;
+ }
+
+ MAKE_PSR;
+ update_gpr_pointers();
+}
+
+
+
+//-------------------------------------------------
+// execute_saverestore - execute a save or restore
+// opcode
//-------------------------------------------------
-void mb86901_device::save_restore_update_cwp(UINT32 op, UINT8 new_cwp)
+void mb86901_device::execute_saverestore(UINT32 op)
{
- UINT32 arg1 = RS1REG;
- UINT32 arg2 = USEIMM ? SIMM13 : RS2REG;
+ /* The SPARC Instruction Manual: Version 8, page 177, "Appendix C - ISP Descriptions - SAVE and RESTORE Instructions" (SPARCv8.pdf, pg. 174)
+
+ operand2 := if (i = 0) then r[rs2] else sign_extend(simm13);
+
+ if (SAVE) then (
+ new_cwp <- (CWP - 1) modulo NWINDOWS;
+ next;
+ if ((WIM and (1 << new_cwp)) != 0) then (
+ trap <- 1;
+ window_overflow <- 1
+ ) else (
+ result <- r[rs1] + operand2; { operands from old window }
+ CWP <- new_cwp
+ )
+ ) else if (RESTORE) then (
+ new_cwp <- (CWP + 1) modulo NWINDOWS;
+ next;
+ if ((WIM and (1 << new_cwp)) != 0) then (
+ trap <- 1;
+ window_overflow <- 1
+ ) else (
+ result <- r[rs1] + operand2; { operands from old window }
+ CWP <- new_cwp
+ )
+ );
+ next;
+ if ((trap = 0) and (rd != 0)) then
+ r[rd] <- result { destination in new window }
+ */
+
+ UINT32 rs1 = RS1REG;
+ UINT32 operand2 = USEIMM ? SIMM13 : RS2REG;
+
+ UINT32 result = 0;
+ if (OP3 == OP3_SAVE)
+ {
+ UINT8 new_cwp = ((CWP + NWINDOWS) - 1) % NWINDOWS;
+ if ((WIM & (1 << new_cwp)) != 0)
+ {
+ m_trap = 1;
+ m_window_overflow = 1;
+ }
+ else
+ {
+ result = rs1 + operand2;
+ CWP = new_cwp;
+ }
+ }
+ else if (OP3 == OP3_RESTORE)
+ {
+ UINT8 new_cwp = (CWP + 1) % NWINDOWS;
+ if ((WIM & (1 << new_cwp)) != 0)
+ {
+ m_trap = 1;
+ m_window_underflow = 1;
+ }
+ else
+ {
+ result = rs1 + operand2;
+ CWP = new_cwp;
+ }
+ }
- m_cwp = new_cwp;
MAKE_PSR;
update_gpr_pointers();
- SET_RDREG(arg1 + arg2);
+ if (m_trap == 0 && RD != 0)
+ RDREG = result;
}
+
+//-------------------------------------------------
+// execute_jmpl - execute a jump and link opcode
+//-------------------------------------------------
+
+void mb86901_device::execute_jmpl(UINT32 op)
+{
+ /* The SPARC Instruction Manual: Version 8, page 180, "Appendix C - ISP Descriptions - SAVE and RESTORE Instructions" (SPARCv8.pdf, pg. 177)
+
+ jump_address <- r[rs1] + (if (i = 0) then r[rs2] else sign_extend(simm13));
+ next;
+ if (jump_address<1:0> != 0) then (
+ trap <- 1;
+ mem_address_not_aligned <- 1
+ ) else (
+ if (rd != 0) then r[rd] <- PC;
+ PC <- nPC;
+ nPC <- jump_address
+ )
+ */
+
+ UINT32 jump_address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
+
+ if (jump_address & 3)
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ }
+ else
+ {
+ if (RD != 0)
+ RDREG = PC;
+ PC = nPC;
+ nPC = jump_address;
+ }
+}
+
+
//-------------------------------------------------
// execute_group2 - execute an opcode in group 2,
// mostly ALU ops
//-------------------------------------------------
-bool mb86901_device::execute_group2(UINT32 op)
+void mb86901_device::execute_group2(UINT32 op)
{
- UINT32 arg1 = RS1REG;
- UINT32 arg2 = USEIMM ? SIMM13 : RS2REG;
-
switch (OP3)
{
- case 0: // add
- SET_RDREG(arg1 + arg2);
+ case OP3_ADD:
+ case OP3_ADDX:
+ case OP3_ADDCC:
+ case OP3_ADDXCC:
+ execute_add(op);
+ break;
+
+ case OP3_SUB:
+ case OP3_SUBX:
+ case OP3_SUBCC:
+ case OP3_SUBXCC:
+ execute_sub(op);
+ break;
+
+ case OP3_TADDCC:
+ case OP3_TADDCCTV:
+ execute_taddcc(op);
break;
- case 1: // and
- SET_RDREG(arg1 & arg2);
+
+ case OP3_TSUBCC:
+ case OP3_TSUBCCTV:
+ execute_tsubcc(op);
break;
- case 2: // or
- SET_RDREG(arg1 | arg2);
+
+ case OP3_AND:
+ case OP3_OR:
+ case OP3_XOR:
+ case OP3_ANDN:
+ case OP3_ORN:
+ case OP3_XNOR:
+ case OP3_ANDCC:
+ case OP3_ORCC:
+ case OP3_XORCC:
+ case OP3_ANDNCC:
+ case OP3_ORNCC:
+ case OP3_XNORCC:
+ execute_logical(op);
break;
- case 3: // xor
- SET_RDREG(arg1 ^ arg2);
+
+ case OP3_MULSCC:
+ execute_mulscc(op);
break;
- case 4: // sub
- SET_RDREG(arg1 - arg2);
+
+ case OP3_SLL:
+ case OP3_SRL:
+ case OP3_SRA:
+ execute_shift(op);
break;
- case 5: // andn
- SET_RDREG(arg1 & ~arg2);
+
+ case OP3_RDASR:
+ case OP3_RDPSR:
+ case OP3_RDWIM:
+ case OP3_RDTBR:
+ execute_rdsr(op);
break;
- case 6: // orn
- SET_RDREG(arg1 | ~arg2);
+
+ case OP3_WRASR:
+ case OP3_WRPSR:
+ case OP3_WRWIM:
+ case OP3_WRTBR:
+ execute_wrsr(op);
break;
- case 7: // xnor
- SET_RDREG(arg1 ^ ~arg2);
+
+ case OP3_FPOP1:
+ case OP3_FPOP2:
+ // Not yet implemented
+ break;
+
+ case OP3_JMPL:
+ execute_jmpl(op);
+ break;
+
+ case OP3_RETT:
+ execute_rett(op);
+ break;
+
+ case OP3_TICC:
+ execute_ticc(op);
break;
- case 8: // addx
- SET_RDREG(arg1 + arg2 + (ICC_C_SET ? 1 : 0));
+
+ case OP3_SAVE:
+ case OP3_RESTORE:
+ execute_saverestore(op);
break;
+
#if SPARCV8
- case 10: // umul, SPARCv8
+ case OP3_UMUL: // SPARCv8
{
+ UINT32 arg1 = RS1REG;
+ UINT32 arg2 = USEIMM ? SIMM13 : RS2REG;
UINT64 result = (UINT64)arg1 * (UINT64)arg2;
Y = (UINT32)(result >> 32);
SET_RDREG((UINT32)result);
break;
}
- case 11: // smul, SPARCv8
+ case OP3_SMUL: // SPARCv8
{
+ UINT32 arg1 = RS1REG;
+ UINT32 arg2 = USEIMM ? SIMM13 : RS2REG;
INT64 result = (INT64)(INT32)arg1 * (INT64)(INT32)arg2;
Y = (UINT32)((UINT64)result >> 32);
SET_RDREG((UINT32)result);
break;
}
-#endif
- case 12: // subx
- SET_RDREG(arg1 - arg2 - (ICC_C_SET ? 1 : 0));
- break;
-#if SPARCV8
- case 14: // udiv, SPARCv8
+ case OP3_UDIV: // SPARCv8
{
+ UINT32 arg1 = RS1REG;
+ UINT32 arg2 = USEIMM ? SIMM13 : RS2REG;
UINT64 dividend = ((UINT64)Y << 32) || arg1;
UINT32 divisor = arg2;
UINT64 quotient = dividend / divisor;
@@ -490,8 +1383,10 @@ bool mb86901_device::execute_group2(UINT32 op)
SET_RDREG((UINT32)quotient);
break;
}
- case 15: // sdiv, SPARCv8
+ case OP3_SDIV: // SPARCv8
{
+ UINT32 arg1 = RS1REG;
+ UINT32 arg2 = USEIMM ? SIMM13 : RS2REG;
INT64 dividend = ((INT64)(INT32)Y << 32) || arg1;
INT32 divisor = arg2;
INT64 quotient = dividend / divisor;
@@ -513,118 +1408,30 @@ bool mb86901_device::execute_group2(UINT32 op)
SET_RDREG((UINT32)quotient);
break;
}
-#endif
- case 16: // addcc
- {
- UINT32 result = arg1 + arg2;
- TEST_ICC_NZ(result);
- if ((arg1 & 0x80000000) == (arg2 & 0x80000000) && (arg2 & 0x80000000) != (result & 0x80000000))
- SET_ICC_V_FLAG;
- if (result < arg1 || result < arg2)
- SET_ICC_C_FLAG;
- SET_RDREG(result);
- break;
- }
- case 17: // andcc
- {
- UINT32 result = arg1 & arg2;
- TEST_ICC_NZ(result);
- SET_RDREG(result);
- break;
- }
- case 18: // orcc
- {
- UINT32 result = arg1 | arg2;
- TEST_ICC_NZ(result);
- SET_RDREG(result);
- break;
- }
- case 19: // xorcc
- {
- UINT32 result = arg1 ^ arg2;
- TEST_ICC_NZ(result);
- SET_RDREG(result);
- break;
- }
- case 20: // subcc
- {
- UINT32 result = arg1 - arg2;
- TEST_ICC_NZ(result);
- if ((arg1 & 0x80000000) != (arg2 & 0x80000000) && (arg2 & 0x80000000) != (result & 0x80000000))
- SET_ICC_V_FLAG;
- if (result > arg1)
- SET_ICC_C_FLAG;
- SET_RDREG(result);
- break;
- }
- case 21: // andncc
- {
- UINT32 result = arg1 & ~arg2;
- TEST_ICC_NZ(result);
- SET_RDREG(result);
- break;
- }
- case 22: // orncc
- {
- UINT32 result = arg1 | ~arg2;
- TEST_ICC_NZ(result);
- SET_RDREG(result);
- break;
- }
- case 23: // xnorcc
- {
- UINT32 result = arg1 ^ ~arg2;
- TEST_ICC_NZ(result);
- SET_RDREG(result);
- break;
- }
- case 24: // addxcc
- {
- UINT32 c = (ICC_C_SET ? 1 : 0);
- UINT32 argt = arg2 + c;
- UINT32 result = arg1 + argt;
- TEST_ICC_NZ(result);
- if (((arg1 & 0x80000000) == (argt & 0x80000000) && (arg1 & 0x80000000) != (result & 0x80000000)) || (c != 0 && arg2 == 0x7fffffff))
- SET_ICC_V_FLAG;
- if (result < arg1 || result < arg2 || (result == arg1 && arg2 != 0))
- SET_ICC_C_FLAG;
- SET_RDREG(result);
- break;
- }
-#if SPARCV8
- case 26: // umulcc, SPARCv8
+ case OP3_UMULCC: // SPARCv8
{
+ UINT32 arg1 = RS1REG;
+ UINT32 arg2 = USEIMM ? SIMM13 : RS2REG;
UINT64 result = (UINT64)arg1 * (UINT64)arg2;
Y = (UINT32)(result >> 32);
TEST_ICC_NZ(result);
SET_RDREG((UINT32)result);
break;
}
- case 27: // smulcc, SPARCv8
+ case OP3_SMULCC: // SPARCv8
{
+ UINT32 arg1 = RS1REG;
+ UINT32 arg2 = USEIMM ? SIMM13 : RS2REG;
INT64 result = (INT64)(INT32)arg1 * (INT64)(INT32)arg2;
Y = (UINT32)((UINT64)result >> 32);
TEST_ICC_NZ(result);
SET_RDREG((UINT32)result);
break;
}
-#endif
- case 28: // subxcc
- {
- UINT32 c = (ICC_C_SET ? 1 : 0);
- UINT32 argt = arg2 + c;
- UINT32 result = arg1 - argt;
- TEST_ICC_NZ(result);
- if (((arg1 & 0x80000000) != (argt & 0x80000000) && (arg1 & 0x80000000) != (result & 0x80000000)) || (c != 0 && arg2 == 0x80000000))
- SET_ICC_V_FLAG;
- if (result > arg1 || (result == arg1 && arg2 != 0))
- SET_ICC_C_FLAG;
- SET_RDREG(result);
- break;
- }
-#if SPARCV8
- case 30: // udivcc, SPARCv8
+ case OP3_UDIVCC: // SPARCv8
{
+ UINT32 arg1 = RS1REG;
+ UINT32 arg2 = USEIMM ? SIMM13 : RS2REG;
UINT64 dividend = ((UINT64)Y << 32) || arg1;
UINT32 divisor = arg2;
UINT64 quotient = dividend / divisor;
@@ -643,8 +1450,10 @@ bool mb86901_device::execute_group2(UINT32 op)
SET_RDREG((UINT32)quotient);
break;
}
- case 31: // sdiv, SPARCv8
+ case OP3_SDIVCC: // SPARCv8
{
+ UINT32 arg1 = RS1REG;
+ UINT32 arg2 = USEIMM ? SIMM13 : RS2REG;
INT64 dividend = ((INT64)(INT32)Y << 32) || arg1;
INT32 divisor = arg2;
INT64 quotient = dividend / divisor;
@@ -675,367 +1484,790 @@ bool mb86901_device::execute_group2(UINT32 op)
SET_RDREG((UINT32)quotient);
break;
}
+ case OP3_CPOP1: // SPARCv8
+ break;
+ case OP3_CPOP2: // SPARCv8
+ break;
#endif
- case 32: // taddcc
- {
- UINT32 result = arg1 + arg2;
- TEST_ICC_NZ(result);
- if (((arg1 & 0x80000000) == (arg2 & 0x80000000) && (arg2 & 0x80000000) != (result & 0x80000000)) || ((arg1 & 3) != 0) || ((arg2 & 3) != 0))
- SET_ICC_V_FLAG;
- if (result < arg1 || result < arg2)
- SET_ICC_C_FLAG;
- SET_RDREG(result);
+
+ default:
+ m_trap = 1;
+ m_illegal_instruction = 1;
break;
- }
- case 33: // tsubcc
+ }
+}
+
+
+
+//-------------------------------------------------
+// update_gpr_pointers - cache pointers to
+// the registers in our current window
+//-------------------------------------------------
+
+void mb86901_device::update_gpr_pointers()
+{
+ for (int i = 0; i < 8; i++)
+ {
+ m_regs[ 8 + i] = &m_r[8 + (( 0 + m_cwp * 16 + i) % (NWINDOWS * 16))];
+ m_regs[16 + i] = &m_r[8 + (( 8 + m_cwp * 16 + i) % (NWINDOWS * 16))];
+ m_regs[24 + i] = &m_r[8 + ((16 + m_cwp * 16 + i) % (NWINDOWS * 16))];
+ }
+}
+
+
+//-------------------------------------------------
+// execute_store - execute a store-type opcode
+//-------------------------------------------------
+
+void mb86901_device::execute_store(UINT32 op)
+{
+ /* The SPARC Instruction Manual: Version 8, page 165, "Appendix C - ISP Descriptions - Store Instructions" (SPARCv8.pdf, pg. 162)
+
+ if ( (S = 0) and (STDA or STA or STHA or STBA or STDFQ or STDCQ) ) then (
+ trap <- 1;
+ privileged_instruction <- 1
+ ) else if ((i = 1) and (STDA or STA or STHA or STBA)) then (
+ trap <- 1;
+ illegal_instruction <- 1
+ );
+ next;
+ if (trap = 0) then (
+ if (STD or ST or STH or STB or STF or STDF or STFSR or STDFQ or STCSR or STC or STDC or STDCQ) then (
+ address <- r[rs1] + (if (i = 0) then r[rs2] else sign_extend(simm13));
+ addr_space <- (if (S = 0) then 10 else 11)
+ ) else if (STDA or STA or STHA or STBA) then (
+ address <- r[rs1] + r[rs2];
+ addr_space <- asi
+ );
+ if ((STF or STDF or STFSR or STDFQ) and
+ ((EF = 0) or (bp_FPU_present = 0)) ) then (
+ trap <- 1;
+ fp_disabled <- 1;
+ );
+ if ((STC or STDC or STCSR or STDCQ) and
+ ((EC = 0) or (bp_CP_present = 0)) ) then (
+ trap <- 1;
+ cp_disabled <- 1;
+ )
+ );
+ next;
+ if (trap = 0) then (
+ if ((STH or STHA) and (address<0> != 0)) then (
+ trap <- 1;
+ mem_address_not_aligned <- 1
+ ) else if ((ST or STA or STF or STFSR or STC or STCSR) and (address<1:0> != 0)) then (
+ trap <- 1;
+ mem_address_not_aligned <- 1
+ ) else if ((STD or STDA or STDF or STDFQ or STDC or STDCQ) and (address<2:0> != 0)) then (
+ trap <- 1;
+ mem_address_not_aligned <- 1
+ ) else (
+ if (STDFQ and ((implementation has no floating-point queue) or (FSR.qne = 0))) then (
+ trap <- 1;
+ fp_exception <- 1;
+ ftt <- sequence_error;
+ );
+ if (STDCQ and ((implementation has no coprocessor queue)) then (
+ trap <- 1;
+ cp_exception <- 1;
+ { possibly additional implementation-dependent actions }
+ );
+ if (STDF and (rd<0> != 0)) then (
+ trap <- 1;
+ fp_exception <- 1;
+ ftt <- invalid_fp_register;
+ )
+ )
+ );
+ next;
+ if (trap = 0) then (
+ if (STF) then ( byte_mask <- 1111; data0 <- f[rd] )
+ else if (STC) then ( byte_mask <- 1111; data0 <- implementation_dependent_value )
+ else if (STDF) then ( byte_mask <- 1111; data0 <- f[rd & 0x1e] )
+ else if (STDC) then ( byte_mask <- 1111; data0 <- implementation_dependent_value )
+ else if (STD or STDA) then ( byte_mask <- 1111; data0 <- r[rd & 0x1e] )
+ else if (STDFQ) then ( byte_mask <- 1111; data0 <- implementation_dependent_value )
+ else if (STDCQ) then ( byte_mask <- 1111; data0 <- implementation_dependent_value )
+ else if (STFSR) then (
+ while ((FSR.qne = 1) and (trap = 0)) (
+ // wait for pending floating-point instructions to complete
+ )
+ next;
+ byte_mask <- 1111; data0 <- FSR
+ ) else if (STCSR) then (
+ { implementation-dependent actions }
+ byte_mask <- 1111; data0 <- CSR
+ ) else if (ST or STA) then ( byte_mask <- 1111; data0 = r[rd] )
+ else if (STH or STHA) then (
+ if (address<1:0> = 0) then (
+ byte_mask <- 1100; data0 <- shift_left_logical(r[rd], 16) )
+ else if (address<1:0> = 2) then (
+ byte_mask <- 0011; data0 <- r[rd] )
+ ) else if (STB or STBA) then (
+ if (address<1:0> = 0) then (
+ byte_mask <- 1000; data0 <- shift_left_logical(r[rd], 24) )
+ ) else if (address<1:0> = 1) then (
+ byte_mask <- 0100; data0 <- shift_left_logical(r[rd], 16) )
+ ) else if (address<1:0> = 2) then (
+ byte_mask <- 0010; data0 <- shift_left_logical(r[rd], 8) )
+ ) else if (address<1:0> = 3) then (
+ byte_mask <- 0001; data0 <- r[rd] )
+ )
+ );
+ );
+ next;
+ if (trap = 0) then (
+ MAE <- memory_write(addr_space, address, byte_mask, data1);
+ next;
+ if (MAE = 1) then (
+ trap <- 1;
+ data_access_exception <- 1
+ )
+ );
+ if ((trap = 0) and (STD or STDA or STDF or STDC or STDFQ or STDCQ)) then (
+ if (STD or STDA) then ( data1 <- r[rd or 00001] )
+ else if (STDF) then ( data1 <- f[rd or 00001] )
+ else if (STDC) then ( data1 <- implementation_dependent_value }
+ else if (STDFQ) then ( data1 <- implementation_dependent_value }
+ else if (STDCQ) then ( data1 <- implementation_dependent_value }
+ next;
+ MAE <- memory_write(addr_space, address + 4, 1111, data1);
+ next;
+ if (MAE = 1) then ( { MAE = 1 only due to a "non-resumable machine-check error" }
+ trap <- 1;
+ data_access_exception <- 1
+ )
+ );
+ */
+
+ if (IS_USER && (STDA || STA || STHA || STBA || STDFQ || STDCQ))
+ {
+ m_trap = 1;
+ m_privileged_instruction = 1;
+ }
+ else if (USEIMM && (STDA || STA || STHA || STBA))
+ {
+ m_trap = 1;
+ m_illegal_instruction = 1;
+ }
+
+ UINT32 address = 0;
+ UINT8 addr_space = 0;
+ if (!m_trap)
+ {
+ if (STD || ST || STH || STB || STF || STDF || STFSR || STDFQ || STCSR || STC || STDC || STDCQ)
{
- UINT32 result = arg1 - arg2;
- TEST_ICC_NZ(result);
- if (((arg1 & 0x80000000) == (arg2 & 0x80000000) && (arg2 & 0x80000000) != (result & 0x80000000)) || ((arg1 & 3) != 0) || ((arg2 & 3) != 0))
- SET_ICC_V_FLAG;
- if (result > arg1)
- SET_ICC_C_FLAG;
- SET_RDREG(result);
- break;
+ address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
+ addr_space = (IS_USER ? 10 : 11);
}
- case 34: // taddcctv
+ else if (STDA || STA || STHA || STBA)
{
- UINT32 result = arg1 + arg2;
- bool v = ((arg1 & 0x80000000) == (arg2 & 0x80000000) && (arg2 & 0x80000000) != (result & 0x80000000)) || ((arg1 & 3) != 0) || ((arg2 & 3) != 0);
- if (v)
- {
- trap(SPARC_TAG_OVERFLOW);
- }
- else
- {
- TEST_ICC_NZ(result);
- if (result < arg1 || result < arg2)
- SET_ICC_C_FLAG;
- SET_RDREG(result);
- }
- break;
+ address = RS1REG + RS2REG;
+ addr_space = ASI;
}
- case 35: // tsubcctv
+ if ((STF || STDF || STFSR || STDFQ) && (!EF || !m_bp_fpu_present))
{
- UINT32 result = arg1 - arg2;
- bool v = ((arg1 & 0x80000000) == (arg2 & 0x80000000) && (arg2 & 0x80000000) != (result & 0x80000000)) || ((arg1 & 3) != 0) || ((arg2 & 3) != 0);
- if (v)
- {
- trap(SPARC_TAG_OVERFLOW);
- }
- else
- {
- TEST_ICC_NZ(result);
- if (result > arg1)
- SET_ICC_C_FLAG;
- SET_RDREG(result);
- }
- break;
+ m_trap = 1;
+ m_fp_disabled = 1;
}
- case 36: // mulscc
+ if ((STC || STDC || STCSR || STDCQ) && (!EC || !m_bp_cp_present))
{
- // Explanatory quotes from The SPARC Architecture Manual Version 8, pg. 112 (pg. 110 in sparcv8.pdf)
-
- // (1) The multiplier is established as r[rs2] if the i field is zero, or sign_ext(simm13) if the i field is one.
- UINT32 multiplier = arg2;
-
- // (2) A 32-bit value is computed by shifting r[rs1] right by one bit with "N xor V" from the PSR replacing the
- // high-order bit. (This is the proper sign for the previous partial product.)
- UINT32 rs1 = arg1;
- bool n = ICC_N_SET;
- bool v = ICC_V_SET;
- UINT32 shifted = (rs1 >> 1) | ((n ^ v) ? 0x80000000 : 0);
-
- if (m_y & 1)
- { // (3) If the least significant bit of the Y register = 1, the shifted value from step (2) is added to the multiplier.
- arg1 = multiplier;
- arg2 = shifted;
- }
- else
- { // If the LSB of the Y register = 0, then 0 is added to the shifted value from step (2).
- arg1 = shifted;
- arg2 = 0;
- }
-
- // (4) The sum from step (3) is written into r[rd].
- UINT32 result = arg1 + arg2;
- SET_RDREG(result);
-
- // (5) The integer condition codes, icc, are updated according to the addition performed in step (3).
- TEST_ICC_NZ(result);
- if ((arg1 & 0x80000000) == (arg2 & 0x80000000) && (arg2 & 0x80000000) != (result & 0x80000000))
- SET_ICC_V_FLAG;
- if (result < arg1 || result < arg2)
- SET_ICC_C_FLAG;
+ m_trap = 1;
+ m_cp_disabled = 1;
+ }
+ }
- // (6) The Y register is shifted right by one bit, with the LSB of the unshifted r[rs1] replacing the MSB of Y.
- m_y = (m_y >> 1) | ((rs1 & 1) ? 0x80000000 : 0);
- break;
+ if (!m_trap)
+ {
+ if ((STH || STHA) && ((address & 1) != 0))
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
}
- case 37: // sll
- SET_RDREG(arg1 << arg2);
- break;
- case 38: // srl
- SET_RDREG(arg1 >> arg2);
- break;
- case 39: // sra
- SET_RDREG(INT32(arg1) >> arg2);
- break;
- case 40: // rdy
- if (RS1 == 0)
- { // rd y
- SET_RDREG(m_y);
- }
-#if SPARCV8
- else if (RS1 == 15 && RD == 0)
- { // stbar, SPARCv8
- // no-op, as this implementation assumes Total Store Ordering
- }
- else
- { // rd asr, SPARCv8
- logerror("Unimplemented instruction: rd asr");
- }
-#endif
- break;
- case 41: // rd psr
- if (IS_USER)
- {
- trap(SPARC_PRIVILEGED_INSTRUCTION);
- }
- else
- {
- SET_RDREG(m_psr);
- }
- break;
- case 42: // rd wim
- if (IS_USER)
- {
- trap(SPARC_PRIVILEGED_INSTRUCTION);
- }
- else
- {
- SET_RDREG(m_wim);
- }
- break;
- case 43: // rd tbr
- if (IS_USER)
- {
- trap(SPARC_PRIVILEGED_INSTRUCTION);
- }
- else
+ else if ((ST || STA || STF || STFSR || STC || STCSR) && ((address & 3) != 0))
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ }
+ else if ((STD || STDA || STDF || STDFQ || STDC || STDCQ) && ((address & 7) != 0))
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ }
+ else
+ {
+ if (STDFQ)
{
- SET_RDREG(m_tbr);
+ // assume no floating-point queue for now
+ m_trap = 1;
+ m_fp_exception = 1;
+ m_ftt = m_fpu_sequence_err;
}
- break;
- case 48:
- if (RD == 0)
- { // wr y
- m_y = arg1 ^ arg2;
- }
-#if SPARCV8
- else
- { // wr asr, SPARCv8
- logerror("Unimplemented instruction: wr asr");
- }
-#endif
- break;
- case 49: // wr psr
- if (IS_USER)
+ if (STDCQ)
{
- trap(SPARC_PRIVILEGED_INSTRUCTION);
+ // assume no coprocessor queue for now
+ m_trap = 1;
+ m_cp_exception = 1;
+ // { possibly additional implementation-dependent actions }
}
- else
+ if (STDF && ((RD & 1) != 0))
{
- UINT32 new_psr = (arg1 ^ arg2) & ~PSR_ZERO_MASK;
- if ((new_psr & PSR_CWP_MASK) >= WINDOW_COUNT)
- {
- trap(SPARC_ILLEGAL_INSTRUCTION);
- }
- else
- {
- m_psr = new_psr;
- BREAK_PSR;
- }
+ m_trap = 1;
+ m_fp_exception = 1;
+ m_ftt = 0xff;
}
- break;
- case 50: // wr wim
- if (IS_USER)
+ }
+ }
+
+ UINT32 data0 = 0;
+ if (!m_trap)
+ {
+ //UINT8 byte_mask;
+ if (STF)
+ {
+ //byte_mask = 15;
+ data0 = FREG(RD);
+ }
+ else if (STC)
+ {
+ //byte_mask = 15;
+ data0 = 0;
+ }
+ else if (STDF)
+ {
+ //byte_mask = 15;
+ data0 = FREG(RD & 0x1e);
+ }
+ else if (STDC)
+ {
+ //byte_mask = 15;
+ data0 = 0;
+ }
+ else if (STD || STDA)
+ {
+ //byte_mask = 15;
+ data0 = REG(RD & 0x1e);
+ }
+ else if (STDFQ)
+ {
+ //byte_mask = 15;
+ data0 = 0;
+ }
+ else if (STDCQ)
+ {
+ //byte_mask = 15;
+ data0 = 0;
+ }
+ else if (STFSR)
+ {
+ // while ((FSR.qne = 1) and (trap = 0)) (
+ // wait for pending floating-point instructions to complete
+ // )
+ // next;
+ //byte_mask = 15;
+ data0 = FSR;
+ }
+ else if (STCSR)
+ {
+ // { implementation-dependent actions }
+ //byte_mask = 15;
+ data0 = 0;
+ }
+ else if (ST || STA)
+ {
+ //byte_mask = 15;
+ data0 = REG(RD);
+ }
+ else if (STH || STHA)
+ {
+ if ((address & 3) == 0)
{
- trap(SPARC_PRIVILEGED_INSTRUCTION);
+ //byte_mask = 12;
+ data0 = REG(RD) << 16;
}
- else
+ else if ((address & 3) == 2)
{
- m_wim = (arg1 ^ arg2) & 0x7f;
+ //byte_mask = 3;
+ data0 = REG(RD);
}
- break;
- case 51: // wr tbr
- if (IS_USER)
+ }
+ else if (STB || STBA)
+ {
+ if ((address & 3) == 0)
{
- trap(SPARC_PRIVILEGED_INSTRUCTION);
+ //byte_mask = 8;
+ data0 = REG(RD) << 24;
}
- else
+ else if ((address & 3) == 1)
{
- m_tbr = (arg1 ^ arg2) & 0xfffff000;
- printf("wr (%08x ^ %08x) & 0xfffff000 (%08x),tbr", arg1, arg2, m_tbr);
+ //byte_mask = 4;
+ data0 = REG(RD) << 16;
}
- break;
- case 52: // FPop1
- if (FPU_DISABLED)
+ else if ((address & 3) == 2)
{
- trap(SPARC_FLOATING_POINT_DISABLED);
+ //byte_mask = 2;
+ data0 = REG(RD) << 8;
}
- break;
- case 53: // FPop2
- if (FPU_DISABLED)
+ else if ((address & 3) == 3)
{
- trap(SPARC_FLOATING_POINT_DISABLED);
+ //byte_mask = 1;
+ data0 = REG(RD);
}
- break;
- case 56: // jmpl
+ }
+ }
+
+ if (!m_trap)
+ {
+ write_sized_word(addr_space, address, data0, (ST || STA || STD || STDA || STF || STDF || STDFQ || STFSR || STC || STDC || STDCQ || STCSR) ? 4 : ((STH || STHA) ? 2 : 1));
+ if (MAE)
{
- UINT32 addr = ADDRESS;
- m_icount--;
- if (addr & 3)
- {
- trap(SPARC_MEM_ADDRESS_NOT_ALIGNED);
- }
- else
- {
- SET_RDREG(PC);
- PC = nPC;
- nPC = addr;
- return false;
- }
- break;
+ m_trap = 1;
+ m_data_access_exception = 1;
+ }
+ }
+ if (!m_trap && (STD || STDA || STDF || STDC || STDFQ || STDCQ))
+ {
+ UINT32 data1 = 0;
+ if (STD || STDA)
+ {
+ data1 = REG(RD | 1);
}
- case 57: // rett
+ else if (STDF)
{
- UINT8 new_cwp = (m_cwp + 1) % WINDOW_COUNT;
- if (TRAPS_ENABLED)
- {
- if (IS_USER)
- {
- trap(SPARC_PRIVILEGED_INSTRUCTION);
- }
+ data1 = FREG(RD | 1);
+ }
+ else if (STDC)
+ {
+ data1 = 0;
+ }
+ else if (STDFQ)
+ {
+ data1 = 0;
+ }
+ else if (STDCQ)
+ {
+ data1 = 0;
+ }
+
+ write_sized_word(addr_space, address + 4, data1, 4);
+ if (MAE)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ }
+ }
+}
+
+//-------------------------------------------------
+// execute_load - execute a load-type opcode
+//-------------------------------------------------
+
+void mb86901_device::execute_load(UINT32 op)
+{
+ /* The SPARC Instruction Manual: Version 8, page 163, "Appendix C - ISP Descriptions - C.9. Instruction Defintions - Load Instructions" (SPARCv8.pdf, pg. 160)
+
+ if (LDD or LD or LDSH or LDUH or LDSB or LDUB or LDDF or LDF or LDFSR or LDDC or LDC or LDCSR) then (
+ address <- r[rs1] + (if (i = 0) then r[rs2] else sign_extend(simm13));
+ addr_space <- (if (S = 0) then 10 else 11)
+ ) else if (LDDA or LDA or LDSHA or LDUHA or LDSBA or LDUBA) then (
+ if (S = 0) then (
+ trap <- 1;
+ privileged_instruction <- 1
+ ) else if (i = 1) then (
+ trap <- 1;
+ illegal_instruction <- 1
+ ) else (
+ address <- r[rs1] + r[rs2];
+ addr_space <- asi
+ )
+ )
+ next;
+ if (trap = 0) then (
+ if ( (LDF or LDDF or LDFSR) and ((EF = 0) or (bp_FPU_present = 0)) then (
+ trap <- 1;
+ fp_disabled <- 1
+ ) else if ( (LDC or LDDC or LDCSR) and ((EC = 0) or (bp_CP_present = 0)) then (
+ trap <- 1;
+ cp_disabled <- 1
+ ) else if ( ( (LDD or LDDA or LDDF or LDDC) and (address<2:0> != 0)) or
+ ((LD or LDA or LDF or LDFSR or LDC or LDCSR) and (address<1:0> != 0)) or
+ ((LDSH or LDSHA or LDUH or LDUHA) and address<0> != 0) ) then (
+ trap <- 1;
+ mem_address_not_aligned <- 1
+ ) else if (LDDF and (rd<0> != 0)) then (
+ trap <- 1;
+ fp_exception <- 1;
+ ftt <- invalid_fpr_register
+ ) else if ((LDF or LDDF or LDFSR) and (an FPU sequence error is detected)) then (
+ trap <- 1;
+ fp_exception <- 1;
+ ftt <- sequence_error
+ ) else if ((LDC or LDDC or LDCSR) and (a CP sequence error is detected)) then (
+ trap <- 1;
+ cp_exception <- 1;
+ { possibly additional implementation-dependent actions }
+ )
+ );
+ next;
+ if (trap = 0) then {
+ (data, MAE) <- memory_read(addr_space, address);
+ next;
+ if (MAE = 1) then (
+ trap <- 1;
+ data_access_exception <- 1;
+ ) else (
+ if (LDSB or LDSBA or LDUB or LDUBA) then (
+ if (address<1:0> = 0) then byte <- data<31:24>
+ else if (address<1:0> = 1) then byte <- data<23:16>
+ else if (address<1:0> = 2) then byte <- data<15: 8>
+ else if (address<1:0> = 3) then byte <- data< 7: 0>
+ next;
+ if (LDSB or LDSBA) then
+ word0 <- sign_extend_byte(byte)
else
- {
- trap(SPARC_ILLEGAL_INSTRUCTION);
- }
- break;
- }
- else
- {
- if (IS_USER)
- {
- trap(SPARC_RESET, SPARC_PRIVILEGED_INSTRUCTION);
- break;
- }
- else if (m_wim & (1 << new_cwp))
- {
- trap(SPARC_RESET, SPARC_WINDOW_UNDERFLOW);
- break;
- }
- else if (ADDRESS & 3)
- {
- trap(SPARC_RESET, SPARC_MEM_ADDRESS_NOT_ALIGNED);
- break;
- }
- }
+ word0 <- zero_extend_byte(byte)
+ ) else if (LDSH or LDSHA or LDUH or LDUHA) then (
+ if (address<1:0> = 0) then halfword <- data<31:16>
+ else if (address<1:0> = 2) then halfword <- data<15: 0>
+ next;
+ if (LDSH or LDSHA) then
+ word0 <- sign_extend_halfword(halfword)
+ else
+ word0 <- zero_extend_halfword(halfword)
+ ) else
+ word0 <- data
+ )
+ );
+ next;
+ if (trap = 0) then (
+ if ( (rd != 0) and (LD or LDA or LDSH or LDSHA
+ or LDUHA or LDUH or LDSB or LDSBA or LDUB or LDUBA) ) then
+ r[rd] <- word0
+ else if (LDF) then f[rd] <- word0
+ else if (LDC) then { implementation-dependent actions }
+ else if (LDFSR) then FSR <- word0
+ else if (LDCSR) then CSR <- word0
+ else if (LDD or LDDA) then r[rd and 11110] <- word0
+ else if (LDDF) then f[rd and 11110] <- word0
+ else if (LDDC) then { implementation-dependent actions }
+ );
+ next;
+ if (((trap = 0) and (LDD or LDDA or LDDF or LDDC)) then (
+ (word1, MAE) <- memory_read(addr_space, address + 4);
+ next;
+ if (MAE = 1) then ( { MAE = 1 only due to a "non-resumable machine-check error" }
+ trap <- 1;
+ data_access_exception <- 1 )
+ else if (LDD or LDDA) then r[rd or 1] <- word1
+ else if (LDDF) then f[rd or 1] <- word1
+ else if (LDDC) then { implementation-dependent actions }
+ );
+ */
+
+ UINT32 address = 0;
+ UINT8 addr_space = 0;
+ if (LDD || LD || LDSH || LDUH || LDSB || LDUB || LDDF || LDF || LDFSR || LDDC || LDC || LDCSR)
+ {
+ address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
+ addr_space = (IS_USER ? 10 : 11);
+ }
+ else if (LDDA || LDA || LDSHA || LDUHA || LDSBA || LDUBA)
+ {
+ if (IS_USER)
+ {
+ m_trap = 1;
+ m_privileged_instruction = 1;
+ }
+ else if (USEIMM)
+ {
+ m_trap = 1;
+ m_illegal_instruction = 1;
+ }
+ else
+ {
+ address = RS1REG + RS2REG;
+ addr_space = ASI;
+ }
+ }
- m_cwp = new_cwp;
+ if (!m_trap)
+ {
+ if ((LDF || LDDF || LDFSR) && (EF == 0 || m_bp_fpu_present == 0))
+ {
+ m_trap = 1;
+ m_fp_disabled = 1;
+ }
+ else if ((LDC || LDDC || LDCSR) && (EC == 0 || m_bp_cp_present == 0))
+ {
+ m_trap = 1;
+ m_cp_disabled = 1;
+ }
+ else if (((LDD || LDDA || LDDF || LDDC) && ((address & 7) != 0)) ||
+ ((LD || LDA || LDF || LDFSR || LDC || LDCSR) && ((address & 3) != 0)) ||
+ ((LDSH || LDSHA || LDUH || LDUHA) && ((address & 1) != 0)))
+ {
+ m_trap = 1;
+ m_mem_address_not_aligned = 1;
+ }
+ else if (LDDF && ((RD & 1) != 0))
+ {
+ m_trap = 1;
+ m_fp_exception = 1;
+ m_ftt = 0xff;
+ }
+ else if ((LDF || LDDF || LDFSR) && m_fpu_sequence_err != 0)
+ {
+ m_trap = 1;
+ m_fp_exception = 1;
+ m_ftt = m_fpu_sequence_err;
+ }
+ else if ((LDC || LDDC || LDCSR) && m_cp_sequence_err != 0)
+ {
+ m_trap = 1;
+ m_cp_exception = 1;
+ // possibly additional implementation-dependent actions
+ }
+ }
- m_s = m_ps;
- m_insn_asi = m_s ? 9 : 8;
- m_data_asi = m_s ? 11 : 10;
- m_et = true;
+ UINT32 word0(0);
+ if (!m_trap)
+ {
+ UINT32 data = read_sized_word(addr_space, address, (LD || LDD || LDA || LDDA) ? 4 : ((LDUH || LDSH || LDUHA || LDSHA) ? 2 : 1));
- UINT32 target = arg1 + arg2;
- PC = nPC;
- nPC = target;
- return false;
+ if (m_mae)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
}
- case 58: // ticc
- return execute_ticc(op);
-#if SPARCV8
- case 59:
- // SPARCv8
- if (RD == 0)
- { // flush, SPARCv8
- }
- break;
-#endif
- case 60: // save
+ else
{
- UINT8 new_cwp = ((m_cwp + WINDOW_COUNT) - 1) % WINDOW_COUNT;
- if (m_wim & (1 << new_cwp))
- {
- trap(SPARC_WINDOW_OVERFLOW);
- }
- else
+ if (LDSB || LDSBA || LDUB || LDUBA)
{
- save_restore_update_cwp(op, new_cwp);
+ UINT8 byte = 0;
+ if ((address & 3) == 0) byte = (data >> 24) & 0xff;
+ else if ((address & 3) == 1) byte = (data >> 16) & 0xff;
+ else if ((address & 3) == 2) byte = (data >> 8) & 0xff;
+ else if ((address & 3) == 3) byte = data & 0xff;
+
+ if (LDSB || LDSBA)
+ word0 = (((INT32)byte) << 24) >> 24;
+ else
+ word0 = byte;
}
- break;
- }
- case 61: // restore
- {
- UINT8 new_cwp = (m_cwp + 1) % WINDOW_COUNT;
- if (m_wim & (1 << new_cwp))
+ else if (LDSH || LDSHA || LDUH || LDUHA)
{
- trap(SPARC_WINDOW_UNDERFLOW);
+ UINT16 halfword = 0;
+ if ((address & 3) == 0) halfword = (data >> 16) & 0xffff;
+ else if ((address & 3) == 2) halfword = data & 0xffff;
+
+ if (LDSH || LDSHA)
+ word0 = (((INT32)halfword) << 16) >> 16;
+ else
+ word0 = halfword;
}
else
{
- save_restore_update_cwp(op, new_cwp);
+ word0 = data;
}
- break;
}
- default:
- trap(SPARC_ILLEGAL_INSTRUCTION);
- break;
}
- return true;
-}
+ if (!m_trap)
+ {
+ if ((RD != 0) && (LD || LDA || LDSH || LDSHA || LDUHA || LDUH || LDSB || LDSBA || LDUB || LDUBA))
+ {
+ RDREG = word0;
+ }
+ else if (LDF) FDREG = word0;
+ else if (LDC) { } // implementation-dependent actions
+ else if (LDFSR) FSR = word0;
+ else if (LDD || LDDA) REG(RD & 0x1e) = word0;
+ else if (LDDF) FREG(RD & 0x1e) = word0;
+ else if (LDDC) { } // implementation-dependent actions
+ }
+ if (!m_trap)
+ {
+ UINT32 word1 = read_sized_word(addr_space, address + 4, 4);
+ if (MAE)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ }
+ else if (LDD || LDDA) REG(RD | 1) = word1;
+ else if (LDDF) FREG(RD | 1) = word1;
+ else if (LDDC) { } // implementation-dependent actions
+ }
+}
//-------------------------------------------------
-// update_gpr_pointers - cache pointers to
-// the registers in our current window
+// execute_ldstub - execute an atomic load-store
+// instruction
//-------------------------------------------------
-void mb86901_device::update_gpr_pointers()
+void mb86901_device::execute_ldstub(UINT32 op)
{
- for (int i = 0; i < 8; i++)
+ /* The SPARC Instruction Manual: Version 8, page 169, "Appendix C - ISP Descriptions - Atomic Load-Store Unsigned Byte Instructions" (SPARCv8.pdf, pg. 166)
+
+ if (LDSTUB) then (
+ address <- r[rs1] + (if (i = 0) then r[rs2] else sign_extend(simm13));
+ addr_space <- (if (S = 0) then 10 else 11)
+ } else if (LDSTUBA) then (
+ if (S = 0) then (
+ trap <- 1;
+ privileged_instruction <- 1
+ ) else if (i = 1) then (
+ trap <- 1;
+ illegal_instruction <- 1
+ ) else (
+ address <- r[rs1] + r[rs2];
+ addr_space <- asi
+ )
+ );
+ next;
+ if (trap = 0) then (
+ while ( (pb_block_ldst_byte = 1) or (pb_block_ldst_word = 1) ) then (
+ { wait for lock(s) to be lifted }
+ { an implementation actually need only block when another LDSTUB or SWAP
+ is pending on the same byte in memory as the one addressed by this LDSTUB }
+ };
+ next;
+ pb_block_ldst_byte <- 1;
+ next;
+ (data, MAE) <- memory_read(addr_space, address);
+ next;
+ if (MAE = 1) then (
+ trap <- 1;
+ data_access_exception <- 1
+ )
+ )
+ next;
+ if (trap = 0) then (
+ if (address<1:0> = 0) then ( byte_mask <- 1000 )
+ else if (address<1:0> = 1) then ( byte_mask <- 0100 )
+ else if (address<1:0> = 2) then ( byte_mask <- 0010 )
+ else if (address<1:0> = 3) then ( byte_mask <- 0001 )
+ ;
+ next;
+ MAE <- memory_write(addr_space, address, byte_mask, FFFFFFFF);
+ next;
+ pb_block_ldst_byte <- 0;
+ if (MAE = 1) then ( { MAE = 1 only due to a "non-resumable machine-check error" }
+ trap <- 1;
+ data_access_exception <- 1
+ ) else (
+ if (address<1:0> = 0) then word <- zero_extend_byte(data<31:24>)
+ else if (address<1:0> = 1) then word <- zero_extend_byte(data<23:24>)
+ else if (address<1:0> = 2) then word <- zero_extend_byte(data<15: 8>)
+ else if (address<1:0> = 3) then word <- zero_extend_byte(data< 7: 0>)
+ next;
+ if (rd != 0) then r[rd] <- word
+ )
+ );
+ */
+
+ UINT32 address = 0;
+ UINT8 addr_space = 0;
+ if (LDSTUB)
{
- m_regs[ 8 + i] = &m_r[8 + (( 0 + m_cwp * 16 + i) % (WINDOW_COUNT * 16))];
- m_regs[16 + i] = &m_r[8 + (( 8 + m_cwp * 16 + i) % (WINDOW_COUNT * 16))];
- m_regs[24 + i] = &m_r[8 + ((16 + m_cwp * 16 + i) % (WINDOW_COUNT * 16))];
+ address = RS1REG + (USEIMM ? SIMM13 : RS2REG);
+ addr_space = (IS_USER ? 10 : 11);
}
-}
-
-bool mb86901_device::check_main_traps(UINT32 op, bool privileged, UINT32 alignment, UINT8 registeralign, bool noimmediate)
-{
- bool trap_queued = false;
- if (privileged && !m_s)
+ else if (LDSTUBA)
{
- trap(SPARC_PRIVILEGED_INSTRUCTION);
- trap_queued = true;
+ if (IS_USER)
+ {
+ m_trap = 1;
+ m_privileged_instruction = 1;
+ }
+ else if (USEIMM)
+ {
+ m_trap = 1;
+ m_illegal_instruction = 1;
+ }
+ else
+ {
+ address = RS1REG + RS2REG;
+ addr_space = ASI;
+ }
}
- if (alignment & ADDRESS)
+
+ UINT32 data(0);
+ if (!m_trap)
{
- trap(SPARC_MEM_ADDRESS_NOT_ALIGNED);
- trap_queued = true;
+ while (m_pb_block_ldst_byte || m_pb_block_ldst_word)
+ {
+ // { wait for lock(s) to be lifted }
+ // { an implementation actually need only block when another LDSTUB or SWAP
+ // is pending on the same byte in memory as the one addressed by this LDSTUB }
+ }
+
+ m_pb_block_ldst_byte = 1;
+
+ data = read_sized_word(addr_space, address, 1);
+
+ if (MAE)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ }
}
- if ((registeralign & RD) || (noimmediate && USEIMM))
+
+ if (!m_trap)
{
- trap(SPARC_ILLEGAL_INSTRUCTION);
- trap_queued = true;
+ //UINT8 byte_mask;
+ if ((address & 3) == 0)
+ {
+ //byte_mask = 8;
+ }
+ else if ((address & 3) == 1)
+ {
+ //byte_mask = 4;
+ }
+ else if ((address & 3) == 2)
+ {
+ //byte_mask = 2;
+ }
+ else if ((address & 3) == 3)
+ {
+ //byte_mask = 1;
+ }
+ write_sized_word(addr_space, address, 0xffffffff, 1);
+
+ m_pb_block_ldst_byte = 0;
+
+ if (MAE)
+ {
+ m_trap = 1;
+ m_data_access_exception = 1;
+ }
+ else
+ {
+ UINT32 word;
+ if ((address & 3) == 0)
+ {
+ word = (data >> 24) & 0xff;
+ }
+ else if ((address & 3) == 1)
+ {
+ word = (data >> 16) & 0xff;
+ }
+ else if ((address & 3) == 2)
+ {
+ word = (data >> 8) & 0xff;
+ }
+ else // if ((address & 3) == 3)
+ {
+ word = data & 0xff;
+ }
+ if (RD != 0)
+ RDREG = word;
+ }
}
- return trap_queued;
}
+
//-------------------------------------------------
// execute_group3 - execute an opcode in group 3
// (load/store)
@@ -1056,221 +2288,54 @@ void mb86901_device::execute_group3(UINT32 op)
switch (OP3)
{
- case 0: // ld
- {
- check_main_traps(op, false, 3, 0, false);
- UINT32 result = read_word(m_data_asi, ADDRESS);
- if (MAE || HOLD_BUS)
- break;
- SET_RDREG(result);
- break;
- }
- case 1: // ldub
- {
- UINT32 result = read_byte(m_data_asi, ADDRESS);
- if (MAE || HOLD_BUS)
- break;
- SET_RDREG(result);
- break;
- }
- case 2: // lduh
- {
- check_main_traps(op, false, 1, 0, false);
- UINT32 result = read_half(m_data_asi, ADDRESS);
- if (MAE || HOLD_BUS)
- break;
- SET_RDREG(result);
- break;
- }
- case 3: // ldd
- {
- check_main_traps(op, false, 7, 1, false);
- UINT32 result = read_word(m_data_asi, ADDRESS);
- if (MAE || HOLD_BUS)
- break;
- SET_RDREG(result);
- result = read_word(m_data_asi, ADDRESS+4);
- if (MAE || HOLD_BUS)
- break;
- REG(RD+1) = result;
- break;
- }
- case 4: // st
- check_main_traps(op, false, 3, 0, false);
- write_word(m_data_asi, ADDRESS, RDREG);
- break;
- case 5: // stb
- write_byte(m_data_asi, ADDRESS, UINT8(RDREG));
- break;
- case 6: // sth
- check_main_traps(op, false, 1, 0, false);
- write_word(m_data_asi, ADDRESS, UINT16(RDREG));
- break;
- case 7: // std
- check_main_traps(op, false, 7, 1, false);
- write_word(m_data_asi, ADDRESS, RDREG);
- if (MAE || HOLD_BUS)
- break;
- write_word(m_data_asi, ADDRESS+4, REG(RD+1));
- break;
- case 9: // ldsb
- {
- UINT32 result = read_signed_byte(m_data_asi, ADDRESS);
- if (MAE || HOLD_BUS)
- break;
- SET_RDREG(result);
- break;
- }
- case 10: // lsdh
- {
- check_main_traps(op, false, 1, 0, false);
- UINT32 result = read_signed_half(m_data_asi, ADDRESS);
- if (MAE || HOLD_BUS)
- break;
- SET_RDREG(result);
- break;
- }
- case 13: // ldstub
- {
- UINT32 result = read_byte(m_data_asi, ADDRESS);
- if (MAE || HOLD_BUS)
- break;
- SET_RDREG(result);
- write_byte(m_data_asi, ADDRESS, 0xff);
- break;
- }
- case 15: // swap, SPARCv8
- break;
- case 16: // lda
- {
- check_main_traps(op, true, 3, 0, true);
- UINT32 result = read_word(ASI, ADDRESS);
- if (MAE || HOLD_BUS)
- break;
- SET_RDREG(result);
- break;
- }
- case 17: // lduba
- {
- check_main_traps(op, true, 0, 0, true);
- UINT32 result = read_byte(ASI, ADDRESS);
- if (MAE || HOLD_BUS)
- break;
- SET_RDREG(result);
- break;
- }
- case 18: // lduha
- {
- check_main_traps(op, true, 1, 0, true);
- UINT32 result = read_half(ASI, ADDRESS);
- if (MAE || HOLD_BUS)
- break;
- SET_RDREG(result);
- break;
- }
- case 19: // ldda
- {
- check_main_traps(op, true, 7, 1, true);
- UINT32 result = read_word(ASI, ADDRESS);
- if (MAE || HOLD_BUS)
- break;
- SET_RDREG(result);
- result = read_word(ASI, ADDRESS+4);
- if (MAE || HOLD_BUS)
- break;
- REG(RD+1) = result;
- break;
- }
- case 20: // sta
- check_main_traps(op, true, 3, 0, true);
- write_word(ASI, ADDRESS, RDREG);
- break;
- case 21: // stba
- check_main_traps(op, true, 0, 0, true);
- write_byte(ASI, ADDRESS, UINT8(RDREG));
- break;
- case 22: // stha
- check_main_traps(op, true, 1, 0, true);
- write_half(ASI, ADDRESS, UINT16(RDREG));
- break;
- case 23: // stda
- check_main_traps(op, true, 7, 1, true);
- write_word(ASI, ADDRESS, RDREG);
- if (MAE || HOLD_BUS)
- break;
- write_word(ASI, ADDRESS+4, REG(RD+1));
- break;
- case 25: // ldsba
- {
- check_main_traps(op, true, 0, 0, true);
- UINT32 result = read_signed_byte(ASI, ADDRESS);
- if (MAE || HOLD_BUS)
- break;
- SET_RDREG(result);
- break;
- }
- case 26: // ldsha
- {
- check_main_traps(op, true, 1, 0, true);
- UINT32 result = read_signed_half(ASI, ADDRESS);
- if (MAE || HOLD_BUS)
- break;
- SET_RDREG(result);
- break;
- }
- case 29: // ldstuba
- {
- check_main_traps(op, true, 0, 0, true);
- UINT32 result = read_byte(ASI, ADDRESS);
- if (MAE || HOLD_BUS)
- break;
- SET_RDREG(result);
- write_byte(ASI, ADDRESS, 0xff);
- break;
- }
- case 31: // swapa, SPARCv8
- break;
- case 32: // ld fpr
- if (FPU_DISABLED)
- trap(SPARC_FLOATING_POINT_DISABLED);
- break;
- case 33: // ld fsr
- if (FPU_DISABLED)
- trap(SPARC_FLOATING_POINT_DISABLED);
- break;
- case 35: // ldd fpr
- if (FPU_DISABLED)
- trap(SPARC_FLOATING_POINT_DISABLED);
- break;
- case 36: // st fpr
- if (FPU_DISABLED)
- trap(SPARC_FLOATING_POINT_DISABLED);
- break;
- case 37: // st fsr
- if (FPU_DISABLED)
- trap(SPARC_FLOATING_POINT_DISABLED);
- break;
- case 38: // std fq, SPARCv8
- if (FPU_DISABLED)
- trap(SPARC_FLOATING_POINT_DISABLED);
- break;
- case 39: // std fpr
- if (FPU_DISABLED)
- trap(SPARC_FLOATING_POINT_DISABLED);
- break;
- case 40: // ld cpr, SPARCv8
- break;
- case 41: // ld csr, SPARCv8
- break;
- case 43: // ldd cpr, SPARCv8
- break;
- case 44: // st cpr, SPARCv8
- break;
- case 45: // st csr, SPARCv8
- break;
- case 46: // std cq, SPARCv8
- break;
- case 47: // std cpr, SPARCv8
+ case OP3_LD:
+ case OP3_LDUB:
+ case OP3_LDUH:
+ case OP3_LDD:
+ case OP3_LDSB:
+ case OP3_LDSH:
+ case OP3_LDA:
+ case OP3_LDUBA:
+ case OP3_LDUHA:
+ case OP3_LDDA:
+ case OP3_LDSBA:
+ case OP3_LDSHA:
+ case OP3_LDFPR:
+ case OP3_LDFSR:
+ case OP3_LDDFPR:
+ case OP3_LDCPR:
+ case OP3_LDCSR:
+ case OP3_LDDCPR:
+ execute_load(op);
+ break;
+
+ case OP3_ST:
+ case OP3_STB:
+ case OP3_STH:
+ case OP3_STD:
+ case OP3_STA:
+ case OP3_STBA:
+ case OP3_STHA:
+ case OP3_STDA:
+ case OP3_STFPR:
+ case OP3_STFSR:
+ case OP3_STDFQ:
+ case OP3_STDFPR:
+ case OP3_STCPR:
+ case OP3_STCSR:
+ case OP3_STDCQ:
+ case OP3_STDCPR:
+ execute_store(op);
+ break;
+
+ case OP3_LDSTUB:
+ case OP3_LDSTUBA:
+ execute_ldstub(op);
+ break;
+
+ case OP3_SWAP: // SPARCv8
+ break;
+ case OP3_SWAPA: // SPARCv8
break;
}
@@ -1299,7 +2364,7 @@ bool mb86901_device::evaluate_condition(UINT32 op)
case 0: take = false; break; // bn ba
case 1: take = z; break; // bz bne
case 2: take = z | (n ^ z); break; // ble bg
- case 3: take = n ^ z; break; // bl bge
+ case 3: take = n ^ v; break; // bl bge
case 4: take = c | z; break; // bleu bgu
case 5: take = c; break; // bcs bcc
case 6: take = n; break; // bneg bpos
@@ -1312,129 +2377,627 @@ bool mb86901_device::evaluate_condition(UINT32 op)
return take;
}
+
//-------------------------------------------------
// execute_bicc - execute a branch opcode
//-------------------------------------------------
-bool mb86901_device::execute_bicc(UINT32 op)
+void mb86901_device::execute_bicc(UINT32 op)
{
- bool branch_taken = evaluate_condition(op);
+ /* The SPARC Instruction Manual: Version 8, page 178, "Appendix C - ISP Descriptions - Branch on Integer Condition Instructions" (SPARCv8.pdf, pg. 175)
+
+ eval_icc := (
+ if (BNE) then (if (Z = 0) then 1 else 0);
+ if (BE) then (if (Z = 1) then 1 else 0);
+ if (BG) then (if ((Z or (N xor V)) = 0) then 1 else 0);
+ if (BLE) then (if ((Z or (N xor V)) = 1) then 1 else 0);
+ if (BGE) then (if ((N xor V) = 0) then 1 else 0);
+ if (BL) then (if ((N xor V) = 1) then 1 else 0);
+ if (BGU) then (if ((C = 0) and (Z = 0)) then 1 else 0);
+ if (BLEU) then (if ((C = 1) or (Z = 1)) then 1 else 0);
+ if (BCC) then (if (C = 0) then 1 else 0);
+ if (BCS) then (if (C = 1) then 1 else 0);
+ if (BPOS) then (if (N = 0) then 1 else 0);
+ if (BNEG) then (if (N = 1) then 1 else 0);
+ if (BVC) then (if (V = 0) then 1 else 0);
+ if (BVS) then (if (V = 1) then 1 else 0);
+ if (BA) then 1;
+ if (BN) then 0;
+ )
+ PC <- nPC;
+ if (eval_icc = 1) then (
+ nPC <- PC + sign_extend(disp22[]00);
+ if (BA and (a = 1)) then
+ annul <- 1 { only for annulling Branch-Always }
+ ) else (
+ nPC <- nPC + 4;
+ if (a = 1) then
+ annul <- 1 { only for annulling branches other than BA }
+ )
+ */
+ bool branch_taken = evaluate_condition(op);
+ UINT32 pc = PC;
+ PC = nPC;
if (branch_taken)
{
- UINT32 brpc = PC + DISP22;
- PC = nPC;
- nPC = brpc;
- return false;
+ nPC = pc + DISP22;
+ if (COND == COND_BA && ANNUL)
+ m_annul = 1;
}
else
{
- m_icount--;
+ nPC = nPC + 4;
+ if (ANNUL)
+ m_annul = 1;
}
+}
- if (ANNUL && (!branch_taken || COND == 8))
+
+//-------------------------------------------------
+// execute_ticc - execute a conditional trap
+//-------------------------------------------------
+
+void mb86901_device::execute_ticc(UINT32 op)
+{
+ /* The SPARC Instruction Manual: Version 8, page 182, "Appendix C - ISP Descriptions - Trap on Integer Condition Instructions" (SPARCv8.pdf, pg. 179)
+
+ trap_eval_icc := (
+ if (TNE) then (if (Z = 0) then 1 else 0);
+ if (TE) then (if (Z = 1) then 1 else 0);
+ if (TG) then (if ((Z or (N xor V)) = 0) then 1 else 0);
+ if (TLE) then (if ((Z or (N xor V)) = 1) then 1 else 0);
+ if (TGE) then (if ((N xor V) = 0) then 1 else 0);
+ if (TL) then (if ((N xor V) = 1) then 1 else 0);
+ if (TGU) then (if ((C = 0) and (Z = 0)) then 1 else 0);
+ if (TLEU) then (if ((C = 1) or (Z = 1)) then 1 else 0);
+ if (TCC) then (if (C = 0) then 1 else 0);
+ if (TCS) then (if (C = 1) then 1 else 0);
+ if (TPOS) then (if (N = 0) then 1 else 0);
+ if (TNEG) then (if (N = 1) then 1 else 0);
+ if (TVC) then (if (V = 0) then 1 else 0);
+ if (TVS) then (if (V = 1) then 1 else 0);
+ if (TA) then 1;
+ if (TN) then 0;
+ )
+
+ trap_number := r[rs1] + (if (i = 0) then r[rs2] else sign_extend(software_trap#));
+
+ if (Ticc) then (
+ if (trap_eval_icc = 1) then (
+ trap <- 1;
+ trap_instruction <- 1;
+ ticc_trap_type <- trap_number<6:0>
+ ) else (
+ PC <- nPC;
+ nPC <- nPC + 4;
+ )
+ );
+ */
+
+ bool trap_eval_icc = evaluate_condition(op);
+
+ UINT8 trap_number = RS1REG + (USEIMM ? SIMM7 : RS2REG);
+
+ if (COND)
{
- PC = nPC;
- nPC = PC + 4;
- m_icount -= 1;
- return false;
+ if (trap_eval_icc)
+ {
+ m_trap = 1;
+ m_trap_instruction = 1;
+ m_ticc_trap_type = trap_number & 0x7f;
+ }
+ else
+ {
+ PC = nPC;
+ nPC = nPC + 4;
+ }
}
-
- return true;
}
+
//-------------------------------------------------
-// execute_ticc - execute a conditional trap
+// select_trap - prioritize traps and perform any
+// additional functions from taking them
//-------------------------------------------------
-bool mb86901_device::execute_ticc(UINT32 op)
+void mb86901_device::select_trap()
{
- bool trap_taken = evaluate_condition(op);
+ if (!m_trap)
+ return;
- printf("ticc @ %x\n", PC);
- if (trap_taken)
+ if (m_reset_trap)
{
- UINT32 arg2 = USEIMM ? SIMM7 : RS2REG;
- UINT8 tt = 128 + ((RS1REG + arg2) & 0x7f);
- trap(SPARC_TRAP_INSTRUCTION, tt);
- m_icount -= 3;
- return false;
+ m_trap = 0;
+ return;
}
-
- return true;
+ else if (!ET)
+ {
+ m_execute_mode = 0;
+ m_error_mode = 1;
+ }
+ else if (m_data_store_error)
+ m_tt = 0x2b;
+ else if (m_instruction_access_error)
+ m_tt = 0x21;
+ else if (m_r_register_access_error)
+ m_tt = 0x20;
+ else if (m_instruction_access_exception)
+ m_tt = 0x01;
+ else if (m_privileged_instruction)
+ m_tt = 0x03;
+ else if (m_illegal_instruction)
+ m_tt = 0x02;
+ else if (m_fp_disabled)
+ m_tt = 0x04;
+ else if (m_cp_disabled)
+ m_tt = 0x24;
+ else if (m_unimplemented_FLUSH)
+ m_tt = 0x25;
+ else if (m_window_overflow)
+ m_tt = 0x05;
+ else if (m_window_underflow)
+ m_tt = 0x06;
+ else if (m_mem_address_not_aligned)
+ m_tt = 0x07;
+ else if (m_fp_exception)
+ m_tt = 0x08;
+ else if (m_cp_exception)
+ m_tt = 0x28;
+ else if (m_data_access_error)
+ m_tt = 0x29;
+ else if (m_data_access_exception)
+ m_tt = 0x09;
+ else if (m_tag_overflow)
+ m_tt = 0x0a;
+ else if (m_division_by_zero)
+ m_tt = 0x2a;
+ else if (m_trap_instruction)
+ m_tt = 0x80 | m_ticc_trap_type;
+ else if (m_interrupt_level > 0)
+ m_tt = 0x10 | m_interrupt_level;
+
+ m_instruction_access_exception = 0;
+ m_illegal_instruction = 0;
+ m_privileged_instruction = 0;
+ m_fp_disabled = 0;
+ m_cp_disabled = 0;
+ m_window_overflow = 0;
+ m_window_underflow = 0;
+ m_mem_address_not_aligned = 0;
+ m_fp_exception = 0;
+ m_cp_exception = 0;
+ m_data_access_exception = 0;
+ m_tag_overflow = 0;
+ m_division_by_zero = 0;
+ m_trap_instruction = 0;
+ m_interrupt_level = 0;
}
//-------------------------------------------------
-// trap - flag an incoming trap of a given
-// type
+// execute_trap - prioritize and invoke traps
+// that have been flagged by the previous
+// instructions, if any.
//-------------------------------------------------
-void mb86901_device::trap(UINT8 type, UINT8 tt_override)
+void mb86901_device::execute_trap()
{
- if (type == SPARC_RESET)
+ /* The SPARC Instruction Manual: Version 8, page 161, "Appendix C - C.8. Traps" (SPARCv8.pdf, pg. 158)
+
+ select_trap; { see below }
+ next;
+
+ if (error_mode = 0) then (
+ ET <- 0;
+ PS <- S;
+ CWP <- (CWP - 1) modulo NWINDOWS;
+
+ next;
+ if (annul = 0) then (
+ r[17] <- PC;
+ r[18] <- nPC;
+ ) else { annul != 0) } (
+ r[17] <- nPC;
+ r[18] <- nPC + 4;
+ annul <- 0;
+ )
+
+ next;
+ S <- 1;
+ if (reset_trap = 0) then (
+ PC <- TBR;
+ nPC <- TBR + 4;
+ ) else { reset_trap = 1 } (
+ PC <- 0;
+ nPC <- 4;
+ reset_trap <- 0;
+ )
+ );
+
+ select_trap := (
+ if (reset_trap = 1) then { ignore ET, and leave tt unchanged }
+ else if (ET = 0) then (
+ execute_mode <- 0;
+ error_mode <- 1 )
+ else if (data_store_error = 1) then tt <- 00101011
+ else if (instruction_access_error = 1) then tt <- 00100001
+ else if (r_register_access_error = 1) then tt <- 00100000
+ else if (instruction_access_exception = 1) then tt <- 00000001
+ else if (privileged_instruction = 1) then tt <- 00000011
+ else if (illegal_instruction = 1) then tt <- 00000010
+ else if (fp_disabled = 1) then tt <- 00000100
+ else if (cp_disabled = 1) then tt <- 00100100
+ else if (unimplemented_FLUSH = 1) then tt <- 00100101
+ else if (window_overflow = 1) then tt <- 00000101
+ else if (window_underflow = 1) then tt <- 00000110
+ else if (mem_address_not_aligned = 1) then tt <- 00000111
+ else if (fp_exception = 1) then tt <- 00001000
+ else if (cp_exception = 1) then tt <- 00101000
+ else if (data_access_error = 1) then tt <- 00101001
+ else if (data_access_exception = 1) then tt <- 00001001
+ else if (tag_overflow = 1) then tt <- 00001010
+ else if (division_by_zero = 1) then tt <- 00101010
+ else if (trap_instruction = 1) then tt <- 1[]ticc_trap_type
+ else if (interrupt_level > 0) then tt <- 0001[]interrupt_level;
+
+ next;
+
+ trap <- 0;
+ instruction_access_exception <- 0;
+ illegal_instruction <- 0;
+ privileged_instruction <- 0;
+ fp_disabled <- 0;
+ cp_disabled <- 0;
+ window_overflow <- 0;
+ window_underflow <- 0;
+ mem_address_not_aligned <- 0;
+ fp_exception <- 0;
+ cp_exception <- 0;
+ data_access_exception <- 0;
+ tag_overflow <- 0;
+ division_by_zero <- 0;
+ trap_instruction <- 0;
+ interrupt_level <- 0;
+ );
+ */
+
+ if (!m_trap)
+ return;
+
+ select_trap();
+
+ if (!m_error_mode)
{
- m_queued_priority = m_trap_priorities[0];
- m_queued_tt = tt_override;
- }
- else
- {
- if (type == SPARC_TRAP_INSTRUCTION)
+ ET = 0;
+ PS = S;
+ CWP = ((CWP + NWINDOWS) - 1) % NWINDOWS;
+
+ if (m_annul == 0)
+ {
+ REG(17) = PC;
+ REG(18) = nPC;
+ }
+ else
{
- type = tt_override;
+ REG(17) = nPC;
+ REG(18) = nPC + 4;
+ m_annul = 0;
}
- if (type >= SPARC_INT1 && type <= SPARC_INT14)
+ S = 1;
+ if (!m_reset_trap)
+ {
+ PC = TBR;
+ nPC = TBR + 4;
+ }
+ else
{
- if (!ET)
- return;
- int irl = (type - SPARC_INT1) + 1;
- if (irl <= PIL)
- return;
+ PC = 0;
+ nPC = 4;
+ m_reset_trap = 0;
}
- if (m_trap_priorities[type] < m_queued_priority)
+ }
+
+ MAKE_PSR;
+ update_gpr_pointers();
+}
+
+
+//-------------------------------------------------
+// complete_instruction_execution - execute a
+// single fetched instruction that has been
+// checked for FP-disabled, CP-disabled, and
+// validity.
+//-------------------------------------------------
+
+void mb86901_device::complete_instruction_execution(UINT32 op)
+{
+ switch (OP)
+ {
+ case OP_TYPE0: // Bicc, SETHI, FBfcc
+ switch (OP2)
{
- m_queued_priority = m_trap_priorities[type];
- m_queued_tt = type;
+ case OP2_UNIMP: // unimp
+ printf("unimp @ %x\n", PC);
+ break;
+ case OP2_BICC: // branch on integer condition codes
+ execute_bicc(op);
+ break;
+ case OP2_SETHI: // sethi
+ SET_RDREG(IMM22);
+ break;
+ case OP2_FBFCC: // branch on floating-point condition codes
+ printf("fbfcc @ %x\n", PC);
+ break;
+#if SPARCV8
+ case OP2_CBCCC: // branch on coprocessor condition codes, SPARCv8
+ break;
+#endif
+ default:
+ printf("unknown %08x @ %x\n", op, PC);
+ break;
}
+ break;
+
+ case OP_CALL: // call
+ {
+ UINT32 pc = PC;
+ UINT32 callpc = PC + DISP30;
+ PC = nPC;
+ nPC = callpc;
+
+ REG(15) = pc;
+ break;
+ }
+
+ case OP_ALU:
+ execute_group2(op);
+ break;
+
+ case OP_LDST:
+ execute_group3(op);
+ break;
+ default:
+ break;
}
}
//-------------------------------------------------
-// invoke_queued_traps - prioritize and invoke
-// traps that have been queued by the previous
-// instruction, if any. Returns true if a trap
-// was invoked.
+// dispatch_instruction - dispatch the previously
+// fetched instruction
//-------------------------------------------------
-bool mb86901_device::invoke_queued_traps()
+void mb86901_device::dispatch_instruction(UINT32 op)
{
- if (m_queued_priority != SPARC_NO_TRAP)
+ /* The SPARC Instruction Manual: Version 8, page 159, "Appendix C - ISP Descriptions - C.6. Instruction Dispatch" (SPARCv8.pdf, pg. 156)
+
+ illegal_IU_instr :- (
+ if ( ( (op == 00) and (op2 == 000) ) { UNIMP instruction }
+ or
+ ( ((op=11) or (op=10)) and (op3=unassigned) )
+ then 1 else 0
+
+ if (illegal_IU_instr = 1) then (
+ trap <- 1
+ illegal_instruction <- 1
+ );
+ if ((FPop1 or FPop2 or FBfcc) and ((EF = 0) or (bp_FPU_present = 0))) then (
+ trap <- 1;
+ fp_disabled <- 1
+ );
+ if (CPop1 or CPop2 or CBccc) and ((EC = 0) or (bp_CP_present = 0))) then (
+ trap <- 1;
+ cp_disabled <- 1
+ );
+ next;
+ if (trap = 0) then (
+ { code for specific instruction, defined below }
+ );
+ */
+ bool illegal_IU_instr = (OP == 0 && OP2 == 0) || ((OP == 3 && !m_ldst_op3_assigned[OP3]) || (OP == 2 && !m_alu_op3_assigned[OP3]));
+
+ if (illegal_IU_instr)
{
- m_et = false;
- m_ps = m_s;
- m_s = true;
- m_cwp = ((m_cwp + WINDOW_COUNT) - 1) % WINDOW_COUNT;
+ m_trap = 1;
+ m_illegal_instruction = 1;
+
+ }
+ if (((OP == OP_ALU && (OP3 == OP3_FPOP1 || OP3 == OP3_FPOP2)) || (OP == OP_TYPE0 && OP2 == OP2_FBFCC)) && (!EF || !m_bp_fpu_present))
+ {
+ m_trap = 1;
+ m_fp_disabled = 1;
+ }
+ if (((OP == OP_ALU && (OP3 == OP3_CPOP1 || OP3 == OP3_CPOP2)) || (OP == OP_TYPE0 && OP2 == OP2_CBCCC)) && (!EC || !m_bp_cp_present))
+ {
+ m_trap = 1;
+ m_cp_disabled = 1;
+ }
+
+ if (!m_trap)
+ {
+ complete_instruction_execution(op);
+ }
+}
+
+
+//-------------------------------------------------
+// complete_fp_execution - completes execution
+// of a floating-point operation
+//-------------------------------------------------
+
+void mb86901_device::complete_fp_execution(UINT32 /*op*/)
+{
+}
+
+
+//-------------------------------------------------
+// execute_step - perform one step in execute
+// mode (versus error or reset modes)
+//-------------------------------------------------
+
+void mb86901_device::execute_step()
+{
+ /* The SPARC Instruction Manual: Version 8, page 156, "Appendix C - ISP Descriptions - C.5. Processor States and Instruction Dispatch" (SPARCv8.pdf, pg. 153)
+
+ if (bp_reset_in = 1) then (
+ execute_mode <- 0;
+ reset_mode <- 1;
+ break { out of while (execute_mode = 1) loop }
+ ) else if ((ET = 1) and ((bp_IRL = 15) or (bp_IRL > PIL))) then (
+ trap <- 1;
+ interrupt_level <- bp_IRL
+ );
+ next;
+
+ if (trap = 1) then execute_trap; { See Section C.8 }
+
+ if (execute_mode = 1) then ( { execute_trap may have set execute_mode to 0 }
+
+ { the following code emulates the delayed nature of the write-state-register instructions.
+ PSR <- PSR'; PSR' <- PSR''; PSR'' <- PSR'''; PSR''' <- PSR'''';
+ ASR <- ASR'; ASR' <- ASR''; ASR'' <- ASR'''; ASR''' <- ASR'''';
+ TBR <- TBR'; TBR' <- TBR''; TBR'' <- TBR'''; TBR''' <- TBR'''';
+ WIM <- WIM'; WIM' <- WIM''; WIM'' <- WIM'''; WIM''' <- WIM'''';
+ Y <- Y'; Y' <- Y''; Y'' <- Y'''; Y''' <- Y'''';
+ next;
+
+ addr_space := (if (S = 0) then 8 else 9);
+ (instruction, MAE) <- memory_read(addr_space, PC);
+ next;
+
+ if ( (MAE = 1) and (annul = 0) ) then (
+ trap <- 1;
+ instruction_access_exception <- 1
+ ) else (
+ if (annul = 0) then (
+ dispatch_instruction ; { See Section C.6 }
+ next;
+ if (FPop1 or FPop2) then (
+ complete_fp_execution { See Section C.7 }
+ )
+ next;
+ if ( (trap = 0) and
+ not (CALL or RETT or JMPL or Bicc or FBfcc or CBccc or Ticc) ) then (
+ PC <- nPC;
+ nPC <- nPC + 4
+ )
+ ) else { annul != 0 } (
+ annul <- 0;
+ PC <- nPC;
+ nPC <- nPC + 4
+ )
+ )
+ )
+ */
+ if (m_bp_reset_in)
+ {
+ m_execute_mode = 0;
+ m_reset_mode = 1;
+ return;
+ }
+ else if (ET && (m_bp_irl == 15 || m_bp_irl > PIL))
+ {
+ m_trap = 1;
+ m_interrupt_level = m_bp_irl;
+ }
+
+ if (m_trap) execute_trap();
+
+ if (m_execute_mode)
+ {
+ // write-state-register delay not yet implemented
+
+ UINT32 addr_space = (IS_USER ? 8 : 9);
+ UINT32 op = read_sized_word(addr_space, PC, 4);
+
+ if (MAE && !m_annul)
+ {
+ m_trap = 1;
+ m_instruction_access_exception = 1;
+ }
+ else
+ {
+ if (!m_annul)
+ {
+ dispatch_instruction(op);
- MAKE_PSR;
- update_gpr_pointers();
+ if (OP3 == OP3_FPOP1 || OP3 == OP3_FPOP2)
+ {
+ complete_fp_execution(op);
+ }
- REG(17) = PC;
- REG(18) = nPC;
+ if (m_trap == 0 && !(OP == OP_CALL || (OP == OP_TYPE0 && (OP2 == OP2_BICC || OP2 == OP2_FBFCC || OP2 == OP2_CBCCC)) || (OP == OP_ALU && (JMPL || TICC || RETT))))
+ {
+ PC = nPC;
+ nPC = nPC + 4;
+ }
+ }
+ else
+ {
+
+ m_annul = 0;
+ PC = nPC;
+ nPC = nPC + 4;
+ }
+ }
+ }
+}
- m_tbr |= m_queued_tt << 4;
- PC = m_tbr;
- nPC = m_tbr + 4;
+//-------------------------------------------------
+// reset_step - step one cycle in reset mode
+//-------------------------------------------------
- m_queued_priority = SPARC_NO_TRAP;
- m_queued_tt = 0;
- return true;
+void mb86901_device::reset_step()
+{
+ /* The SPARC Instruction Manual: Version 8, page 156, "Appendix C - ISP Descriptions - C.5. Processor States and Instruction Dispatch" (SPARCv8.pdf, pg. 153)
+
+ while (reset_mode = 1) (
+ if (bp_reset_in = 0) then (
+ reset_mode <- 0;
+ execute_mode <- 1;
+ trap <- 1;
+ reset_trap <- 1;
+ )
+ );
+ */
+
+ if (!m_bp_reset_in)
+ {
+ m_reset_mode = 0;
+ m_execute_mode = 1;
+ m_trap = 1;
+ m_reset_trap = 1;
}
+}
+
- return false;
+//-------------------------------------------------
+// error_step - step one cycle in error mode
+//-------------------------------------------------
+
+void mb86901_device::error_step()
+{
+ /* The SPARC Instruction Manual: Version 8, page 157, "Appendix C - ISP Descriptions - C.5. Processor States and Instruction Dispatch" (SPARCv8.pdf, pg. 154)
+
+ while (error_mode = 1) (
+ if (bp_reset_in = 1) then (
+ error_mode <- 0;
+ reset_mode <- 1;
+ pb_error <- 0
+ )
+ );
+ */
+
+ if (m_bp_reset_in)
+ {
+ m_error_mode = 0;
+ m_reset_mode = 1;
+ m_pb_error = 0;
+ }
}
@@ -1449,79 +3012,25 @@ void mb86901_device::execute_run()
while (m_icount > 0)
{
- bool trap_was_queued = invoke_queued_traps();
- if (trap_was_queued)
- {
- m_icount -= 4;
- continue;
- }
-
- debugger_instruction_hook(this, m_pc);
-
if (HOLD_BUS)
{
m_icount--;
continue;
}
- UINT32 op = GET_OPCODE;
- bool update_npc = true;
+ debugger_instruction_hook(this, m_pc);
- switch (OP)
- {
- case 0: // Bicc, SETHI, FBfcc
- switch (OP2)
- {
- case 0: // unimp
- printf("unimp @ %x\n", PC);
- break;
- case 2: // branch on integer condition codes
- update_npc = execute_bicc(op);
- break;
- case 4: // sethi
- SET_RDREG(IMM22);
- break;
- case 6: // branch on floating-point condition codes
- printf("fbfcc @ %x\n", PC);
- break;
-#if SPARCV8
- case 7: // branch on coprocessor condition codes, SPARCv8
- break;
-#endif
- default:
- printf("unknown %08x @ %x\n", op, PC);
- break;
- }
- break;
- case 1: // call
+ if (m_reset_mode)
{
- UINT32 pc = PC;
- UINT32 callpc = PC + DISP30;
- PC = nPC;
- nPC = callpc;
-
- REG(15) = pc;
-
- update_npc = false;
- break;
+ reset_step();
}
- case 2:
- update_npc = execute_group2(op);
- break;
- case 3: // loads, stores
- execute_group3(op);
- break;
- default:
- break;
+ else if (m_error_mode)
+ {
+ error_step();
}
-
- REG(0) = 0;
-
- bool trap_taken = invoke_queued_traps();
- if (!trap_taken && update_npc && !HOLD_BUS)
+ else if (m_execute_mode)
{
- PC = nPC;
- nPC = PC + 4;
+ execute_step();
}
if (debug)
diff --git a/src/devices/cpu/sparc/sparc.h b/src/devices/cpu/sparc/sparc.h
index a5e31751ed2..bb6c33d9933 100644
--- a/src/devices/cpu/sparc/sparc.h
+++ b/src/devices/cpu/sparc/sparc.h
@@ -16,7 +16,7 @@
#define SPARC_INSTRUCTION_ACCESS_EXCEPTION 1
#define SPARC_ILLEGAL_INSTRUCTION 2
#define SPARC_PRIVILEGED_INSTRUCTION 3
-#define SPARC_FLOATING_POINT_DISABLED 4
+#define SPARC_FP_DISABLED 4
#define SPARC_WINDOW_OVERFLOW 5
#define SPARC_WINDOW_UNDERFLOW 6
#define SPARC_MEM_ADDRESS_NOT_ALIGNED 7
@@ -40,6 +40,7 @@
#define SPARC_INT15 31
#define SPARC_TRAP_INSTRUCTION 128
+#define SPARC_FPU_SEQUENCE_ERROR
// TODO: when there are more SPARC CPUs, move setter to a base class
#define MCFG_SPARC_ADD_ASI_DESC(desc) \
mb86901_device::add_asi_desc(*device, desc);
@@ -85,35 +86,56 @@ public:
protected:
template<typename T> void add_asi_desc(const T &desc) { m_dasm.add_asi_desc(desc); }
- bool invoke_queued_traps();
- bool check_main_traps(UINT32 op, bool privileged, UINT32 alignment, UINT8 registeralign, bool noimmediate);
-
void update_gpr_pointers();
- void save_restore_update_cwp(UINT32 op, UINT8 new_cwp);
- bool execute_group2(UINT32 op);
+
+ void execute_add(UINT32 op);
+ void execute_taddcc(UINT32 op);
+ void execute_sub(UINT32 op);
+ void execute_tsubcc(UINT32 op);
+ void execute_logical(UINT32 op);
+ void execute_shift(UINT32 op);
+ void execute_mulscc(UINT32 op);
+ void execute_rdsr(UINT32 op);
+ void execute_wrsr(UINT32 op);
+ void execute_rett(UINT32 op);
+ void execute_saverestore(UINT32 op);
+ void execute_jmpl(UINT32 op);
+ void execute_group2(UINT32 op);
+
+ void execute_load(UINT32 op);
+ void execute_store(UINT32 op);
+ void execute_ldstub(UINT32 op);
void execute_group3(UINT32 op);
- bool execute_bicc(UINT32 op);
- bool execute_ticc(UINT32 op);
+
bool evaluate_condition(UINT32 op);
+ void execute_bicc(UINT32 op);
+ void execute_ticc(UINT32 op);
+ void select_trap();
+ void execute_trap();
+
+ void complete_instruction_execution(UINT32 op);
+ void dispatch_instruction(UINT32 op);
+ void complete_fp_execution(UINT32 /*op*/);
+ void execute_step();
+
+ void reset_step();
+ void error_step();
// address spaces
const address_space_config m_program_config;
// memory access
- UINT32 read_byte(UINT8 asi, UINT32 address);
- INT32 read_signed_byte(UINT8 asi, UINT32 address);
- UINT32 read_half(UINT8 asi, UINT32 address);
- INT32 read_signed_half(UINT8 asi, UINT32 address);
- UINT32 read_word(UINT8 asi, UINT32 address);
- UINT64 read_doubleword(UINT8 asi, UINT32 address);
- void write_byte(UINT8 asi, UINT32 address, UINT8 data);
- void write_half(UINT8 asi, UINT32 address, UINT16 data);
- void write_word(UINT8 asi, UINT32 address, UINT32 data);
- void write_doubleword(UINT8 asi, UINT32 address, UINT64 data);
+ UINT32 read_sized_word(UINT8 asi, UINT32 address, int size);
+ void write_sized_word(UINT8 asi, UINT32 address, UINT32 data, int size);
// general-purpose registers
UINT32 m_r[120];
+ // FPU registers
+ UINT32 m_fpr[32];
+ UINT32 m_fsr;
+ UINT8 m_ftt;
+
// control/status registers
UINT32 m_pc;
UINT32 m_npc;
@@ -122,6 +144,45 @@ protected:
UINT32 m_tbr;
UINT32 m_y;
+ bool m_bp_reset_in;
+ UINT8 m_bp_irl;
+ bool m_bp_fpu_present;
+ bool m_bp_cp_present;
+ bool m_pb_error;
+ bool m_pb_block_ldst_byte;
+ bool m_pb_block_ldst_word;
+
+ // trap and error registers
+ bool m_trap;
+ UINT8 m_tt;
+ UINT8 m_ticc_trap_type;
+ UINT8 m_interrupt_level;
+ bool m_privileged_instruction;
+ bool m_illegal_instruction;
+ bool m_mem_address_not_aligned;
+ bool m_fp_disabled;
+ bool m_fp_exception;
+ bool m_cp_disabled; // SPARCv8
+ bool m_cp_exception; // SPARCv8
+ bool m_unimplemented_FLUSH; // SPARCv8
+ bool m_r_register_access_error; // SPARCv8
+ bool m_instruction_access_error; // SPARCv8
+ bool m_instruction_access_exception;
+ bool m_data_access_error; // SPARCv8
+ bool m_data_store_error; // SPARCv8
+ bool m_data_access_exception;
+ bool m_division_by_zero; // SPARCv8
+ bool m_trap_instruction;
+ bool m_window_underflow;
+ bool m_window_overflow;
+ bool m_tag_overflow;
+ bool m_reset_mode;
+ bool m_reset_trap;
+ bool m_execute_mode;
+ bool m_error_mode;
+ UINT8 m_fpu_sequence_err;
+ UINT8 m_cp_sequence_err;
+
// fields separated out from PSR (Processor State Register)
UINT8 m_impl; // implementation (always 0 in MB86901)
UINT8 m_ver; // version (always 0 in MB86901)
@@ -134,19 +195,20 @@ protected:
bool m_et; // enable traps
UINT8 m_cwp; // current window pointer
+ bool m_alu_op3_assigned[64];
+ bool m_ldst_op3_assigned[64];
+
// register windowing helpers
UINT32* m_regs[32];
// addressing helpers
- UINT8 m_insn_asi;
- UINT8 m_data_asi;
UINT8 m_asi;
// other internal states
- UINT32 m_trap_priorities[256];
- UINT32 m_queued_tt;
- UINT32 m_queued_priority;
+ bool m_privileged_asr[32];
+ bool m_illegal_instruction_asr[32];
bool m_mae;
+ bool m_annul;
bool m_hold_bus;
int m_icount;
@@ -158,7 +220,7 @@ protected:
address_space *m_program;
// processor configuration
- static const int WINDOW_COUNT;
+ static const int NWINDOWS;
};
// device type definition
diff --git a/src/devices/cpu/sparc/sparcdasm.cpp b/src/devices/cpu/sparc/sparcdasm.cpp
index 6422c0a567f..0b7bb50e110 100644
--- a/src/devices/cpu/sparc/sparcdasm.cpp
+++ b/src/devices/cpu/sparc/sparcdasm.cpp
@@ -479,6 +479,7 @@ inline void sparc_disassembler::print(char *&output, const char *fmt, ...)
sparc_disassembler::sparc_disassembler(unsigned version)
: m_version(version)
+ , m_vis_level(0)
, m_op_field_width(9)
, m_branch_desc{
EMPTY_BRANCH_DESC,
@@ -537,6 +538,7 @@ sparc_disassembler::sparc_disassembler(unsigned version)
void sparc_disassembler::enable_vis1()
{
+ m_vis_level = std::max(m_vis_level, 1U);
m_op_field_width = std::max(m_op_field_width, 12);
add_vis_op_desc(VIS1_OP_DESC);
add_state_reg_desc(VIS1_STATE_REG_DESC);
@@ -547,6 +549,7 @@ void sparc_disassembler::enable_vis1()
void sparc_disassembler::enable_vis2()
{
enable_vis1();
+ m_vis_level = std::max(m_vis_level, 2U);
add_vis_op_desc(VIS2_OP_DESC);
}
@@ -1052,7 +1055,7 @@ offs_t sparc_disassembler::dasm_fpop2(char *buf, offs_t pc, UINT32 op) const
case 1: mnemonic = "fmovs"; shift = false; break;
case 2: mnemonic = "fmovd"; shift = true; break;
case 3: mnemonic = "fmovq"; shift = true; break;
- default: mnemonic = nullptr;
+ default: mnemonic = nullptr; shift = false; break;
}
if (mnemonic)
{
@@ -1114,6 +1117,11 @@ offs_t sparc_disassembler::dasm_impdep1(char *buf, offs_t pc, UINT32 op) const
dasm_vis_arg(buf, args, it->second.rd, RD);
return 4 | DASMFLAG_SUPPORTED;
}
+ else if ((m_vis_level >= 2) && (OPF == 0x081))
+ {
+ print(buf, "%-*s0x%x", m_op_field_width, "siam", IAMODE);
+ return 4 | DASMFLAG_SUPPORTED;
+ }
// TODO: driver hook for other kinds of coprocessor?
@@ -1200,6 +1208,7 @@ offs_t sparc_disassembler::dasm_ldst(char *buf, offs_t pc, UINT32 op) const
print(buf, "%-*s%%fsr,[", m_op_field_width, (RD == 1) ? "stx" : "st");
dasm_address(buf, op);
*buf++ = ']';
+ *buf = '\0';
return 4 | DASMFLAG_SUPPORTED;
}
break;
@@ -1236,7 +1245,7 @@ offs_t sparc_disassembler::dasm_ldst(char *buf, offs_t pc, UINT32 op) const
if (OP3 == 0x3d) dasm_asi(buf, op);
const auto it(m_prftch_desc.find(RD));
if (it != m_prftch_desc.end()) print(buf, ",%s", it->second.name);
- else print(buf, ",0x%02x", RD);
+ else print(buf, ",0x%02x", RD);
if (OP3 == 0x3d) dasm_asi_comment(buf, op);
}
return 4 | DASMFLAG_SUPPORTED;
@@ -1257,12 +1266,14 @@ offs_t sparc_disassembler::dasm_ldst(char *buf, offs_t pc, UINT32 op) const
print(buf, "%-*s%%%csr,[", m_op_field_width, "st", (OP3 == 0x35) ? 'c' : 'f');
dasm_address(buf, op);
*buf++ = ']';
+ *buf = '\0';
return 4 | DASMFLAG_SUPPORTED;
case 0x26: // Store Floating-point deferred-trap Queue
case 0x36: // Store Coprocessor deferred-trap Queue
print(buf, "%-*s%%%cq,[", m_op_field_width, "std", (OP3 == 0x36) ? 'c' : 'f');
dasm_address(buf, op);
*buf++ = ']';
+ *buf = '\0';
return 4 | DASMFLAG_SUPPORTED;
}
}
@@ -1279,6 +1290,7 @@ offs_t sparc_disassembler::dasm_ldst(char *buf, offs_t pc, UINT32 op) const
print(buf, "%-*s[", m_op_field_width, it->second.g0_synth);
dasm_address(buf, op);
*buf++ = ']';
+ *buf = '\0';
if (it->second.alternate)
{
dasm_asi(buf, op);
@@ -1296,6 +1308,7 @@ offs_t sparc_disassembler::dasm_ldst(char *buf, offs_t pc, UINT32 op) const
*buf++ = '[';
dasm_address(buf, op);
*buf++ = ']';
+ *buf = '\0';
if (it->second.alternate) dasm_asi(buf, op);
if (!it->second.rd_first)
{
diff --git a/src/devices/cpu/sparc/sparcdasm.h b/src/devices/cpu/sparc/sparcdasm.h
index 77e39eda177..986eedacdb7 100644
--- a/src/devices/cpu/sparc/sparcdasm.h
+++ b/src/devices/cpu/sparc/sparcdasm.h
@@ -17,6 +17,8 @@ class sparc_disassembler
public:
struct asi_desc
{
+ asi_desc() { }
+ asi_desc(const char *name_, const char *desc_) : name(name_), desc(desc_) { }
const char *name = nullptr;
const char *desc = nullptr;
};
@@ -24,14 +26,18 @@ public:
struct state_reg_desc
{
- bool reserved = false;
- const char *read_name = nullptr;
- const char *write_name = nullptr;
+ state_reg_desc() { }
+ state_reg_desc(bool reserved_, const char *read_name_, const char *write_name_) : reserved(reserved_), read_name(read_name_), write_name(write_name_) { }
+ bool reserved = false;
+ const char *read_name = nullptr;
+ const char *write_name = nullptr;
};
typedef std::map<UINT8, state_reg_desc> state_reg_desc_map;
struct prftch_desc
{
+ prftch_desc() { }
+ prftch_desc(const char *name_) : name(name_) { }
const char *name = nullptr;
};
typedef std::map<UINT8, prftch_desc> prftch_desc_map;
@@ -107,6 +113,8 @@ private:
struct fpop1_desc
{
+ fpop1_desc() { }
+ fpop1_desc(bool three_op_, bool rs1_shift_, bool rs2_shift_, bool rd_shift_, const char *mnemonic_) : three_op(three_op_), rs1_shift(rs1_shift_), rs2_shift(rs2_shift_), rd_shift(rd_shift_), mnemonic(mnemonic_) { }
bool three_op = true;
bool rs1_shift = false;
bool rs2_shift = false;
@@ -117,6 +125,8 @@ private:
struct fpop2_desc
{
+ fpop2_desc() { }
+ fpop2_desc(bool int_rs1_, bool shift_, const char *mnemonic_) : int_rs1(int_rs1_), shift(shift_), mnemonic(mnemonic_) { }
bool int_rs1 = false;
bool shift = false;
const char *mnemonic = nullptr;
@@ -125,6 +135,8 @@ private:
struct ldst_desc
{
+ ldst_desc() { }
+ ldst_desc(bool rd_first_, bool alternate_, char rd_alt_reg_, bool rd_shift_, const char *mnemonic_, const char *g0_synth_) : rd_first(rd_first_), alternate(alternate_), rd_alt_reg(rd_alt_reg_), rd_shift(rd_shift_), mnemonic(mnemonic_), g0_synth(g0_synth_) { }
bool rd_first = false;
bool alternate = false;
char rd_alt_reg = '\0';
@@ -137,6 +149,8 @@ private:
struct vis_op_desc
{
enum arg { X, I, Fs, Fd };
+ vis_op_desc() { }
+ vis_op_desc(arg rs1_, arg rs2_, arg rd_, bool collapse_, const char *mnemonic_) : rs1(rs1_), rs2(rs2_), rd(rd_), collapse(collapse_), mnemonic(mnemonic_) { }
arg rs1 = X;
arg rs2 = X;
arg rd = X;
@@ -206,6 +220,7 @@ private:
static const vis_op_desc_map::value_type VIS2_OP_DESC[];
unsigned m_version;
+ unsigned m_vis_level;
int m_op_field_width;
branch_desc m_branch_desc[8];
int_op_desc_map m_int_op_desc;
@@ -218,8 +233,4 @@ private:
vis_op_desc_map m_vis_op_desc;
};
-CPU_DISASSEMBLE( sparcv7 );
-CPU_DISASSEMBLE( sparcv8 );
-CPU_DISASSEMBLE( sparcv9 );
-
#endif // MAME_DEVICES_CPU_SPARC_SPARC_DASM_H
diff --git a/src/devices/cpu/sparc/sparcdefs.h b/src/devices/cpu/sparc/sparcdefs.h
index 2d988c5605c..bf2319d7bb7 100644
--- a/src/devices/cpu/sparc/sparcdefs.h
+++ b/src/devices/cpu/sparc/sparcdefs.h
@@ -12,8 +12,6 @@
#ifndef __MB86901_DEFS_H__
#define __MB86901_DEFS_H__
-#define GET_OPCODE 0; { m_asi = m_insn_asi; op = m_program->read_dword(m_pc); }
-
#define PSR_CWP_MASK 0x0000001f
#define PSR_ET_SHIFT 5
#define PSR_ET_MASK 0x00000020
@@ -43,21 +41,25 @@
#define PSR_ZERO_MASK (PSR_IMPL_MASK | PSR_VER_MASK | PSR_RES_MASK)
#define ICC_N_SET (m_psr & PSR_N_MASK)
+#define ICC_N (ICC_N_SET ? 1 : 0)
#define ICC_N_CLEAR (!ICC_N_SET)
#define SET_ICC_N_FLAG do { m_psr |= PSR_N_MASK; } while(0);
#define CLEAR_ICC_N_FLAG do { m_psr &= ~PSR_N_MASK; } while(0);
#define ICC_Z_SET (m_psr & PSR_Z_MASK)
+#define ICC_Z (ICC_Z_SET ? 1 : 0)
#define ICC_Z_CLEAR (!ICC_Z_SET)
#define SET_ICC_Z_FLAG do { m_psr |= PSR_Z_MASK; } while(0);
#define CLEAR_ICC_Z_FLAG do { m_psr &= ~PSR_Z_MASK; } while(0);
#define ICC_V_SET (m_psr & PSR_V_MASK)
-#define ICC_V_CLEAR (!ICC_B_SET)
+#define ICC_V (ICC_V_SET ? 1 : 0)
+#define ICC_V_CLEAR (!ICC_V_SET)
#define SET_ICC_V_FLAG do { m_psr |= PSR_V_MASK; } while(0);
#define CLEAR_ICC_V_FLAG do { m_psr &= ~PSR_V_MASK; } while(0);
#define ICC_C_SET (m_psr & PSR_C_MASK)
+#define ICC_C (ICC_C_SET ? 1 : 0)
#define ICC_C_CLEAR (!ICC_C_SET)
#define SET_ICC_C_FLAG do { m_psr |= PSR_C_MASK; } while(0);
#define CLEAR_ICC_C_FLAG do { m_psr &= ~PSR_C_MASK; } while(0);
@@ -66,18 +68,23 @@
#define TEST_ICC_NZ(x) do { m_psr &= ~PSR_ICC_MASK; m_psr |= (x & 0x80000000) ? PSR_N_MASK : 0; m_psr |= (x == 0) ? PSR_Z_MASK : 0; } while (0);
-#define MAKE_PSR do { m_psr = (m_impl << PSR_IMPL_SHIFT) | (m_ver << PSR_VER_SHIFT) | (m_icc << PSR_ICC_SHIFT) | (m_ec ? PSR_EC_MASK : 0) | (m_ef ? PSR_EF_MASK : 0) | (m_pil << PSR_PIL_SHIFT) | (m_s ? PSR_S_MASK : 0) | (m_ps ? PSR_PS_MASK : 0) | (m_et ? PSR_ET_MASK : 0) | m_cwp; m_insn_asi = m_s ? 9 : 8; m_data_asi = m_s ? 11 : 10; } while(0);
-#define BREAK_PSR do { m_icc = (m_psr & PSR_ICC_MASK) >> PSR_ICC_SHIFT; m_ec = m_psr & PSR_EC_MASK; m_ef = m_psr & PSR_EF_MASK; m_pil = (m_psr & PSR_PIL_MASK) >> PSR_PIL_SHIFT; m_s = m_psr & PSR_S_MASK; m_ps = m_psr & PSR_PS_MASK; m_et = m_psr & PSR_ET_MASK; m_cwp = m_psr & PSR_CWP_MASK; m_insn_asi = m_s ? 9 : 8; m_data_asi = m_s ? 11 : 10; } while(0);
+#define MAKE_PSR do { m_psr = (m_impl << PSR_IMPL_SHIFT) | (m_ver << PSR_VER_SHIFT) | (m_icc << PSR_ICC_SHIFT) | (m_ec ? PSR_EC_MASK : 0) | (m_ef ? PSR_EF_MASK : 0) | (m_pil << PSR_PIL_SHIFT) | (m_s ? PSR_S_MASK : 0) | (m_ps ? PSR_PS_MASK : 0) | (m_et ? PSR_ET_MASK : 0) | m_cwp; } while(0);
+#define BREAK_PSR do { m_icc = (m_psr & PSR_ICC_MASK) >> PSR_ICC_SHIFT; m_ec = m_psr & PSR_EC_MASK; m_ef = m_psr & PSR_EF_MASK; m_pil = (m_psr & PSR_PIL_MASK) >> PSR_PIL_SHIFT; m_s = m_psr & PSR_S_MASK; m_ps = m_psr & PSR_PS_MASK; m_et = m_psr & PSR_ET_MASK; m_cwp = m_psr & PSR_CWP_MASK; } while(0);
#define MAKE_ICC do { m_icc = (m_psr & PSR_ICC_MASK) >> PSR_ICC_SHIFT; } while(0);
+#define CWP m_cwp
+#define S m_s
+#define PS m_ps
+
#define IS_SUPERVISOR (m_psr & PSR_S_MASK)
#define IS_USER (!IS_SUPERVISOR)
#define TRAPS_ENABLED (m_psr & PSR_ET_MASK)
#define TRAPS_DISABLED (!TRAPS_ENABLED)
-#define FPU_ENABLED (m_psr & PSR_EF_MASK)
-#define FPU_DISABLED (!FPU_ENABLED)
+#define PSR m_psr
+#define WIM m_wim
+#define TBR m_tbr
#define OP (op >> 30) // gangnam style
#define OP2 ((op >> 22) & 7)
@@ -95,11 +102,12 @@
#define SIMM13 (INT32(op << 19) >> 19)
#define SIMM11 (INT32(op << 21) >> 21)
#define SIMM10 (INT32(op << 22) >> 22)
+#define SIMM8 (INT32(op << 24) >> 24)
#define IMM7 (op & 0x7f)
#define SIMM7 (INT32(op << 25) >> 25)
-#define SIMM8 (INT32(op << 24) >> 24)
#define SHCNT32 (op & 31)
#define SHCNT64 (op & 63)
+#define IAMODE (op & 0x7)
#define USEIMM ((op >> 13) & 1)
#define USEEXT ((op >> 12) & 1)
@@ -121,11 +129,15 @@
#define RS1 ((op >> 14) & 31)
#define RS2 (op & 31)
-#define REG(x) *m_regs[x]
+#define FREG(x) m_fpr[(x)]
+#define FDREG m_fpr[RD]
+#define FSR m_fsr
+
+#define REG(x) *m_regs[(x)]
#define RDREG *m_regs[RD]
#define RS1REG *m_regs[RS1]
#define RS2REG *m_regs[RS2]
-#define SET_RDREG(x) if(RD) { RDREG = x; }
+#define SET_RDREG(x) if(RD) { RDREG = (x); }
#define ADDRESS (USEIMM ? (RS1REG + SIMM13) : (RS1REG + RS2REG))
#define PC m_pc
@@ -134,8 +146,180 @@
#define Y m_y
#define ET m_et
+#define EF m_ef
+#define EC m_ec
#define PIL m_pil
#define MAE m_mae
#define HOLD_BUS m_hold_bus
+
+#define BIT31(x) ((x) & 0x80000000)
+
+#define UPDATE_PC true
+#define PC_UPDATED false
+
+#define OP_TYPE0 0
+#define OP_CALL 1
+#define OP_ALU 2
+#define OP_LDST 3
+
+#define OP2_UNIMP 0
+#define OP2_BICC 2
+#define OP2_SETHI 4
+#define OP2_FBFCC 6
+#define OP2_CBCCC 7
+
+#define OP3_ADD 0
+#define OP3_AND 1
+#define OP3_OR 2
+#define OP3_XOR 3
+#define OP3_SUB 4
+#define OP3_ANDN 5
+#define OP3_ORN 6
+#define OP3_XNOR 7
+#define OP3_ADDX 8
+#define OP3_UMUL 10
+#define OP3_SMUL 11
+#define OP3_SUBX 12
+#define OP3_UDIV 14
+#define OP3_SDIV 15
+#define OP3_ADDCC 16
+#define OP3_ANDCC 17
+#define OP3_ORCC 18
+#define OP3_XORCC 19
+#define OP3_SUBCC 20
+#define OP3_ANDNCC 21
+#define OP3_ORNCC 22
+#define OP3_XNORCC 23
+#define OP3_ADDXCC 24
+#define OP3_UMULCC 26
+#define OP3_SMULCC 27
+#define OP3_SUBXCC 28
+#define OP3_UDIVCC 30
+#define OP3_SDIVCC 31
+#define OP3_TADDCC 32
+#define OP3_TSUBCC 33
+#define OP3_TADDCCTV 34
+#define OP3_TSUBCCTV 35
+#define OP3_MULSCC 36
+#define OP3_SLL 37
+#define OP3_SRL 38
+#define OP3_SRA 39
+#define OP3_RDASR 40
+#define OP3_RDPSR 41
+#define OP3_RDWIM 42
+#define OP3_RDTBR 43
+#define OP3_WRASR 48
+#define OP3_WRPSR 49
+#define OP3_WRWIM 50
+#define OP3_WRTBR 51
+#define OP3_FPOP1 52
+#define OP3_FPOP2 53
+#define OP3_JMPL 56
+#define OP3_RETT 57
+#define OP3_TICC 58
+#define OP3_SAVE 60
+#define OP3_RESTORE 61
+
+#define OP3_LD 0
+#define OP3_LDUB 1
+#define OP3_LDUH 2
+#define OP3_LDD 3
+#define OP3_ST 4
+#define OP3_STB 5
+#define OP3_STH 6
+#define OP3_STD 7
+#define OP3_LDSB 9
+#define OP3_LDSH 10
+#define OP3_LDSTUB 13
+#define OP3_SWAP 15
+#define OP3_LDA 16
+#define OP3_LDUBA 17
+#define OP3_LDUHA 18
+#define OP3_LDDA 19
+#define OP3_STA 20
+#define OP3_STBA 21
+#define OP3_STHA 22
+#define OP3_STDA 23
+#define OP3_LDSBA 25
+#define OP3_LDSHA 26
+#define OP3_LDSTUBA 29
+#define OP3_SWAPA 31
+#define OP3_LDFPR 32
+#define OP3_LDFSR 33
+#define OP3_LDDFPR 35
+#define OP3_STFPR 36
+#define OP3_STFSR 37
+#define OP3_STDFQ 38
+#define OP3_STDFPR 39
+#define OP3_LDCPR 40
+#define OP3_LDCSR 41
+#define OP3_LDDCPR 43
+#define OP3_STCPR 44
+#define OP3_STCSR 45
+#define OP3_STDCQ 46
+#define OP3_STDCPR 47
+#define OP3_CPOP1 54
+#define OP3_CPOP2 55
+
+#define COND_BN 0
+#define COND_BE 1
+#define COND_BLE 2
+#define COND_BL 3
+#define COND_BLEU 4
+#define COND_BCS 5
+#define COND_BNEG 6
+#define COND_BVS 7
+#define COND_BA 8
+#define COND_BNE 9
+#define COND_BG 10
+#define COND_BGE 11
+#define COND_BGU 12
+#define COND_BCC 13
+#define COND_BPOS 14
+#define COND_BVC 15
+
+#define LDD (OP3 == OP3_LDD)
+#define LD (OP3 == OP3_LD)
+#define LDSH (OP3 == OP3_LDSH)
+#define LDUH (OP3 == OP3_LDUH)
+#define LDSB (OP3 == OP3_LDSB)
+#define LDUB (OP3 == OP3_LDUB)
+#define LDDF (OP3 == OP3_LDDFPR)
+#define LDF (OP3 == OP3_LDFPR)
+#define LDFSR (OP3 == OP3_LDFSR)
+#define LDDC (OP3 == OP3_LDDCPR)
+#define LDC (OP3 == OP3_LDCPR)
+#define LDCSR (OP3 == OP3_LDCSR)
+#define LDDA (OP3 == OP3_LDDA)
+#define LDA (OP3 == OP3_LDA)
+#define LDSHA (OP3 == OP3_LDSHA)
+#define LDUHA (OP3 == OP3_LDUHA)
+#define LDSBA (OP3 == OP3_LDSBA)
+#define LDUBA (OP3 == OP3_LDUBA)
+
+#define STD (OP3 == OP3_STD)
+#define ST (OP3 == OP3_ST)
+#define STH (OP3 == OP3_STH)
+#define STB (OP3 == OP3_STB)
+#define STDA (OP3 == OP3_STDA)
+#define STA (OP3 == OP3_STA)
+#define STHA (OP3 == OP3_STHA)
+#define STBA (OP3 == OP3_STBA)
+#define STF (OP3 == OP3_STFPR)
+#define STFSR (OP3 == OP3_STFSR)
+#define STDFQ (OP3 == OP3_STDFQ)
+#define STDF (OP3 == OP3_STDFPR)
+#define STC (OP3 == OP3_STCPR)
+#define STCSR (OP3 == OP3_STCSR)
+#define STDCQ (OP3 == OP3_STDCQ)
+#define STDC (OP3 == OP3_STDCPR)
+
+#define JMPL (OP3 == OP3_JMPL)
+#define TICC (OP3 == OP3_TICC)
+#define RETT (OP3 == OP3_RETT)
+
+#define LDSTUB (OP3 == OP3_LDSTUB)
+#define LDSTUBA (OP3 == OP3_LDSTUBA)
+
#endif // __MB86901_DEFS_H__ \ No newline at end of file
diff --git a/src/devices/machine/netlist.cpp b/src/devices/machine/netlist.cpp
index 7160b696b52..b924e052e50 100644
--- a/src/devices/machine/netlist.cpp
+++ b/src/devices/machine/netlist.cpp
@@ -103,7 +103,7 @@ void netlist_mame_analog_output_t::custom_netlist_additions(netlist::setup_t &se
plib::owned_ptr<netlist::device_t> dev = plib::owned_ptr<netlist::device_t>::Create<NETLIB_NAME(analog_callback)>(setup.netlist(), setup.build_fqn(dname));
static_cast<NETLIB_NAME(analog_callback) *>(dev.get())->register_callback(m_delegate);
- setup.register_dev(std::move(dev));
+ setup.netlist().register_dev(std::move(dev));
setup.register_link(dname + ".IN", m_in);
}
diff --git a/src/devices/machine/netlist.h b/src/devices/machine/netlist.h
index 606cd4af283..ad2cfdd47d1 100644
--- a/src/devices/machine/netlist.h
+++ b/src/devices/machine/netlist.h
@@ -66,11 +66,11 @@
// Extensions to interface netlist with MAME code ....
// ----------------------------------------------------------------------------------------
-class netlist_source_memregion_t : public netlist::setup_t::source_t
+class netlist_source_memregion_t : public netlist::source_t
{
public:
netlist_source_memregion_t(pstring name)
- : netlist::setup_t::source_t(), m_name(name)
+ : netlist::source_t(), m_name(name)
{
}
@@ -80,7 +80,7 @@ private:
};
#define MEMREGION_SOURCE(_name) \
- setup.register_source(std::make_shared<netlist_source_memregion_t>(_name));
+ setup.register_source(plib::make_unique_base<netlist::source_t, netlist_source_memregion_t>(_name));
#define NETDEV_ANALOG_CALLBACK_MEMBER(_name) \
void _name(const double data, const attotime &time)
diff --git a/src/lib/netlist/build/makefile b/src/lib/netlist/build/makefile
index c1729cc0c39..0a3efaa70f8 100644
--- a/src/lib/netlist/build/makefile
+++ b/src/lib/netlist/build/makefile
@@ -23,7 +23,7 @@ CDEFS = -DPSTANDALONE=1 -DPTR64=1
CFLAGS = $(LTO) -g -O3 -std=c++11 -march=native -I.. -Wall -Wpedantic -Wsign-compare -Wextra -Wno-unused-parameter
LDFLAGS = $(LTO) -g -O3 -std=c++11 -lpthread -ldl
-CC = @g++-5
+CC = g++-5
LD = @g++-5
MD = @mkdir
RM = @rm
@@ -49,8 +49,10 @@ OBJS = $(POBJS) $(NLOBJS)
POBJS := \
$(POBJ)/pstring.o \
$(POBJ)/palloc.o \
+ $(POBJ)/pchrono.o \
$(POBJ)/pdynlib.o \
$(POBJ)/pfmtlog.o \
+ $(POBJ)/poptions.o \
$(POBJ)/pparser.o \
$(POBJ)/pstate.o \
$(POBJ)/pstream.o \
@@ -101,6 +103,13 @@ NLOBJS := \
$(NLOBJ)/solver/nld_solver.o \
$(NLOBJ)/tools/nl_convert.o \
+ALL_OBJS = $(OBJS) $(NLOBJ)/prg/nltool.o $(NLOBJ)/prg/nlwav.o
+SOURCES = $(patsubst $(OBJ)%, $(SRC)%, $(ALL_OBJS:.o=.cpp))
+
+#-------------------------------------------------
+# all
+#-------------------------------------------------
+
all: maketree $(TARGETS)
#-------------------------------------------------
@@ -108,7 +117,7 @@ all: maketree $(TARGETS)
#-------------------------------------------------
clean:
- $(RM) -rf $(OBJS) $(TARGETS)
+ $(RM) -rf $(OBJS) $(TARGETS) .depend
#-------------------------------------------------
# nltool
@@ -131,6 +140,20 @@ $(sort $(OBJDIRS)):
maketree: $(sort $(OBJDIRS))
+#-------------------------------------------------
+# depends
+#-------------------------------------------------
+
+depend: .depend
+
+.depend: $(SOURCES)
+ @echo creating .depend
+ @rm -f ./.depend
+ @for i in $(SOURCES); do \
+ $(CC) $(CFLAGS) -MM $$i -MT `echo $$i | sed -e 's/$(SRC)/$(OBJ)/' -e 's/.cpp/.o/' ` >>./.depend; \
+ done
+
+-include .depend
#-------------------------------------------------
# generic rules
@@ -138,15 +161,15 @@ maketree: $(sort $(OBJDIRS))
$(OBJ)/%.o: $(SRC)/%.cpp
@echo Compiling $<...
- $(CC) $(CDEFS) $(CFLAGS) -c $< -o $@
+ @$(CC) $(CDEFS) $(CFLAGS) -c $< -o $@
$(OBJ)/%.pp: $(SRC)/%.cpp | $(OSPREBUILD)
@echo Compiling $<...
- $(CC) $(CDEFS) $(CFLAGS) -E $< -o $@
+ @$(CC) $(CDEFS) $(CFLAGS) -E $< -o $@
$(OBJ)/%.s: $(SRC)/%.cpp | $(OSPREBUILD)
@echo Compiling $<...
- $(CC) $(CDEFS) $(CFLAGS) -S $< -o $@
+ @$(CC) $(CDEFS) $(CFLAGS) -S $< -o $@
$(OBJ)/%.a:
@echo Archiving $@...
diff --git a/src/lib/netlist/devices/nld_74279.cpp b/src/lib/netlist/devices/nld_74279.cpp
index 7fb75f946fb..7bcbadff855 100644
--- a/src/lib/netlist/devices/nld_74279.cpp
+++ b/src/lib/netlist/devices/nld_74279.cpp
@@ -13,8 +13,8 @@ namespace netlist
namespace devices
{
- NETLIB_TRUTHTABLE(74279A, 3, 1, 0);
- NETLIB_TRUTHTABLE(74279B, 4, 1, 0);
+ NETLIB_TRUTHTABLE(74279A, 3, 1);
+ NETLIB_TRUTHTABLE(74279B, 4, 1);
NETLIB_OBJECT(74279_dip)
{
diff --git a/src/lib/netlist/devices/nld_7493.cpp b/src/lib/netlist/devices/nld_7493.cpp
index 8a12333e596..31faa5191dc 100644
--- a/src/lib/netlist/devices/nld_7493.cpp
+++ b/src/lib/netlist/devices/nld_7493.cpp
@@ -101,8 +101,8 @@ namespace netlist
NETLIB_UPDATE(7493ff)
{
- const netlist_time out_delay = NLTIME_FROM_NS(18);
- if (m_reset != 0)
+ constexpr netlist_time out_delay = NLTIME_FROM_NS(18);
+ if (m_reset)
{
m_state ^= 1;
OUTLOGIC(m_Q, m_state, out_delay);
diff --git a/src/lib/netlist/devices/nld_9312.cpp b/src/lib/netlist/devices/nld_9312.cpp
index 0191a905ebc..33b6d8e7a87 100644
--- a/src/lib/netlist/devices/nld_9312.cpp
+++ b/src/lib/netlist/devices/nld_9312.cpp
@@ -32,7 +32,7 @@ namespace netlist
/* The truthtable implementation is a lot faster than
* the carefully crafted code :-(
*/
- NETLIB_TRUTHTABLE(9312, 12, 2, 0);
+ NETLIB_TRUTHTABLE(9312, 12, 2);
#else
NETLIB_OBJECT(9312)
diff --git a/src/lib/netlist/devices/nld_9316.cpp b/src/lib/netlist/devices/nld_9316.cpp
index 8c6b70c5810..3033ace81bc 100644
--- a/src/lib/netlist/devices/nld_9316.cpp
+++ b/src/lib/netlist/devices/nld_9316.cpp
@@ -44,15 +44,15 @@ namespace netlist
{
NETLIB_CONSTRUCTOR(9316_sub)
, m_CLK(*this, "CLK")
+ , m_cnt(*this, "m_cnt", 0)
+ , m_loadq(*this, "m_loadq", 0)
+ , m_ent(*this, "m_ent", 0)
, m_QA(*this, "QA")
, m_QB(*this, "QB")
, m_QC(*this, "QC")
, m_QD(*this, "QD")
, m_RC(*this, "RC")
, m_ABCD(nullptr)
- , m_cnt(*this, "m_cnt", 0)
- , m_loadq(*this, "m_loadq", 0)
- , m_ent(*this, "m_ent", 0)
{
}
@@ -60,11 +60,20 @@ namespace netlist
NETLIB_UPDATEI();
public:
- inline void update_outputs_all(const uint_fast8_t cnt, const netlist_time out_delay);
- inline void update_outputs(const uint_fast8_t cnt);
+ void update_outputs_all(const uint_fast8_t cnt, const netlist_time out_delay)
+ {
+ OUTLOGIC(m_QA, (cnt >> 0) & 1, out_delay);
+ OUTLOGIC(m_QB, (cnt >> 1) & 1, out_delay);
+ OUTLOGIC(m_QC, (cnt >> 2) & 1, out_delay);
+ OUTLOGIC(m_QD, (cnt >> 3) & 1, out_delay);
+ }
logic_input_t m_CLK;
+ state_var_u8 m_cnt;
+ state_var_u8 m_loadq;
+ state_var_u8 m_ent;
+
logic_output_t m_QA;
logic_output_t m_QB;
logic_output_t m_QC;
@@ -72,11 +81,6 @@ namespace netlist
logic_output_t m_RC;
NETLIB_NAME(9316_subABCD) *m_ABCD;
-
- state_var_u8 m_cnt;
- state_var_u8 m_loadq;
- state_var_u8 m_ent;
-
};
NETLIB_OBJECT(9316)
@@ -173,7 +177,7 @@ namespace netlist
break;
default:
m_cnt++;
- update_outputs(m_cnt);
+ update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
break;
}
}
@@ -209,58 +213,6 @@ namespace netlist
}
}
- inline NETLIB_FUNC_VOID(9316_sub, update_outputs_all, (const uint_fast8_t cnt, const netlist_time out_delay))
- {
- OUTLOGIC(m_QA, (cnt >> 0) & 1, out_delay);
- OUTLOGIC(m_QB, (cnt >> 1) & 1, out_delay);
- OUTLOGIC(m_QC, (cnt >> 2) & 1, out_delay);
- OUTLOGIC(m_QD, (cnt >> 3) & 1, out_delay);
- }
-
- inline NETLIB_FUNC_VOID(9316_sub, update_outputs, (const uint_fast8_t cnt))
- {
- /* static */ const netlist_time out_delay = NLTIME_FROM_NS(20);
- #if 0
- // for (int i=0; i<4; i++)
- // OUTLOGIC(m_Q[i], (cnt >> i) & 1, delay[i]);
- OUTLOGIC(m_QA, (cnt >> 0) & 1, out_delay);
- OUTLOGIC(m_QB, (cnt >> 1) & 1, out_delay);
- OUTLOGIC(m_QC, (cnt >> 2) & 1, out_delay);
- OUTLOGIC(m_QD, (cnt >> 3) & 1, out_delay);
- #else
- if ((cnt & 1) == 1)
- OUTLOGIC(m_QA, 1, out_delay);
- else
- {
- OUTLOGIC(m_QA, 0, out_delay);
- switch (cnt)
- {
- case 0x00:
- OUTLOGIC(m_QB, 0, out_delay);
- OUTLOGIC(m_QC, 0, out_delay);
- OUTLOGIC(m_QD, 0, out_delay);
- break;
- case 0x02:
- case 0x06:
- case 0x0A:
- case 0x0E:
- OUTLOGIC(m_QB, 1, out_delay);
- break;
- case 0x04:
- case 0x0C:
- OUTLOGIC(m_QB, 0, out_delay);
- OUTLOGIC(m_QC, 1, out_delay);
- break;
- case 0x08:
- OUTLOGIC(m_QB, 0, out_delay);
- OUTLOGIC(m_QC, 0, out_delay);
- OUTLOGIC(m_QD, 1, out_delay);
- break;
- }
-
- }
- #endif
- }
NETLIB_DEVICE_IMPL(9316)
NETLIB_DEVICE_IMPL(9316_dip)
diff --git a/src/lib/netlist/devices/nld_truthtable.cpp b/src/lib/netlist/devices/nld_truthtable.cpp
index 9ed524e58b1..29895ae8b4c 100644
--- a/src/lib/netlist/devices/nld_truthtable.cpp
+++ b/src/lib/netlist/devices/nld_truthtable.cpp
@@ -7,13 +7,14 @@
#include "nld_truthtable.h"
#include "plib/plists.h"
+#include "nl_setup.h"
namespace netlist
{
namespace devices
{
- template<unsigned m_NI, unsigned m_NO, int has_state>
+ template<unsigned m_NI, unsigned m_NO>
class netlist_factory_truthtable_t : public netlist_base_factory_truthtable_t
{
P_PREVENT_COPYING(netlist_factory_truthtable_t)
@@ -25,11 +26,11 @@ namespace netlist
plib::owned_ptr<device_t> Create(netlist_t &anetlist, const pstring &name) override
{
- typedef nld_truthtable_t<m_NI, m_NO, has_state> tt_type;
+ typedef nld_truthtable_t<m_NI, m_NO> tt_type;
return plib::owned_ptr<device_t>::Create<tt_type>(anetlist, name, m_family, &m_ttbl, m_desc);
}
private:
- typename nld_truthtable_t<m_NI, m_NO, has_state>::truthtable_t m_ttbl;
+ typename nld_truthtable_t<m_NI, m_NO>::truthtable_t m_ttbl;
};
static const uint_least64_t all_set = ~((uint_least64_t) 0);
@@ -259,20 +260,17 @@ void truthtable_desc_t::setup(const plib::pstring_vector_t &truthtable, uint_lea
}
-#define ENTRYX(n, m, h) case (n * 1000 + m * 10 + h): \
- { using xtype = netlist_factory_truthtable_t<n, m, h>; \
- return plib::owned_ptr<netlist_base_factory_truthtable_t>::Create<xtype>(name,classname,def_param); } break
-
-#define ENTRYY(n, m) ENTRYX(n, m, 0); ENTRYX(n, m, 1)
+#define ENTRYY(n, m) case (n * 100 + m): \
+ { using xtype = netlist_factory_truthtable_t<n, m>; \
+ ret = new xtype(desc.name, desc.classname, desc.def_param); } break
#define ENTRY(n) ENTRYY(n, 1); ENTRYY(n, 2); ENTRYY(n, 3); ENTRYY(n, 4); ENTRYY(n, 5); ENTRYY(n, 6)
-plib::owned_ptr<netlist_base_factory_truthtable_t> nl_tt_factory_create(const unsigned ni, const unsigned no,
- const unsigned has_state,
- const pstring &name, const pstring &classname,
- const pstring &def_param)
+void tt_factory_create(setup_t &setup, tt_desc &desc)
{
- switch (ni * 1000 + no * 10 + has_state)
+ netlist_base_factory_truthtable_t *ret;
+
+ switch (desc.ni * 100 + desc.no)
{
ENTRY(1);
ENTRY(2);
@@ -285,10 +283,13 @@ plib::owned_ptr<netlist_base_factory_truthtable_t> nl_tt_factory_create(const un
ENTRY(9);
ENTRY(10);
default:
- pstring msg = plib::pfmt("unable to create truthtable<{1},{2},{3}>")(ni)(no)(has_state);
+ pstring msg = plib::pfmt("unable to create truthtable<{1},{2}>")(desc.ni)(desc.no);
nl_assert_always(false, msg);
}
- //return nullptr;
+ ret->m_desc = desc.desc;
+ if (desc.family != "")
+ ret->m_family = setup.family_from_model(desc.family);
+ setup.factory().register_device(std::unique_ptr<netlist_base_factory_truthtable_t>(ret));
}
} //namespace devices
diff --git a/src/lib/netlist/devices/nld_truthtable.h b/src/lib/netlist/devices/nld_truthtable.h
index d30ff03704c..157aea166fc 100644
--- a/src/lib/netlist/devices/nld_truthtable.h
+++ b/src/lib/netlist/devices/nld_truthtable.h
@@ -13,39 +13,22 @@
#include <new>
#include <cstdint>
-#include "nl_base.h"
+#include "nl_setup.h"
#include "nl_factory.h"
#include "plib/plists.h"
-#define NETLIB_TRUTHTABLE(cname, nIN, nOUT, state) \
- class NETLIB_NAME(cname) : public nld_truthtable_t<nIN, nOUT, state> \
+#define NETLIB_TRUTHTABLE(cname, nIN, nOUT) \
+ class NETLIB_NAME(cname) : public nld_truthtable_t<nIN, nOUT> \
{ \
public: \
template <class C> \
- NETLIB_NAME(cname)(C &owner, const pstring &name) \
- : nld_truthtable_t<nIN, nOUT, state>(owner, name, nullptr, &m_ttbl, m_desc) { } \
+ NETLIB_NAME(cname)(C &owner, const pstring &name) \
+ : nld_truthtable_t<nIN, nOUT>(owner, name, nullptr, &m_ttbl, m_desc) { } \
private: \
static truthtable_t m_ttbl; \
static const char *m_desc[]; \
}
-#define TRUTHTABLE_START(cname, in, out, has_state, def_params) \
- { \
- auto ttd = netlist::devices::nl_tt_factory_create(in, out, has_state, \
- # cname, # cname, "+" def_params);
-
-#define TT_HEAD(x) \
- ttd->m_desc.push_back(x);
-
-#define TT_LINE(x) \
- ttd->m_desc.push_back(x);
-
-#define TT_FAMILY(x) \
- ttd->m_family = setup.family_from_model(x);
-
-#define TRUTHTABLE_END() \
- setup.factory().register_device(std::move(ttd)); \
- }
namespace netlist
{
@@ -121,11 +104,11 @@ namespace netlist
struct truthtable_desc_t
{
- truthtable_desc_t(int NO, int NI, int has_state, bool *initialized,
+ truthtable_desc_t(int NO, int NI, bool *initialized,
packed_int outs, uint_least8_t *timing, netlist_time *timing_nt)
- : m_NO(NO), m_NI(NI), /*m_has_state(has_state),*/ m_initialized(initialized),
+ : m_NO(NO), m_NI(NI), m_initialized(initialized),
m_outs(outs), m_timing(timing), m_timing_nt(timing_nt),
- m_num_bits(m_NI + has_state * (m_NI + m_NO)),
+ m_num_bits(m_NI),
m_size(1 << (m_num_bits))
{
}
@@ -154,15 +137,15 @@ namespace netlist
};
- template<unsigned m_NI, unsigned m_NO, int m_has_state>
+ template<unsigned m_NI, unsigned m_NO>
NETLIB_OBJECT(truthtable_t)
{
private:
family_setter_t m_fam;
public:
- static const int m_num_bits = m_NI + m_has_state * (m_NI + m_NO);
- static const int m_size = (1 << (m_num_bits));
+ static constexpr int m_num_bits = m_NI;
+ static constexpr int m_size = (1 << (m_num_bits));
struct truthtable_t
{
@@ -180,10 +163,8 @@ namespace netlist
truthtable_t *ttp, const char *desc[])
: device_t(owner, name)
, m_fam(*this, fam)
- , m_last_state(*this, "m_last_state", 0)
, m_ign(*this, "m_ign", 0)
, m_active(*this, "m_active", 1)
- , m_use_deactivate(*this, "USE_DEACTIVATE", true)
, m_ttp(ttp)
{
while (*desc != nullptr && **desc != 0 )
@@ -199,10 +180,8 @@ namespace netlist
truthtable_t *ttp, const plib::pstring_vector_t &desc)
: device_t(owner, name)
, m_fam(*this, fam)
- , m_last_state(*this, "m_last_state", 0)
, m_ign(*this, "m_ign", 0)
, m_active(*this, "m_active", 1)
- , m_use_deactivate(*this, "USE_DEACTIVATE", true)
, m_ttp(ttp)
{
m_desc = desc;
@@ -211,6 +190,8 @@ namespace netlist
void startxx()
{
+ set_hint_deactivate(true);
+
pstring header = m_desc[0];
plib::pstring_vector_t io(header,"|");
@@ -249,8 +230,9 @@ namespace netlist
m_ign = 0;
- truthtable_desc_t desc(m_NO, m_NI, m_has_state,
- &m_ttp->m_initialized, packed_int(m_ttp->m_outs), m_ttp->m_timing, m_ttp->m_timing_nt);
+ truthtable_desc_t desc(m_NO, m_NI, &m_ttp->m_initialized,
+ packed_int(m_ttp->m_outs),
+ m_ttp->m_timing, m_ttp->m_timing_nt);
desc.setup(m_desc, disabled_ignore * 0);
#if 0
@@ -272,7 +254,6 @@ namespace netlist
for (std::size_t i=0; i<m_NO;i++)
if (this->m_Q[i].net().num_cons()>0)
m_active++;
- m_last_state = 0;
}
NETLIB_UPDATEI()
@@ -283,7 +264,7 @@ namespace netlist
public:
void inc_active() override
{
- if (m_NI > 1 && m_has_state == 0 && m_use_deactivate)
+ if (m_NI > 1)
if (++m_active == 1)
{
process<false>();
@@ -298,7 +279,7 @@ namespace netlist
* can decide for each individual gate whether it is benefitial to
* ignore deactivation.
*/
- if (m_NI > 1 && m_has_state == 0 && m_use_deactivate)
+ if (m_NI > 1)
if (--m_active == 0)
{
for (std::size_t i = 0; i< m_NI; i++)
@@ -322,7 +303,7 @@ namespace netlist
netlist_time mt = netlist_time::zero();
uint_least64_t state = 0;
- if (m_NI > 1 && !m_has_state)
+ if (m_NI > 1)
{
auto ign = m_ign;
if (!doOUT)
@@ -354,9 +335,6 @@ namespace netlist
}
auto nstate = state;
- if (m_has_state)
- nstate |= (m_last_state << m_NI);
-
const auto outstate = m_ttp->m_outs[nstate];
const auto out = outstate & ((1 << m_NO) - 1);
@@ -373,10 +351,7 @@ namespace netlist
for (std::size_t i = 0; i < m_NO; i++)
m_Q[i].net().set_Q_time((out >> i) & 1, mt + m_ttp->m_timing_nt[m_ttp->m_timing[timebase + i]]);
- if (m_has_state)
- m_last_state = (state << m_NO) | out;
-
- if (m_NI > 1 && !m_has_state)
+ if (m_NI > 1)
{
auto ign(m_ign);
for (std::size_t i = 0; ign != 0; ign >>= 1, i++)
@@ -386,11 +361,9 @@ namespace netlist
}
/* FIXME: check width */
- state_var_u32 m_last_state;
- state_var_u32 m_ign;
- state_var_s32 m_active;
- param_logic_t m_use_deactivate;
- truthtable_t *m_ttp;
+ state_var_u32 m_ign;
+ state_var_s32 m_active;
+ truthtable_t * m_ttp;
plib::pstring_vector_t m_desc;
};
@@ -411,10 +384,7 @@ namespace netlist
const logic_family_desc_t *m_family;
};
- plib::owned_ptr<netlist_base_factory_truthtable_t> nl_tt_factory_create(const unsigned ni, const unsigned no,
- const unsigned has_state,
- const pstring &name, const pstring &classname,
- const pstring &def_param);
+ void tt_factory_create(setup_t &setup, tt_desc &desc);
} //namespace devices
} // namespace netlist
diff --git a/src/lib/netlist/macro/nlm_cd4xxx.cpp b/src/lib/netlist/macro/nlm_cd4xxx.cpp
index f7eda575bab..d622881abb4 100644
--- a/src/lib/netlist/macro/nlm_cd4xxx.cpp
+++ b/src/lib/netlist/macro/nlm_cd4xxx.cpp
@@ -155,7 +155,7 @@ NETLIST_END()
NETLIST_START(CD4XXX_lib)
- TRUTHTABLE_START(CD4001_NOR, 2, 1, 0, "")
+ TRUTHTABLE_START(CD4001_NOR, 2, 1, "")
TT_HEAD("A , B | Q ")
TT_LINE("0,0|1|85")
TT_LINE("X,1|0|120")
diff --git a/src/lib/netlist/macro/nlm_other.cpp b/src/lib/netlist/macro/nlm_other.cpp
index 9a5e54af737..6fd73a29fe8 100644
--- a/src/lib/netlist/macro/nlm_other.cpp
+++ b/src/lib/netlist/macro/nlm_other.cpp
@@ -45,7 +45,7 @@ NETLIST_START(MC14584B_DIP)
NETLIST_END()
NETLIST_START(otheric_lib)
- TRUTHTABLE_START(MC14584B_GATE, 1, 1, 0, "")
+ TRUTHTABLE_START(MC14584B_GATE, 1, 1, "")
TT_HEAD(" A | Q ")
TT_LINE(" 0 | 1 |100")
TT_LINE(" 1 | 0 |100")
diff --git a/src/lib/netlist/macro/nlm_ttl74xx.cpp b/src/lib/netlist/macro/nlm_ttl74xx.cpp
index 25bf7573c03..41065012690 100644
--- a/src/lib/netlist/macro/nlm_ttl74xx.cpp
+++ b/src/lib/netlist/macro/nlm_ttl74xx.cpp
@@ -542,7 +542,7 @@ NETLIST_END()
NETLIST_START(TTL74XX_lib)
- TRUTHTABLE_START(TTL_7400_GATE, 2, 1, 0, "")
+ TRUTHTABLE_START(TTL_7400_GATE, 2, 1, "")
TT_HEAD("A,B|Q ")
TT_LINE("0,X|1|22")
TT_LINE("X,0|1|22")
@@ -550,7 +550,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7400_NAND, 2, 1, 0, "A,B")
+ TRUTHTABLE_START(TTL_7400_NAND, 2, 1, "A,B")
TT_HEAD("A,B|Q ")
TT_LINE("0,X|1|22")
TT_LINE("X,0|1|22")
@@ -558,7 +558,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7402_GATE, 2, 1, 0, "")
+ TRUTHTABLE_START(TTL_7402_GATE, 2, 1, "")
TT_HEAD("A,B|Q ")
TT_LINE("0,0|1|22")
TT_LINE("X,1|0|15")
@@ -566,7 +566,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7402_NOR, 2, 1, 0, "A,B")
+ TRUTHTABLE_START(TTL_7402_NOR, 2, 1, "A,B")
TT_HEAD("A,B|Q ")
TT_LINE("0,0|1|22")
TT_LINE("X,1|0|15")
@@ -574,21 +574,21 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7404_GATE, 1, 1, 0, "")
+ TRUTHTABLE_START(TTL_7404_GATE, 1, 1, "")
TT_HEAD(" A | Q ")
TT_LINE(" 0 | 1 |22")
TT_LINE(" 1 | 0 |15")
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7404_INVERT, 1, 1, 0, "A")
+ TRUTHTABLE_START(TTL_7404_INVERT, 1, 1, "A")
TT_HEAD(" A | Q ")
TT_LINE(" 0 | 1 |22")
TT_LINE(" 1 | 0 |15")
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7408_GATE, 2, 1, 0, "")
+ TRUTHTABLE_START(TTL_7408_GATE, 2, 1, "")
TT_HEAD("A,B|Q ")
TT_LINE("0,X|0|15")
TT_LINE("X,0|0|15")
@@ -596,7 +596,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7408_AND, 2, 1, 0, "A,B")
+ TRUTHTABLE_START(TTL_7408_AND, 2, 1, "A,B")
TT_HEAD("A,B|Q ")
TT_LINE("0,X|0|15")
TT_LINE("X,0|0|15")
@@ -604,7 +604,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7410_NAND, 3, 1, 0, "A,B,C")
+ TRUTHTABLE_START(TTL_7410_NAND, 3, 1, "A,B,C")
TT_HEAD("A,B,C|Q ")
TT_LINE("0,X,X|1|22")
TT_LINE("X,0,X|1|22")
@@ -613,7 +613,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7410_GATE, 3, 1, 0, "")
+ TRUTHTABLE_START(TTL_7410_GATE, 3, 1, "")
TT_HEAD("A,B,C|Q ")
TT_LINE("0,X,X|1|22")
TT_LINE("X,0,X|1|22")
@@ -622,7 +622,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7411_AND, 3, 1, 0, "A,B,C")
+ TRUTHTABLE_START(TTL_7411_AND, 3, 1, "A,B,C")
TT_HEAD("A,B,C|Q ")
TT_LINE("0,X,X|0|15")
TT_LINE("X,0,X|0|15")
@@ -631,7 +631,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7411_GATE, 3, 1, 0, "")
+ TRUTHTABLE_START(TTL_7411_GATE, 3, 1, "")
TT_HEAD("A,B,C|Q ")
TT_LINE("0,X,X|0|15")
TT_LINE("X,0,X|0|15")
@@ -640,7 +640,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7416_GATE, 1, 1, 0, "")
+ TRUTHTABLE_START(TTL_7416_GATE, 1, 1, "")
TT_HEAD(" A | Q ")
TT_LINE(" 0 | 1 |15")
TT_LINE(" 1 | 0 |23")
@@ -648,7 +648,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XXOC")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7420_GATE, 4, 1, 0, "")
+ TRUTHTABLE_START(TTL_7420_GATE, 4, 1, "")
TT_HEAD("A,B,C,D|Q ")
TT_LINE("0,X,X,X|1|22")
TT_LINE("X,0,X,X|1|22")
@@ -658,7 +658,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7420_NAND, 4, 1, 0, "A,B,C,D")
+ TRUTHTABLE_START(TTL_7420_NAND, 4, 1, "A,B,C,D")
TT_HEAD("A,B,C,D|Q ")
TT_LINE("0,X,X,X|1|22")
TT_LINE("X,0,X,X|1|22")
@@ -668,7 +668,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7425_GATE, 4, 1, 0, "")
+ TRUTHTABLE_START(TTL_7425_GATE, 4, 1, "")
TT_HEAD("A,B,C,D|Q ")
TT_LINE("1,X,X,X|0|15")
TT_LINE("X,1,X,X|0|15")
@@ -678,7 +678,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7425_NOR, 4, 1, 0, "A,B,C,D")
+ TRUTHTABLE_START(TTL_7425_NOR, 4, 1, "A,B,C,D")
TT_HEAD("A,B,C,D|Q ")
TT_LINE("1,X,X,X|0|15")
TT_LINE("X,1,X,X|0|15")
@@ -688,7 +688,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7427_GATE, 3, 1, 0, "")
+ TRUTHTABLE_START(TTL_7427_GATE, 3, 1, "")
TT_HEAD("A,B,C|Q ")
TT_LINE("1,X,X|0|15")
TT_LINE("X,1,X|0|15")
@@ -697,7 +697,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7427_NOR, 3, 1, 0, "A,B,C")
+ TRUTHTABLE_START(TTL_7427_NOR, 3, 1, "A,B,C")
TT_HEAD("A,B,C|Q ")
TT_LINE("1,X,X|0|15")
TT_LINE("X,1,X|0|15")
@@ -706,7 +706,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7430_GATE, 8, 1, 0, "")
+ TRUTHTABLE_START(TTL_7430_GATE, 8, 1, "")
TT_HEAD("A,B,C,D,E,F,G,H|Q ")
TT_LINE("0,X,X,X,X,X,X,X|1|22")
TT_LINE("X,0,X,X,X,X,X,X|1|22")
@@ -720,7 +720,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7430_NAND, 8, 1, 0, "A,B,C,D,E,F,G,H")
+ TRUTHTABLE_START(TTL_7430_NAND, 8, 1, "A,B,C,D,E,F,G,H")
TT_HEAD("A,B,C,D,E,F,G,H|Q ")
TT_LINE("0,X,X,X,X,X,X,X|1|22")
TT_LINE("X,0,X,X,X,X,X,X|1|22")
@@ -734,7 +734,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7432_GATE, 2, 1, 0, "")
+ TRUTHTABLE_START(TTL_7432_GATE, 2, 1, "")
TT_HEAD("A,B|Q ")
TT_LINE("1,X|1|22")
TT_LINE("X,1|1|22")
@@ -742,7 +742,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7432_OR, 2, 1, 0, "A,B")
+ TRUTHTABLE_START(TTL_7432_OR, 2, 1, "A,B")
TT_HEAD("A,B|Q ")
TT_LINE("1,X|1|22")
TT_LINE("X,1|1|22")
@@ -754,7 +754,7 @@ NETLIST_START(TTL74XX_lib)
* Netlist currently does not model over currents (should it ever?)
*/
- TRUTHTABLE_START(TTL_7437_GATE, 2, 1, 0, "")
+ TRUTHTABLE_START(TTL_7437_GATE, 2, 1, "")
TT_HEAD("A,B|Q ")
TT_LINE("0,X|1|22")
TT_LINE("X,0|1|22")
@@ -762,7 +762,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7437_NAND, 2, 1, 0, "A,B")
+ TRUTHTABLE_START(TTL_7437_NAND, 2, 1, "A,B")
TT_HEAD("A,B|Q ")
TT_LINE("0,X|1|22")
TT_LINE("X,0|1|22")
@@ -770,7 +770,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7486_GATE, 2, 1, 0, "")
+ TRUTHTABLE_START(TTL_7486_GATE, 2, 1, "")
TT_HEAD("A,B|Q ")
TT_LINE("0,0|0|15")
TT_LINE("0,1|1|22")
@@ -779,7 +779,7 @@ NETLIST_START(TTL74XX_lib)
TT_FAMILY("74XX")
TRUTHTABLE_END()
- TRUTHTABLE_START(TTL_7486_XOR, 2, 1, 0, "A,B")
+ TRUTHTABLE_START(TTL_7486_XOR, 2, 1, "A,B")
TT_HEAD("A,B|Q ")
TT_LINE("0,0|0|15")
TT_LINE("0,1|1|22")
diff --git a/src/lib/netlist/nl_base.cpp b/src/lib/netlist/nl_base.cpp
index e40ec1dc5d3..e20c240a374 100644
--- a/src/lib/netlist/nl_base.cpp
+++ b/src/lib/netlist/nl_base.cpp
@@ -189,7 +189,6 @@ netlist_t::netlist_t(const pstring &aname)
: m_state()
, m_time(netlist_time::zero())
, m_queue(*this)
- , m_use_deactivate(0)
, m_mainclock(nullptr)
, m_solver(nullptr)
, m_gnd(nullptr)
@@ -218,6 +217,14 @@ nl_double netlist_t::gmin() const
return solver()->gmin();
}
+void netlist_t::register_dev(plib::owned_ptr<device_t> dev)
+{
+ for (auto & d : m_devices)
+ if (d->name() == dev->name())
+ log().fatal("Error adding {1} to device list. Duplicate name \n", d->name());
+ m_devices.push_back(std::move(dev));
+}
+
void netlist_t::start()
{
/* load the library ... */
@@ -226,42 +233,6 @@ void netlist_t::start()
m_lib = plib::palloc<plib::dynlib>(libpath);
- /* make sure the solver and parameters are started first! */
-
- for (auto & e : setup().m_device_factory)
- {
- if ( setup().factory().is_class<devices::NETLIB_NAME(mainclock)>(e.second)
- || setup().factory().is_class<devices::NETLIB_NAME(solver)>(e.second)
- || setup().factory().is_class<devices::NETLIB_NAME(gnd)>(e.second)
- || setup().factory().is_class<devices::NETLIB_NAME(netlistparams)>(e.second))
- {
- auto dev = plib::owned_ptr<device_t>(e.second->Create(*this, e.first));
- setup().register_dev(std::move(dev));
- }
- }
-
- log().debug("Searching for mainclock and solver ...\n");
-
- m_mainclock = get_single_device<devices::NETLIB_NAME(mainclock)>("mainclock");
- m_solver = get_single_device<devices::NETLIB_NAME(solver)>("solver");
- m_gnd = get_single_device<devices::NETLIB_NAME(gnd)>("gnd");
- m_params = get_single_device<devices::NETLIB_NAME(netlistparams)>("parameter");
-
- m_use_deactivate = (m_params->m_use_deactivate.Value() ? true : false);
-
- /* create devices */
-
- for (auto & e : setup().m_device_factory)
- {
- if ( !setup().factory().is_class<devices::NETLIB_NAME(mainclock)>(e.second)
- && !setup().factory().is_class<devices::NETLIB_NAME(solver)>(e.second)
- && !setup().factory().is_class<devices::NETLIB_NAME(gnd)>(e.second)
- && !setup().factory().is_class<devices::NETLIB_NAME(netlistparams)>(e.second))
- {
- auto dev = plib::owned_ptr<device_t>(e.second->Create(*this, e.first));
- setup().register_dev(std::move(dev));
- }
- }
}
@@ -334,6 +305,8 @@ void netlist_t::process_queue(const netlist_time &delta)
m_queue.push(stop, nullptr);
+ m_stat_mainloop.start();
+
if (m_mainclock == nullptr)
{
queue_t::entry_t e(m_queue.pop());
@@ -341,7 +314,7 @@ void netlist_t::process_queue(const netlist_time &delta)
while (e.m_object != nullptr)
{
e.m_object->update_devs();
- add_to_stat(m_perf_out_processed, 1);
+ m_perf_out_processed.inc();
e = m_queue.pop();
m_time = e.m_exec_time;
}
@@ -367,27 +340,67 @@ void netlist_t::process_queue(const netlist_time &delta)
if (e.m_object == nullptr)
break;
e.m_object->update_devs();
- add_to_stat(m_perf_out_processed, 1);
+ m_perf_out_processed.inc();
}
mc_net.set_time(mc_time);
}
+ m_stat_mainloop.stop();
}
void netlist_t::print_stats() const
{
-#if (NL_KEEP_STATISTICS)
+ if (nperftime_t::enabled)
{
- for (auto & entry : m_devices)
+ std::vector<size_t> index;
+ for (size_t i=0; i<m_devices.size(); i++)
+ index.push_back(i);
+
+ std::sort(index.begin(), index.end(),
+ [&](size_t i1, size_t i2) { return m_devices[i1]->m_stat_total_time.total() < m_devices[i2]->m_stat_total_time.total(); });
+
+ nperftime_t::type total_time(0);
+ uint_least64_t total_count(0);
+
+ for (auto & j : index)
{
- log().verbose("Device {1:20} : {2:12} {3:12} {4:15}", entry->name(),
- entry->stat_call_count, entry->stat_update_count,
- (long int) entry->stat_total_time / (entry->stat_update_count + 1));
+ auto entry = m_devices[j].get();
+ log().verbose("Device {1:20} : {2:12} {3:12} {4:15} {5:12}", entry->name(),
+ entry->m_stat_call_count(), entry->m_stat_total_time.count(),
+ entry->m_stat_total_time.total(), entry->m_stat_inc_active());
+ total_time += entry->m_stat_total_time.total();
+ total_count += entry->m_stat_total_time.count();
}
- log().verbose("Queue Pushes {1:15}", queue().m_prof_call);
- log().verbose("Queue Moves {1:15}", queue().m_prof_sortmove);
+ nperftime_t overhead;
+ nperftime_t test;
+ overhead.start();
+ for (int j=0; j<100000;j++)
+ {
+ test.start();
+ test.stop();
+ }
+ overhead.stop();
+
+ uint_least64_t total_overhead = (uint_least64_t) overhead()*(uint_least64_t)total_count/(uint_least64_t)200000;
+
+ log().verbose("Queue Pushes {1:15}", queue().m_prof_call());
+ log().verbose("Queue Moves {1:15}", queue().m_prof_sortmove());
+
+ log().verbose("Total loop {1:15}", m_stat_mainloop());
+ /* Only one serialization should be counted in total time */
+ /* But two are contained in m_stat_mainloop */
+ log().verbose("Total devices {1:15}", total_time);
+ log().verbose("");
+ log().verbose("Take the next lines with a grain of salt. They depend on the measurement implementation.");
+ log().verbose("Total overhead {1:15}", total_overhead);
+ log().verbose("Overhead per pop {1:11}", (m_stat_mainloop()-2*total_overhead - (total_time - total_overhead ))/queue().m_prof_call());
+ log().verbose("");
+ for (auto &entry : m_devices)
+ {
+ if (entry->m_stat_inc_active() > 3 * entry->m_stat_total_time.count())
+ log().verbose("HINT({}, NO_DEACTIVATE)", entry->name());
+ }
}
-#endif
}
// ----------------------------------------------------------------------------------------
@@ -419,10 +432,9 @@ core_device_t::core_device_t(netlist_t &owner, const pstring &name)
: object_t(name)
, logic_family_t()
, netlist_ref(owner)
-#if (NL_KEEP_STATISTICS)
- , stat_total_time(0)
- , stat_update_count(0)
- , stat_call_count(0)
+ , m_hint_deactivate(false)
+#if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
+ , m_static_update()
#endif
{
if (logic_family() == nullptr)
@@ -433,10 +445,9 @@ core_device_t::core_device_t(core_device_t &owner, const pstring &name)
: object_t(owner.name() + "." + name)
, logic_family_t()
, netlist_ref(owner.netlist())
-#if (NL_KEEP_STATISTICS)
- , stat_total_time(0)
- , stat_update_count(0)
- , stat_call_count(0)
+ , m_hint_deactivate(false)
+#if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
+ , m_static_update()
#endif
{
set_logic_family(owner.logic_family());
@@ -586,14 +597,10 @@ void net_t::inc_active(core_terminal_t &term)
{
m_active++;
m_list_active.push_front(&term);
- nl_assert(m_active <= num_cons());
+ nl_assert(m_active <= (int) num_cons());
if (m_active == 1)
{
- if (netlist().use_deactivate())
- {
- railterminal().device().do_inc_active();
- //m_cur_Q = m_new_Q;
- }
+ railterminal().device().do_inc_active();
if (m_in_queue == 0)
{
if (m_time > netlist().time())
@@ -607,8 +614,6 @@ void net_t::inc_active(core_terminal_t &term)
m_in_queue = 2;
}
}
- //else if (netlist().use_deactivate())
- // m_cur_Q = m_new_Q;
}
}
@@ -617,7 +622,7 @@ void net_t::dec_active(core_terminal_t &term)
--m_active;
nl_assert(m_active >= 0);
m_list_active.remove(&term);
- if (m_active == 0 && netlist().use_deactivate())
+ if (m_active == 0)
railterminal().device().do_dec_active();
}
@@ -656,7 +661,7 @@ void net_t::update_devs()
for (auto & p : m_list_active)
{
- inc_stat(p.device().stat_call_count);
+ p.device().m_stat_call_count.inc();
if ((p.state() & mask) != 0)
p.device().update_dev();
}
@@ -945,10 +950,6 @@ nl_double param_model_t::model_value(const pstring &entity)
}
-} // namespace
-
-namespace netlist
-{
namespace devices
{
diff --git a/src/lib/netlist/nl_base.h b/src/lib/netlist/nl_base.h
index 1587cefb99b..1451e18038d 100644
--- a/src/lib/netlist/nl_base.h
+++ b/src/lib/netlist/nl_base.h
@@ -892,10 +892,9 @@ namespace netlist
void update_dev()
{
- begin_timing(stat_total_time);
- inc_stat(stat_update_count);
+ m_stat_total_time.start();
do_update();
- end_timing(stat_total_time);
+ m_stat_total_time.stop();
}
void do_update() NOEXCEPT
@@ -912,9 +911,21 @@ namespace netlist
void set_delegate_pointer();
void stop_dev();
- void do_inc_active() { inc_active(); }
- void do_dec_active() { dec_active(); }
+ void do_inc_active()
+ {
+ if (m_hint_deactivate)
+ {
+ m_stat_inc_active.inc();
+ inc_active();
+ }
+ }
+ void do_dec_active()
+ {
+ if (m_hint_deactivate)
+ dec_active();
+ }
void do_reset() { reset(); }
+ void set_hint_deactivate(bool v) { m_hint_deactivate = v; }
netlist_sig_t INPLOGIC_PASSIVE(logic_input_t &inp);
netlist_sig_t INPLOGIC(const logic_input_t &inp) const
@@ -928,12 +939,10 @@ namespace netlist
nl_double TERMANALOG(const terminal_t &term) const { return term.net().Q_Analog(); }
void OUTANALOG(analog_output_t &out, const nl_double val) { out.set_Q(val); }
- #if (NL_KEEP_STATISTICS)
/* stats */
- plib::ticks_t stat_total_time;
- int_fast32_t stat_update_count;
- int_fast32_t stat_call_count;
- #endif
+ nperftime_t m_stat_total_time;
+ nperfcount_t m_stat_call_count;
+ nperfcount_t m_stat_inc_active;
protected:
@@ -953,12 +962,12 @@ namespace netlist
virtual bool needs_update_after_param_change() const { return false; }
private:
-
- #if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
+ bool m_hint_deactivate;
+ #if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
typedef void (core_device_t::*net_update_delegate)();
- #elif ((NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV) || (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL))
+ #elif ((NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV) || (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL))
using net_update_delegate = MEMBER_ABI void (*)(core_device_t *);
- #endif
+ #endif
#if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
net_update_delegate m_static_update;
@@ -966,22 +975,6 @@ namespace netlist
};
// -----------------------------------------------------------------------------
- // param_ref_t
- // -----------------------------------------------------------------------------
-
- struct param_ref_t
- {
- param_ref_t(const pstring name, core_device_t &device, param_t &param)
- : m_name(name)
- , m_device(device)
- , m_param(param)
- { }
- pstring m_name;
- core_device_t &m_device;
- param_t &m_param;
- };
-
- // -----------------------------------------------------------------------------
// device_t
// -----------------------------------------------------------------------------
@@ -1071,8 +1064,9 @@ namespace netlist
// -----------------------------------------------------------------------------
- class netlist_t : public plib::plog_dispatch_intf //, public device_owner_t
+ class netlist_t : public plib::plog_dispatch_intf
{
+ friend class setup_t;
P_PREVENT_COPYING(netlist_t)
public:
@@ -1097,13 +1091,14 @@ namespace netlist
void process_queue(const netlist_time &delta);
void abort_current_queue_slice() { m_queue.retime(m_time, nullptr); }
- bool use_deactivate() const { return m_use_deactivate; }
-
void rebuild_lists(); /* must be called after post_load ! */
void set_setup(setup_t *asetup) { m_setup = asetup; }
setup_t &setup() { return *m_setup; }
+
+ void register_dev(plib::owned_ptr<device_t> dev);
+
net_t *find_net(const pstring &name);
template<class device_class>
@@ -1165,22 +1160,21 @@ namespace netlist
/* sole use is to manage lifetime of family objects */
std::vector<std::pair<pstring, std::unique_ptr<logic_family_desc_t>>> m_family_cache;
-protected:
+ protected:
- #if (NL_KEEP_STATISTICS)
// performance
- int m_perf_out_processed;
- int m_perf_inp_processed;
- int m_perf_inp_active;
- #endif
+ nperfcount_t m_perf_out_processed;
+ nperfcount_t m_perf_inp_processed;
+ nperfcount_t m_perf_inp_active;
private:
plib::state_manager_t m_state;
/* mostly rw */
netlist_time m_time;
queue_t m_queue;
- /* mostly rw */
- bool m_use_deactivate;
+
+ nperftime_t m_stat_mainloop;
+ /* mostly ro */
devices::NETLIB_NAME(mainclock) * m_mainclock;
devices::NETLIB_NAME(solver) * m_solver;
diff --git a/src/lib/netlist/nl_config.h b/src/lib/netlist/nl_config.h
index 19d8e3561ad..153057dbc22 100644
--- a/src/lib/netlist/nl_config.h
+++ b/src/lib/netlist/nl_config.h
@@ -11,6 +11,7 @@
#include <cstdint>
#include "plib/pconfig.h"
+#include "plib/pchrono.h"
//============================================================
// SETUP
@@ -111,18 +112,16 @@
// Performance tracking
//============================================================
+namespace netlist
+{
#if NL_KEEP_STATISTICS
-#define add_to_stat(v,x) do { v += (x); } while (0)
-#define inc_stat(v) add_to_stat(v, 1)
-#define begin_timing(v) do { v -= plib::profile_ticks(); } while (0)
-#define end_timing(v) do { v += plib::profile_ticks(); } while (0)
+using nperftime_t = plib::timer<plib::exact_ticks, true>;
+using nperfcount_t = plib::counter<true>;
#else
-#define add_to_stat(v,x) do { } while (0)
-#define inc_stat(v) add_to_stat(v, 1)
-#define begin_timing(v) do { } while (0)
-#define end_timing(v) do { } while (0)
+using nperftime_t = plib::chrono::timer<plib::chrono::exact_ticks, false>;
+using nperfcount_t = plib::chrono::counter<false>;
#endif
-
+}
//============================================================
// General
//============================================================
diff --git a/src/lib/netlist/nl_factory.h b/src/lib/netlist/nl_factory.h
index b85e85bf6b8..f97dad9bf5a 100644
--- a/src/lib/netlist/nl_factory.h
+++ b/src/lib/netlist/nl_factory.h
@@ -65,7 +65,7 @@ namespace netlist
}
};
- class factory_list_t : public std::vector<plib::owned_ptr<base_factory_t>>
+ class factory_list_t : public std::vector<std::unique_ptr<base_factory_t>>
{
public:
factory_list_t(setup_t &m_setup);
@@ -75,10 +75,10 @@ namespace netlist
void register_device(const pstring &name, const pstring &classname,
const pstring &def_param)
{
- register_device(plib::owned_ptr<base_factory_t>::Create<factory_t<device_class>>(name, classname, def_param));
+ register_device(std::unique_ptr<base_factory_t>(new factory_t<device_class>(name, classname, def_param)));
}
- void register_device(plib::owned_ptr<base_factory_t> factory)
+ void register_device(std::unique_ptr<base_factory_t> factory)
{
for (auto & e : *this)
if (e->name() == factory->name())
@@ -104,14 +104,14 @@ namespace netlist
// factory_creator_ptr_t
// -----------------------------------------------------------------------------
- using factory_creator_ptr_t = plib::owned_ptr<base_factory_t> (*)(const pstring &name, const pstring &classname,
+ using factory_creator_ptr_t = std::unique_ptr<base_factory_t> (*)(const pstring &name, const pstring &classname,
const pstring &def_param);
template <typename T>
- plib::owned_ptr<base_factory_t> factory_creator_t(const pstring &name, const pstring &classname,
+ std::unique_ptr<base_factory_t> factory_creator_t(const pstring &name, const pstring &classname,
const pstring &def_param)
{
- return plib::owned_ptr<base_factory_t>::Create<factory_t<T>>(name, classname, def_param);
+ return std::unique_ptr<base_factory_t>(new factory_t<T>(name, classname, def_param));
}
}
diff --git a/src/lib/netlist/nl_lists.h b/src/lib/netlist/nl_lists.h
index 475e0e285c2..9e6cc335b5b 100644
--- a/src/lib/netlist/nl_lists.h
+++ b/src/lib/netlist/nl_lists.h
@@ -10,10 +10,11 @@
#ifndef NLLISTS_H_
#define NLLISTS_H_
+#include <atomic>
+
#include "nl_config.h"
#include "plib/plists.h"
-
-#include <atomic>
+#include "plib/pchrono.h"
// ----------------------------------------------------------------------------------------
@@ -36,10 +37,6 @@ namespace netlist
timed_queue(unsigned list_size)
: m_list(list_size)
-#if (NL_KEEP_STATISTICS)
- , m_prof_sortmove(0)
- , m_prof_call(0)
-#endif
{
#if HAS_OPENMP && USE_OPENMP
m_lock = 0;
@@ -60,11 +57,11 @@ namespace netlist
for (; t > (i - 1)->m_exec_time; --i)
{
*(i) = *(i-1);
- inc_stat(m_prof_sortmove);
+ m_prof_sortmove.inc();
}
*i = { t, o };
++m_end;
- inc_stat(m_prof_call);
+ m_prof_call.inc();
#if HAS_OPENMP && USE_OPENMP
m_lock = 0;
#endif
@@ -132,12 +129,9 @@ namespace netlist
std::vector<entry_t> m_list;
public:
- #if (NL_KEEP_STATISTICS)
// profiling
- std::size_t m_prof_sortmove;
- std::size_t m_prof_call;
- #endif
-
+ nperfcount_t m_prof_sortmove;
+ nperfcount_t m_prof_call;
};
}
diff --git a/src/lib/netlist/nl_parser.cpp b/src/lib/netlist/nl_parser.cpp
index 14aabdf4a0e..bc27913e6b0 100644
--- a/src/lib/netlist/nl_parser.cpp
+++ b/src/lib/netlist/nl_parser.cpp
@@ -45,6 +45,7 @@ bool parser_t::parse(const pstring nlname)
m_tok_NET_C = register_token("NET_C");
m_tok_FRONTIER = register_token("OPTIMIZE_FRONTIER");
m_tok_PARAM = register_token("PARAM");
+ m_tok_HINT = register_token("HINT");
m_tok_NET_MODEL = register_token("NET_MODEL");
m_tok_INCLUDE = register_token("INCLUDE");
m_tok_LOCAL_SOURCE = register_token("LOCAL_SOURCE");
@@ -120,6 +121,8 @@ void parser_t::parse_netlist(ATTR_UNUSED const pstring &nlname)
frontier();
else if (token.is(m_tok_PARAM))
netdev_param();
+ else if (token.is(m_tok_HINT))
+ netdev_hint();
else if (token.is(m_tok_NET_MODEL))
net_model();
else if (token.is(m_tok_SUBMODEL))
@@ -153,13 +156,16 @@ void parser_t::net_truthtable_start()
require_token(m_tok_comma);
unsigned no = get_number_long();
require_token(m_tok_comma);
- unsigned hs = get_number_long();
- require_token(m_tok_comma);
pstring def_param = get_string();
require_token(m_tok_param_right);
- plib::owned_ptr<netlist::devices::netlist_base_factory_truthtable_t> ttd = netlist::devices::nl_tt_factory_create(ni, no, hs,
- name, name, "+" + def_param);
+ netlist::tt_desc desc;
+ desc.classname = name;
+ desc.name = name;
+ desc.ni = ni;
+ desc.no = no;
+ desc.def_param = "+" + def_param;
+ desc.family = "";
while (true)
{
@@ -168,19 +174,19 @@ void parser_t::net_truthtable_start()
if (token.is(m_tok_TT_HEAD))
{
require_token(m_tok_param_left);
- ttd->m_desc.push_back(get_string());
+ desc.desc.push_back(get_string());
require_token(m_tok_param_right);
}
else if (token.is(m_tok_TT_LINE))
{
require_token(m_tok_param_left);
- ttd->m_desc.push_back(get_string());
+ desc.desc.push_back(get_string());
require_token(m_tok_param_right);
}
else if (token.is(m_tok_TT_FAMILY))
{
require_token(m_tok_param_left);
- ttd->m_family = m_setup.family_from_model(get_string());
+ desc.family = get_string();
require_token(m_tok_param_right);
}
else
@@ -188,7 +194,7 @@ void parser_t::net_truthtable_start()
require_token(token, m_tok_TRUTHTABLE_END);
require_token(m_tok_param_left);
require_token(m_tok_param_right);
- m_setup.factory().register_device(std::move(ttd));
+ netlist::devices::tt_factory_create(m_setup, desc);
return;
}
}
@@ -339,6 +345,15 @@ void parser_t::netdev_param()
require_token(m_tok_param_right);
}
+void parser_t::netdev_hint()
+{
+ pstring dev(get_identifier());
+ require_token(m_tok_comma);
+ pstring hint(get_identifier());
+ m_setup.register_param(dev + ".HINT_" + hint, 1);
+ require_token(m_tok_param_right);
+}
+
void parser_t::device(const pstring &dev_type)
{
if (m_setup.is_library_item(dev_type))
@@ -431,7 +446,7 @@ nl_double parser_t::eval_param(const token_t tok)
val = tok.str();
ret = val.as_double(&e);
if (e)
- error("Error with parameter ...\n");
+ error(plib::pfmt("Error with parameter {1}...\n")(val));
}
return ret * facs[f];
diff --git a/src/lib/netlist/nl_parser.h b/src/lib/netlist/nl_parser.h
index 7338fb01abd..5c915e69997 100644
--- a/src/lib/netlist/nl_parser.h
+++ b/src/lib/netlist/nl_parser.h
@@ -27,6 +27,7 @@ namespace netlist
void net_alias();
void dippins();
void netdev_param();
+ void netdev_hint();
void net_c();
void frontier();
void device(const pstring &dev_type);
@@ -54,6 +55,7 @@ namespace netlist
token_id_t m_tok_DIPPINS;
token_id_t m_tok_FRONTIER;
token_id_t m_tok_PARAM;
+ token_id_t m_tok_HINT;
token_id_t m_tok_NET_MODEL;
token_id_t m_tok_NETLIST_START;
token_id_t m_tok_NETLIST_END;
diff --git a/src/lib/netlist/nl_setup.cpp b/src/lib/netlist/nl_setup.cpp
index 5b7099a9e14..0582f8a9070 100644
--- a/src/lib/netlist/nl_setup.cpp
+++ b/src/lib/netlist/nl_setup.cpp
@@ -16,6 +16,7 @@
#include "nl_parser.h"
#include "nl_factory.h"
#include "devices/net_lib.h"
+#include "devices/nld_truthtable.h"
#include "devices/nlid_system.h"
#include "analog/nld_twoterm.h"
#include "solver/nld_solver.h"
@@ -99,15 +100,6 @@ void setup_t::namespace_pop()
m_namespace_stack.pop();
}
-
-void setup_t::register_dev(plib::owned_ptr<device_t> dev)
-{
- for (auto & d : netlist().m_devices)
- if (d->name() == dev->name())
- log().fatal("Error adding {1} to device list. Duplicate name \n", d->name());
- netlist().m_devices.push_back(std::move(dev));
-}
-
void setup_t::register_lib_entry(const pstring &name)
{
if (plib::container::contains(m_lib, name))
@@ -453,7 +445,7 @@ devices::nld_base_proxy *setup_t::get_d_a_proxy(core_terminal_t &out)
proxy = new_proxy.get();
- register_dev(std::move(new_proxy));
+ netlist().register_dev(std::move(new_proxy));
}
return proxy;
}
@@ -471,7 +463,7 @@ void setup_t::connect_input_output(core_terminal_t &in, core_terminal_t &out)
proxy->m_Q.net().register_con(in);
out.net().register_con(proxy->m_I);
- register_dev(std::move(proxy));
+ netlist().register_dev(std::move(proxy));
}
else if (out.is_logic() && in.is_analog())
@@ -514,7 +506,7 @@ void setup_t::connect_terminal_input(terminal_t &term, core_terminal_t &inp)
else
proxy->m_Q.net().register_con(inp);
- register_dev(std::move(proxy));
+ netlist().register_dev(std::move(proxy));
}
else
{
@@ -781,13 +773,77 @@ void setup_t::start_devices()
auto nc = factory().factory_by_name("LOG")->Create(netlist(), name);
register_link(name + ".I", ll);
log().debug(" dynamic link {1}: <{2}>\n",ll, name);
- register_dev(std::move(nc));
+ netlist().register_dev(std::move(nc));
+ }
+ }
+
+ /* make sure the solver and parameters are started first! */
+
+ for (auto & e : m_device_factory)
+ {
+ if ( factory().is_class<devices::NETLIB_NAME(mainclock)>(e.second)
+ || factory().is_class<devices::NETLIB_NAME(solver)>(e.second)
+ || factory().is_class<devices::NETLIB_NAME(gnd)>(e.second)
+ || factory().is_class<devices::NETLIB_NAME(netlistparams)>(e.second))
+ {
+ auto dev = plib::owned_ptr<device_t>(e.second->Create(netlist(), e.first));
+ netlist().register_dev(std::move(dev));
+ }
+ }
+
+ log().debug("Searching for mainclock and solver ...\n");
+
+ netlist().m_mainclock = netlist().get_single_device<devices::NETLIB_NAME(mainclock)>("mainclock");
+ netlist().m_solver = netlist().get_single_device<devices::NETLIB_NAME(solver)>("solver");
+ netlist().m_gnd = netlist().get_single_device<devices::NETLIB_NAME(gnd)>("gnd");
+ netlist().m_params = netlist().get_single_device<devices::NETLIB_NAME(netlistparams)>("parameter");
+
+ /* create devices */
+
+ for (auto & e : m_device_factory)
+ {
+ if ( !factory().is_class<devices::NETLIB_NAME(mainclock)>(e.second)
+ && !factory().is_class<devices::NETLIB_NAME(solver)>(e.second)
+ && !factory().is_class<devices::NETLIB_NAME(gnd)>(e.second)
+ && !factory().is_class<devices::NETLIB_NAME(netlistparams)>(e.second))
+ {
+ auto dev = plib::owned_ptr<device_t>(e.second->Create(netlist(), e.first));
+ netlist().register_dev(std::move(dev));
+ }
+ }
+
+ bool use_deactivate = (netlist().m_params->m_use_deactivate.Value() ? true : false);
+
+ for (auto &d : netlist().m_devices)
+ {
+ if (use_deactivate)
+ {
+ auto p = m_param_values.find(d->name() + ".HINT_NO_DEACTIVATE");
+ if (p != m_param_values.end())
+ {
+ //FIXME: Error checking
+ auto v = p->second.as_long();
+ d->set_hint_deactivate(!v);
+ }
}
+ else
+ d->set_hint_deactivate(false);
}
netlist().start();
+
}
+plib::plog_base<NL_DEBUG> &setup_t::log()
+{
+ return netlist().log();
+}
+const plib::plog_base<NL_DEBUG> &setup_t::log() const
+{
+ return netlist().log();
+}
+
+
// ----------------------------------------------------------------------------------------
// Model / family
// ----------------------------------------------------------------------------------------
@@ -926,13 +982,19 @@ nl_double setup_t::model_value(model_map_t &map, const pstring &entity)
return tmp.as_double() * factor;
}
+void setup_t::tt_factory_create(tt_desc &desc)
+{
+ devices::tt_factory_create(*this, desc);
+}
+
+
// ----------------------------------------------------------------------------------------
// Sources
// ----------------------------------------------------------------------------------------
void setup_t::include(const pstring &netlist_name)
{
- for (auto source : m_sources)
+ for (auto &source : m_sources)
{
if (source->parse(*this, netlist_name))
return;
diff --git a/src/lib/netlist/nl_setup.h b/src/lib/netlist/nl_setup.h
index 39ef1c514ff..2fee7210aa9 100644
--- a/src/lib/netlist/nl_setup.h
+++ b/src/lib/netlist/nl_setup.h
@@ -11,7 +11,13 @@
#include <memory>
#include <stack>
#include <unordered_map>
+#include <vector>
+#include "plib/pstring.h"
+#include "plib/palloc.h"
+#include "plib/pfmtlog.h"
+#include "plib/putil.h"
+#include "nl_config.h"
#include "nl_base.h"
#include "nl_factory.h"
@@ -34,75 +40,136 @@
#define NET_REGISTER_DEV(type, name) \
setup.register_dev(# type, # name);
-#define NET_CONNECT(name, input, output) \
+#define NET_CONNECT(name, input, output) \
setup.register_link(# name "." # input, # output);
-#define NET_C(term1, ...) \
+#define NET_C(term1, ...) \
setup.register_link_arr( # term1 ", " # __VA_ARGS__);
-#define PARAM(name, val) \
+#define PARAM(name, val) \
setup.register_param(# name, val);
-#define NETDEV_PARAMI(name, param, val) \
+#define HINT(name, val) \
+ setup.register_param(# name ".HINT_" # val, 1);
+
+#define NETDEV_PARAMI(name, param, val) \
setup.register_param(# name "." # param, val);
#define NETLIST_NAME(name) netlist ## _ ## name
-#define NETLIST_EXTERNAL(name) \
+#define NETLIST_EXTERNAL(name) \
void NETLIST_NAME(name)(netlist::setup_t &setup);
-#define NETLIST_START(name) \
-void NETLIST_NAME(name)(netlist::setup_t &setup) \
+#define NETLIST_START(name) \
+void NETLIST_NAME(name)(netlist::setup_t &setup) \
{
+
#define NETLIST_END() }
-#define LOCAL_SOURCE(name) \
- setup.register_source(std::make_shared<netlist::source_proc_t>(# name, &NETLIST_NAME(name)));
+#define LOCAL_SOURCE(name) \
+ setup.register_source(plib::make_unique_base<netlist::source_t, netlist::source_proc_t>(# name, &NETLIST_NAME(name)));
-#define LOCAL_LIB_ENTRY(name) \
- LOCAL_SOURCE(name) \
+#define LOCAL_LIB_ENTRY(name) \
+ LOCAL_SOURCE(name) \
setup.register_lib_entry(# name);
-#define INCLUDE(name) \
+#define INCLUDE(name) \
setup.include(# name);
-#define SUBMODEL(model, name) \
- setup.namespace_push(# name); \
- NETLIST_NAME(model)(setup); \
+#define SUBMODEL(model, name) \
+ setup.namespace_push(# name); \
+ NETLIST_NAME(model)(setup); \
setup.namespace_pop();
-// ----------------------------------------------------------------------------------------
-// netlist_setup_t
-// ----------------------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
+// truthtable defines
+// -----------------------------------------------------------------------------
+
+#define TRUTHTABLE_START(cname, in, out, def_params) \
+ { \
+ netlist::tt_desc desc; \
+ desc.name = #cname ; \
+ desc.classname = #cname ; \
+ desc.ni = in; \
+ desc.no = out; \
+ desc.def_param = pstring("+") + def_params; \
+ desc.family = "";
+
+#define TT_HEAD(x) \
+ desc.desc.push_back(x);
+
+#define TT_LINE(x) \
+ desc.desc.push_back(x);
+
+#define TT_FAMILY(x) \
+ desc.family = x;
+
+#define TRUTHTABLE_END() \
+ netlist::devices::tt_factory_create(setup, desc); \
+ }
+
namespace netlist
{
- // Forward definition so we keep nl_factory.h out of the public
- class factory_list_t;
+ // -----------------------------------------------------------------------------
+ // truthtable desc
+ // -----------------------------------------------------------------------------
- class setup_t
+ struct tt_desc
+ {
+ pstring name;
+ pstring classname;
+ unsigned ni;
+ unsigned no;
+ pstring def_param;
+ plib::pstring_vector_t desc;
+ pstring family;
+ };
+
+ // -----------------------------------------------------------------------------
+ // param_ref_t
+ // -----------------------------------------------------------------------------
+
+ struct param_ref_t
+ {
+ param_ref_t(const pstring name, core_device_t &device, param_t &param)
+ : m_name(name)
+ , m_device(device)
+ , m_param(param)
+ { }
+ pstring m_name;
+ core_device_t &m_device;
+ param_t &m_param;
+ };
+
+ // ----------------------------------------------------------------------------------------
+ // A Generic netlist sources implementation
+ // ----------------------------------------------------------------------------------------
+
+ class source_t
{
- P_PREVENT_COPYING(setup_t)
public:
+ using list_t = std::vector<std::unique_ptr<source_t>>;
- // ----------------------------------------------------------------------------------------
- // A Generic netlist sources implementation
- // ----------------------------------------------------------------------------------------
+ source_t()
+ {}
- class source_t
- {
- public:
- using list_t = std::vector<std::shared_ptr<source_t>>;
+ virtual ~source_t() { }
+
+ virtual bool parse(setup_t &setup, const pstring &name) = 0;
+ private:
+ };
- source_t()
- {}
+ // ----------------------------------------------------------------------------------------
+ // setup_t
+ // ----------------------------------------------------------------------------------------
- virtual ~source_t() { }
- virtual bool parse(setup_t &setup, const pstring &name) = 0;
- private:
- };
+ class setup_t
+ {
+ P_PREVENT_COPYING(setup_t)
+ public:
using link_t = std::pair<pstring, pstring>;
@@ -118,7 +185,6 @@ namespace netlist
void register_term(core_terminal_t &obj);
- void register_dev(plib::owned_ptr<device_t> dev);
void register_dev(const pstring &classname, const pstring &name);
void register_lib_entry(const pstring &name);
@@ -160,10 +226,9 @@ namespace netlist
/* register a source */
- template <class C>
- void register_source(std::shared_ptr<C> src)
+ void register_source(std::unique_ptr<source_t> &&src)
{
- m_sources.push_back(std::static_pointer_cast<source_t>(src));
+ m_sources.push_back(std::move(src));
}
factory_list_t &factory() { return m_factory; }
@@ -179,11 +244,15 @@ namespace netlist
void model_parse(const pstring &model, model_map_t &map);
- plib::plog_base<NL_DEBUG> &log() { return netlist().log(); }
- const plib::plog_base<NL_DEBUG> &log() const { return netlist().log(); }
+ plib::plog_base<NL_DEBUG> &log();
+ const plib::plog_base<NL_DEBUG> &log() const;
std::vector<std::pair<pstring, base_factory_t *>> m_device_factory;
+ /* FIXME: truth table trampoline */
+
+ void tt_factory_create(tt_desc &desc);
+
protected:
private:
@@ -232,12 +301,12 @@ namespace netlist
// ----------------------------------------------------------------------------------------
- class source_string_t : public setup_t::source_t
+ class source_string_t : public source_t
{
public:
source_string_t(const pstring &source)
- : setup_t::source_t(), m_str(source)
+ : source_t(), m_str(source)
{
}
@@ -247,12 +316,12 @@ namespace netlist
pstring m_str;
};
- class source_file_t : public setup_t::source_t
+ class source_file_t : public source_t
{
public:
source_file_t(const pstring &filename)
- : setup_t::source_t(), m_filename(filename)
+ : source_t(), m_filename(filename)
{
}
@@ -262,11 +331,11 @@ namespace netlist
pstring m_filename;
};
- class source_mem_t : public setup_t::source_t
+ class source_mem_t : public source_t
{
public:
source_mem_t(const char *mem)
- : setup_t::source_t(), m_str(mem)
+ : source_t(), m_str(mem)
{
}
@@ -276,11 +345,11 @@ namespace netlist
pstring m_str;
};
- class source_proc_t : public setup_t::source_t
+ class source_proc_t : public source_t
{
public:
source_proc_t(pstring name, void (*setup_func)(setup_t &))
- : setup_t::source_t(),
+ : source_t(),
m_setup_func(setup_func),
m_setup_func_name(name)
{
diff --git a/src/lib/netlist/nl_time.h b/src/lib/netlist/nl_time.h
index 0a4caac1ac6..974ba4c669c 100644
--- a/src/lib/netlist/nl_time.h
+++ b/src/lib/netlist/nl_time.h
@@ -42,7 +42,7 @@ namespace netlist
constexpr explicit ptime(const double t) = delete;
//: m_time((internal_type) ( t * (double) resolution)) { }
- constexpr explicit ptime(const internal_type nom, const internal_type den)
+ constexpr explicit ptime(const internal_type nom, const internal_type den) NOEXCEPT
: m_time(nom * (resolution / den)) { }
ptime &operator=(const ptime rhs) { m_time = rhs.m_time; return *this; }
@@ -100,7 +100,7 @@ namespace netlist
friend bool operator!=(const ptime &lhs, const ptime &rhs)
{
- return lhs.m_time != rhs.m_time;
+ return !(lhs == rhs);
}
constexpr internal_type as_raw() const { return m_time; }
@@ -109,16 +109,16 @@ namespace netlist
// for save states ....
internal_type *get_internaltype_ptr() { return &m_time; }
- static inline constexpr ptime from_nsec(const internal_type ns) { return ptime(ns, UINT64_C(1000000000)); }
- static inline constexpr ptime from_usec(const internal_type us) { return ptime(us, UINT64_C(1000000)); }
- static inline constexpr ptime from_msec(const internal_type ms) { return ptime(ms, UINT64_C(1000)); }
- static inline constexpr ptime from_hz(const internal_type hz) { return ptime(1 , hz); }
- static inline constexpr ptime from_raw(const internal_type raw) { return ptime(raw, resolution); }
- static inline constexpr ptime from_double(const double t) { return ptime((internal_type) ( t * (double) resolution), resolution); }
+ static constexpr ptime from_nsec(const internal_type ns) { return ptime(ns, UINT64_C(1000000000)); }
+ static constexpr ptime from_usec(const internal_type us) { return ptime(us, UINT64_C(1000000)); }
+ static constexpr ptime from_msec(const internal_type ms) { return ptime(ms, UINT64_C(1000)); }
+ static constexpr ptime from_hz(const internal_type hz) { return ptime(1 , hz); }
+ static constexpr ptime from_raw(const internal_type raw) { return ptime(raw, resolution); }
+ static constexpr ptime from_double(const double t) { return ptime((internal_type) ( t * (double) resolution), resolution); }
- static inline constexpr ptime zero() { return ptime(0, resolution); }
- static inline constexpr ptime quantum() { return ptime(1, resolution); }
- static inline constexpr ptime never() { return ptime(plib::numeric_limits<internal_type>::max(), resolution); }
+ static constexpr ptime zero() { return ptime(0, resolution); }
+ static constexpr ptime quantum() { return ptime(1, resolution); }
+ static constexpr ptime never() { return ptime(plib::numeric_limits<internal_type>::max(), resolution); }
private:
internal_type m_time;
};
diff --git a/src/lib/netlist/plib/pchrono.cpp b/src/lib/netlist/plib/pchrono.cpp
new file mode 100644
index 00000000000..3beb3b2f161
--- /dev/null
+++ b/src/lib/netlist/plib/pchrono.cpp
@@ -0,0 +1,55 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+
+#include <chrono>
+
+#include "pchrono.h"
+
+namespace plib {
+namespace chrono {
+
+
+#if defined(__x86_64__) && !defined(_clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
+
+fast_ticks::type fast_ticks::per_second()
+{
+ static type persec = 0;
+ if (persec == 0)
+ {
+ type x = 0;
+ system_ticks::type t = system_ticks::start();
+ system_ticks::type e;
+ x = -start();
+ do {
+ e = system_ticks::stop();
+ } while (e - t < system_ticks::per_second() / 100 );
+ x += stop();
+ persec = (type)(double)((double) x * (double) system_ticks::per_second() / double (e - t));
+ }
+ return persec;
+}
+
+#if PUSE_ACCURATE_STATS && PHAS_RDTSCP
+exact_ticks::type exact_ticks::per_second()
+{
+ static type persec = 0;
+ if (persec == 0)
+ {
+ type x = 0;
+ system_ticks::type t = system_ticks::start();
+ system_ticks::type e;
+ x = -start();
+ do {
+ e = system_ticks::stop();
+ } while (e - t < system_ticks::per_second() / 100 );
+ x += stop();
+ persec = (type)(double)((double) x * (double) system_ticks::per_second() / double (e - t));
+ }
+ return persec;
+}
+#endif
+
+#endif
+
+}
+}
diff --git a/src/lib/netlist/plib/pchrono.h b/src/lib/netlist/plib/pchrono.h
new file mode 100644
index 00000000000..805842007f2
--- /dev/null
+++ b/src/lib/netlist/plib/pchrono.h
@@ -0,0 +1,213 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * pchrono.h
+ *
+ */
+
+#ifndef PCHRONO_H_
+#define PCHRONO_H_
+
+#include <cstdint>
+#include <thread>
+#include <chrono>
+
+#include "pconfig.h"
+
+namespace plib {
+namespace chrono {
+ template <typename T>
+ struct sys_ticks
+ {
+ typedef typename T::rep type;
+ static inline type start() { return T::now().time_since_epoch().count(); }
+ static inline type stop() { return T::now().time_since_epoch().count(); }
+ static inline constexpr type per_second() { return T::period::den / T::period::num; }
+ };
+
+ using hires_ticks = sys_ticks<std::chrono::high_resolution_clock>;
+ using steady_ticks = sys_ticks<std::chrono::steady_clock>;
+ using system_ticks = sys_ticks<std::chrono::system_clock>;
+
+ #if defined(__x86_64__) && !defined(_clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
+
+ #if PHAS_RDTSCP
+ struct fast_ticks
+ {
+ typedef int64_t type;
+ static inline type start()
+ {
+ int64_t v;
+ __asm__ __volatile__ (
+ "rdtscp;"
+ "shl $32, %%rdx;"
+ "or %%rdx, %%rax;"
+ : "=a"(v) /* outputs */
+ : /* inputs */
+ : "%rcx", "%rdx" /* clobbers */
+ );
+ return v;
+ }
+ static inline type stop()
+ {
+ return start();
+ }
+ static type per_second();
+ };
+
+ #else
+ struct fast_ticks
+ {
+ typedef int64_t type;
+ static inline type start()
+ {
+ int64_t v;
+ __asm__ __volatile__ (
+ "rdtsc;"
+ "shl $32, %%rdx;"
+ "or %%rdx, %%rax;"
+ : "=a"(v) /* outputs */
+ : /* inputs */
+ : "%rdx" /* clobbers */
+ );
+ return v;
+ }
+ static inline type stop()
+ {
+ return start();
+ }
+ static type per_second();
+ };
+
+ #endif
+
+
+ /* Based on "How to Benchmark Code Execution Times on Intel® IA-32 and IA-64
+ * Instruction Set Architectures", Intel, 2010
+ *
+ */
+ #if PUSE_ACCURATE_STATS && PHAS_RDTSCP
+ /*
+ * kills performance completely, but is accurate
+ * cpuid serializes, but clobbers ebx and ecx
+ *
+ */
+
+ struct exact_ticks
+ {
+ typedef int64_t type;
+
+ static inline type start()
+ {
+ int64_t v;
+ __asm__ __volatile__ (
+ "cpuid;"
+ //"xor %%eax, %%eax\n\t"
+ "rdtsc;"
+ "shl $32, %%rdx;"
+ "or %%rdx, %%rax;"
+ : "=a"(v) /* outputs */
+ : "a"(0x0) /* inputs */
+ : "%ebx", "%ecx", "%rdx" /* clobbers*/
+ );
+ return v;
+ }
+ static inline type stop()
+ {
+ int64_t v;
+ __asm__ __volatile__ (
+ "rdtscp;"
+ "shl $32, %%rdx;"
+ "or %%rax, %%rdx;"
+ "mov %%rdx, %%r10;"
+ "xor %%eax, %%eax\n\t"
+ "cpuid;"
+ "mov %%r10, %%rax;"
+ : "=a" (v)
+ :
+ : "%ebx", "%ecx", "%rdx", "%r10"
+ );
+ return v;
+ }
+
+ static type per_second();
+ };
+ #else
+ using exact_ticks = fast_ticks;
+ #endif
+
+
+ #else
+ using fast_ticks = hires_ticks;
+ using exact_ticks = fast_ticks;
+ #endif
+
+ template<bool enabled_>
+ struct counter
+ {
+ counter() : m_count(0) { }
+ typedef uint_least64_t type;
+ type operator()() const { return m_count; }
+ void inc() { ++m_count; }
+ void reset() { m_count = 0; }
+ constexpr static bool enabled = enabled_;
+ private:
+ type m_count;
+ };
+
+ template<>
+ struct counter<false>
+ {
+ typedef uint_least64_t type;
+ constexpr type operator()() const { return 0; }
+ void inc() const { }
+ void reset() const { }
+ constexpr static bool enabled = false;
+ };
+
+
+ template< typename T, bool enabled_ = true>
+ struct timer
+ {
+ typedef typename T::type type;
+ typedef uint_least64_t ctype;
+
+ timer() : m_time(0), m_count(0) { }
+
+ type operator()() const { return m_time; }
+
+ void start() { m_time -= T::start(); }
+ void stop() { m_time += T::stop(); ++m_count; }
+ void reset() { m_time = 0; m_count = 0; }
+ type average() const { return (m_count == 0) ? 0 : m_time / m_count; }
+ type total() const { return m_time; }
+ ctype count() const { return m_count; }
+
+ double as_seconds() const { return (double) total() / (double) T::per_second(); }
+
+ constexpr static bool enabled = enabled_;
+ private:
+ type m_time;
+ ctype m_count;
+ };
+
+ template<typename T>
+ struct timer<T, false>
+ {
+ typedef typename T::type type;
+ typedef uint_least64_t ctype;
+ constexpr type operator()() const { return 0; }
+ void start() const { }
+ void stop() const { }
+ void reset() const { }
+ constexpr type average() const { return 0; }
+ constexpr type total() const { return 0; }
+ constexpr ctype count() const { return 0; }
+ constexpr double as_seconds() const { return 0.0; }
+ constexpr static bool enabled = false;
+ };
+
+ } // namespace chrono
+} // namespace plib
+
+#endif /* PCHRONO_H_ */
diff --git a/src/lib/netlist/plib/pconfig.h b/src/lib/netlist/plib/pconfig.h
index 48a7e740a8f..5c1582cdec8 100644
--- a/src/lib/netlist/plib/pconfig.h
+++ b/src/lib/netlist/plib/pconfig.h
@@ -12,9 +12,22 @@
#include <thread>
#include <chrono>
-#ifndef PSTANDALONE
- #define PSTANDALONE (0)
-#endif
+/*
+ * Define this for more accurate measurements if you processor supports
+ * RDTSCP.
+ */
+#define PHAS_RDTSCP (1)
+
+/*
+ * Define this to use accurate timing measurements. Only works
+ * if PHAS_RDTSCP == 1
+ */
+#define PUSE_ACCURATE_STATS (1)
+
+/*
+ * Set this to one if you want to use 128 bit int for ptime.
+ * This is for tests only.
+ */
#define PHAS_INT128 (0)
@@ -75,30 +88,6 @@ typedef __int128_t INT128;
namespace plib {
-using ticks_t = int64_t;
-
-static inline ticks_t ticks()
-{
- return std::chrono::high_resolution_clock::now().time_since_epoch().count();
-}
-static inline ticks_t ticks_per_second()
-{
- return std::chrono::high_resolution_clock::period::den / std::chrono::high_resolution_clock::period::num;
-}
-
-#if defined(__x86_64__) && !defined(_clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
-
-static inline ticks_t profile_ticks()
-{
- unsigned hi, lo;
- __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));
- return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );
-}
-
-#else
-static inline ticks_t profile_ticks() { return ticks(); }
-#endif
-
/*
* The following class was derived from the MAME delegate.h code.
* It derives a pointer to a member function.
diff --git a/src/lib/netlist/plib/poptions.cpp b/src/lib/netlist/plib/poptions.cpp
new file mode 100644
index 00000000000..8b2db8cf19e
--- /dev/null
+++ b/src/lib/netlist/plib/poptions.cpp
@@ -0,0 +1,226 @@
+// license:GPL-2.0+
+// copyright-holders:Couriersud
+/*
+ * poptions.cpp
+ *
+ */
+
+#include "poptions.h"
+
+namespace plib {
+
+/***************************************************************************
+ Options
+***************************************************************************/
+
+ option::option()
+ : m_short(""), m_long(""), m_help(""), m_has_argument(false)
+ {}
+
+ option::option(options &parent, pstring ashort, pstring along, pstring help, bool has_argument)
+ : m_short(ashort), m_long(along), m_help(help), m_has_argument(has_argument)
+ {
+ parent.register_option(this);
+ }
+
+ option::~option()
+ {
+ }
+
+ int option_str::parse(pstring argument)
+ {
+ m_val = argument;
+ return 0;
+ }
+
+ int option_str_limit::parse(pstring argument)
+ {
+ if (plib::container::contains(m_limit, argument))
+ {
+ m_val = argument;
+ return 0;
+ }
+ else
+ return 1;
+ }
+
+ int option_bool::parse(ATTR_UNUSED pstring argument)
+ {
+ m_val = true;
+ return 0;
+ }
+
+ int option_double::parse(pstring argument)
+ {
+ bool err = false;
+ m_val = argument.as_double(&err);
+ return (err ? 1 : 0);
+ }
+
+ options::options()
+ {
+
+ }
+
+ options::options(option *o[])
+ {
+ int i=0;
+ while (o[i] != nullptr)
+ {
+ m_opts.push_back(o[i]);
+ i++;
+ }
+ }
+
+ options::~options()
+ {
+ m_opts.clear();
+ }
+
+ void options::register_option(option *opt)
+ {
+ m_opts.push_back(opt);
+ }
+
+ int options::parse(int argc, char *argv[])
+ {
+ m_app = argv[0];
+
+ for (int i=1; i<argc; )
+ {
+ pstring arg(argv[i]);
+ option *opt = nullptr;
+ pstring opt_arg;
+ bool has_equal_arg = false;
+
+ if (arg.startsWith("--"))
+ {
+ auto v = pstring_vector_t(arg.substr(2),"=");
+ opt = getopt_long(v[0]);
+ has_equal_arg = (v.size() > 1);
+ if (has_equal_arg) opt_arg = v[1];
+ }
+ else if (arg.startsWith("-"))
+ {
+ opt = getopt_short(arg.substr(1));
+ }
+ else
+ return i;
+ if (opt == nullptr)
+ return i;
+ if (opt->has_argument())
+ {
+ if (has_equal_arg)
+ {
+ if (opt->parse(opt_arg) != 0)
+ return i;
+ }
+ else
+ {
+ i++; // FIXME: are there more arguments?
+ if (opt->parse(argv[i]) != 0)
+ return i - 1;
+ }
+ }
+ else
+ {
+ if (has_equal_arg)
+ return i;
+ opt->parse("");
+ }
+ i++;
+ }
+ return argc;
+ }
+
+ pstring options::split_paragraphs(pstring text, unsigned width, unsigned ident,
+ unsigned firstline_ident)
+ {
+ auto paragraphs = pstring_vector_t(text,"\n");
+ pstring ret("");
+
+ for (auto &p : paragraphs)
+ {
+ pstring line = pstring("").rpad(" ", firstline_ident);
+ for (auto &s : pstring_vector_t(p, " "))
+ {
+ if (line.len() + s.len() > width)
+ {
+ ret += line + "\n";
+ line = pstring("").rpad(" ", ident);
+ }
+ line += s + " ";
+ }
+ ret += line + "\n";
+ }
+ return ret;
+ }
+
+ pstring options::help(pstring description, pstring usage,
+ unsigned width, unsigned ident)
+ {
+ pstring ret;
+
+ ret = split_paragraphs(description, width, 0, 0) + "\n";
+ ret += "Usage:\t" + usage + "\n\nOptions:\n";
+
+ for (auto & opt : m_opts )
+ {
+ pstring line = "";
+ if (opt->short_opt() != "")
+ line += " -" + opt->short_opt();
+ if (opt->long_opt() != "")
+ {
+ if (line != "")
+ line += ", ";
+ else
+ line = " ";
+ line += "--" + opt->long_opt();
+ if (opt->has_argument())
+ {
+ line += "=";
+ option_str_limit *ol = dynamic_cast<option_str_limit *>(opt);
+ if (ol)
+ {
+ for (auto &v : ol->limit())
+ {
+ line += v + "|";
+ }
+ line = line.left(line.len() - 1);
+ }
+ else
+ line += "Value";
+ }
+ }
+ line = line.rpad(" ", 20) + " ";
+ if (line.len() > 21)
+ {
+ ret += line + "\n";
+ ret += split_paragraphs(opt->help(), 72, 21, 21);
+ }
+ else
+ ret += split_paragraphs(line + opt->help(), 72, 21, 0);
+ }
+ return ret;
+ }
+
+ option *options::getopt_short(pstring arg)
+ {
+ for (auto & opt : m_opts)
+ {
+ if (opt->short_opt() == arg)
+ return opt;
+ }
+ return nullptr;
+ }
+ option *options::getopt_long(pstring arg)
+ {
+ for (auto & opt : m_opts)
+ {
+ if (opt->long_opt() == arg)
+ return opt;
+ }
+ return nullptr;
+ }
+
+} // namespace plib
diff --git a/src/lib/netlist/plib/poptions.h b/src/lib/netlist/plib/poptions.h
index 3ab1adb78c6..6ddac682d66 100644
--- a/src/lib/netlist/plib/poptions.h
+++ b/src/lib/netlist/plib/poptions.h
@@ -27,35 +27,34 @@ class options;
class option
{
public:
- option()
- : m_short(""), m_long(""), m_help(""), m_has_argument(false)
- {}
-
- option(pstring ashort, pstring along, pstring help, bool has_argument, options *parent = nullptr);
+ option();
+ option(options &parent, pstring ashort, pstring along, pstring help, bool has_argument);
- virtual ~option()
- {
- }
+ virtual ~option();
/* no_argument options will be called with "" argument */
- virtual int parse(ATTR_UNUSED pstring argument) { return 0; }
+ virtual int parse(ATTR_UNUSED pstring argument) = 0;
+ pstring short_opt() { return m_short; }
+ pstring long_opt() { return m_long; }
+ pstring help() { return m_help; }
+ bool has_argument() { return m_has_argument ; }
+private:
pstring m_short;
pstring m_long;
pstring m_help;
bool m_has_argument;
-private:
};
class option_str : public option
{
public:
- option_str(pstring ashort, pstring along, pstring defval, pstring help, options *parent = nullptr)
- : option(ashort, along, help, true, parent), m_val(defval)
+ option_str(options &parent, pstring ashort, pstring along, pstring defval, pstring help)
+ : option(parent, ashort, along, help, true), m_val(defval)
{}
- virtual int parse(pstring argument) override { m_val = argument; return 0; }
+ virtual int parse(pstring argument) override;
pstring operator ()() { return m_val; }
private:
@@ -65,22 +64,15 @@ private:
class option_str_limit : public option
{
public:
- option_str_limit(pstring ashort, pstring along, pstring defval, pstring limit, pstring help, options *parent = nullptr)
- : option(ashort, along, help, true, parent), m_val(defval), m_limit(limit, ":")
+ option_str_limit(options &parent, pstring ashort, pstring along, pstring defval, pstring limit, pstring help)
+ : option(parent, ashort, along, help, true), m_val(defval), m_limit(limit, ":")
{}
- virtual int parse(pstring argument) override
- {
- if (plib::container::contains(m_limit, argument))
- {
- m_val = argument;
- return 0;
- }
- else
- return 1;
- }
+ virtual int parse(pstring argument) override;
pstring operator ()() { return m_val; }
+ const plib::pstring_vector_t &limit() { return m_limit; }
+
private:
pstring m_val;
plib::pstring_vector_t m_limit;
@@ -89,11 +81,11 @@ private:
class option_bool : public option
{
public:
- option_bool(pstring ashort, pstring along, pstring help, options *parent = nullptr)
- : option(ashort, along, help, false, parent), m_val(false)
+ option_bool(options &parent, pstring ashort, pstring along, pstring help)
+ : option(parent, ashort, along, help, false), m_val(false)
{}
- virtual int parse(ATTR_UNUSED pstring argument) override { m_val = true; return 0; }
+ virtual int parse(ATTR_UNUSED pstring argument) override;
bool operator ()() { return m_val; }
private:
@@ -103,16 +95,11 @@ private:
class option_double : public option
{
public:
- option_double(pstring ashort, pstring along, double defval, pstring help, options *parent = nullptr)
- : option(ashort, along, help, true, parent), m_val(defval)
+ option_double(options &parent, pstring ashort, pstring along, double defval, pstring help)
+ : option(parent, ashort, along, help, true), m_val(defval)
{}
- virtual int parse(pstring argument) override
- {
- bool err = false;
- m_val = argument.as_double(&err);
- return (err ? 1 : 0);
- }
+ virtual int parse(pstring argument) override;
double operator ()() { return m_val; }
private:
@@ -123,117 +110,30 @@ class options
{
public:
- options() {}
-
- options(option *o[])
- {
- int i=0;
- while (o[i] != nullptr)
- {
- m_opts.push_back(o[i]);
- i++;
- }
- }
-
- ~options()
- {
- m_opts.clear();
- }
-
- void register_option(option *opt)
- {
- m_opts.push_back(opt);
- }
-
- int parse(int argc, char *argv[])
- {
- m_app = argv[0];
-
- for (int i=1; i<argc; )
- {
- pstring arg(argv[i]);
- option *opt = nullptr;
-
- if (arg.startsWith("--"))
- {
- opt = getopt_long(arg.substr(2));
- }
- else if (arg.startsWith("-"))
- {
- opt = getopt_short(arg.substr(1));
- }
- else
- return i;
- if (opt == nullptr)
- return i;
- if (opt->m_has_argument)
- {
- i++; // FIXME: are there more arguments?
- if (opt->parse(argv[i]) != 0)
- return i - 1;
- }
- else
- opt->parse("");
- i++;
- }
- return argc;
- }
-
- pstring help()
- {
- pstring ret;
-
- for (auto & opt : m_opts )
- {
- pstring line = "";
- if (opt->m_short != "")
- line += " -" + opt->m_short;
- if (opt->m_long != "")
- {
- if (line != "")
- line += ", ";
- else
- line = " ";
- line += "--" + opt->m_long;
- }
- line = line.rpad(" ", 20).cat(opt->m_help);
- ret = ret + line + "\n";
- }
- return ret;
- }
+ options();
+ options(option *o[]);
+
+ ~options();
+
+ void register_option(option *opt);
+ int parse(int argc, char *argv[]);
+
+ pstring help(pstring description, pstring usage,
+ unsigned width = 72, unsigned ident = 20);
+
pstring app() { return m_app; }
private:
+ static pstring split_paragraphs(pstring text, unsigned width, unsigned ident,
+ unsigned firstline_ident);
- option *getopt_short(pstring arg)
- {
- for (auto & opt : m_opts)
- {
- if (opt->m_short == arg)
- return opt;
- }
- return nullptr;
- }
- option *getopt_long(pstring arg)
- {
- for (auto & opt : m_opts)
- {
- if (opt->m_long == arg)
- return opt;
- }
- return nullptr;
- }
+ option *getopt_short(pstring arg);
+ option *getopt_long(pstring arg);
std::vector<option *> m_opts;
pstring m_app;
};
-option::option(pstring ashort, pstring along, pstring help, bool has_argument, options *parent)
-: m_short(ashort), m_long(along), m_help(help), m_has_argument(has_argument)
-{
- if (parent != nullptr)
- parent->register_option(this);
-}
}
diff --git a/src/lib/netlist/plib/pstring.cpp b/src/lib/netlist/plib/pstring.cpp
index f6dff95fb12..20573f5bfa5 100644
--- a/src/lib/netlist/plib/pstring.cpp
+++ b/src/lib/netlist/plib/pstring.cpp
@@ -258,7 +258,7 @@ const pstring_t<F> pstring_t<F>::rpad(const pstring_t &ws, const unsigned cnt) c
pstring_t ret(*this);
while (ret.len() < cnt)
ret += ws;
- return pstring_t(ret).substr(0, cnt);
+ return ret;
}
diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp
index 5687cd42078..8d753e212c6 100644
--- a/src/lib/netlist/prg/nltool.cpp
+++ b/src/lib/netlist/prg/nltool.cpp
@@ -26,16 +26,17 @@ class tool_options_t : public plib::options
public:
tool_options_t() :
plib::options(),
- opt_ttr ("t", "time_to_run", 1.0, "time to run the emulation (seconds)", this),
- opt_name("n", "name", "", "netlist in file to run; default is first one", this),
- opt_logs("l", "logs", "", "colon separated list of terminals to log", this),
- opt_file("f", "file", "-", "file to process (default is stdin)", this),
- opt_type("y", "type", "spice", "spice:eagle", "type of file to be converted: spice,eagle", this),
- opt_cmd ("c", "cmd", "run", "run|convert|listdevices|static", this),
- opt_inp( "i", "input", "", "input file to process (default is none)", this),
- opt_verb("v", "verbose", "be verbose - this produces lots of output", this),
- opt_quiet("q", "quiet", "be quiet - no warnings", this),
- opt_help("h", "help", "display help", this)
+ opt_ttr (*this, "t", "time_to_run", 1.0, "time to run the emulation (seconds)"),
+ opt_name(*this, "n", "name", "", "netlist in file to run; default is first one"),
+ opt_logs(*this, "l", "logs", "", "colon separated list of terminals to log"),
+ opt_file(*this, "f", "file", "-", "file to process (default is stdin)"),
+ opt_type(*this, "y", "type", "spice", "spice:eagle", "type of file to be converted: spice,eagle"),
+ opt_cmd (*this, "c", "cmd", "run", "run:convert:listdevices:static", "run|convert|listdevices|static"),
+ opt_inp(*this, "i", "input", "", "input file to process (default is none)"),
+ opt_verb(*this, "v", "verbose", "be verbose - this produces lots of output"),
+ opt_quiet(*this, "q", "quiet", "be quiet - no warnings"),
+ opt_version(*this, "", "version", "display version and exit"),
+ opt_help(*this, "h", "help", "display help and exit")
{}
plib::option_double opt_ttr;
@@ -43,10 +44,11 @@ public:
plib::option_str opt_logs;
plib::option_str opt_file;
plib::option_str_limit opt_type;
- plib::option_str opt_cmd;
+ plib::option_str_limit opt_cmd;
plib::option_str opt_inp;
plib::option_bool opt_verb;
plib::option_bool opt_quiet;
+ plib::option_bool opt_version;
plib::option_bool opt_help;
};
@@ -92,7 +94,8 @@ public:
{
// read the netlist ...
- m_setup->register_source(std::make_shared<netlist::source_file_t>(filename));
+ m_setup->register_source(plib::make_unique_base<netlist::source_t,
+ netlist::source_file_t>(filename));
m_setup->include(name);
log_setup();
@@ -133,14 +136,9 @@ private:
void usage(tool_options_t &opts)
{
- perr("{}",
- "Usage:\n"
- " nltool --help\n"
- " nltool [options]\n"
- "\n"
- "Where:\n"
- );
- perr("{}\n", opts.help().cstr());
+ pout("{}\n", opts.help(
+ "nltool serves as the Swiss Army knife to run, test and convert netlists.",
+ "nltool [options]").cstr());
}
struct input_t
@@ -207,7 +205,10 @@ std::vector<input_t> *read_input(netlist::netlist_t *netlist, pstring fname)
static void run(tool_options_t &opts)
{
netlist_tool_t nt("netlist");
- plib::ticks_t t = plib::ticks();
+ plib::chrono::timer<plib::chrono::system_ticks> t;
+ //plib::perftime_t<plib::exact_ticks> t;
+
+ t.start();
nt.m_opts = &opts;
nt.init();
@@ -222,10 +223,13 @@ static void run(tool_options_t &opts)
std::vector<input_t> *inps = read_input(&nt, opts.opt_inp());
double ttr = opts.opt_ttr();
+ t.stop();
- pout("startup time ==> {1:5.3f}\n", (double) (plib::ticks() - t) / (double) plib::ticks_per_second() );
+ pout("startup time ==> {1:5.3f}\n", t.as_seconds() );
pout("runnning ...\n");
- t = plib::ticks();
+
+ t.reset();
+ t.start();
unsigned pos = 0;
netlist::netlist_time nlt = netlist::netlist_time::zero();
@@ -241,7 +245,9 @@ static void run(tool_options_t &opts)
nt.stop();
plib::pfree(inps);
- double emutime = (double) (plib::ticks() - t) / (double) plib::ticks_per_second();
+ t.stop();
+
+ double emutime = t.as_seconds();
pout("{1:f} seconds emulation took {2:f} real time ==> {3:5.2f}%\n", ttr, emutime, ttr/emutime*100.0);
}
@@ -273,7 +279,8 @@ static void listdevices()
nt.init();
netlist::factory_list_t &list = nt.setup().factory();
- nt.setup().register_source(std::make_shared<netlist::source_proc_t>("dummy", &netlist_dummy));
+ nt.setup().register_source(plib::make_unique_base<netlist::source_t,
+ netlist::source_proc_t>("dummy", &netlist_dummy));
nt.setup().include("dummy");
nt.setup().start_devices();
@@ -351,7 +358,7 @@ int main(int argc, char *argv[])
tool_options_t opts;
int ret;
- perr("{}", "WARNING: This is Work In Progress! - It may fail anytime\n");
+ //perr("{}", "WARNING: This is Work In Progress! - It may fail anytime\n");
//perr("Update dispatching using method {}\n", pmf_verbose[NL_PMF_TYPE]);
if ((ret = opts.parse(argc, argv)) != argc)
{
@@ -363,7 +370,19 @@ int main(int argc, char *argv[])
if (opts.opt_help())
{
usage(opts);
- return 1;
+ return 0;
+ }
+
+ if (opts.opt_version())
+ {
+ pout(
+ "nltool (netlist) 0.1\n"
+ "Copyright (C) 2016 Couriersud\n"
+ "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>.\n"
+ "This is free software: you are free to change and redistribute it.\n"
+ "There is NO WARRANTY, to the extent permitted by law.\n\n"
+ "Written by Couriersud.\n");
+ return 0;
}
pstring cmd = opts.opt_cmd();
diff --git a/src/lib/netlist/prg/nlwav.cpp b/src/lib/netlist/prg/nlwav.cpp
index d822b78d231..0f560cbe62d 100644
--- a/src/lib/netlist/prg/nlwav.cpp
+++ b/src/lib/netlist/prg/nlwav.cpp
@@ -13,21 +13,29 @@ class nlwav_options_t : public plib::options
public:
nlwav_options_t() :
plib::options(),
- opt_inp( "i", "input", "", "input file", this),
- opt_out( "o", "output", "", "output file", this),
- opt_amp( "a", "amp", 10000.0, "amplification after mean correction", this),
- opt_verb("v", "verbose", "be verbose - this produces lots of output", this),
- opt_quiet("q", "quiet", "be quiet - no warnings", this),
- opt_help("h", "help", "display help", this)
+ opt_inp(*this, "i", "input", "", "input file"),
+ opt_out(*this, "o", "output", "", "output file"),
+ opt_amp(*this, "a", "amp", 10000.0, "amplification after mean correction"),
+ opt_verb(*this, "v", "verbose", "be verbose - this produces lots of output"),
+ opt_quiet(*this,"q", "quiet", "be quiet - no warnings"),
+ opt_version(*this, "", "version", "display version and exit"),
+ opt_help(*this, "h", "help", "display help and exit")
{}
plib::option_str opt_inp;
plib::option_str opt_out;
plib::option_double opt_amp;
plib::option_bool opt_verb;
plib::option_bool opt_quiet;
+ plib::option_bool opt_version;
plib::option_bool opt_help;
};
+plib::pstdout pout_strm;
+plib::pstderr perr_strm;
+
+plib::pstream_fmt_writer_t pout(pout_strm);
+plib::pstream_fmt_writer_t perr(perr_strm);
+
/* http://de.wikipedia.org/wiki/RIFF_WAVE */
class wav_t
{
@@ -196,26 +204,20 @@ void convert(nlwav_options_t &opts)
//printf("%f %f\n", t, v);
#endif
}
- printf("Mean (low freq filter): %f\n", mean);
- printf("Mean (static): %f\n", means / (double) n);
- printf("Amp + %f\n", 32000.0 / (maxsam- mean));
- printf("Amp - %f\n", -32000.0 / (minsam- mean));
+ pout("Mean (low freq filter): {}\n", mean);
+ pout("Mean (static): {}\n", means / (double) n);
+ pout("Amp + {}\n", 32000.0 / (maxsam- mean));
+ pout("Amp - {}\n", -32000.0 / (minsam- mean));
wo.close();
fo.close();
fin.close();
}
-void usage(nlwav_options_t &opts)
+void usage(plib::pstream_fmt_writer_t &fw, nlwav_options_t &opts)
{
- fprintf(stderr,
- "Usage:\n"
- " nltool -help\n"
- " nltool [options]\n"
- "\n"
- "Where:\n"
- );
- fprintf(stderr, "%s\n", opts.help().cstr());
+ fw("{}\n", opts.help("Convert netlist log files into wav files.\n",
+ "nltool [options]").cstr());
}
@@ -226,15 +228,27 @@ int main(int argc, char *argv[])
if ((ret = opts.parse(argc, argv)) != argc)
{
- fprintf(stderr, "Error parsing %s\n", argv[ret]);
- usage(opts);
+ perr("Error parsing {}\n", argv[ret]);
+ usage(perr, opts);
return 1;
}
if (opts.opt_help())
{
- usage(opts);
- return 1;
+ usage(pout, opts);
+ return 0;
+ }
+
+ if (opts.opt_version())
+ {
+ pout(
+ "nlwav (netlist) 0.1\n"
+ "Copyright (C) 2016 Couriersud\n"
+ "License GPLv2+: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>.\n"
+ "This is free software: you are free to change and redistribute it.\n"
+ "There is NO WARRANTY, to the extent permitted by law.\n\n"
+ "Written by Couriersud.\n");
+ return 0;
}
convert(opts);
diff --git a/src/lib/netlist/tools/nl_convert.cpp b/src/lib/netlist/tools/nl_convert.cpp
index 545377cc494..d8a7401018e 100644
--- a/src/lib/netlist/tools/nl_convert.cpp
+++ b/src/lib/netlist/tools/nl_convert.cpp
@@ -18,7 +18,7 @@
void nl_convert_base_t::add_pin_alias(const pstring &devname, const pstring &name, const pstring &alias)
{
pstring pname = devname + "." + name;
- m_pins.insert({pname, plib::make_unique<pin_alias_t>(pname, devname + "." + alias)});
+ m_pins.emplace(pname, plib::make_unique<pin_alias_t>(pname, devname + "." + alias));
}
void nl_convert_base_t::add_ext_alias(const pstring &alias)
@@ -26,7 +26,7 @@ void nl_convert_base_t::add_ext_alias(const pstring &alias)
m_ext_alias.push_back(alias);
}
-void nl_convert_base_t::add_device(std::shared_ptr<dev_t> dev)
+void nl_convert_base_t::add_device(std::unique_ptr<dev_t> dev)
{
for (auto & d : m_devs)
if (d->name() == dev->name())
@@ -34,20 +34,20 @@ void nl_convert_base_t::add_device(std::shared_ptr<dev_t> dev)
out("ERROR: Duplicate device {1} ignored.", dev->name());
return;
}
- m_devs.push_back(dev);
+ m_devs.push_back(std::move(dev));
}
void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname, const pstring &amodel)
{
- add_device(std::make_shared<dev_t>(atype, aname, amodel));
+ add_device(plib::make_unique<dev_t>(atype, aname, amodel));
}
void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname, double aval)
{
- add_device(std::make_shared<dev_t>(atype, aname, aval));
+ add_device(plib::make_unique<dev_t>(atype, aname, aval));
}
void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname)
{
- add_device(std::make_shared<dev_t>(atype, aname));
+ add_device(plib::make_unique<dev_t>(atype, aname));
}
void nl_convert_base_t::add_term(pstring netname, pstring termname)
@@ -58,9 +58,9 @@ void nl_convert_base_t::add_term(pstring netname, pstring termname)
net = m_nets[netname].get();
else
{
- auto nets = std::make_shared<net_t>(netname);
+ auto nets = plib::make_unique<net_t>(netname);
net = nets.get();
- m_nets.insert({netname, nets});
+ m_nets.emplace(netname, std::move(nets));
}
/* if there is a pin alias, translate ... */
@@ -84,10 +84,11 @@ void nl_convert_base_t::dump_nl()
net->set_no_export();
}
- std::vector<int> sorted;
- for (unsigned i=0; i < m_devs.size(); i++)
+ std::vector<size_t> sorted;
+ for (size_t i=0; i < m_devs.size(); i++)
sorted.push_back(i);
- std::sort(sorted.begin(), sorted.end(), plib::indexed_compare<std::vector<std::shared_ptr<dev_t>>>(m_devs));
+ std::sort(sorted.begin(), sorted.end(),
+ [&](size_t i1, size_t i2) { return m_devs[i1]->name() < m_devs[i2]->name(); });
for (std::size_t i=0; i<m_devs.size(); i++)
{
diff --git a/src/lib/netlist/tools/nl_convert.h b/src/lib/netlist/tools/nl_convert.h
index a2e0dc99ecb..90bae5533eb 100644
--- a/src/lib/netlist/tools/nl_convert.h
+++ b/src/lib/netlist/tools/nl_convert.h
@@ -126,14 +126,14 @@ private:
private:
- void add_device(std::shared_ptr<dev_t> dev);
+ void add_device(std::unique_ptr<dev_t> dev);
plib::postringstream m_buf;
- std::vector<std::shared_ptr<dev_t>> m_devs;
- std::unordered_map<pstring, std::shared_ptr<net_t> > m_nets;
+ std::vector<std::unique_ptr<dev_t>> m_devs;
+ std::unordered_map<pstring, std::unique_ptr<net_t> > m_nets;
std::vector<pstring> m_ext_alias;
- std::unordered_map<pstring, std::shared_ptr<pin_alias_t>> m_pins;
+ std::unordered_map<pstring, std::unique_ptr<pin_alias_t>> m_pins;
static unit_t m_units[];
diff --git a/src/mame/drivers/galpani3.cpp b/src/mame/drivers/galpani3.cpp
index 89d8e0dedbf..17e8f2d0b87 100644
--- a/src/mame/drivers/galpani3.cpp
+++ b/src/mame/drivers/galpani3.cpp
@@ -582,9 +582,8 @@ ROM_START( galpani3hk )
ROM_LOAD( "gp340100.122", 0x200000, 0x200000, CRC(746fe4a8) SHA1(a5126ae9e83d556277d31b166296a708c311a902) ) // 19950414GROMBCap
ROM_LOAD( "gp340200.121", 0x400000, 0x200000, CRC(e9bc15c8) SHA1(2c6a10e768709d1937d9206970553f4101ce9016) ) // 19950414GROMCCap
ROM_LOAD( "gp340300.120", 0x600000, 0x200000, CRC(59062eef) SHA1(936977c20d83540c1e0f65d429c7ebea201ef991) ) // 19950414GROMDCap
- // I'm guessing these are the same as the Korea set, because the regular ones don't give correct gfx, but it should be checked
- ROM_LOAD16_BYTE( "g3g0k0.101", 0xe00000, 0x080000, CRC(23d895b0) SHA1(621cc1500e26c3fe4410eefadd325891e7806f85) ) // 19950523GROMECap
- ROM_LOAD16_BYTE( "g3g1k0.100", 0xe00001, 0x080000, CRC(9b1eac6d) SHA1(1393d42a7ad70af90fa0f48fb8da7e2f9085f98f) ) //
+ ROM_LOAD16_BYTE( "g3g0h0.101", 0xe00000, 0x040000, CRC(dca3109a) SHA1(d7741e992ffc9f8f57ce6770bf4bcb8d0858d72b) ) // 19950523GROMECap
+ ROM_LOAD16_BYTE( "g3g1h0.100", 0xe00001, 0x040000, CRC(2ebe6ed0) SHA1(72d487c7f6339d7a39b04e95e76d0c4f3e432240) ) //
ROM_REGION( 0x300000, "ymz", 0 ) /* Samples */
ROM_LOAD( "gp310100.40", 0x000000, 0x200000, CRC(6a0b1d12) SHA1(11fed80b96d07fddb27599743991c58c12c048e0) )
diff --git a/src/mame/drivers/goldnpkr.cpp b/src/mame/drivers/goldnpkr.cpp
index 1e8a2cb9086..860b7dd0a55 100644
--- a/src/mame/drivers/goldnpkr.cpp
+++ b/src/mame/drivers/goldnpkr.cpp
@@ -23,7 +23,7 @@
* Jack Potten's Poker (set 6), 198?, Bootleg.
* Jack Potten's Poker (set 7, Royale GFX), 198?, Bootleg.
* Jack Potten's Poker (set 8, Australian), 198?, Bootleg.
- * Good Luck, 198?, Unknown.
+ * Jack Potten's Poker (set 9, 'just 4 fun'), 198?, Bootleg.
* Jack Potten's Poker (NGold, set 1), 198?, Unknown.
* Jack Potten's Poker (NGold, set 2), 198?, Unknown.
* Jack Potten's Poker (NGold, set 3), 198?, Unknown.
@@ -49,6 +49,8 @@
* Buena Suerte (Spanish, set 20), 1991, Unknown.
* Buena Suerte (Spanish, set 21), 1991, Unknown.
* Buena Suerte (Spanish, set 22), 1991, Unknown.
+ * Buena Suerte (Spanish/Portuguese, set 23), 1991, Unknown.
+ * Good Luck, 198?, Unknown.
* Falcons Wild - World Wide Poker, 1983, Falcon.
* Falcons Wild - World Wide Poker (VK set 1), 1990, Video Klein.
* Falcons Wild - World Wide Poker (VK set 2), 1990, Video Klein.
@@ -96,7 +98,6 @@
* Witch Up & Down (Export, 6T/12T ver 1.02), 1998, Video Klein.
* Witch Strike (Export, 6T/12T ver 1.01A), 1992, Video Klein.
* Witch Strike (Export, 6T/12T ver 1.01B), 1992, Video Klein.
- * Witch Jackpot (Export, 6T/12T ver 0.25), 1992-1996, Video Klein.
* Witch Jack (Export, 6T/12T ver 0.40), 1992-1996, Video Klein.
* Witch Jack (Export, 6T/12T ver 0.40T), 1992-1996, Video Klein.
* Witch Jack (Export, 6T/12T ver 0.62), 1992-1996, Video Klein.
@@ -107,11 +108,12 @@
* Witch Jack (Export, 6T/12T ver 0.87), 1992-1996, Video Klein.
* Witch Jack (Export, 6T/12T ver 0.87-88), 1992-1996, Video Klein.
* Witch Jack (Export, 6T/12T ver 0.87-89), 1992-1996, Video Klein.
+ * Witch Jackpot (Export, 6T/12T ver 0.25), 1992-1996, Video Klein.
* PlayMan Poker (German), 1981, PM / Beck Elektronik.
- * Super Loco 93 (Spanish, set 1), 1993, Unknown.
- * Super Loco 93 (Spanish, set 2), 1993, Unknown.
* Royale (set 1), 198?, Unknown.
* Royale (set 2), 198?, Unknown.
+ * Super Loco 93 (Spanish, set 1), 1993, Unknown.
+ * Super Loco 93 (Spanish, set 2), 1993, Unknown.
* Maverik, 198?, Unknown.
* Brasil 86, 1986, Unknown.
* Brasil 87, 1987, Unknown.
@@ -131,6 +133,8 @@
* Bonne Chance! (Golden Poker prequel HW, set 2), 198?, Unknown.
* Mundial/Mondial (Italian/French), 1987, Unknown.
* Super 98 (3-hands, ICP-1), 199?, Unknown.
+ * unknown animal-themed game (bottom), 199?, Unknown.
+ * unknown animal-themed game (top), 199?, Unknown.
************************************************************************************
@@ -3749,6 +3753,72 @@ static INPUT_PORTS_START( geniea )
INPUT_PORTS_END
+static INPUT_PORTS_START( bsuertev )
+ /* Multiplexed - 4x5bits */
+ PORT_INCLUDE( bsuerte )
+
+ PORT_MODIFY("IN0-0")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_IMPULSE(3) PORT_NAME("Coin In") // Key '5'
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Attendant Key") PORT_CODE(KEYCODE_0)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_GAMBLE_D_UP ) // Key '3'
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_DEAL ) PORT_NAME("Deal / Settings") // Key '2'
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_POKER_CANCEL ) // Key 'N'
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+
+ PORT_MODIFY("IN0-1")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Unknown IN0-1 0x01") PORT_CODE(KEYCODE_K)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_NAME("Payout") PORT_CODE(KEYCODE_W)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_GAMBLE_TAKE ) // Key '4'
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_HIGH ) PORT_NAME("Big / Black") // Key 'A'
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_GAMBLE_LOW ) PORT_NAME("Small / Red") // Key 'S'
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+
+ PORT_MODIFY("IN0-2")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_POKER_HOLD1 ) // Key 'Z'
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_POKER_HOLD2 ) // Key 'X'
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_POKER_HOLD3 ) // Key 'C'
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_POKER_HOLD4 ) // Key 'V'
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_POKER_HOLD5 ) // Key 'B'
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+
+ PORT_MODIFY("IN0-3")
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SERVICE ) PORT_NAME("Supervisor Key") PORT_CODE(KEYCODE_9)
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Unknown IN0-3 0x02") PORT_CODE(KEYCODE_J)
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_COIN2 ) PORT_IMPULSE(3) PORT_NAME("Note In") // Key '6'
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_GAMBLE_BET ) // Key 'M'
+ PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_OTHER ) PORT_NAME("Unknown IN0-3 0x10") PORT_CODE(KEYCODE_L)
+ PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
+
+ PORT_MODIFY("SW1")
+ /* only bits 4-7 are connected here and were routed to SW1 1-4 */
+ PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNUSED )
+ PORT_DIPNAME( 0x10, 0x10, "Par Simple" ) PORT_DIPLOCATION("SW1:1")
+ PORT_DIPSETTING( 0x10, DEF_STR( No ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( Yes ) )
+ PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SW1:2")
+ PORT_DIPSETTING( 0x20, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SW1:3")
+ PORT_DIPSETTING( 0x40, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+ PORT_DIPNAME( 0x80, 0x80, DEF_STR( Unknown ) ) PORT_DIPLOCATION("SW1:4")
+ PORT_DIPSETTING( 0x80, DEF_STR( Off ) )
+ PORT_DIPSETTING( 0x00, DEF_STR( On ) )
+INPUT_PORTS_END
+
+
+
/*********************************************
* Graphics Layouts *
*********************************************/
@@ -5120,6 +5190,51 @@ ROM_START( bsuerteu )
ROM_LOAD( "82s129.9c", 0x0000, 0x0100, CRC(7f31066b) SHA1(15420780ec6b2870fc4539ec3afe4f0c58eedf12) ) /* PROM dump needed */
ROM_END
+/*
+ Buena Suerte.
+
+ Brazilian copy of Protel HW, but with inferior quality.
+
+ Golden Poker derivative, with blue killer circuitry.
+ Suitable for "Good Luck" and "Buena Suerte" games.
+ Addressing, ROM banks, and edge connector close to Magic Fly.
+
+ Discrete sound need to be traced...
+
+ 30x2-pins Edge connector + 10-pin connector.
+ (see Protel set for pinouts)
+
+ Software is a hack that mix spanish and portuguese words.
+ Suitable for southern Brazil, or north of Argentina.
+
+ DIP switches are just replaced with fixed bridges.
+ Minimal hand is set in Double Pair.
+
+ GFX ROMs are identical to the Protel set.
+
+*/
+ROM_START( bsuertev )
+ ROM_REGION( 0x10000, "maincpu", 0 ) // Brazilian copy of Protel PCB.
+ ROM_LOAD( "main.16a", 0x4000, 0x4000, CRC(d56849ce) SHA1(2bba9821e53679b024d74ac1e023bf6bc6750c29) )
+
+ ROM_REGION( 0x6000, "gfx", 0 )
+ ROM_LOAD( "1.4a", 0x0000, 0x2000, CRC(943d200b) SHA1(e0c9d626be8e075e2087efc020c710aed3ca7511) ) // 4th quarter has the cards bitplane.
+ ROM_LOAD( "2.6a", 0x2000, 0x2000, CRC(e0c7fb67) SHA1(26b6dc9615121b86160352bb969e9fb0f5ed3618) ) // 4th quarter has the cards bitplane.
+ ROM_LOAD( "3.7a", 0x4000, 0x2000, CRC(2b888258) SHA1(e16587119f548298a5d23d0cb9250badc0321b93) ) // 3rd quarter has the cards bitplane, 4th quarter has the charset.
+
+ ROM_REGION( 0x1800, "gfx1", 0 )
+ ROM_FILL( 0x0000, 0x1000, 0x0000 ) // filling the R-G bitplanes.
+ ROM_COPY( "gfx", 0x5800, 0x1000, 0x0800 ) // chars.
+
+ ROM_REGION( 0x1800, "gfx2", 0 )
+ ROM_COPY( "gfx", 0x1800, 0x0000, 0x0800 ) // cards deck gfx, bitplane 1.
+ ROM_COPY( "gfx", 0x3800, 0x0800, 0x0800 ) // cards deck gfx, bitplane 2.
+ ROM_COPY( "gfx", 0x5000, 0x1000, 0x0800 ) // cards deck gfx, bitplane 3.
+
+ ROM_REGION( 0x0100, "proms", 0 )
+ ROM_LOAD( "n82s129an.9c", 0x0000, 0x0100, CRC(7f31066b) SHA1(15420780ec6b2870fc4539ec3afe4f0c58eedf12) ) // PROM dump verified.
+ROM_END
+
/**************************************** VIDEO KLEIN SETS ****************************************/
@@ -10766,6 +10881,7 @@ GAMEL( 1991, bsuerter, bsuerte, witchcrd, bsuerte, driver_device, 0,
GAMEL( 1991, bsuertes, bsuerte, witchcrd, bsuerte, driver_device, 0, ROT0, "<unknown>", "Buena Suerte (Spanish, set 20)", 0, layout_goldnpkr )
GAMEL( 1991, bsuertet, bsuerte, witchcrd, bsuerte, driver_device, 0, ROT0, "<unknown>", "Buena Suerte (Spanish, set 21)", 0, layout_goldnpkr )
GAMEL( 1991, bsuerteu, bsuerte, witchcrd, bsuerte, driver_device, 0, ROT0, "<unknown>", "Buena Suerte (Spanish, set 22)", 0, layout_goldnpkr )
+GAMEL( 1991, bsuertev, bsuerte, witchcrd, bsuertev, driver_device, 0, ROT0, "<unknown>", "Buena Suerte (Spanish/Portuguese, set 23)", 0, layout_goldnpkr )
GAMEL( 1991, goodluck, bsuerte, witchcrd, goodluck, driver_device, 0, ROT0, "<unknown>", "Good Luck", 0, layout_goldnpkr )
GAMEL( 1991, falcnwld, 0, wildcard, wildcard, driver_device, 0, ROT0, "TVG", "Falcons Wild - Wild Card 1991 (TVG)", 0, layout_goldnpkr )
diff --git a/src/mame/drivers/tomcat.cpp b/src/mame/drivers/tomcat.cpp
index 48b2769c333..fec676031c2 100644
--- a/src/mame/drivers/tomcat.cpp
+++ b/src/mame/drivers/tomcat.cpp
@@ -315,7 +315,7 @@ static ADDRESS_MAP_START( tomcat_map, AS_PROGRAM, 16, tomcat_state )
ADDRESS_MAP_END
static ADDRESS_MAP_START( dsp_map, AS_PROGRAM, 16, tomcat_state )
- AM_RANGE(0x0000, 0x1fff) AM_RAM AM_SHARE("shared_ram")
+ AM_RANGE(0x0000, 0x0fff) AM_RAM AM_SHARE("shared_ram")
ADDRESS_MAP_END
static ADDRESS_MAP_START( dsp_io_map, AS_IO, 16, tomcat_state )
diff --git a/src/mame/machine/nl_breakout.cpp b/src/mame/machine/nl_breakout.cpp
index 1cfd879c91a..5920e8cf1a2 100644
--- a/src/mame/machine/nl_breakout.cpp
+++ b/src/mame/machine/nl_breakout.cpp
@@ -275,6 +275,7 @@ CIRCUIT_LAYOUT( breakout )
CHIP("H5", 9312)
CHIP("H6", 9310)
CHIP("H7", 7408) //sometimes looks like N7 on schematic
+ //PARAM(H7.USE_DEACTIVATE, 0)
CHIP("H8", 7474)
CHIP("H9", 7474)
@@ -1700,6 +1701,36 @@ CIRCUIT_LAYOUT( breakout )
NET_C(GND, D9.1, D9.2, D9.13, D9.3, D9.4, D9.5)
+ HINT(A3.1.sub, NO_DEACTIVATE)
+ HINT(B6.s3, NO_DEACTIVATE)
+ HINT(C4.s3, NO_DEACTIVATE)
+ HINT(C4.s4, NO_DEACTIVATE)
+ HINT(C5.s3, NO_DEACTIVATE)
+ HINT(C5.s4, NO_DEACTIVATE)
+ HINT(D3.2.sub, NO_DEACTIVATE)
+ HINT(E2.s2, NO_DEACTIVATE)
+ HINT(E3.s2, NO_DEACTIVATE)
+ HINT(E5.s4, NO_DEACTIVATE)
+ HINT(E8.2.sub, NO_DEACTIVATE)
+ HINT(E9.s6, NO_DEACTIVATE)
+ HINT(F5.2.sub, NO_DEACTIVATE)
+ HINT(H2.s1, NO_DEACTIVATE)
+ HINT(H3.s1, NO_DEACTIVATE)
+ HINT(H6.sub, NO_DEACTIVATE)
+ HINT(J3.s4, NO_DEACTIVATE)
+ HINT(J5, NO_DEACTIVATE)
+ HINT(J6.sub, NO_DEACTIVATE)
+ HINT(J8.1, NO_DEACTIVATE)
+ HINT(J8.3, NO_DEACTIVATE)
+ HINT(K4.s4, NO_DEACTIVATE)
+ HINT(M3.s2, NO_DEACTIVATE)
+ HINT(M3.s4, NO_DEACTIVATE)
+ HINT(M4.s2, NO_DEACTIVATE)
+ HINT(M6.sub, NO_DEACTIVATE)
+ HINT(M8.s1, NO_DEACTIVATE)
+ HINT(N6.sub, NO_DEACTIVATE)
+ HINT(N7.s3, NO_DEACTIVATE)
+
CIRCUIT_LAYOUT_END
/*
diff --git a/src/mame/machine/nl_pong.cpp b/src/mame/machine/nl_pong.cpp
index 456448ab067..d03ae825d78 100644
--- a/src/mame/machine/nl_pong.cpp
+++ b/src/mame/machine/nl_pong.cpp
@@ -27,7 +27,6 @@ NETLIST_START(pong_fast)
TTL_INPUT(high, 1)
TTL_INPUT(low, 0)
-#if 1
#if (FAST_CLOCK)
/* abstracting this, performance increases by 60%
* No surprise, the clock is extremely expensive */
@@ -38,12 +37,6 @@ NETLIST_START(pong_fast)
TTL_74107(ic_f6a, xclk, high, high, high)
ALIAS(clk, ic_f6a.Q)
#endif
-#else
- // benchmarking ...
- NETDEV_TTL_CONST(clk, 0)
- MAINCLOCK(xclk)
- PARAM(xclk.FREQ, 7159000.0*2)
-#endif
/* 3V Logic - Just a resistor - the value is not given in schematics */
@@ -577,5 +570,41 @@ NETLIST_START(pong_fast)
NET_C(RV2.2, RV3.2)
ALIAS(videomix, RV3.2)
+#if 1
+ HINT(clk, NO_DEACTIVATE)
+ HINT(ic_e1d, NO_DEACTIVATE)
+ HINT(ic_e1c, NO_DEACTIVATE)
+ HINT(ic_f1.A, NO_DEACTIVATE)
+ HINT(ic_f1.D, NO_DEACTIVATE)
+ HINT(ic_g1d, NO_DEACTIVATE)
+ HINT(ic_h1a, NO_DEACTIVATE)
+ HINT(ic_h1d, NO_DEACTIVATE)
+ HINT(ic_h3b.sub, NO_DEACTIVATE)
+ HINT(ic_g6b.sub, NO_DEACTIVATE)
+ HINT(ic_c2a.sub, NO_DEACTIVATE)
+ HINT(hit_sound, NO_DEACTIVATE)
+ HINT(topbothitsound, NO_DEACTIVATE)
+ HINT(ic_c9b, NO_DEACTIVATE)
+ HINT(ic_b8.D, NO_DEACTIVATE)
+ HINT(ic_b7a, NO_DEACTIVATE)
+ HINT(ic_a7b, NO_DEACTIVATE)
+ HINT(ic_c9a, NO_DEACTIVATE)
+ HINT(ic_a8.D, NO_DEACTIVATE)
+ HINT(ic_b7d, NO_DEACTIVATE)
+ HINT(ic_a7a, NO_DEACTIVATE)
+ HINT(ic_g1a, NO_DEACTIVATE)
+ HINT(ic_c8a.sub, NO_DEACTIVATE)
+ HINT(ic_c8b.sub, NO_DEACTIVATE)
+ HINT(ic_d8b, NO_DEACTIVATE)
+ HINT(ic_d6a.sub, NO_DEACTIVATE)
+ HINT(ic_d6b.sub, NO_DEACTIVATE)
+ HINT(ic_c6a.sub, NO_DEACTIVATE)
+ HINT(ic_c6b.sub, NO_DEACTIVATE)
+ HINT(ic_e5b, NO_DEACTIVATE)
+ HINT(ic_e4c, NO_DEACTIVATE)
+ HINT(ic_d4b, NO_DEACTIVATE)
+ HINT(ic_g1b, NO_DEACTIVATE)
+#endif
+
NETLIST_END()
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index c97e81588fc..09a5f35c2fb 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -13322,6 +13322,7 @@ bsuerter // 1991, Unknown
bsuertes // 1991, Unknown
bsuertet // 1991, Unknown
bsuerteu // 1991, Unknown
+bsuertev // 1991, Unknown
caspoker // 1987, PM / Beck Elektronik.
falcnwld // 1991, TVG
falcnwlda // (c) 1990, Video Klein
diff --git a/src/mame/video/abc1600.cpp b/src/mame/video/abc1600.cpp
index 4b928d76635..2c947d5772a 100644
--- a/src/mame/video/abc1600.cpp
+++ b/src/mame/video/abc1600.cpp
@@ -80,7 +80,7 @@ ADDRESS_MAP_END
static ADDRESS_MAP_START( mover_map, AS_0, 16, abc1600_mover_device )
- AM_RANGE(0x00000, 0x7ffff) AM_RAM
+ AM_RANGE(0x00000, 0x3ffff) AM_RAM
ADDRESS_MAP_END