Merge pull request #989 from MooglyGuy/master

Rewrite SPARC emulation based on detailed descriptions from SPARC manual [Ryan Holtz]
This commit is contained in:
Vas Crabb 2016-06-23 10:32:26 +10:00 committed by GitHub
commit b68b262e1b
3 changed files with 2710 additions and 956 deletions

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,7 @@
#define SPARC_INSTRUCTION_ACCESS_EXCEPTION 1
#define SPARC_ILLEGAL_INSTRUCTION 2
#define SPARC_PRIVILEGED_INSTRUCTION 3
#define SPARC_FLOATING_POINT_DISABLED 4
#define SPARC_FP_DISABLED 4
#define SPARC_WINDOW_OVERFLOW 5
#define SPARC_WINDOW_UNDERFLOW 6
#define SPARC_MEM_ADDRESS_NOT_ALIGNED 7
@ -40,6 +40,7 @@
#define SPARC_INT15 31
#define SPARC_TRAP_INSTRUCTION 128
#define SPARC_FPU_SEQUENCE_ERROR
// TODO: when there are more SPARC CPUs, move setter to a base class
#define MCFG_SPARC_ADD_ASI_DESC(desc) \
mb86901_device::add_asi_desc(*device, desc);
@ -85,35 +86,56 @@ public:
protected:
template<typename T> void add_asi_desc(const T &desc) { m_dasm.add_asi_desc(desc); }
bool invoke_queued_traps();
bool check_main_traps(UINT32 op, bool privileged, UINT32 alignment, UINT8 registeralign, bool noimmediate);
void update_gpr_pointers();
void save_restore_update_cwp(UINT32 op, UINT8 new_cwp);
bool execute_group2(UINT32 op);
void execute_add(UINT32 op);
void execute_taddcc(UINT32 op);
void execute_sub(UINT32 op);
void execute_tsubcc(UINT32 op);
void execute_logical(UINT32 op);
void execute_shift(UINT32 op);
void execute_mulscc(UINT32 op);
void execute_rdsr(UINT32 op);
void execute_wrsr(UINT32 op);
void execute_rett(UINT32 op);
void execute_saverestore(UINT32 op);
void execute_jmpl(UINT32 op);
void execute_group2(UINT32 op);
void execute_load(UINT32 op);
void execute_store(UINT32 op);
void execute_ldstub(UINT32 op);
void execute_group3(UINT32 op);
bool execute_bicc(UINT32 op);
bool execute_ticc(UINT32 op);
bool evaluate_condition(UINT32 op);
void execute_bicc(UINT32 op);
void execute_ticc(UINT32 op);
void select_trap();
void execute_trap();
void complete_instruction_execution(UINT32 op);
void dispatch_instruction(UINT32 op);
void complete_fp_execution(UINT32 /*op*/);
void execute_step();
void reset_step();
void error_step();
// address spaces
const address_space_config m_program_config;
// memory access
UINT32 read_byte(UINT8 asi, UINT32 address);
INT32 read_signed_byte(UINT8 asi, UINT32 address);
UINT32 read_half(UINT8 asi, UINT32 address);
INT32 read_signed_half(UINT8 asi, UINT32 address);
UINT32 read_word(UINT8 asi, UINT32 address);
UINT64 read_doubleword(UINT8 asi, UINT32 address);
void write_byte(UINT8 asi, UINT32 address, UINT8 data);
void write_half(UINT8 asi, UINT32 address, UINT16 data);
void write_word(UINT8 asi, UINT32 address, UINT32 data);
void write_doubleword(UINT8 asi, UINT32 address, UINT64 data);
UINT32 read_sized_word(UINT8 asi, UINT32 address, int size);
void write_sized_word(UINT8 asi, UINT32 address, UINT32 data, int size);
// general-purpose registers
UINT32 m_r[120];
// FPU registers
UINT32 m_fpr[32];
UINT32 m_fsr;
UINT8 m_ftt;
// control/status registers
UINT32 m_pc;
UINT32 m_npc;
@ -122,6 +144,45 @@ protected:
UINT32 m_tbr;
UINT32 m_y;
bool m_bp_reset_in;
UINT8 m_bp_irl;
bool m_bp_fpu_present;
bool m_bp_cp_present;
bool m_pb_error;
bool m_pb_block_ldst_byte;
bool m_pb_block_ldst_word;
// trap and error registers
bool m_trap;
UINT8 m_tt;
UINT8 m_ticc_trap_type;
UINT8 m_interrupt_level;
bool m_privileged_instruction;
bool m_illegal_instruction;
bool m_mem_address_not_aligned;
bool m_fp_disabled;
bool m_fp_exception;
bool m_cp_disabled; // SPARCv8
bool m_cp_exception; // SPARCv8
bool m_unimplemented_FLUSH; // SPARCv8
bool m_r_register_access_error; // SPARCv8
bool m_instruction_access_error; // SPARCv8
bool m_instruction_access_exception;
bool m_data_access_error; // SPARCv8
bool m_data_store_error; // SPARCv8
bool m_data_access_exception;
bool m_division_by_zero; // SPARCv8
bool m_trap_instruction;
bool m_window_underflow;
bool m_window_overflow;
bool m_tag_overflow;
bool m_reset_mode;
bool m_reset_trap;
bool m_execute_mode;
bool m_error_mode;
UINT8 m_fpu_sequence_err;
UINT8 m_cp_sequence_err;
// fields separated out from PSR (Processor State Register)
UINT8 m_impl; // implementation (always 0 in MB86901)
UINT8 m_ver; // version (always 0 in MB86901)
@ -134,19 +195,20 @@ protected:
bool m_et; // enable traps
UINT8 m_cwp; // current window pointer
bool m_alu_op3_assigned[64];
bool m_ldst_op3_assigned[64];
// register windowing helpers
UINT32* m_regs[32];
// addressing helpers
UINT8 m_insn_asi;
UINT8 m_data_asi;
UINT8 m_asi;
// other internal states
UINT32 m_trap_priorities[256];
UINT32 m_queued_tt;
UINT32 m_queued_priority;
bool m_privileged_asr[32];
bool m_illegal_instruction_asr[32];
bool m_mae;
bool m_annul;
bool m_hold_bus;
int m_icount;
@ -158,7 +220,7 @@ protected:
address_space *m_program;
// processor configuration
static const int WINDOW_COUNT;
static const int NWINDOWS;
};
// device type definition

View File

@ -12,8 +12,6 @@
#ifndef __MB86901_DEFS_H__
#define __MB86901_DEFS_H__
#define GET_OPCODE 0; { m_asi = m_insn_asi; op = m_program->read_dword(m_pc); }
#define PSR_CWP_MASK 0x0000001f
#define PSR_ET_SHIFT 5
#define PSR_ET_MASK 0x00000020
@ -43,21 +41,25 @@
#define PSR_ZERO_MASK (PSR_IMPL_MASK | PSR_VER_MASK | PSR_RES_MASK)
#define ICC_N_SET (m_psr & PSR_N_MASK)
#define ICC_N (ICC_N_SET ? 1 : 0)
#define ICC_N_CLEAR (!ICC_N_SET)
#define SET_ICC_N_FLAG do { m_psr |= PSR_N_MASK; } while(0);
#define CLEAR_ICC_N_FLAG do { m_psr &= ~PSR_N_MASK; } while(0);
#define ICC_Z_SET (m_psr & PSR_Z_MASK)
#define ICC_Z (ICC_Z_SET ? 1 : 0)
#define ICC_Z_CLEAR (!ICC_Z_SET)
#define SET_ICC_Z_FLAG do { m_psr |= PSR_Z_MASK; } while(0);
#define CLEAR_ICC_Z_FLAG do { m_psr &= ~PSR_Z_MASK; } while(0);
#define ICC_V_SET (m_psr & PSR_V_MASK)
#define ICC_V_CLEAR (!ICC_B_SET)
#define ICC_V (ICC_V_SET ? 1 : 0)
#define ICC_V_CLEAR (!ICC_V_SET)
#define SET_ICC_V_FLAG do { m_psr |= PSR_V_MASK; } while(0);
#define CLEAR_ICC_V_FLAG do { m_psr &= ~PSR_V_MASK; } while(0);
#define ICC_C_SET (m_psr & PSR_C_MASK)
#define ICC_C (ICC_C_SET ? 1 : 0)
#define ICC_C_CLEAR (!ICC_C_SET)
#define SET_ICC_C_FLAG do { m_psr |= PSR_C_MASK; } while(0);
#define CLEAR_ICC_C_FLAG do { m_psr &= ~PSR_C_MASK; } while(0);
@ -66,18 +68,23 @@
#define TEST_ICC_NZ(x) do { m_psr &= ~PSR_ICC_MASK; m_psr |= (x & 0x80000000) ? PSR_N_MASK : 0; m_psr |= (x == 0) ? PSR_Z_MASK : 0; } while (0);
#define MAKE_PSR do { m_psr = (m_impl << PSR_IMPL_SHIFT) | (m_ver << PSR_VER_SHIFT) | (m_icc << PSR_ICC_SHIFT) | (m_ec ? PSR_EC_MASK : 0) | (m_ef ? PSR_EF_MASK : 0) | (m_pil << PSR_PIL_SHIFT) | (m_s ? PSR_S_MASK : 0) | (m_ps ? PSR_PS_MASK : 0) | (m_et ? PSR_ET_MASK : 0) | m_cwp; m_insn_asi = m_s ? 9 : 8; m_data_asi = m_s ? 11 : 10; } while(0);
#define BREAK_PSR do { m_icc = (m_psr & PSR_ICC_MASK) >> PSR_ICC_SHIFT; m_ec = m_psr & PSR_EC_MASK; m_ef = m_psr & PSR_EF_MASK; m_pil = (m_psr & PSR_PIL_MASK) >> PSR_PIL_SHIFT; m_s = m_psr & PSR_S_MASK; m_ps = m_psr & PSR_PS_MASK; m_et = m_psr & PSR_ET_MASK; m_cwp = m_psr & PSR_CWP_MASK; m_insn_asi = m_s ? 9 : 8; m_data_asi = m_s ? 11 : 10; } while(0);
#define MAKE_PSR do { m_psr = (m_impl << PSR_IMPL_SHIFT) | (m_ver << PSR_VER_SHIFT) | (m_icc << PSR_ICC_SHIFT) | (m_ec ? PSR_EC_MASK : 0) | (m_ef ? PSR_EF_MASK : 0) | (m_pil << PSR_PIL_SHIFT) | (m_s ? PSR_S_MASK : 0) | (m_ps ? PSR_PS_MASK : 0) | (m_et ? PSR_ET_MASK : 0) | m_cwp; } while(0);
#define BREAK_PSR do { m_icc = (m_psr & PSR_ICC_MASK) >> PSR_ICC_SHIFT; m_ec = m_psr & PSR_EC_MASK; m_ef = m_psr & PSR_EF_MASK; m_pil = (m_psr & PSR_PIL_MASK) >> PSR_PIL_SHIFT; m_s = m_psr & PSR_S_MASK; m_ps = m_psr & PSR_PS_MASK; m_et = m_psr & PSR_ET_MASK; m_cwp = m_psr & PSR_CWP_MASK; } while(0);
#define MAKE_ICC do { m_icc = (m_psr & PSR_ICC_MASK) >> PSR_ICC_SHIFT; } while(0);
#define CWP m_cwp
#define S m_s
#define PS m_ps
#define IS_SUPERVISOR (m_psr & PSR_S_MASK)
#define IS_USER (!IS_SUPERVISOR)
#define TRAPS_ENABLED (m_psr & PSR_ET_MASK)
#define TRAPS_DISABLED (!TRAPS_ENABLED)
#define FPU_ENABLED (m_psr & PSR_EF_MASK)
#define FPU_DISABLED (!FPU_ENABLED)
#define PSR m_psr
#define WIM m_wim
#define TBR m_tbr
#define OP (op >> 30) // gangnam style
#define OP2 ((op >> 22) & 7)
@ -121,11 +128,15 @@
#define RS1 ((op >> 14) & 31)
#define RS2 (op & 31)
#define REG(x) *m_regs[x]
#define FREG(x) m_fpr[(x)]
#define FDREG m_fpr[RD]
#define FSR m_fsr
#define REG(x) *m_regs[(x)]
#define RDREG *m_regs[RD]
#define RS1REG *m_regs[RS1]
#define RS2REG *m_regs[RS2]
#define SET_RDREG(x) if(RD) { RDREG = x; }
#define SET_RDREG(x) if(RD) { RDREG = (x); }
#define ADDRESS (USEIMM ? (RS1REG + SIMM13) : (RS1REG + RS2REG))
#define PC m_pc
@ -134,8 +145,180 @@
#define Y m_y
#define ET m_et
#define EF m_ef
#define EC m_ec
#define PIL m_pil
#define MAE m_mae
#define HOLD_BUS m_hold_bus
#define BIT31(x) ((x) & 0x80000000)
#define UPDATE_PC true
#define PC_UPDATED false
#define OP_TYPE0 0
#define OP_CALL 1
#define OP_ALU 2
#define OP_LDST 3
#define OP2_UNIMP 0
#define OP2_BICC 2
#define OP2_SETHI 4
#define OP2_FBFCC 6
#define OP2_CBCCC 7
#define OP3_ADD 0
#define OP3_AND 1
#define OP3_OR 2
#define OP3_XOR 3
#define OP3_SUB 4
#define OP3_ANDN 5
#define OP3_ORN 6
#define OP3_XNOR 7
#define OP3_ADDX 8
#define OP3_UMUL 10
#define OP3_SMUL 11
#define OP3_SUBX 12
#define OP3_UDIV 14
#define OP3_SDIV 15
#define OP3_ADDCC 16
#define OP3_ANDCC 17
#define OP3_ORCC 18
#define OP3_XORCC 19
#define OP3_SUBCC 20
#define OP3_ANDNCC 21
#define OP3_ORNCC 22
#define OP3_XNORCC 23
#define OP3_ADDXCC 24
#define OP3_UMULCC 26
#define OP3_SMULCC 27
#define OP3_SUBXCC 28
#define OP3_UDIVCC 30
#define OP3_SDIVCC 31
#define OP3_TADDCC 32
#define OP3_TSUBCC 33
#define OP3_TADDCCTV 34
#define OP3_TSUBCCTV 35
#define OP3_MULSCC 36
#define OP3_SLL 37
#define OP3_SRL 38
#define OP3_SRA 39
#define OP3_RDASR 40
#define OP3_RDPSR 41
#define OP3_RDWIM 42
#define OP3_RDTBR 43
#define OP3_WRASR 48
#define OP3_WRPSR 49
#define OP3_WRWIM 50
#define OP3_WRTBR 51
#define OP3_FPOP1 52
#define OP3_FPOP2 53
#define OP3_JMPL 56
#define OP3_RETT 57
#define OP3_TICC 58
#define OP3_SAVE 60
#define OP3_RESTORE 61
#define OP3_LD 0
#define OP3_LDUB 1
#define OP3_LDUH 2
#define OP3_LDD 3
#define OP3_ST 4
#define OP3_STB 5
#define OP3_STH 6
#define OP3_STD 7
#define OP3_LDSB 9
#define OP3_LDSH 10
#define OP3_LDSTUB 13
#define OP3_SWAP 15
#define OP3_LDA 16
#define OP3_LDUBA 17
#define OP3_LDUHA 18
#define OP3_LDDA 19
#define OP3_STA 20
#define OP3_STBA 21
#define OP3_STHA 22
#define OP3_STDA 23
#define OP3_LDSBA 25
#define OP3_LDSHA 26
#define OP3_LDSTUBA 29
#define OP3_SWAPA 31
#define OP3_LDFPR 32
#define OP3_LDFSR 33
#define OP3_LDDFPR 35
#define OP3_STFPR 36
#define OP3_STFSR 37
#define OP3_STDFQ 38
#define OP3_STDFPR 39
#define OP3_LDCPR 40
#define OP3_LDCSR 41
#define OP3_LDDCPR 43
#define OP3_STCPR 44
#define OP3_STCSR 45
#define OP3_STDCQ 46
#define OP3_STDCPR 47
#define OP3_CPOP1 54
#define OP3_CPOP2 55
#define COND_BN 0
#define COND_BE 1
#define COND_BLE 2
#define COND_BL 3
#define COND_BLEU 4
#define COND_BCS 5
#define COND_BNEG 6
#define COND_BVS 7
#define COND_BA 8
#define COND_BNE 9
#define COND_BG 10
#define COND_BGE 11
#define COND_BGU 12
#define COND_BCC 13
#define COND_BPOS 14
#define COND_BVC 15
#define LDD (OP3 == OP3_LDD)
#define LD (OP3 == OP3_LD)
#define LDSH (OP3 == OP3_LDSH)
#define LDUH (OP3 == OP3_LDUH)
#define LDSB (OP3 == OP3_LDSB)
#define LDUB (OP3 == OP3_LDUB)
#define LDDF (OP3 == OP3_LDDFPR)
#define LDF (OP3 == OP3_LDFPR)
#define LDFSR (OP3 == OP3_LDFSR)
#define LDDC (OP3 == OP3_LDDCPR)
#define LDC (OP3 == OP3_LDCPR)
#define LDCSR (OP3 == OP3_LDCSR)
#define LDDA (OP3 == OP3_LDDA)
#define LDA (OP3 == OP3_LDA)
#define LDSHA (OP3 == OP3_LDSHA)
#define LDUHA (OP3 == OP3_LDUHA)
#define LDSBA (OP3 == OP3_LDSBA)
#define LDUBA (OP3 == OP3_LDUBA)
#define STD (OP3 == OP3_STD)
#define ST (OP3 == OP3_ST)
#define STH (OP3 == OP3_STH)
#define STB (OP3 == OP3_STB)
#define STDA (OP3 == OP3_STDA)
#define STA (OP3 == OP3_STA)
#define STHA (OP3 == OP3_STHA)
#define STBA (OP3 == OP3_STBA)
#define STF (OP3 == OP3_STFPR)
#define STFSR (OP3 == OP3_STFSR)
#define STDFQ (OP3 == OP3_STDFQ)
#define STDF (OP3 == OP3_STDFPR)
#define STC (OP3 == OP3_STCPR)
#define STCSR (OP3 == OP3_STCSR)
#define STDCQ (OP3 == OP3_STDCQ)
#define STDC (OP3 == OP3_STDCPR)
#define JMPL (OP3 == OP3_JMPL)
#define TICC (OP3 == OP3_TICC)
#define RETT (OP3 == OP3_RETT)
#define LDSTUB (OP3 == OP3_LDSTUB)
#define LDSTUBA (OP3 == OP3_LDSTUBA)
#endif // __MB86901_DEFS_H__