1 // license:GPL-2.0+ 2 // copyright-holders:Segher Boessenkool, Ryan Holtz, David Haywood 3 /***************************************************************************** 4 5 SunPlus µ'nSP emulator 6 7 Copyright 2008-2017 Segher Boessenkool <segher@kernel.crashing.org> 8 Licensed under the terms of the GNU GPL, version 2 9 http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 10 11 Ported to MAME framework by Ryan Holtz 12 13 *****************************************************************************/ 14 15 #ifndef MAME_CPU_UNSP_UNSP_H 16 #define MAME_CPU_UNSP_UNSP_H 17 18 #pragma once 19 20 #include "cpu/drcfe.h" 21 #include "cpu/drcuml.h" 22 #include "cpu/drcumlsh.h" 23 #include "unspdefs.h" 24 25 /*************************************************************************** 26 CONSTANTS 27 ***************************************************************************/ 28 29 /* map variables */ 30 #define MAPVAR_PC M0 31 #define MAPVAR_CYCLES M1 32 33 #define SINGLE_INSTRUCTION_MODE (0) 34 35 #define ENABLE_UNSP_DRC (0) 36 37 #define UNSP_LOG_OPCODES (0) 38 #define UNSP_LOG_REGS (0) 39 40 //************************************************************************** 41 // TYPE DEFINITIONS 42 //************************************************************************** 43 44 class unsp_frontend; 45 46 // ======================> unsp_device 47 48 enum 49 { 50 UNSP_SP = 1, 51 UNSP_R1, 52 UNSP_R2, 53 UNSP_R3, 54 UNSP_R4, 55 UNSP_BP, 56 UNSP_SR, 57 UNSP_PC, 58 59 UNSP_GPR_COUNT = UNSP_PC, 60 61 UNSP_IRQ_EN, 62 UNSP_FIQ_EN, 63 UNSP_FIR_MOV_EN, 64 UNSP_SB, 65 UNSP_AQ, 66 UNSP_FRA, 67 UNSP_BNK, 68 UNSP_INE, 69 #if UNSP_LOG_OPCODES || UNSP_LOG_REGS 70 UNSP_PRI, 71 UNSP_LOG_OPS 72 #else 73 UNSP_PRI 74 #endif 75 }; 76 77 enum 78 { 79 UNSP_FIQ_LINE = 0, 80 UNSP_IRQ0_LINE, 81 UNSP_IRQ1_LINE, 82 UNSP_IRQ2_LINE, 83 UNSP_IRQ3_LINE, 84 UNSP_IRQ4_LINE, 85 UNSP_IRQ5_LINE, 86 UNSP_IRQ6_LINE, 87 UNSP_IRQ7_LINE, 88 UNSP_BRK_LINE, 89 90 UNSP_NUM_LINES 91 }; 92 93 class unsp_device : public cpu_device 94 { 95 friend class unsp_frontend; 96 97 public: 98 // construction/destruction 99 unsp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 100 virtual ~unsp_device(); 101 102 uint8_t get_csb(); 103 104 void set_ds(uint16_t ds); 105 uint16_t get_ds(); 106 107 void set_fr(uint16_t fr); 108 uint16_t get_fr(); 109 110 inline void ccfunc_unimplemented(); 111 void invalidate_cache(); 112 113 #if UNSP_LOG_REGS 114 void log_regs(); 115 void log_write(uint32_t addr, uint32_t data); 116 void cfunc_log_write(); 117 #endif 118 119 void cfunc_muls(); 120 121 protected: 122 unsp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal); 123 124 // device-level overrides 125 virtual void device_start() override; 126 virtual void device_reset() override; 127 virtual void device_stop() override; 128 129 // device_execute_interface overrides execute_min_cycles()130 virtual uint32_t execute_min_cycles() const noexcept override { return 5; } execute_max_cycles()131 virtual uint32_t execute_max_cycles() const noexcept override { return 5; } execute_input_lines()132 virtual uint32_t execute_input_lines() const noexcept override { return 0; } 133 virtual void execute_run() override; 134 virtual void execute_set_input(int inputnum, int state) override; 135 136 // device_memory_interface overrides 137 virtual space_config_vector memory_space_config() const override; 138 139 // device_state_interface overrides 140 virtual void state_import(const device_state_entry& entry) override; 141 virtual void state_export(const device_state_entry& entry) override; 142 virtual void state_string_export(const device_state_entry& entry, std::string& str) const override; 143 144 // device_disasm_interface overrides 145 virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; 146 147 // HACK: IRQ line state can only be modified directly by hardware on-board the SPG SoC itself. 148 // Therefore, to avoid an unnecessary scheduler sync when the derived spg2xx_device sets or 149 // clears an interrupt line, we provide this direct accessor. 150 void set_state_unsynced(int inputnum, int state); 151 152 enum : uint32_t 153 { 154 REG_SP = 0, 155 REG_R1, 156 REG_R2, 157 REG_R3, 158 REG_R4, 159 REG_BP, 160 REG_SR, 161 REG_PC, 162 163 REG_SR1 = 0, 164 REG_SR2, 165 REG_SR3, 166 REG_SR4 167 }; 168 169 /* internal compiler state */ 170 struct compiler_state 171 { 172 compiler_state(compiler_state const&) = delete; 173 compiler_state& operator=(compiler_state const&) = delete; 174 175 uint32_t m_cycles; /* accumulated cycles */ 176 uml::code_label m_labelnum; /* index for local labels */ 177 }; 178 179 struct internal_unsp_state 180 { 181 uint32_t m_r[16]; // required to be 32 bits due to DRC 182 uint32_t m_secbank[4]; 183 uint32_t m_enable_irq; 184 uint32_t m_enable_fiq; 185 uint32_t m_fir_move; 186 uint32_t m_fiq; 187 uint32_t m_irq; 188 uint32_t m_sirq; 189 uint32_t m_sb; 190 uint32_t m_aq; 191 uint32_t m_fra; 192 uint32_t m_bnk; 193 uint32_t m_ine; 194 uint32_t m_pri; 195 196 uint32_t m_divq_bit; 197 uint32_t m_divq_dividend; 198 uint32_t m_divq_divisor; 199 uint32_t m_divq_a; 200 201 uint32_t m_arg0; 202 uint32_t m_arg1; 203 uint32_t m_jmpdest; 204 205 int m_icount; 206 }; 207 208 /* core state */ 209 internal_unsp_state* m_core; 210 211 protected: read16(uint32_t address)212 uint16_t read16(uint32_t address) { return m_program.read_word(address); } 213 write16(uint32_t address,uint16_t data)214 void write16(uint32_t address, uint16_t data) 215 { 216 #if UNSP_LOG_REGS 217 log_write(address, data); 218 #endif 219 m_program.write_word(address, data); 220 } 221 add_lpc(const int32_t offset)222 void add_lpc(const int32_t offset) 223 { 224 const uint32_t new_lpc = UNSP_LPC + offset; 225 m_core->m_r[REG_PC] = (uint16_t)new_lpc; 226 m_core->m_r[REG_SR] &= 0xffc0; 227 m_core->m_r[REG_SR] |= (new_lpc >> 16) & 0x3f; 228 } 229 230 void execute_fxxx_000_group(uint16_t op); 231 void execute_fxxx_001_group(uint16_t op); 232 void execute_fxxx_010_group(uint16_t op); 233 void execute_fxxx_011_group(uint16_t op); 234 virtual void execute_fxxx_101_group(uint16_t op); 235 void execute_fxxx_110_group(uint16_t op); 236 void execute_fxxx_111_group(uint16_t op); 237 void execute_fxxx_group(uint16_t op); 238 void execute_fxxx_100_group(uint16_t op); 239 virtual void execute_extended_group(uint16_t op); 240 virtual void execute_exxx_group(uint16_t op); 241 void execute_muls_ss(const uint16_t rd, const uint16_t rs, const uint16_t size); 242 void unimplemented_opcode(uint16_t op); 243 void unimplemented_opcode(uint16_t op, uint16_t ximm); 244 void unimplemented_opcode(uint16_t op, uint16_t ximm, uint16_t ximm_2); op_is_divq(const uint16_t op)245 virtual bool op_is_divq(const uint16_t op) { return false; } 246 247 int m_iso; 248 249 static char const *const regs[]; 250 static char const *const extregs[]; 251 static char const *const bitops[]; 252 static char const *const lsft[]; 253 static char const *const aluops[]; 254 static char const *const forms[]; 255 256 void push(uint32_t value, uint32_t *reg); 257 uint16_t pop(uint32_t *reg); 258 259 void update_nz(uint32_t value); 260 void update_nzsc(uint32_t value, uint16_t r0, uint16_t r1); 261 bool do_basic_alu_ops(const uint16_t& op0, uint32_t& lres, uint16_t& r0, uint16_t& r1, uint32_t& r2, bool update_flags); 262 263 private: 264 // compilation boundaries -- how far back/forward does the analysis extend? 265 enum : uint32_t 266 { 267 COMPILE_BACKWARDS_BYTES = 128, 268 COMPILE_FORWARDS_BYTES = 512, 269 COMPILE_MAX_INSTRUCTIONS = (COMPILE_BACKWARDS_BYTES / 4) + (COMPILE_FORWARDS_BYTES / 4), 270 COMPILE_MAX_SEQUENCE = 64 271 }; 272 273 // exit codes 274 enum : int 275 { 276 EXECUTE_OUT_OF_CYCLES = 0, 277 EXECUTE_MISSING_CODE = 1, 278 EXECUTE_UNMAPPED_CODE = 2, 279 EXECUTE_RESET_CACHE = 3 280 }; 281 282 283 void execute_jumps(const uint16_t op); 284 void execute_remaining(const uint16_t op); 285 void execute_one(const uint16_t op); 286 287 288 289 address_space_config m_program_config; 290 memory_access<23, 1, -1, ENDIANNESS_BIG>::cache m_cache; 291 memory_access<23, 1, -1, ENDIANNESS_BIG>::specific m_program; 292 293 uint32_t m_debugger_temp; 294 #if UNSP_LOG_OPCODES || UNSP_LOG_REGS 295 uint32_t m_log_ops; 296 #endif 297 298 inline void trigger_fiq(); 299 inline void trigger_irq(int line); 300 void check_irqs(); 301 302 drc_cache m_drccache; 303 std::unique_ptr<drcuml_state> m_drcuml; 304 std::unique_ptr<unsp_frontend> m_drcfe; 305 uint32_t m_drcoptions; 306 uint8_t m_cache_dirty; 307 308 uml::parameter m_regmap[16]; 309 uml::code_handle *m_entry; 310 uml::code_handle *m_nocode; 311 uml::code_handle *m_out_of_cycles; 312 uml::code_handle *m_check_interrupts; 313 uml::code_handle *m_trigger_fiq; 314 uml::code_handle *m_trigger_irq; 315 316 uml::code_handle *m_mem_read; 317 uml::code_handle *m_mem_write; 318 319 bool m_enable_drc; 320 321 void execute_run_drc(); 322 void flush_drc_cache(); 323 void code_flush_cache(); 324 void code_compile_block(offs_t pc); 325 void load_fast_iregs(drcuml_block &block); 326 void save_fast_iregs(drcuml_block &block); 327 328 void static_generate_entry_point(); 329 void static_generate_nocode_handler(); 330 void static_generate_out_of_cycles(); 331 void static_generate_check_interrupts(); 332 void static_generate_trigger_fiq(); 333 void static_generate_trigger_irq(); 334 void static_generate_memory_accessor(bool iswrite, const char *name, uml::code_handle *&handleptr); 335 336 void generate_branch(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc); 337 void generate_check_cycles(drcuml_block &block, compiler_state &compiler, uml::parameter param); 338 void generate_checksum_block(drcuml_block &block, compiler_state &compiler, const opcode_desc *seqhead, const opcode_desc *seqlast); 339 void generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc); 340 void generate_add_lpc(drcuml_block &block, int32_t offset); 341 void generate_update_nzsc(drcuml_block &block); 342 void generate_update_nz(drcuml_block &block); 343 void log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32_t op); 344 bool generate_opcode(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc); 345 346 #if UNSP_LOG_REGS 347 FILE *m_log_file; 348 #endif 349 protected: 350 int m_numregs; 351 }; 352 353 354 class unsp_11_device : public unsp_device 355 { 356 public: 357 // construction/destruction 358 unsp_11_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 359 360 protected: 361 unsp_11_device(const machine_config& mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal); 362 363 private: 364 }; 365 366 class unsp_12_device : public unsp_11_device 367 { 368 public: 369 // construction/destruction 370 unsp_12_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 371 372 protected: 373 unsp_12_device(const machine_config& mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal); 374 375 virtual void execute_fxxx_101_group(uint16_t op) override; 376 virtual void execute_exxx_group(uint16_t op) override; 377 void execute_divq(uint16_t op); 378 bool op_is_divq(const uint16_t op) override; 379 380 virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; 381 }; 382 383 class unsp_20_device : public unsp_12_device 384 { 385 public: 386 // construction/destruction 387 unsp_20_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 388 389 protected: 390 unsp_20_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal); 391 392 virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; 393 virtual void execute_extended_group(uint16_t op) override; 394 395 virtual void device_start() override; 396 virtual void device_reset() override; 397 398 private: 399 enum 400 { 401 UNSP20_R8 = 0, 402 UNSP20_R9, 403 UNSP20_R10, 404 UNSP20_R11, 405 UNSP20_R12, 406 UNSP20_R13, 407 UNSP20_R14, 408 UNSP20_R15 409 }; 410 }; 411 412 413 414 DECLARE_DEVICE_TYPE(UNSP, unsp_device) 415 DECLARE_DEVICE_TYPE(UNSP_11, unsp_11_device) 416 DECLARE_DEVICE_TYPE(UNSP_12, unsp_12_device) 417 DECLARE_DEVICE_TYPE(UNSP_20, unsp_20_device) 418 419 420 #endif // MAME_CPU_UNSP_UNSP_H 421