diff options
Diffstat (limited to 'src')
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 ¶m) - : 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 ¶m) + : 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 |