--- previous/src/dimension/i860.hpp 2018/04/24 19:30:01 1.1 +++ previous/src/dimension/i860.hpp 2018/04/24 19:33:26 1.1.1.3 @@ -23,14 +23,13 @@ #include #include #include -#include +#include #include - +#include + #include "i860cfg.h" -#include "nd_sdl.h" - -const int LOG_WARN = 3; -extern "C" void Log_Printf(int nType, const char *psFormat, ...); +#include "host.h" +#include "nd_sdl.hpp" typedef uint64_t UINT64; typedef int64_t INT64; @@ -45,48 +44,131 @@ typedef uint8_t UINT8; typedef int8_t INT8; typedef int64_t offs_t; + +extern "C" { + class NextDimension; + + void nd_nbic_interrupt(void); + void Statusbar_SetNdLed(int state); + typedef void (*mem_rd_func)(NextDimension*, UINT32, UINT32*); + typedef void (*mem_wr_func)(NextDimension*, UINT32, const UINT32*); +} +#if WITH_SOFTFLOAT_I860 extern "C" { - UINT8 nd_board_cs8get(UINT32 addr); - UINT8 nd_board_bget(UINT32 addr); - void nd_board_bput(UINT32 addr, UINT8 val); - UINT16 nd_board_wget(UINT32 addr); - void nd_board_wput(UINT32 addr, UINT16 val); - UINT32 nd_board_lget(UINT32 addr); - void nd_board_lput(UINT32 addr, UINT32 val); - void nd_board_put (UINT32 addr, UINT32 val); - - void nd_board_rd8_le (UINT32 addr, UINT32* val); - void nd_board_rd16_le (UINT32 addr, UINT32* val); - void nd_board_rd32_le (UINT32 addr, UINT32* val); - void nd_board_rd64_le (UINT32 addr, UINT32* val); - void nd_board_rd128_le(UINT32 addr, UINT32* val); - - void nd_board_rd8_be (UINT32 addr, UINT32* val); - void nd_board_rd16_be (UINT32 addr, UINT32* val); - void nd_board_rd32_be (UINT32 addr, UINT32* val); - void nd_board_rd64_be (UINT32 addr, UINT32* val); - void nd_board_rd128_be(UINT32 addr, UINT32* val); - - void nd_board_wr8_le (UINT32 addr, const UINT32* val); - void nd_board_wr16_le (UINT32 addr, const UINT32* val); - void nd_board_wr32_le (UINT32 addr, const UINT32* val); - void nd_board_wr64_le (UINT32 addr, const UINT32* val); - void nd_board_wr128_le(UINT32 addr, const UINT32* val); - - void nd_board_wr8_be (UINT32 addr, const UINT32* val); - void nd_board_wr16_be (UINT32 addr, const UINT32* val); - void nd_board_wr32_be (UINT32 addr, const UINT32* val); - void nd_board_wr64_be (UINT32 addr, const UINT32* val); - void nd_board_wr128_be(UINT32 addr, const UINT32* val); +#include +} +typedef float32 FLOAT32; +typedef float64 FLOAT64; - void nd_nbic_interrupt(void); - bool nd_dbg_cmd(const char* cmd); - void Statusbar_SetNdLed(int state); +#define FLOAT32_ZERO 0x00000000 +#define FLOAT32_ONE 0x3F800000 +#define FLOAT32_IS_NEG(x) ((x) & 0x80000000) +#define FLOAT32_IS_ZERO(x) (((x) & 0x7FFFFFFF) == 0x00000000) +#define FLOAT64_ZERO LIT64(0x0000000000000000) +#define FLOAT64_ONE LIT64(0x3FF0000000000000) +#define FLOAT64_IS_NEG(x) ((x) & LIT64(0x8000000000000000)) +#define FLOAT64_IS_ZERO(x) (((x) & LIT64(0x7FFFFFFFFFFFFFFF)) == LIT64(0x0000000000000000)) + +#define float32_add(x,y) float32_add(x,y,&m_fpcs) +#define float32_sub(x,y) float32_sub(x,y,&m_fpcs) +#define float32_mul(x,y) float32_mul(x,y,&m_fpcs) +#define float32_div(x,y) float32_div(x,y,&m_fpcs) +#define float32_sqrt(x) float32_sqrt(x,&m_fpcs) +#define float32_to_int32(x) float32_to_int32(x,&m_fpcs) +#define float32_to_int32_round_to_zero(x) float32_to_int32_round_to_zero(x,&m_fpcs) +#define float32_to_float64(x) float32_to_float64(x,&m_fpcs) +#define float32_gt(x,y) float32_gt(x,y,&m_fpcs) +#define float32_le(x,y) float32_le(x,y,&m_fpcs) +#define float32_eq(x,y) float32_eq(x,y,&m_fpcs) +#define float64_add(x,y) float64_add(x,y,&m_fpcs) +#define float64_sub(x,y) float64_sub(x,y,&m_fpcs) +#define float64_mul(x,y) float64_mul(x,y,&m_fpcs) +#define float64_div(x,y) float64_div(x,y,&m_fpcs) +#define float64_sqrt(x) float64_sqrt(x,&m_fpcs) +#define float64_to_int32(x) float64_to_int32(x,&m_fpcs) +#define float64_to_int32_round_to_zero(x) float64_to_int32_round_to_zero(x,&m_fpcs) +#define float64_to_float32(x) float64_to_float32(x,&m_fpcs) +#define float64_gt(x,y) float64_gt(x,y,&m_fpcs) +#define float64_le(x,y) float64_le(x,y,&m_fpcs) +#define float64_eq(x,y) float64_eq(x,y,&m_fpcs) + +static inline void reset_fpcs(float_ctrl* fp_control) { + float_init(fp_control); +} + +static inline void float_set_rounding_mode (int mode, float_ctrl* fp_control) { + switch (mode) { + case 0: set_float_rounding_mode(float_round_nearest_even, fp_control); break; + case 1: set_float_rounding_mode(float_round_down, fp_control); break; + case 2: set_float_rounding_mode(float_round_up, fp_control); break; + case 3: set_float_rounding_mode(float_round_to_zero, fp_control); break; + } +} + +#else // NATIVE FLOAT + +#include +#ifdef __MINGW32__ +#define _GLIBCXX_HAVE_FENV_H 1 +#endif +#include +#if __APPLE__ +#else +#pragma STDC FENV_ACCESS ON +#endif + +typedef float FLOAT32; +typedef double FLOAT64; + +#define float_ctrl int + +#define FLOAT32_ZERO 0.0 +#define FLOAT32_ONE 1.0 +#define FLOAT32_IS_NEG(x) ((x) < 0.0) +#define FLOAT32_IS_ZERO(x) ((x) == 0.0) +#define FLOAT64_ZERO 0.0 +#define FLOAT64_ONE 1.0 +#define FLOAT64_IS_NEG(x) ((x) < 0.0) +#define FLOAT64_IS_ZERO(x) ((x) == 0.0) + +#define float32_add(x,y) ((x)+(y)) +#define float32_sub(x,y) ((x)-(y)) +#define float32_mul(x,y) ((x)*(y)) +#define float32_div(x,y) ((x)/(y)) +#define float32_sqrt(x) (sqrt(x)) +#define float32_to_int32(x) (rint(x)) +#define float32_to_int32_round_to_zero(x) ((UINT32)(x)) +#define float32_to_float64(x) ((double)(x)) +#define float32_gt(x,y) ((x)>(y)) +#define float32_le(x,y) ((x)<=(y)) +#define float32_eq(x,y) ((x)==(y)) +#define float64_add(x,y) ((x)+(y)) +#define float64_sub(x,y) ((x)-(y)) +#define float64_mul(x,y) ((x)*(y)) +#define float64_div(x,y) ((x)/(y)) +#define float64_sqrt(x) (sqrt(x)) +#define float64_to_int32(x) (rint(x)) +#define float64_to_int32_round_to_zero(x) ((UINT32)(x)) +#define float64_to_float32(x) ((float)(x)) +#define float64_gt(x,y) ((x)>(y)) +#define float64_le(x,y) ((x)<=(y)) +#define float64_eq(x,y) ((x)==(y)) + +static inline void reset_fpcs(float_ctrl* dummy) { + *dummy = 0; +} + +static inline void float_set_rounding_mode (int mode, float_ctrl* dummy) { + switch (mode) { + case 0: fesetround(FE_TONEAREST); break; + case 1: fesetround(FE_DOWNWARD); break; + case 2: fesetround(FE_UPWARD); break; + case 3: fesetround(FE_TOWARDZERO); break; + } } +#endif // NATIVE FLOAT -typedef void (*mem_rd_func)(UINT32, UINT32*); -typedef void (*mem_wr_func)(UINT32, const UINT32*); /*************************************************************************** REGISTER ENUMERATION @@ -122,11 +204,13 @@ enum { }; enum { - MSG_NONE = 0x00, - MSG_I860_RESET = 0x01, - MSG_I860_KILL = 0x02, - MSG_DBG_BREAK = 0x04, - MSG_INTR = 0x08, + MSG_NONE = 0x00, + MSG_I860_RESET = 0x01, + MSG_I860_KILL = 0x02, + MSG_DBG_BREAK = 0x04, + MSG_INTR = 0x08, + MSG_DISPLAY_BLANK = 0x10, + MSG_VIDEO_BLANK = 0x20, }; /* dual mode instruction state */ @@ -337,48 +421,46 @@ public: return name; } }; + +class NextDimension; class i860_cpu_device { -public: +public: + NextDimension* nd; + // construction/destruction - i860_cpu_device(); + i860_cpu_device(NextDimension* nd); /* External interface */ - void send_msg(int msg); - void init(); - void uninit(); + void init(void); + void set_run_func(void); + void uninit(void); void halt(bool state); - inline bool is_halted() {return m_halt;}; - + void pause(bool state); + inline bool is_halted(void) {return m_halt;}; + + /* i860 cycle counter */ + int i860cycles; /* Run one i860 cycle */ - void run_cycle(); + void run_cycle(void); /* Run the i860 thread */ void run(); - /* i860 thread message handler */ - bool handle_msgs(); - /* External tick event for the i860 emulator to update real-time dependent state + interrupt flag */ - void tick(bool intr); - /* Lock acquired by debugger to block other threads (e.g. m68k) */ - lock_t m_debugger_lock; + /* i860 thread message handler */ + bool handle_msgs(int msg); + + static int thread(void* data); -#if ENABLE_PERF_COUNTERS - UINT64 m_m68k_cylces; -#endif - + const char* reports(double realTime, double hostTIme); private: // debugger void debugger(char cmd, const char* format, ...); - void debugger(); + void debugger(void); - /* Message port for host->i860 communication */ - volatile int m_port; - lock_t m_port_lock; + // softfloat control and status + float_ctrl m_fpcs; -#if ENABLE_I860_THREAD - thread_t* m_thread; -#endif + thread_t* m_thread; -#if ENABLE_PERF_COUNTERS UINT64 m_insn_decoded; UINT64 m_icache_hit; UINT64 m_icache_miss; @@ -387,15 +469,13 @@ private: UINT64 m_tlb_miss; UINT64 m_tlb_inval; UINT64 m_intrs; - UINT32 m_time_delta_ms; - UINT32 m_abs_time_ms; - - void dump_reset_perfc(); -#endif - + UINT32 m_last_rt; + UINT32 m_last_vt; + char m_report[1024]; + /* Debugger stuff */ char m_lastcmd; - char m_console[512*1024]; + char m_console[32*1024]; int m_console_idx; bool m_break_on_next_msg; UINT32 m_traceback[256]; @@ -427,8 +507,8 @@ private: /* Special registers (4 x 64-bits). */ union { - float s; - double d; + FLOAT32 s; + FLOAT64 d; } m_KR, m_KI, m_T; UINT64 m_merge; @@ -438,8 +518,8 @@ private: { /* The stage contents. */ union { - float s; - double d; + FLOAT32 s; + FLOAT64 d; } val; /* The stage status bits. */ @@ -454,8 +534,8 @@ private: struct { /* The stage contents. */ union { - float s; - double d; + FLOAT32 s; + FLOAT64 d; } val; /* The stage status bits. */ @@ -469,8 +549,8 @@ private: struct { /* The stage contents. */ union { - float s; - double d; + FLOAT32 s; + FLOAT64 d; } val; /* The stage status bits. */ @@ -484,8 +564,8 @@ private: struct { /* The stage contents. */ union { - float s; - double d; + FLOAT32 s; + FLOAT64 d; } val; /* The stage status bits. */ @@ -507,7 +587,7 @@ private: * Halt state. Can be set externally */ volatile bool m_halt; - + /* Indicate an instruction just generated a trap, needs to go to the trap address or a control-flow instruction, so we know the PC is updated. */ @@ -522,9 +602,9 @@ private: void set_mem_access(bool be); UINT8 rdcs8(UINT32 addr); - void writemem_emu(UINT32 addr, int size, UINT8 *data); - void writemem_emu(UINT32 addr, int size, UINT8 *data, UINT32 wmask); - void readmem_emu (UINT32 addr, int size, UINT8 *data); + inline void writemem_emu(UINT32 addr, int size, UINT8 *data); + inline void writemem_emu(UINT32 addr, int size, UINT8 *data, UINT32 wmask); + inline void readmem_emu (UINT32 addr, int size, UINT8 *data); /* instructions */ void insn_ld_ctrl (UINT32 insn); @@ -594,21 +674,25 @@ private: void insn_form (UINT32 insn); void insn_faddp (UINT32 insn); void insn_faddz (UINT32 insn); - + + void dec_unrecog (UINT32 insn); + /* register access */ UINT32 get_iregval(int gr); void set_iregval(int gr, UINT32 val); - float get_fregval_s (int fr); - void set_fregval_s (int fr, float s); - double get_fregval_d (int fr); - void set_fregval_d (int fr, double d); + FLOAT32 get_fregval_s (int fr); + void set_fregval_s (int fr, FLOAT32 s); + FLOAT64 get_fregval_d (int fr); + void set_fregval_d (int fr, FLOAT64 d); void SET_PSR_CC(int val); void invalidate_icache(); void invalidate_tlb(); - UINT64 ifetch64(const UINT32 pc); + inline UINT64 ifetch64(const UINT32 pc); + UINT64 ifetch64(const UINT32 pc, const UINT32 vaddr, int const cidx); UINT32 ifetch(const UINT32 pc); UINT32 ifetch_notrap(const UINT32 pc); + const char* trap_info(); void handle_trap(UINT32 savepc); void ret_from_trap(); void unrecog_opcode (UINT32 pc, UINT32 insn); @@ -618,11 +702,12 @@ private: void dump_state (); UINT32 disasm (UINT32 addr, int len); offs_t disasm(char* buffer, offs_t pc); - void dbg_db (UINT32 addr, int len); + void dbg_memdump (UINT32 addr, int len); int delay_slots(UINT32 insn); - UINT32 get_address_translation (UINT32 vaddr, int is_dataref, int is_write); - float get_fval_from_optype_s (UINT32 insn, int optype); - double get_fval_from_optype_d (UINT32 insn, int optype); + UINT32 get_address_translation(UINT32 vaddr, int is_dataref, int is_write); + inline UINT32 get_address_translation(UINT32 vaddr, UINT32 voffset, UINT32 tlbidx, int is_dataref, int is_write); + FLOAT32 get_fval_from_optype_s (UINT32 insn, int optype); + FLOAT64 get_fval_from_optype_d (UINT32 insn, int optype); int memtest(bool be); void dbg_check_wr(UINT32 addr, int size, UINT8* data); @@ -635,19 +720,13 @@ private: void intr(); typedef void (i860_cpu_device::*insn_func)(UINT32); - struct decode_tbl_t - { - /* Execute function for this opcode. */ - insn_func insn_exec; - /* Flags for this opcode. */ - char flags; - }; - static const decode_tbl_t decode_tbl[64]; - static const decode_tbl_t core_esc_decode_tbl[8]; - static const decode_tbl_t fp_decode_tbl[128]; + static const insn_func decode_tbl[64]; + static const insn_func core_esc_decode_tbl[8]; + static const insn_func fp_decode_tbl[128]; + static insn_func decoder_tbl[8192]; }; /* disassembler */ int i860_disassembler(UINT32 pc, UINT32 insn, char* buffer); - + #endif /* __I860_H__ */