diff options
Diffstat (limited to 'src/devices/cpu/sparc/mb86901.cpp')
-rw-r--r-- | src/devices/cpu/sparc/mb86901.cpp | 4195 |
1 files changed, 0 insertions, 4195 deletions
diff --git a/src/devices/cpu/sparc/mb86901.cpp b/src/devices/cpu/sparc/mb86901.cpp deleted file mode 100644 index 809df3db8f3..00000000000 --- a/src/devices/cpu/sparc/mb86901.cpp +++ /dev/null @@ -1,4195 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz -//================================================================ -// -// mb86901.cpp - Emulation for the Fujitsu MB86901 / LSI L64801 -// processors. Both chips are identical both -// electrically and functionally, and implement -// the integer instructions in a SPARC v7 -// compatible instruction set. -// -// Notes: -// - The CPU core implementation has been simplified -// somewhat compared to the spec. In particular, bus -// holding on read/write accesses is disabled, as there -// is currently no use made of it, and it is unlikely to -// ever be. -// -// To-Do: -// - Ops: FBFcc, LDF, STF -// - Test: SPARCv8 ops are untested -// - FPU support -// - Coprocessor support -// -//================================================================ - -#include "emu.h" -#include "sparc.h" -#include "sparcdefs.h" - -#include "debugger.h" - - -DEFINE_DEVICE_TYPE(MB86901, mb86901_device, "mb86901", "Fujitsu MB86901") - -const int mb86901_device::NWINDOWS = 7; - -#if LOG_FCODES -#include "ss1fcode.ipp" -#endif - -#if SPARCV8 -#include "sparcv8ops.ipp" -#endif - -//------------------------------------------------- -// mb86901_device - constructor -//------------------------------------------------- - -mb86901_device::mb86901_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : cpu_device(mconfig, MB86901, tag, owner, clock) - , m_mmu(*this, finder_base::DUMMY_TAG) -{ - m_default_config = address_space_config("program", ENDIANNESS_BIG, 32, 32); -} - - -void mb86901_device::device_start() -{ -#if LOG_FCODES - m_ss1_fcode_table.clear(); - FILE* input = fopen("names.txt", "rb"); - - if (input != NULL) - { - fseek(input, 0, SEEK_END); - size_t filesize = ftell(input); - fseek(input, 0, SEEK_SET); - - uint8_t *buf = new uint8_t[filesize]; - fread(buf, 1, filesize, input); - fclose(input); - - size_t pos = 0; - while (pos < filesize) - { - // eat newlines - while (pos < filesize && (buf[pos] == 0x0d || buf[pos] == 0x0a)) - pos++; - - if (pos >= filesize) - break; - - // get opcode - uint16_t opcode = 0; - for (int shift = 12; shift >= 0 && pos < filesize; shift -= 4) - { - uint8_t digit = buf[pos]; - if (digit >= 'a' && digit <= 'z') - { - digit &= ~0x20; - } - - if (digit >= '0' && digit <= '9') - { - opcode |= (digit - 0x30) << shift; - } - else if (digit >= 'A' && digit <= 'F') - { - opcode |= ((digit - 0x41) + 10) << shift; - } - pos++; - } - - if (pos >= filesize) - break; - - // skip " : " - pos += 3; - - if (pos >= filesize) - break; - - // read description up to the first space - std::string description; - while (buf[pos] != ' ' && pos < filesize) - { - description += char(buf[pos]); - pos++; - } - - if (pos >= filesize) - break; - - // skip everything else up to the trailing semicolon - while (buf[pos] != ';' && pos < filesize) - pos++; - - if (pos >= filesize) - break; - - if (buf[pos] == ';') - pos++; - - m_ss1_fcode_table[opcode] = description; - } - delete [] buf; - } - m_log_fcodes = false; -#endif - - m_bp_reset_in = false; - 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; - m_bp_irl = 0; - m_irq_state = 0; - - memset(m_dbgregs, 0, 24 * sizeof(uint32_t)); - - 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_setcc, 0, 64 * sizeof(bool)); - m_alu_setcc[OP3_ADDCC] = true; - m_alu_setcc[OP3_ANDCC] = true; - m_alu_setcc[OP3_ORCC] = true; - m_alu_setcc[OP3_XORCC] = true; - m_alu_setcc[OP3_SUBCC] = true; - m_alu_setcc[OP3_ANDNCC] = true; - m_alu_setcc[OP3_ORNCC] = true; - m_alu_setcc[OP3_XNORCC] = true; - m_alu_setcc[OP3_ADDXCC] = true; - m_alu_setcc[OP3_SUBXCC] = true; - m_alu_setcc[OP3_TADDCC] = true; - m_alu_setcc[OP3_TSUBCC] = true; - m_alu_setcc[OP3_TADDCCTV] = true; - m_alu_setcc[OP3_TSUBCCTV] = true; - m_alu_setcc[OP3_MULSCC] = true; -#if SPARCV8 - m_alu_setcc[OP3_UMULCC] = true; - m_alu_setcc[OP3_SMULCC] = true; - m_alu_setcc[OP3_UDIVCC] = true; - m_alu_setcc[OP3_SDIVCC] = true; -#endif - - 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_CPOP1] = true; - m_alu_op3_assigned[OP3_CPOP2] = 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_IFLUSH] = 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; -#endif - - 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_GENPCBASE, "CURPC", m_pc).noshow(); - state_add(STATE_GENFLAGS, "GENFLAGS", m_psr).callimport().callexport().formatstr("%6s").noshow(); - state_add(SPARC_PC, "PC", m_pc).formatstr("%08X"); - state_add(SPARC_NPC, "nPC", m_npc).formatstr("%08X"); - state_add(SPARC_PSR, "PSR", m_psr).formatstr("%08X"); - state_add(SPARC_WIM, "WIM", m_wim).formatstr("%08X"); - state_add(SPARC_TBR, "TBR", m_tbr).formatstr("%08X"); - state_add(SPARC_Y, "Y", m_y).formatstr("%08X"); - state_add(SPARC_ANNUL, "ANNUL", m_no_annul).formatstr("%01u"); - state_add(SPARC_ICC, "icc", m_icc).formatstr("%4s"); - state_add(SPARC_CWP, "CWP", m_cwp).formatstr("%2d"); - char regname[3] = "g0"; - for (int i = 0; i < 8; i++) - { - regname[1] = 0x30 + i; - state_add(SPARC_G0 + i, regname, m_r[i]).formatstr("%08X"); - } - regname[0] = 'o'; - for (int i = 0; i < 8; i++) - { - regname[1] = 0x30 + i; - state_add(SPARC_O0 + i, regname, m_dbgregs[i]).formatstr("%08X"); - } - - regname[0] = 'l'; - for (int i = 0; i < 8; i++) - { - regname[1] = 0x30 + i; - state_add(SPARC_L0 + i, regname, m_dbgregs[8+i]).formatstr("%08X"); - } - regname[0] = 'i'; - for (int i = 0; i < 8; i++) - { - regname[1] = 0x30 + i; - state_add(SPARC_I0 + i, regname, m_dbgregs[16+i]).formatstr("%08X"); - } - - state_add(SPARC_EC, "EC", m_ec).formatstr("%1u"); - state_add(SPARC_EF, "EF", m_ef).formatstr("%1u"); - state_add(SPARC_ET, "ET", m_et).formatstr("%1u"); - state_add(SPARC_PIL, "PIL", m_pil).formatstr("%2d"); - state_add(SPARC_S, "S", m_s).formatstr("%1u"); - state_add(SPARC_PS, "PS", m_ps).formatstr("%1u"); - - char rname[5]; - for (int i = 0; i < 120; i++) - { - sprintf(rname, "r%d", i); - state_add(SPARC_R0 + i, rname, m_r[i]).formatstr("%08X"); - } - - 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_error)); - save_item(NAME(m_pb_block_ldst_byte)); - save_item(NAME(m_pb_block_ldst_word)); - save_item(NAME(m_irq_state)); - 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)); - save_item(NAME(m_ec)); - save_item(NAME(m_ef)); - save_item(NAME(m_pil)); - save_item(NAME(m_s)); - save_item(NAME(m_ps)); - save_item(NAME(m_et)); - save_item(NAME(m_cwp)); - save_item(NAME(m_alu_op3_assigned)); - save_item(NAME(m_ldst_op3_assigned)); - save_item(NAME(m_alu_setcc)); - save_item(NAME(m_privileged_asr)); - save_item(NAME(m_illegal_instruction_asr)); - save_item(NAME(m_mae)); - save_item(NAME(m_no_annul)); - save_item(NAME(m_hold_bus)); - save_item(NAME(m_icount)); - save_item(NAME(m_stashed_icount)); - save_item(NAME(m_insn_space)); - save_item(NAME(m_data_space)); - -#if LOG_FCODES - save_item(NAME(m_ss1_next_pc)); - save_item(NAME(m_ss1_next_opcode)); - save_item(NAME(m_ss1_next_handler_base)); - save_item(NAME(m_ss1_next_entry_point)); - save_item(NAME(m_ss1_next_stack)); - save_item(NAME(m_log_fcodes)); -#endif - - // set our instruction counter - set_icountptr(m_icount); -} - - -void mb86901_device::device_stop() -{ -} - -void mb86901_device::device_resolve_objects() -{ - m_mmu->set_host(this); -} - -void mb86901_device::device_reset() -{ - 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_bp_irl = 0; - m_irq_state = 0; - - m_stashed_icount = -1; - - MAE = false; - HOLD_BUS = false; - m_no_annul = true; - - PC = 0; - nPC = 4; - memset(m_r, 0, sizeof(uint32_t) * 120); - memset(m_fpr, 0, sizeof(uint32_t) * 32); - - WIM = 0; - TBR = 0; - Y = 0; - - PSR = PSR_S_MASK | PSR_PS_MASK; - m_s = true; - m_data_space = 11; - - for (int i = 0; i < 8; i++) - { - m_regs[i] = m_r + i; - } - update_gpr_pointers(); - -#if LOG_FCODES - m_ss1_next_pc = ~0; - m_ss1_next_opcode = ~0; - m_ss1_next_handler_base = ~0; - m_ss1_next_entry_point = ~0; - m_ss1_next_stack = ~0; -#endif -} - - -//------------------------------------------------- -// device_post_load - update register pointers -// after loading a savestate -//------------------------------------------------- - -void mb86901_device::device_post_load() -{ - update_gpr_pointers(); -} - - -//------------------------------------------------- -// memory_space_config - return the configuration -// of the specified address space, or nullptr if -// the space doesn't exist -//------------------------------------------------- - -device_memory_interface::space_config_vector mb86901_device::memory_space_config() const -{ - space_config_vector config_vector; - config_vector.push_back(std::make_pair(AS_PROGRAM, &m_default_config)); - return config_vector; -} - - -//------------------------------------------------- -// 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_t mb86901_device::read_sized_word(const uint8_t asi, const uint32_t address, const uint32_t mem_mask) -{ - assert(asi < 0x20); // We do not currently support ASIs outside the range used by actual Sun machines. - return m_mmu->read_asi(asi, address >> 2, mem_mask); -} - - -//------------------------------------------------- -// 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_sized_word(const uint8_t asi, const uint32_t address, const uint32_t data, const uint32_t mem_mask) -{ - assert(asi < 0x20); // We do not currently support ASIs outside the range used by actual Sun machines. - m_mmu->write_asi(asi, address >> 2, data, mem_mask); -} - - -//------------------------------------------------- -// state_string_export - export state as a string -// for the debugger -//------------------------------------------------- - -void mb86901_device::state_string_export(const device_state_entry &entry, std::string &str) const -{ - switch (entry.index()) - { - case STATE_GENFLAGS: - case SPARC_ANNUL: - str = string_format("%01u", m_no_annul ? 0 : 1); - break; - case SPARC_CWP: - str = string_format("%2u", PSR & PSR_CWP_MASK); - break; - case SPARC_EC: - str = string_format("%01u", PSR & PSR_EC_MASK ? 1 : 0); - break; - case SPARC_EF: - str = string_format("%01u", PSR & PSR_EF_MASK ? 1 : 0); - break; - case SPARC_ET: - str = string_format("%01u", PSR & PSR_ET_MASK ? 1 : 0); - break; - case SPARC_PS: - str = string_format("%01u", PSR & PSR_PS_MASK ? 1 : 0); - break; - case SPARC_S: - str = string_format("%01u", PSR & PSR_S_MASK ? 1 : 0); - break; - case SPARC_PIL: - str = string_format("%02u", (PSR & PSR_PIL_MASK) >> PSR_PIL_SHIFT); - break; - case SPARC_ICC: - str = string_format("%c%c%c%c", ICC_N_SET ? 'n' : ' ', ICC_Z_SET ? 'z' : ' ', ICC_V_SET ? 'v' : ' ', ICC_C_SET ? 'c' : ' '); - break; - case SPARC_O0: case SPARC_O1: case SPARC_O2: case SPARC_O3: case SPARC_O4: case SPARC_O5: case SPARC_O6: case SPARC_O7: - str = string_format("%08X", m_dbgregs[entry.index() - SPARC_O0]); - break; - case SPARC_L0: case SPARC_L1: case SPARC_L2: case SPARC_L3: case SPARC_L4: case SPARC_L5: case SPARC_L6: case SPARC_L7: - str = string_format("%08X", m_dbgregs[8 + (entry.index() - SPARC_L0)]); - break; - case SPARC_I0: case SPARC_I1: case SPARC_I2: case SPARC_I3: case SPARC_I4: case SPARC_I5: case SPARC_I6: case SPARC_I7: - str = string_format("%08X", m_dbgregs[16 + (entry.index() - SPARC_I0)]); - break; - } -} - - -//------------------------------------------------- -// disassemble - call the disassembly -// helper function -//------------------------------------------------- - -std::unique_ptr<util::disasm_interface> mb86901_device::create_disassembler() -{ - auto dasm = std::make_unique<sparc_disassembler>(static_cast<sparc_disassembler::config const *>(this), 7); - m_asi_desc_adder(dasm.get()); - return std::move(dasm); -} - - -//************************************************************************** -// CORE EXECUTION LOOP -//************************************************************************** - -//------------------------------------------------- -// execute_min_cycles - return minimum number of -// cycles it takes for one instruction to execute -//------------------------------------------------- - -uint32_t mb86901_device::execute_min_cycles() const -{ - return 1; -} - - -//------------------------------------------------- -// execute_max_cycles - return maximum number of -// cycles it takes for one instruction to execute -//------------------------------------------------- - -uint32_t mb86901_device::execute_max_cycles() const -{ - return 4; -} - - -//------------------------------------------------- -// execute_input_lines - return the number of -// input/interrupt lines -//------------------------------------------------- - -uint32_t mb86901_device::execute_input_lines() const -{ - return 16; -} - - -//------------------------------------------------- -// execute_set_input - set the state of an input -// line during execution -//------------------------------------------------- - -void mb86901_device::execute_set_input(int inputnum, int state) -{ - switch (inputnum) - { - case SPARC_IRQ1: - case SPARC_IRQ2: - case SPARC_IRQ3: - case SPARC_IRQ4: - case SPARC_IRQ5: - case SPARC_IRQ6: - case SPARC_IRQ7: - case SPARC_IRQ8: - case SPARC_IRQ9: - case SPARC_IRQ10: - case SPARC_IRQ11: - case SPARC_IRQ12: - case SPARC_IRQ13: - case SPARC_IRQ14: - case SPARC_NMI: - { - int index = (inputnum - SPARC_IRQ1) + 1; - if (state) - { - m_irq_state |= 1 << index; - } - else - { - m_irq_state &= ~(1 << index); - } - - for(index = 15; index > 0; index--) - { - if (m_irq_state & (1 << index)) - { - break; - } - } - - m_bp_irl = index; - break; - } - - case SPARC_MAE: - m_mae = (state != 0) ? 1 : 0; - break; - - case SPARC_RESET: - m_bp_reset_in = (state != 0) ? 1 : 0; - break; - } -} - - -//------------------------------------------------- -// execute_add - execute an add-type opcode -//------------------------------------------------- - -void mb86901_device::execute_add(uint32_t 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_t rs1 = RS1REG; - uint32_t operand2 = USEIMM ? SIMM13 : RS2REG; - - uint32_t result = 0; - if (ADD || ADDCC) - result = rs1 + operand2; - else if (ADDX || ADDXCC) - result = rs1 + operand2 + ICC_C; - - if (RDBITS) - RDREG = result; - - if (ADDCC || ADDXCC) - { - CLEAR_ICC; - PSR |= (BIT31(result)) ? PSR_N_MASK : 0; - PSR |= (result == 0) ? PSR_Z_MASK : 0; - PSR |= ((BIT31(rs1) && BIT31(operand2) && !BIT31(result)) || - (!BIT31(rs1) && !BIT31(operand2) && BIT31(result))) ? PSR_V_MASK : 0; - PSR |= ((BIT31(rs1) && BIT31(operand2)) || - (!BIT31(result) && (BIT31(rs1) || BIT31(operand2)))) ? PSR_C_MASK : 0; - } - - PC = nPC; - nPC = nPC + 4; -} - - -//------------------------------------------------- -// execute_taddcc - execute a tagged add-type -// opcode -//------------------------------------------------- - -void mb86901_device::execute_taddcc(uint32_t 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_t rs1 = RS1REG; - uint32_t operand2 = USEIMM ? SIMM13 : RS2REG; - - uint32_t result = rs1 + operand2; - - bool temp_v = (BIT31(rs1) && BIT31(operand2) && !BIT31(result)) || - (!BIT31(rs1) && !BIT31(operand2) && BIT31(result)) || - ((rs1 & 3) != 0 || (operand2 & 3) != 0) ? true : false; - - if (TADDCCTV && temp_v) - { - m_trap = 1; - m_tag_overflow = true; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - 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(rs1) && BIT31(operand2)) || - (!BIT31(result) && (BIT31(rs1) || BIT31(operand2)))) ? PSR_C_MASK : 0; - - if (RDBITS) - RDREG = result; - - PC = nPC; - nPC = nPC + 4; -} - - -//------------------------------------------------- -// execute_sub - execute a subtraction-type -// opcode -//------------------------------------------------- - -void mb86901_device::execute_sub(uint32_t 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_t rs1 = RS1REG; - uint32_t operand2 = USEIMM ? SIMM13 : RS2REG; - - uint32_t result = 0; - if (SUB || SUBCC) - result = rs1 - operand2; - else if (SUBX || SUBXCC) - result = rs1 - operand2 - ICC_C; - - if (RDBITS) - RDREG = result; - - if (SUBCC || SUBXCC) - { - CLEAR_ICC; - PSR |= (BIT31(result)) ? PSR_N_MASK : 0; - PSR |= (result == 0) ? PSR_Z_MASK : 0; - PSR |= ((BIT31(rs1) && !BIT31(operand2) && !BIT31(result)) || - (!BIT31(rs1) && BIT31(operand2) && BIT31(result))) ? PSR_V_MASK : 0; - PSR |= ((!BIT31(rs1) && BIT31(operand2)) || - (BIT31(result) && (!BIT31(rs1) || BIT31(operand2)))) ? PSR_C_MASK : 0; - } - - PC = nPC; - nPC = nPC + 4; -} - - -//-------------------------------------------------- -// execute_tsubcc - execute a tagged subtract-type -// opcode -//-------------------------------------------------- - -void mb86901_device::execute_tsubcc(uint32_t 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_t rs1 = RS1REG; - uint32_t operand2 = USEIMM ? SIMM13 : RS2REG; - - uint32_t result = rs1 - operand2; - - bool temp_v = (BIT31(rs1) && !BIT31(operand2) && !BIT31(result)) || - (!BIT31(rs1) && BIT31(operand2) && BIT31(result)) || - ((rs1 & 3) != 0 || (operand2 & 3) != 0) ? true : false; - - if (TSUBCCTV && temp_v) - { - m_trap = 1; - m_tag_overflow = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - 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(rs1) && BIT31(operand2)) || - (BIT31(result) && (!BIT31(rs1) || BIT31(operand2)))) ? PSR_C_MASK : 0; - - if (RDBITS) - RDREG = result; - - PC = nPC; - nPC = nPC + 4; -} - - -/* 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 -); -*/ - -template <mb86901_device::set_cc SETCC> -void mb86901_device::execute_and(const uint32_t op) -{ - const uint32_t result = RS1REG & (USEIMM ? SIMM13 : RS2REG); - if (RDBITS) RDREG = result; - if (SETCC) - { - CLEAR_ICC; - if (result & 0x80000000) - PSR |= PSR_N_MASK; - else if (!result) - PSR |= PSR_Z_MASK; - } - - PC = nPC; - nPC = nPC + 4; -} - -template <mb86901_device::set_cc SETCC> -void mb86901_device::execute_or(const uint32_t op) -{ - const uint32_t result = RS1REG | (USEIMM ? SIMM13 : RS2REG); - if (RDBITS) RDREG = result; - if (SETCC) - { - CLEAR_ICC; - if (result & 0x80000000) - PSR |= PSR_N_MASK; - else if (!result) - PSR |= PSR_Z_MASK; - } - - PC = nPC; - nPC = nPC + 4; -} - -template <mb86901_device::set_cc SETCC> -void mb86901_device::execute_xor(const uint32_t op) -{ - const uint32_t result = RS1REG ^ (USEIMM ? SIMM13 : RS2REG); - if (RDBITS) RDREG = result; - if (SETCC) - { - CLEAR_ICC; - if (result & 0x80000000) - PSR |= PSR_N_MASK; - else if (!result) - PSR |= PSR_Z_MASK; - } - - PC = nPC; - nPC = nPC + 4; -} - -template <mb86901_device::set_cc SETCC> -void mb86901_device::execute_andn(const uint32_t op) -{ - const uint32_t result = RS1REG & ~(USEIMM ? SIMM13 : RS2REG); - if (RDBITS) RDREG = result; - if (SETCC) - { - CLEAR_ICC; - if (result & 0x80000000) - PSR |= PSR_N_MASK; - else if (!result) - PSR |= PSR_Z_MASK; - } - - PC = nPC; - nPC = nPC + 4; -} - -template <mb86901_device::set_cc SETCC> -void mb86901_device::execute_orn(const uint32_t op) -{ - const uint32_t result = RS1REG | ~(USEIMM ? SIMM13 : RS2REG); - if (RDBITS) RDREG = result; - if (SETCC) - { - CLEAR_ICC; - if (result & 0x80000000) - PSR |= PSR_N_MASK; - else if (!result) - PSR |= PSR_Z_MASK; - } - - PC = nPC; - nPC = nPC + 4; -} - -template <mb86901_device::set_cc SETCC> -void mb86901_device::execute_xnor(const uint32_t op) -{ - const uint32_t result = RS1REG ^ ~(USEIMM ? SIMM13 : RS2REG); - if (RDBITS) RDREG = result; - if (SETCC) - { - CLEAR_ICC; - if (result & 0x80000000) - PSR |= PSR_N_MASK; - else if (!result) - PSR |= PSR_Z_MASK; - } - - PC = nPC; - nPC = nPC + 4; -} - -//------------------------------------------------- -// execute_shift - execute a shift-type opcode, -// sll/srl/sra -//------------------------------------------------- - -void mb86901_device::execute_shift(uint32_t 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_t shift_count = USEIMM ? (SIMM13 & 31) : (RS2REG & 31); - - if (RDBITS) - { - if (SLL) - RDREG = RS1REG << shift_count; - else if (SRL) - RDREG = uint32_t(RS1REG) >> shift_count; - else if (SRA) - RDREG = int32_t(RS1REG) >> shift_count; - } - - PC = nPC; - nPC = nPC + 4; -} - - -//-------------------------------------------------- -// execute_mulscc - execute a multiply step opcode -//-------------------------------------------------- - -void mb86901_device::execute_mulscc(uint32_t 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_t operand1 = ((ICC_N != ICC_V) ? 0x80000000 : 0) | (RS1REG >> 1); - - uint32_t operand2 = (Y & 1) ? (USEIMM ? SIMM13 : RS2REG) : 0; - - uint32_t result = operand1 + operand2; - Y = ((RS1REG & 1) ? 0x80000000 : 0) | (Y >> 1); - - if (RDBITS) - 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; - - PC = nPC; - nPC = nPC + 4; -} - - -//------------------------------------------------- -// execute_rdsr - execute a status register read -// opcode -//------------------------------------------------- - -void mb86901_device::execute_rdsr(uint32_t 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 (((WRPSR || WRWIM || WRTBR) || (WRASR && m_privileged_asr[RS1])) && IS_USER) - { - m_trap = 1; - m_privileged_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - else if (m_illegal_instruction_asr[RS1]) - { - m_trap = 1; - m_illegal_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (RDBITS) - { - if (RDASR) - { - if (RS1 == 0) - { - RDREG = Y; - } - } - else if (RDPSR) - { - RDREG = PSR; - } - else if (RDWIM) - RDREG = WIM; - else if (RDTBR) - RDREG = TBR; - } - - PC = nPC; - nPC = nPC + 4; -} - - -//------------------------------------------------- -// execute_wrsr - execute a status register write -// opcode -//------------------------------------------------- - -void mb86901_device::execute_wrsr(uint32_t 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_t operand2 = USEIMM ? SIMM13 : RS2REG; - - uint32_t result = RS1REG ^ operand2; - - if (WRASR && RD == 0) - { - Y = result; - PC = nPC; - nPC = nPC + 4; - } - else if (WRASR) - { - if (m_privileged_asr[RD] && IS_USER) - { - m_trap = 1; - m_privileged_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - else if (m_illegal_instruction_asr[RD]) - { - m_trap = 1; - m_illegal_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - else - { - // SPARCv8 - PC = nPC; - nPC = nPC + 4; - } - } - else if (WRPSR) - { - if (IS_USER) - { - m_trap = 1; - m_privileged_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - else if ((result & 31) >= NWINDOWS) - { - m_trap = 1; - m_illegal_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - PSR = result &~ PSR_ZERO_MASK; - update_gpr_pointers(); - - m_et = PSR & PSR_ET_MASK; - m_pil = (PSR & PSR_PIL_MASK) >> PSR_PIL_SHIFT; - m_s = PSR & PSR_S_MASK; - if (m_s) - { - m_data_space = 11; - } - else - { - m_data_space = 10; - } - - PC = nPC; - nPC = nPC + 4; - } - else if (WRWIM) - { - if (IS_USER) - { - m_trap = 1; - m_privileged_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - WIM = result & 0x7f; - PC = nPC; - nPC = nPC + 4; - } - else if (WRTBR) - { - if (IS_USER) - { - m_trap = 1; - m_privileged_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - TBR = result & 0xfffff000; - PC = nPC; - nPC = nPC + 4; - } -} - - -//------------------------------------------------- -// execute_rett - execute a return-from-trap -// opcode -//------------------------------------------------- - -void mb86901_device::execute_rett(uint32_t 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_t new_cwp = ((PSR & PSR_CWP_MASK) + 1) % NWINDOWS; - uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - if (m_et) - { - m_trap = 1; - if (IS_USER) - { - m_privileged_instruction = 1; - } - else - { - m_illegal_instruction = 1; - } - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - else if (IS_USER) - { - m_trap = 1; - m_privileged_instruction = 1; - m_tt = 3; - m_execute_mode = 0; - m_error_mode = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - 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; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - else if (address & 3) - { - m_trap = 1; - m_mem_address_not_aligned = 1; - m_tt = 7; - m_execute_mode = 0; - m_error_mode = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - PSR |= PSR_ET_MASK; - m_et = true; - PC = nPC; - nPC = address; - - PSR &= ~PSR_CWP_MASK; - PSR |= new_cwp; - - if (PSR & PSR_PS_MASK) - { - PSR |= PSR_S_MASK; - m_s = true; - m_data_space = 11; - } - else - { - PSR &= ~PSR_S_MASK; - m_s = false; - m_data_space = 10; - } - - update_gpr_pointers(); -} - - - -//------------------------------------------------- -// execute_saverestore - execute a save or restore -// opcode -//------------------------------------------------- - -void mb86901_device::execute_saverestore(uint32_t op) -{ - /* 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_t rs1 = RS1REG; - uint32_t operand2 = USEIMM ? SIMM13 : RS2REG; - - uint32_t result = 0; - if (SAVE) - { - uint8_t new_cwp = (((PSR & PSR_CWP_MASK) + NWINDOWS) - 1) % NWINDOWS; - if ((WIM & (1 << new_cwp)) != 0) - { - m_trap = 1; - m_window_overflow = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - result = rs1 + operand2; - PSR &= ~PSR_CWP_MASK; - PSR |= new_cwp; - } - else if (RESTORE) - { - uint8_t new_cwp = ((PSR & PSR_CWP_MASK) + 1) % NWINDOWS; - if ((WIM & (1 << new_cwp)) != 0) - { - m_trap = 1; - m_window_underflow = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - result = rs1 + operand2; - PSR &= ~PSR_CWP_MASK; - PSR |= new_cwp; - } - - update_gpr_pointers(); - - if (RDBITS) - RDREG = result; - - PC = nPC; - nPC = nPC + 4; -} - - -//------------------------------------------------- -// execute_jmpl - execute a jump and link opcode -//------------------------------------------------- - -void mb86901_device::execute_jmpl(uint32_t 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_t jump_address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - - if (jump_address & 3) - { - m_trap = 1; - m_mem_address_not_aligned = 1; - m_stashed_icount = m_icount; - m_icount = 0; - } - else - { - if (RDBITS) - RDREG = PC; - PC = nPC; - nPC = jump_address; - } -} - - -//------------------------------------------------- -// execute_group2 - execute an opcode in group 2, -// mostly ALU ops -//------------------------------------------------- - -inline void mb86901_device::execute_group2(uint32_t op) -{ - switch (OP3) - { - 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 OP3_TSUBCC: - case OP3_TSUBCCTV: - execute_tsubcc(op); - break; - - case OP3_AND: - execute_and<NOCC>(op); - break; - case OP3_OR: - execute_or<NOCC>(op); - break; - case OP3_XOR: - execute_xor<NOCC>(op); - break; - case OP3_ANDN: - execute_andn<NOCC>(op); - break; - case OP3_ORN: - execute_orn<NOCC>(op); - break; - case OP3_XNOR: - execute_xnor<NOCC>(op); - break; - case OP3_ANDCC: - execute_and<USECC>(op); - break; - case OP3_ORCC: - execute_or<USECC>(op); - break; - case OP3_XORCC: - execute_xor<USECC>(op); - break; - case OP3_ANDNCC: - execute_andn<USECC>(op); - break; - case OP3_ORNCC: - execute_orn<USECC>(op); - break; - case OP3_XNORCC: - execute_xnor<USECC>(op); - break; - - case OP3_MULSCC: - execute_mulscc(op); - break; - - case OP3_SLL: - case OP3_SRL: - case OP3_SRA: - execute_shift(op); - break; - - case OP3_RDASR: - case OP3_RDPSR: - case OP3_RDWIM: - case OP3_RDTBR: - execute_rdsr(op); - break; - - case OP3_WRASR: - case OP3_WRPSR: - case OP3_WRWIM: - case OP3_WRTBR: - execute_wrsr(op); - break; - - case OP3_FPOP1: - case OP3_FPOP2: - if (!(PSR & PSR_EF_MASK) || !m_bp_fpu_present) - { - //printf("fpop @ %08x: %08x\n", PC, op); - m_trap = 1; - m_fp_disabled = 1; - m_stashed_icount = m_icount; - m_icount = 0; - } - complete_fp_execution(op); - return; - - case OP3_JMPL: - execute_jmpl(op); - break; - - case OP3_RETT: - execute_rett(op); - break; - - case OP3_TICC: - execute_ticc(op); - break; - - case OP3_IFLUSH: - // Ignored - PC = nPC; - nPC = nPC + 4; - break; - - case OP3_SAVE: - case OP3_RESTORE: - execute_saverestore(op); - break; - -#if SPARCV8 - case OP3_UMUL: - case OP3_SMUL: - case OP3_UMULCC: - case OP3_SMULCC: - execute_mul(op); - break; - - case OP3_UDIV: - case OP3_SDIV: - case OP3_UDIVCC: - case OP3_SDIVCC: - execute_div(op); - break; - - case OP3_CPOP1: - case OP3_CPOP2: - logerror("fpop @ %08x: %08x\n", PC, op); - m_trap = 1; - m_cp_disabled = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; -#endif - - default: - logerror("illegal instruction at %08x: %08x\n", PC, op); - m_trap = 1; - m_illegal_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - break; - } -} - - - -//------------------------------------------------- -// update_gpr_pointers - cache pointers to -// the registers in our current window -//------------------------------------------------- - -void mb86901_device::update_gpr_pointers() -{ - int cwp = PSR & PSR_CWP_MASK; - for (int i = 0; i < 8; i++) - { - m_regs[ 8 + i] = &m_r[8 + (( 0 + cwp * 16 + i) % (NWINDOWS * 16))]; - m_regs[16 + i] = &m_r[8 + (( 8 + cwp * 16 + i) % (NWINDOWS * 16))]; - m_regs[24 + i] = &m_r[8 + ((16 + cwp * 16 + i) % (NWINDOWS * 16))]; - } -} - - -//------------------------------------------------- -// execute_store - execute a store-type opcode -//------------------------------------------------- - -void mb86901_device::execute_store(uint32_t 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; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - else if (USEIMM && (STDA || STA || STHA || STBA)) - { - m_trap = 1; - m_illegal_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - uint32_t address = 0; - uint8_t addr_space = 0; - if (STD || ST || STH || STB || STF || STDF || STFSR || STDFQ || STCSR || STC || STDC || STDCQ) - { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = m_data_space; - } - else if (STDA || STA || STHA || STBA) - { - address = RS1REG + RS2REG; - addr_space = ASI; - } - if ((STF || STDF || STFSR || STDFQ) && (!(PSR & PSR_EF_MASK) || !m_bp_fpu_present)) - { - m_trap = 1; - m_fp_disabled = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - if ((STC || STDC || STCSR || STDCQ) && (!(PSR & PSR_EC_MASK) || !m_bp_cp_present)) - { - m_trap = 1; - m_cp_disabled = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if ((STH || STHA) && ((address & 1) != 0)) - { - m_trap = 1; - m_stashed_icount = m_icount; - m_icount = 0; - m_mem_address_not_aligned = 1; - return; - } - else if ((ST || STA || STF || STFSR || STC || STCSR) && ((address & 3) != 0)) - { - m_trap = 1; - m_mem_address_not_aligned = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - else if ((STD || STDA || STDF || STDFQ || STDC || STDCQ) && ((address & 7) != 0)) - { - m_trap = 1; - m_mem_address_not_aligned = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (STDFQ) - { - // assume no floating-point queue for now - m_trap = 1; - m_fp_exception = 1; - m_ftt = m_fpu_sequence_err; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - if (STDCQ) - { - // assume no coprocessor queue for now - m_trap = 1; - m_cp_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - // { possibly additional implementation-dependent actions } - return; - } - if (STDF && ((RD & 1) != 0)) - { - m_trap = 1; - m_fp_exception = 1; - m_ftt = 0xff; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - uint32_t data0 = 0; - //uint8_t 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) - { - //byte_mask = 12; - data0 = REG(RD) << 16; - } - else if ((address & 3) == 2) - { - //byte_mask = 3; - data0 = REG(RD); - } - } - else if (STB || STBA) - { - if ((address & 3) == 0) - { - //byte_mask = 8; - data0 = REG(RD) << 24; - } - else if ((address & 3) == 1) - { - //byte_mask = 4; - data0 = REG(RD) << 16; - } - else if ((address & 3) == 2) - { - //byte_mask = 2; - data0 = REG(RD) << 8; - } - else if ((address & 3) == 3) - { - //byte_mask = 1; - data0 = REG(RD); - } - } - - static const uint32_t mask16[4] = { 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000 }; - static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; - m_mmu->write_asi(addr_space, address >> 2, data0, (ST || STA || STD || STDA || STF || STDF || STDFQ || STFSR || STC || STDC || STDCQ || STCSR) ? 0xffffffff : ((STH || STHA) ? mask16[address & 2] : mask8[address & 3])); - if (MAE) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (STD || STDA || STDF || STDC || STDFQ || STDCQ) - { - uint32_t data1 = 0; - if (STD || STDA) - { - data1 = REG(RD | 1); - } - else if (STDF) - { - data1 = FREG(RD | 1); - } - else if (STDC) - { - data1 = 0; - } - else if (STDFQ) - { - data1 = 0; - } - else if (STDCQ) - { - data1 = 0; - } - - m_mmu->write_asi(addr_space, (address + 4) >> 2, data1, 0xffffffff); - if (MAE) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - } - - PC = nPC; - nPC = nPC + 4; -} - -/* 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 - 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 } -); -*/ - -inline void mb86901_device::execute_ldd(uint32_t op) -{ - const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - - if (address & 7) - { - m_trap = 1; - m_mem_address_not_aligned = 1; - m_stashed_icount = m_icount; - m_icount = 0; - } - - const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); - - if (MAE) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (RDBITS) - RDREG = data; - - const uint32_t word1 = m_mmu->read_asi(m_data_space, (address + 4) >> 2, 0xffffffff); - if (MAE) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - REG(RD | 1) = word1; - - PC = nPC; - nPC = nPC + 4; -} - -inline void mb86901_device::execute_ld(uint32_t op) -{ - const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - - if (address & 3) - { - m_trap = 1; - m_mem_address_not_aligned = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); - - if (m_mae) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (RDBITS) - RDREG = data; - - PC = nPC; - nPC = nPC + 4; -} - -inline void mb86901_device::execute_ldsh(uint32_t op) -{ - const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - - if (address & 1) - { - m_trap = 1; - m_mem_address_not_aligned = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - static const uint32_t mask16[4] = { 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000 }; - const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask16[address & 2]); - - if (m_mae) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (RDBITS) - { - if ((address & 3) == 0) RDREG = (int32_t)data >> 16; - else if ((address & 3) == 2) RDREG = ((int32_t)data << 16) >> 16; - } - - PC = nPC; - nPC = nPC + 4; -} - -inline void mb86901_device::execute_lduh(uint32_t op) -{ - const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - - if (address & 1) - { - m_trap = 1; - m_mem_address_not_aligned = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - static const uint32_t mask16[4] = { 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000 }; - const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask16[address & 2]); - - if (m_mae) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (RDBITS) - { - if ((address & 3) == 0) RDREG = data >> 16; - else if ((address & 3) == 2) RDREG = data & 0xffff; - } - - PC = nPC; - nPC = nPC + 4; -} - -inline void mb86901_device::execute_ldsb(uint32_t op) -{ - const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - - static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; - const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask8[address & 3]); - - if (m_mae) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (RDBITS) - { - if ((address & 3) == 0) RDREG = (int32_t)data >> 24; - else if ((address & 3) == 1) RDREG = ((int32_t)data << 8) >> 24; - else if ((address & 3) == 2) RDREG = ((int32_t)data << 16) >> 24; - else if ((address & 3) == 3) RDREG = ((int32_t)data << 24) >> 24; - } - - PC = nPC; - nPC = nPC + 4; -} - -inline void mb86901_device::execute_ldub(uint32_t op) -{ - const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - - static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; - const uint32_t byte_idx = address & 3; - const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, mask8[byte_idx]); - - if (m_mae) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (RDBITS) - { - static const int shifts[4] = { 24, 16, 8, 0 }; - RDREG = (uint8_t)(data >> shifts[byte_idx]); - } - - PC = nPC; - nPC = nPC + 4; -} - -inline void mb86901_device::execute_lddfpr(uint32_t op) -{ - const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - - if (!(PSR & PSR_EF_MASK) || m_bp_fpu_present == 0) - { - m_trap = 1; - m_fp_disabled = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (address & 7) - { - m_trap = 1; - m_mem_address_not_aligned = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (RD & 1) - { - m_trap = 1; - m_fp_exception = 1; - m_ftt = 0xff; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (m_fpu_sequence_err) - { - m_trap = 1; - m_fp_exception = 1; - m_ftt = m_fpu_sequence_err; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); - - if (m_mae) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - FREG(RD & 0x1e) = data; - - const uint32_t word1 = m_mmu->read_asi(m_data_space, (address + 4) >> 2, 0xffffffff); - if (MAE) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - FREG(RD | 1) = word1; - - PC = nPC; - nPC = nPC + 4; -} - -inline void mb86901_device::execute_ldfpr(uint32_t op) -{ - const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - - if (!(PSR & PSR_EF_MASK) || m_bp_fpu_present == 0) - { - m_trap = 1; - m_fp_disabled = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (address & 3) - { - m_trap = 1; - m_mem_address_not_aligned = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (m_fpu_sequence_err) - { - m_trap = 1; - m_fp_exception = 1; - m_ftt = m_fpu_sequence_err; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); - - if (m_mae) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - FDREG = data; - - PC = nPC; - nPC = nPC + 4; -} - -inline void mb86901_device::execute_ldfsr(uint32_t op) -{ - const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - - if (!(PSR & PSR_EF_MASK) || m_bp_fpu_present == 0) - { - m_trap = 1; - m_fp_disabled = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (address & 3) - { - m_trap = 1; - m_mem_address_not_aligned = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (m_fpu_sequence_err) - { - m_trap = 1; - m_fp_exception = 1; - m_ftt = m_fpu_sequence_err; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - const uint32_t data = m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); - - if (m_mae) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - FSR = data; - - PC = nPC; - nPC = nPC + 4; -} - -inline void mb86901_device::execute_lddcpr(uint32_t op) -{ - const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - - if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present) - { - m_trap = 1; - m_cp_disabled = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (address & 7) - { - m_trap = 1; - m_mem_address_not_aligned = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (m_cp_sequence_err) - { - m_trap = 1; - m_cp_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - // possibly additional implementation-dependent actions - return; - } - - m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); - if (MAE) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - // implementation-dependent actions - - m_mmu->read_asi(m_data_space, (address + 4) >> 2, 0xffffffff); - if (MAE) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - // implementation-dependent actions - - PC = nPC; - nPC = nPC + 4; -} - -inline void mb86901_device::execute_ldcpr(uint32_t op) -{ - const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - - if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present) - { - m_trap = 1; - m_cp_disabled = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (address & 3) - { - m_trap = 1; - m_mem_address_not_aligned = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (m_cp_sequence_err) - { - m_trap = 1; - m_cp_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - // possibly additional implementation-dependent actions - return; - } - - m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); - - if (MAE) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - // implementation-dependent actions - - PC = nPC; - nPC = nPC + 4; -} - -inline void mb86901_device::execute_ldcsr(uint32_t op) -{ - const uint32_t address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - - if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present) - { - m_trap = 1; - m_cp_disabled = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (address & 3) - { - m_trap = 1; - m_mem_address_not_aligned = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (m_cp_sequence_err) - { - m_trap = 1; - m_cp_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - // possibly additional implementation-dependent actions - return; - } - - m_mmu->read_asi(m_data_space, address >> 2, 0xffffffff); - - if (MAE) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - // implementation-dependent actions - - PC = nPC; - nPC = nPC + 4; -} - -inline void mb86901_device::execute_ldda(uint32_t op) -{ - if (IS_USER) - { - m_trap = 1; - m_privileged_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - else if (USEIMM) - { - m_trap = 1; - m_illegal_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - const uint32_t address = RS1REG + RS2REG; - const uint32_t addr_space = ASI; - - if (address & 7) - { - m_trap = 1; - m_mem_address_not_aligned = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - const uint32_t data = m_mmu->read_asi(addr_space, address >> 2, 0xffffffff); - - if (m_mae) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (RDBITS) - RDREG = data; - - uint32_t word1 = m_mmu->read_asi(addr_space, (address + 4) >> 2, 0xffffffff); - if (MAE) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - REG(RD | 1) = word1; - - PC = nPC; - nPC = nPC + 4; -} - -inline void mb86901_device::execute_lda(uint32_t op) -{ - if (IS_USER) - { - m_trap = 1; - m_privileged_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - else if (USEIMM) - { - m_trap = 1; - m_illegal_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - const uint32_t address = RS1REG + RS2REG; - - if (address & 3) - { - m_trap = 1; - m_mem_address_not_aligned = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - const uint32_t data = m_mmu->read_asi(ASI, address >> 2, 0xffffffff); - - if (m_mae) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (RDBITS) - RDREG = data; - - PC = nPC; - nPC = nPC + 4; -} - -inline void mb86901_device::execute_ldsha(uint32_t op) -{ - if (IS_USER) - { - m_trap = 1; - m_privileged_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - else if (USEIMM) - { - m_trap = 1; - m_illegal_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - const uint32_t address = RS1REG + RS2REG; - - if (address & 1) - { - m_trap = 1; - m_mem_address_not_aligned = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - static const uint32_t mask16[4] = { 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000 }; - const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask16[address & 2]); - - if (m_mae) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (RDBITS) - { - if ((address & 3) == 0) RDREG = (int32_t)data >> 16; - else if ((address & 3) == 2) RDREG = ((int32_t)data << 16) >> 16; - } - - PC = nPC; - nPC = nPC + 4; -} - -inline void mb86901_device::execute_lduha(uint32_t op) -{ - if (IS_USER) - { - m_trap = 1; - m_privileged_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - else if (USEIMM) - { - m_trap = 1; - m_illegal_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - const uint32_t address = RS1REG + RS2REG; - if (address & 1) - { - m_trap = 1; - m_mem_address_not_aligned = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - static const uint32_t mask16[4] = { 0xffff0000, 0x00000000, 0x0000ffff, 0x00000000 }; - const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask16[address & 2]); - - if (m_mae) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (RDBITS) - { - if ((address & 3) == 0) RDREG = data >> 16; - else if ((address & 3) == 2) RDREG = data & 0xffff; - } - - PC = nPC; - nPC = nPC + 4; -} - -inline void mb86901_device::execute_ldsba(uint32_t op) -{ - if (IS_USER) - { - m_trap = 1; - m_privileged_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - else if (USEIMM) - { - m_trap = 1; - m_illegal_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; - const uint32_t address = RS1REG + RS2REG; - const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask8[address & 3]); - - if (m_mae) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (RDBITS) - { - if ((address & 3) == 0) RDREG = (int32_t)data >> 24; - else if ((address & 3) == 1) RDREG = ((int32_t)data << 8) >> 24; - else if ((address & 3) == 2) RDREG = ((int32_t)data << 16) >> 24; - else if ((address & 3) == 3) RDREG = ((int32_t)data << 24) >> 24; - } - - PC = nPC; - nPC = nPC + 4; -} - -inline void mb86901_device::execute_lduba(uint32_t op) -{ - if (IS_USER) - { - m_trap = 1; - m_privileged_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - else if (USEIMM) - { - m_trap = 1; - m_illegal_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; - const uint32_t address = RS1REG + RS2REG; - const uint32_t data = m_mmu->read_asi(ASI, address >> 2, mask8[address & 3]); - - if (m_mae) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - if (RDBITS) - { - if ((address & 3) == 0) RDREG = data >> 24; - else if ((address & 3) == 1) RDREG = (data >> 16) & 0xff; - else if ((address & 3) == 2) RDREG = (data >> 8) & 0xff; - else if ((address & 3) == 3) RDREG = data & 0xff; - } - - PC = nPC; - nPC = nPC + 4; -} - - -//------------------------------------------------- -// execute_ldstub - execute an atomic load-store -// instruction -//------------------------------------------------- - -void mb86901_device::execute_ldstub(uint32_t op) -{ - /* 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_t address = 0; - uint8_t addr_space = 0; - if (LDSTUB) - { - address = RS1REG + (USEIMM ? SIMM13 : RS2REG); - addr_space = (IS_USER ? 10 : 11); - } - else if (LDSTUBA) - { - if (IS_USER) - { - m_trap = 1; - m_privileged_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - else if (USEIMM) - { - m_trap = 1; - m_illegal_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - else - { - address = RS1REG + RS2REG; - addr_space = ASI; - return; - } - } - - uint32_t data(0); - 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; - - static const uint32_t mask8[4] = { 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff }; - data = m_mmu->read_asi(addr_space, address >> 2, mask8[address & 3]); - - if (MAE) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - m_mmu->write_asi(addr_space, address >> 2, 0xffffffff, mask8[address & 3]); - - m_pb_block_ldst_byte = 0; - - if (MAE) - { - m_trap = 1; - m_data_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - - uint32_t 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 (RDBITS) - RDREG = word; - - PC = nPC; - nPC = nPC + 4; -} - - -//------------------------------------------------- -// execute_group3 - execute an opcode in group 3 -// (load/store) -//------------------------------------------------- - -inline void mb86901_device::execute_group3(uint32_t op) -{ - static const int ldst_cycles[64] = { - 1, 1, 1, 2, 2, 2, 2, 3, - 0, 1, 1, 0, 0, 3, 0, 0, - 1, 1, 1, 2, 2, 2, 2, 3, - 0, 1, 1, 0, 0, 3, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - }; - - switch (OP3) - { - case OP3_LD: - execute_ld(op); - break; - case OP3_LDUB: - execute_ldub(op); - break; - case OP3_LDUH: - execute_lduh(op); - break; - case OP3_LDD: - execute_ldd(op); - break; - case OP3_LDSB: - execute_ldsb(op); - break; - case OP3_LDSH: - execute_ldsh(op); - break; - case OP3_LDA: - execute_lda(op); - break; - case OP3_LDUBA: - execute_lduba(op); - break; - case OP3_LDUHA: - execute_lduha(op); - break; - case OP3_LDDA: - execute_ldda(op); - break; - case OP3_LDSBA: - execute_ldsba(op); - break; - case OP3_LDSHA: - execute_ldsha(op); - break; - case OP3_LDFPR: - execute_ldfpr(op); - break; - case OP3_LDFSR: - execute_ldfsr(op); - break; - case OP3_LDDFPR: - execute_lddfpr(op); - break; - case OP3_LDCPR: - execute_ldcpr(op); - break; - case OP3_LDCSR: - execute_ldcsr(op); - break; - case OP3_LDDCPR: - execute_lddcpr(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; - -#if SPARCV8 - case OP3_SWAP: - case OP3_SWAPA: - execute_swap(op); - break; -#endif - - default: - logerror("illegal instruction at %08x: %08x\n", PC, op); - m_trap = 1; - m_illegal_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - break; - } - - if (MAE /*|| HOLD_BUS*/) - m_icount--; - else - m_icount -= ldst_cycles[OP3]; -} - - -//------------------------------------------------- -// evaluate_condition - evaluate a given integer -// condition code -//------------------------------------------------- - -bool mb86901_device::evaluate_condition(uint32_t op) -{ - // COND & 8 - // 0 8 - // bn ba - // bz bne - // ble bg - // bl bge - // bleu bgu - // bcs bcc - // bneg bpos - // bvs bvc - - switch(COND) - { - case 0: return false; - case 1: return ICC_Z_SET; - case 2: return ICC_Z_SET || (ICC_N != ICC_Z); - case 3: return (ICC_N != ICC_V); - case 4: return ICC_C_SET || ICC_Z_SET; - case 5: return ICC_C_SET; - case 6: return ICC_N_SET; - case 7: return ICC_V_SET; - - case 8: return true; - case 9: return ICC_Z_CLEAR; - case 10: return ICC_Z_CLEAR && ICC_N_CLEAR; - case 11: return (ICC_N == ICC_V); - case 12: return ICC_C_CLEAR && ICC_Z_CLEAR; - case 13: return ICC_C_CLEAR; - case 14: return ICC_N_CLEAR; - case 15: return ICC_V_CLEAR; - } - - return false; -} - - -//------------------------------------------------- -// execute_bicc - execute a branch opcode -//------------------------------------------------- - -void mb86901_device::execute_bicc(uint32_t 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_t pc = PC; - PC = nPC; - if (branch_taken) - { - nPC = pc + DISP22; - if (COND == COND_BA && ANNUL) - m_no_annul = false; - } - else - { - nPC = nPC + 4; - if (ANNUL) - m_no_annul = false; - } -} - - -//------------------------------------------------- -// execute_ticc - execute a conditional trap -//------------------------------------------------- - -void mb86901_device::execute_ticc(uint32_t 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_t trap_number = RS1REG + (USEIMM ? SIMM7 : RS2REG); - - if (COND) - { - if (trap_eval_icc) - { - m_trap = 1; - m_trap_instruction = 1; - m_ticc_trap_type = trap_number & 0x7f; - m_stashed_icount = m_icount; - m_icount = 0; - } - else - { - PC = nPC; - nPC = nPC + 4; - } - } -} - - - -//------------------------------------------------- -// select_trap - prioritize traps and perform any -// additional functions from taking them -//------------------------------------------------- - -void mb86901_device::select_trap() -{ - if (!m_trap) - return; - - if (m_reset_trap) - { - m_trap = 0; - return; - } - else if (!m_et) - { - m_execute_mode = 0; - m_error_mode = 1; - m_stashed_icount = m_icount; - m_icount = 0; - } - 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; - - TBR = (TBR & 0xfffff000) | (m_tt << 4); - m_trap = 0; - 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; - m_mae = 0; -} - - -//------------------------------------------------- -// execute_trap - prioritize and invoke traps -// that have been flagged by the previous -// instructions, if any. -//------------------------------------------------- - -void mb86901_device::execute_trap() -{ - /* 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) - { - PSR &= ~PSR_ET_MASK; - m_et = false; - - if (IS_USER) - PSR &= ~PSR_PS_MASK; - else - PSR |= PSR_PS_MASK; - - PSR |= PSR_S_MASK; - m_s = true; - m_data_space = 11; - - int cwp = PSR & PSR_CWP_MASK; - int new_cwp = ((cwp + NWINDOWS) - 1) % NWINDOWS; - - PSR &= ~PSR_CWP_MASK; - PSR |= new_cwp; - - update_gpr_pointers(); - - if (m_no_annul) - { - REG(17) = PC; - REG(18) = nPC; - } - else - { - REG(17) = nPC; - REG(18) = nPC + 4; - m_no_annul = true; - } - - if (!m_reset_trap) - { - PC = TBR; - nPC = TBR + 4; - } - else - { - PC = 0; - nPC = 4; - m_reset_trap = 0; - } - } -} - - -//------------------------------------------------- -// dispatch_instruction - executes a -// single fetched instruction. -//------------------------------------------------- - -/* 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 } -); -*/ - -inline void mb86901_device::dispatch_instruction(uint32_t op) -{ - const uint8_t op_type = OP; - switch (op_type) - { - case OP_TYPE0: // Bicc, SETHI, FBfcc - switch (OP2) - { - case OP2_UNIMP: // unimp - logerror("unimp @ %x\n", PC); - break; - case OP2_BICC: // branch on integer condition codes - execute_bicc(op); - break; - case OP2_SETHI: // sethi - //SET_RDREG(IMM22); - *m_regs[RD] = op << 10; - m_r[0] = 0; - PC = nPC; - nPC = nPC + 4; - break; - case OP2_FBFCC: // branch on floating-point condition codes - if (!(PSR & PSR_EF_MASK) || !m_bp_fpu_present) - { - logerror("fbfcc at %08x: %08x\n", PC, op); - m_trap = 1; - m_fp_disabled = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - break; -#if SPARCV8 - case OP2_CBCCC: // branch on coprocessor condition codes, SPARCv8 - if (!(PSR & PSR_EC_MASK) || !m_bp_cp_present) - { - logerror("cbccc @ %08x: %08x\n", PC, op); - m_trap = 1; - m_cp_disabled = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - return; -#endif - default: - logerror("illegal instruction at %08x: %08x\n", PC, op); - m_trap = 1; - m_illegal_instruction = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - break; - - case OP_CALL: - { - uint32_t pc = PC; - uint32_t 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; - } -} - -//------------------------------------------------- -// complete_fp_execution - completes execution -// of a floating-point operation -//------------------------------------------------- - -void mb86901_device::complete_fp_execution(uint32_t /*op*/) -{ -} - -//------------------------------------------------- -// execute_step - perform one step in execute -// mode (versus error or reset modes) -//------------------------------------------------- - -inline 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 - ) - ) - ) - */ - - // write-state-register delay not yet implemented - - const uint32_t op = m_mmu->fetch_insn(m_s, PC >> 2); - -#if LOG_FCODES - //if (m_log_fcodes) - { - log_fcodes(); - } -#endif - - if (m_no_annul) - { - if (MAE) - { - m_trap = 1; - m_instruction_access_exception = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - dispatch_instruction(op); - } - else - { - m_no_annul = true; - PC = nPC; - nPC = nPC + 4; - } -} - - -//------------------------------------------------- -// reset_step - step one cycle in reset mode -//------------------------------------------------- - -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; - m_stashed_icount = m_icount; - m_icount = 0; - } -} - - -//------------------------------------------------- -// 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; - m_stashed_icount = m_icount; - m_icount = 0; - } -} - -template <bool CHECK_DEBUG, mb86901_device::running_mode MODE> -void mb86901_device::run_loop() -{ - do - { - /*if (HOLD_BUS) - { - m_icount--; - continue; - }*/ - - if (CHECK_DEBUG) - debugger_instruction_hook(PC); - - if (MODE == MODE_RESET) - { - reset_step(); - } - else if (MODE == MODE_ERROR) - { - error_step(); - } - else if (MODE == MODE_EXECUTE) - { - execute_step(); - } - - if (CHECK_DEBUG) - { - for (int i = 0; i < 8; i++) - { - m_dbgregs[i] = *m_regs[8 + i]; - m_dbgregs[8 + i] = *m_regs[16 + i]; - m_dbgregs[16 + i] = *m_regs[24 + i]; - } - } - --m_icount; - } while (m_icount >= 0); -} - -//------------------------------------------------- -// execute_run - execute a timeslice's worth of -// opcodes -//------------------------------------------------- - -void mb86901_device::execute_run() -{ - bool debug = machine().debug_flags & DEBUG_FLAG_ENABLED; - - if (m_bp_reset_in) - { - m_execute_mode = 0; - m_error_mode = 0; - m_reset_mode = 1; - m_stashed_icount = m_icount; - m_icount = 0; - return; - } - else if (m_et && (m_bp_irl == 15 || m_bp_irl > m_pil)) - { - m_trap = 1; - m_interrupt_level = m_bp_irl; - } - - do - { - if (m_trap) - { - execute_trap(); - } - - if (debug) - { - if (m_reset_mode) - run_loop<true, MODE_RESET>(); - else if (m_error_mode) - run_loop<true, MODE_ERROR>(); - else - run_loop<true, MODE_EXECUTE>(); - } - else - { - if (m_reset_mode) - run_loop<false, MODE_RESET>(); - else if (m_error_mode) - run_loop<false, MODE_ERROR>(); - else - run_loop<false, MODE_EXECUTE>(); - } - - if (m_stashed_icount >= 0) - { - m_icount = m_stashed_icount; - m_stashed_icount = -1; - } - } while (m_icount >= 0); -} - - -//------------------------------------------------- -// get_reg_r - get integer register value for -// disassembler -//------------------------------------------------- - -uint64_t mb86901_device::get_reg_r(unsigned index) const -{ - return REG(index & 31); -} - - -//------------------------------------------------- -// get_reg_pc - get program counter value for -// disassembler -//------------------------------------------------- - -uint64_t mb86901_device::get_translated_pc() const -{ - // FIXME: how do we apply translation to the address so it's in the same space the disassembler sees? - return m_pc; -} - - -//------------------------------------------------- -// get_icc - get integer condition codes for -// disassembler -//------------------------------------------------- - -uint8_t mb86901_device::get_icc() const -{ - return (m_psr & PSR_ICC_MASK) >> PSR_ICC_SHIFT; -} - - -//------------------------------------------------- -// get_icc - get extended integer condition codes -// for disassembler -//------------------------------------------------- - -uint8_t mb86901_device::get_xcc() const -{ - // not present before SPARCv9 - return 0; -} - - -//------------------------------------------------- -// get_icc - get extended integer condition codes -// for disassembler -//------------------------------------------------- - -uint8_t mb86901_device::get_fcc(unsigned index) const -{ - // only one fcc instance before SPARCv9 - return (m_fsr >> 10) & 3; -} |