summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/sparc/mb86901.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/sparc/mb86901.cpp')
-rw-r--r--src/devices/cpu/sparc/mb86901.cpp4195
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;
-}