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     Notes:
14 
15     R3 and R4 together are 'MR' with R4 being the upper part of the 32-bit reg
16 
17 *****************************************************************************/
18 
19 #include "emu.h"
20 #include "unsp.h"
21 #include "unspfe.h"
22 
23 #include "debugger.h"
24 
25 #include "unspdasm.h"
26 
27 #include <climits>
28 
29 DEFINE_DEVICE_TYPE(UNSP,    unsp_device,    "unsp",    "SunPlus u'nSP (ISA 1.0)")
30 // 1.1 is just 1.0 with better CPI?
31 DEFINE_DEVICE_TYPE(UNSP_11, unsp_11_device, "unsp_11", "SunPlus u'nSP (ISA 1.1)")
32  // it's possible that most unSP systems we emulate are 1.2, but are not using 99% of the additional features / instructions over 1.0 (only enable_irq and enable_fiq are meant to be 1.2 specific and used, but that could be a research error)
33 DEFINE_DEVICE_TYPE(UNSP_12, unsp_12_device, "unsp_12", "SunPlus u'nSP (ISA 1.2)")
34 // found on GCM394 die (based on use of 2 extended push/pop opcodes in the smartfp irq), has extra instructions
35 DEFINE_DEVICE_TYPE(UNSP_20, unsp_20_device, "unsp_20", "SunPlus u'nSP (ISA 2.0)")
36 
37 /* size of the execution code cache */
38 #define CACHE_SIZE                      (64 * 1024 * 1024)
39 
unsp_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock,address_map_constructor internal)40 unsp_device::unsp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal)
41 	: cpu_device(mconfig, type, tag, owner, clock)
42 	, m_core(nullptr)
43 	, m_program_config("program", ENDIANNESS_BIG, 16, 23, -1, internal)
44 	, m_debugger_temp(0)
45 #if UNSP_LOG_OPCODES || UNSP_LOG_REGS
46 	, m_log_ops(0)
47 #endif
48 	, m_drccache(CACHE_SIZE + sizeof(unsp_device))
49 	, m_drcuml(nullptr)
50 	, m_drcfe(nullptr)
51 	, m_drcoptions(0)
52 	, m_cache_dirty(0)
53 	, m_entry(nullptr)
54 	, m_nocode(nullptr)
55 	, m_out_of_cycles(nullptr)
56 	, m_check_interrupts(nullptr)
57 	, m_trigger_fiq(nullptr)
58 	, m_trigger_irq(nullptr)
59 	, m_mem_read(nullptr)
60 	, m_mem_write(nullptr)
61 	, m_enable_drc(false)
62 {
63 	m_iso = 10;
64 	m_numregs = 8;
65 }
66 
unsp_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)67 unsp_device::unsp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
68 	: unsp_device(mconfig, UNSP, tag, owner, clock, address_map_constructor())
69 {
70 	m_iso = 10;
71 	m_numregs = 8;
72 }
73 
unsp_11_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)74 unsp_11_device::unsp_11_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
75 	: unsp_device(mconfig, UNSP_11, tag, owner, clock, address_map_constructor())
76 {
77 	m_iso = 11;
78 	m_numregs = 8;
79 }
80 
unsp_11_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock,address_map_constructor internal)81 unsp_11_device::unsp_11_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal)
82 	: unsp_device(mconfig, type, tag, owner, clock, internal)
83 {
84 	m_iso = 11;
85 	m_numregs = 8;
86 }
87 
88 
unsp_12_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)89 unsp_12_device::unsp_12_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
90 	: unsp_11_device(mconfig, UNSP_12, tag, owner, clock, address_map_constructor())
91 {
92 	m_iso = 12;
93 	m_numregs = 8;
94 }
95 
unsp_12_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock,address_map_constructor internal)96 unsp_12_device::unsp_12_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal)
97 	: unsp_11_device(mconfig, type, tag, owner, clock, internal)
98 {
99 	m_iso = 12;
100 	m_numregs = 8;
101 }
102 
unsp_20_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)103 unsp_20_device::unsp_20_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
104 	: unsp_12_device(mconfig, UNSP_20, tag, owner, clock, address_map_constructor())
105 {
106 	m_iso = 20;
107 	m_numregs = 16;
108 }
109 
unsp_20_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock,address_map_constructor internal)110 unsp_20_device::unsp_20_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal)
111 	: unsp_12_device(mconfig, type, tag, owner, clock, internal)
112 {
113 	m_iso = 20;
114 	m_numregs = 16;
115 }
116 
~unsp_device()117 unsp_device::~unsp_device()
118 {
119 }
120 
121 // these are just for logging, can be removed once all ops are implemented
122 char const* const unsp_device::regs[] =
123 {
124 	"sp", "r1", "r2", "r3", "r4", "bp", "sr", "pc"
125 };
126 
127 char const* const unsp_device::bitops[] =
128 {
129 	"tstb", "setb", "clrb", "invb"
130 };
131 
132 // log/barrel shift
133 char const* const unsp_device::lsft[] =
134 {
135 	"asr", "asror", "lsl", "lslor", "lsr", "lsror", "rol", "ror"
136 };
137 
138 char const* const unsp_device::extregs[] =
139 {
140 	"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
141 };
142 
143 char const* const unsp_device::aluops[] =
144 {
145 	"add","adc","sub","sbc","cmp","(invalid)","neg","--","xor","load","or","and","test","store","(invalid)","(invalid)"
146 };
147 
148 char const* const unsp_device::forms[] =
149 {
150 	"[%s]", "[%s--]", "[%s++]", "[++%s]"
151 };
152 
153 
memory_space_config() const154 device_memory_interface::space_config_vector unsp_device::memory_space_config() const
155 {
156 	return space_config_vector {
157 		std::make_pair(AS_PROGRAM, &m_program_config)
158 	};
159 }
160 
create_disassembler()161 std::unique_ptr<util::disasm_interface> unsp_device::create_disassembler()
162 {
163 	return std::make_unique<unsp_disassembler>();
164 }
165 
create_disassembler()166 std::unique_ptr<util::disasm_interface> unsp_12_device::create_disassembler()
167 {
168 	return std::make_unique<unsp_12_disassembler>();
169 }
170 
create_disassembler()171 std::unique_ptr<util::disasm_interface> unsp_20_device::create_disassembler()
172 {
173 	return std::make_unique<unsp_20_disassembler>();
174 }
175 
unimplemented_opcode(uint16_t op)176 void unsp_device::unimplemented_opcode(uint16_t op)
177 {
178 	fatalerror("UNSP: unknown opcode %04x at %04x\n", op, UNSP_LPC);
179 }
180 
unimplemented_opcode(uint16_t op,uint16_t ximm)181 void unsp_device::unimplemented_opcode(uint16_t op, uint16_t ximm)
182 {
183 	fatalerror("UNSP: unknown opcode %04x %04x at %04x\n", op, ximm, UNSP_LPC);
184 }
185 
186 
unimplemented_opcode(uint16_t op,uint16_t ximm,uint16_t ximm_2)187 void unsp_device::unimplemented_opcode(uint16_t op, uint16_t ximm, uint16_t ximm_2)
188 {
189 	fatalerror("UNSP: unknown opcode %04x %04x %04x at %04x\n", op, ximm, ximm_2, UNSP_LPC);
190 }
191 
device_start()192 void unsp_device::device_start()
193 {
194 
195 	m_core = (internal_unsp_state *)m_drccache.alloc_near(sizeof(internal_unsp_state));
196 	memset(m_core, 0, sizeof(internal_unsp_state));
197 
198 #if ENABLE_UNSP_DRC
199 	m_enable_drc = allow_drc() && (m_iso < 12);
200 #else
201 	m_enable_drc = false;
202 #endif
203 
204 #if UNSP_LOG_REGS
205 	if (m_enable_drc)
206 		m_log_file = fopen("unsp_drc.bin", "wb");
207 	else
208 		m_log_file = fopen("unsp_interp.bin", "wb");
209 #endif
210 
211 	m_debugger_temp = 0;
212 
213 	space(AS_PROGRAM).cache(m_cache);
214 	space(AS_PROGRAM).specific(m_program);
215 
216 	uint32_t umlflags = 0;
217 	m_drcuml = std::make_unique<drcuml_state>(*this, m_drccache, umlflags, 1, 23, 0);
218 
219 	// add UML symbols-
220 	m_drcuml->symbol_add(&m_core->m_r[REG_SP], sizeof(uint32_t), "SP");
221 	m_drcuml->symbol_add(&m_core->m_r[REG_R1], sizeof(uint32_t), "R1");
222 	m_drcuml->symbol_add(&m_core->m_r[REG_R2], sizeof(uint32_t), "R2");
223 	m_drcuml->symbol_add(&m_core->m_r[REG_R3], sizeof(uint32_t), "R3");
224 	m_drcuml->symbol_add(&m_core->m_r[REG_R4], sizeof(uint32_t), "R4");
225 	m_drcuml->symbol_add(&m_core->m_r[REG_BP], sizeof(uint32_t), "BP");
226 	m_drcuml->symbol_add(&m_core->m_r[REG_SR], sizeof(uint32_t), "SR");
227 	m_drcuml->symbol_add(&m_core->m_r[REG_PC], sizeof(uint32_t), "PC");
228 	m_drcuml->symbol_add(&m_core->m_enable_irq, sizeof(uint32_t), "IRQE");
229 	m_drcuml->symbol_add(&m_core->m_enable_fiq, sizeof(uint32_t), "FIQE");
230 	m_drcuml->symbol_add(&m_core->m_fir_move, sizeof(uint32_t), "FIR_MOV");
231 	m_drcuml->symbol_add(&m_core->m_sb, sizeof(uint32_t), "SB");
232 	m_drcuml->symbol_add(&m_core->m_aq, sizeof(uint32_t), "AQ");
233 	m_drcuml->symbol_add(&m_core->m_fra, sizeof(uint32_t), "FRA");
234 	m_drcuml->symbol_add(&m_core->m_bnk, sizeof(uint32_t), "BNK");
235 	m_drcuml->symbol_add(&m_core->m_ine, sizeof(uint32_t), "INE");
236 	m_drcuml->symbol_add(&m_core->m_pri, sizeof(uint32_t), "PRI");
237 	m_drcuml->symbol_add(&m_core->m_icount, sizeof(m_core->m_icount), "icount");
238 
239 	/* initialize the front-end helper */
240 	m_drcfe = std::make_unique<unsp_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE);
241 
242 	/* mark the cache dirty so it is updated on next execute */
243 	m_cache_dirty = true;
244 
245 	// register our state for the debugger
246 	state_add(STATE_GENFLAGS, "GENFLAGS", m_core->m_r[REG_SR]).callimport().callexport().formatstr("%4s").noshow();
247 	state_add(UNSP_SP,     "SP", m_core->m_r[REG_SP]).formatstr("%04X");
248 	state_add(UNSP_R1,     "R1", m_core->m_r[REG_R1]).formatstr("%04X");
249 	state_add(UNSP_R2,     "R2", m_core->m_r[REG_R2]).formatstr("%04X");
250 	state_add(UNSP_R3,     "R3", m_core->m_r[REG_R3]).formatstr("%04X");
251 	state_add(UNSP_R4,     "R4", m_core->m_r[REG_R4]).formatstr("%04X");
252 	state_add(UNSP_BP,     "BP", m_core->m_r[REG_BP]).formatstr("%04X");
253 	state_add(UNSP_SR,     "SR", m_core->m_r[REG_SR]).formatstr("%04X");
254 	state_add(UNSP_PC,     "PC", m_debugger_temp).callimport().callexport().formatstr("%06X");
255 	state_add(UNSP_IRQ_EN, "IRQE", m_core->m_enable_irq).formatstr("%1u");
256 	state_add(UNSP_FIQ_EN, "FIQE", m_core->m_enable_fiq).formatstr("%1u");
257 	state_add(UNSP_FIR_MOV_EN, "FIR_MOV", m_core->m_fir_move).formatstr("%1u");
258 	state_add(UNSP_SB,     "SB", m_core->m_sb).formatstr("%1X");
259 	state_add(UNSP_AQ,     "AQ", m_core->m_aq).formatstr("%1u");
260 	state_add(UNSP_FRA,    "FRA", m_core->m_fra).formatstr("%1u");
261 	state_add(UNSP_BNK,    "BNK", m_core->m_bnk).formatstr("%1u");
262 	state_add(UNSP_INE,    "INE", m_core->m_ine).formatstr("%1u");
263 	state_add(UNSP_PRI,    "PRI", m_core->m_pri).formatstr("%1u");
264 #if UNSP_LOG_OPCODES || UNSP_LOG_REGS
265 	state_add(UNSP_LOG_OPS,"LOG", m_log_ops).formatstr("%1u");
266 #endif
267 
268 	state_add(STATE_GENPC, "GENPC", m_debugger_temp).callexport().noshow();
269 	state_add(STATE_GENPCBASE, "CURPC", m_debugger_temp).callexport().noshow();
270 
271 	save_item(NAME(m_core->m_r));
272 	save_item(NAME(m_core->m_enable_irq));
273 	save_item(NAME(m_core->m_enable_fiq));
274 	save_item(NAME(m_core->m_irq));
275 	save_item(NAME(m_core->m_fir_move));
276 	save_item(NAME(m_core->m_sirq));
277 	save_item(NAME(m_core->m_sb));
278 	save_item(NAME(m_core->m_aq));
279 	save_item(NAME(m_core->m_fra));
280 	save_item(NAME(m_core->m_bnk));
281 	save_item(NAME(m_core->m_ine));
282 	save_item(NAME(m_core->m_pri));
283 	save_item(NAME(m_core->m_divq_bit));
284 	save_item(NAME(m_core->m_divq_dividend));
285 	save_item(NAME(m_core->m_divq_divisor));
286 
287 	set_icountptr(m_core->m_icount);
288 }
289 
device_start()290 void unsp_20_device::device_start()
291 {
292 	unsp_12_device::device_start();
293 
294 #if UNSP_LOG_OPCODES || UNSP_LOG_REGS
295 	int baseindex = UNSP_LOG_OPS + 1;
296 #else
297 	int baseindex = UNSP_PRI + 1;
298 #endif
299 
300 	state_add(baseindex + UNSP20_R8,     "R8", m_core->m_r[UNSP20_R8+8]).formatstr("%04X");
301 	state_add(baseindex + UNSP20_R9,     "R9", m_core->m_r[UNSP20_R9+8]).formatstr("%04X");
302 	state_add(baseindex + UNSP20_R10,    "R10", m_core->m_r[UNSP20_R10+8]).formatstr("%04X");
303 	state_add(baseindex + UNSP20_R11,    "R11", m_core->m_r[UNSP20_R11+8]).formatstr("%04X");
304 	state_add(baseindex + UNSP20_R12,    "R12", m_core->m_r[UNSP20_R12+8]).formatstr("%04X");
305 	state_add(baseindex + UNSP20_R13,    "R13", m_core->m_r[UNSP20_R13+8]).formatstr("%04X");
306 	state_add(baseindex + UNSP20_R14,    "R14", m_core->m_r[UNSP20_R14+8]).formatstr("%04X");
307 	state_add(baseindex + UNSP20_R15,    "R15", m_core->m_r[UNSP20_R15+8]).formatstr("%04X");
308 }
309 
device_reset()310 void unsp_device::device_reset()
311 {
312 	for (int i = 0; i < ARRAY_LENGTH(m_core->m_r); i++)
313 	{
314 		if (i < m_numregs)
315 			m_core->m_r[i] = 0;
316 		else
317 			m_core->m_r[i] = 0xdeadbeef;
318 	}
319 
320 	m_core->m_r[REG_PC] = read16(0xfff7);
321 	m_core->m_enable_irq = 0;
322 	m_core->m_enable_fiq = 0;
323 	m_core->m_fir_move = 1;
324 	m_core->m_sb = 0;
325 	m_core->m_aq = 0;
326 	m_core->m_fra = 0;
327 	m_core->m_bnk = 0;
328 	m_core->m_ine = 0;
329 	m_core->m_pri = 8;
330 	m_core->m_fiq = 0;
331 	m_core->m_irq = 0;
332 	m_core->m_sirq = 0;
333 	m_core->m_divq_bit = UINT_MAX;
334 }
335 
device_reset()336 void unsp_20_device::device_reset()
337 {
338 	unsp_12_device::device_reset();
339 }
340 
device_stop()341 void unsp_device::device_stop()
342 {
343 	if (m_drcfe != nullptr)
344 	{
345 		m_drcfe = nullptr;
346 	}
347 	if (m_drcuml != nullptr)
348 	{
349 		m_drcuml = nullptr;
350 	}
351 #if UNSP_LOG_REGS
352 	fclose(m_log_file);
353 #endif
354 }
355 
356 #if UNSP_LOG_REGS
log_regs()357 void unsp_device::log_regs()
358 {
359 	if (m_log_ops == 0)
360 		return;
361 	fwrite(m_core->m_r, sizeof(uint32_t), 8, m_log_file);
362 	fwrite(&m_core->m_sb, sizeof(uint32_t), 1, m_log_file);
363 	fwrite(&m_core->m_icount, sizeof(uint32_t), 1, m_log_file);
364 }
365 
log_write(uint32_t addr,uint32_t data)366 void unsp_device::log_write(uint32_t addr, uint32_t data)
367 {
368 	if (m_log_ops == 0)
369 		return;
370 	addr |= 0x80000000;
371 	fwrite(&addr, sizeof(uint32_t), 1, m_log_file);
372 	fwrite(&data, sizeof(uint32_t), 1, m_log_file);
373 }
374 
375 #endif
376 
state_string_export(const device_state_entry & entry,std::string & str) const377 void unsp_device::state_string_export(const device_state_entry &entry, std::string &str) const
378 {
379 	switch (entry.index())
380 	{
381 		case STATE_GENFLAGS:
382 		{
383 			const uint16_t sr = m_core->m_r[REG_SR];
384 			str = string_format("%c%c%c%c", (sr & UNSP_N) ? 'N' : ' ', (sr & UNSP_Z) ? 'Z' : ' ', (sr & UNSP_S) ? 'S' : ' ', (sr & UNSP_C) ? 'C' : ' ');
385 		}
386 	}
387 }
388 
state_export(const device_state_entry & entry)389 void unsp_device::state_export(const device_state_entry &entry)
390 {
391 	switch (entry.index())
392 	{
393 		case STATE_GENPC:
394 		case STATE_GENPCBASE:
395 		case UNSP_PC:
396 			m_debugger_temp = UNSP_LPC;
397 			break;
398 	}
399 }
400 
state_import(const device_state_entry & entry)401 void unsp_device::state_import(const device_state_entry &entry)
402 {
403 	switch (entry.index())
404 	{
405 		case UNSP_PC:
406 			m_core->m_r[REG_PC] = m_debugger_temp & 0x0000ffff;
407 			m_core->m_r[REG_SR] = (m_core->m_r[REG_SR] & 0xffc0) | ((m_debugger_temp & 0x003f0000) >> 16);
408 			break;
409 	}
410 }
411 
412 /*****************************************************************************/
413 
update_nzsc(uint32_t value,uint16_t r0,uint16_t r1)414 void unsp_device::update_nzsc(uint32_t value, uint16_t r0, uint16_t r1)
415 {
416 	m_core->m_r[REG_SR] &= ~(UNSP_N | UNSP_Z | UNSP_S | UNSP_C);
417 	if (BIT(value, 16) != BIT((r0 ^ r1), 15))
418 		m_core->m_r[REG_SR] |= UNSP_S;
419 	if (BIT(value, 15))
420 		m_core->m_r[REG_SR] |= UNSP_N;
421 	if((uint16_t)value == 0)
422 		m_core->m_r[REG_SR] |= UNSP_Z;
423 	if (BIT(value, 16))
424 		m_core->m_r[REG_SR] |= UNSP_C;
425 }
426 
update_nz(uint32_t value)427 void unsp_device::update_nz(uint32_t value)
428 {
429 	m_core->m_r[REG_SR] &= ~(UNSP_N | UNSP_Z);
430 	if(value & 0x8000)
431 		m_core->m_r[REG_SR] |= UNSP_N;
432 	if((uint16_t)value == 0)
433 		m_core->m_r[REG_SR] |= UNSP_Z;
434 }
435 
push(uint32_t value,uint32_t * reg)436 void unsp_device::push(uint32_t value, uint32_t *reg)
437 {
438 	write16(*reg, (uint16_t)value);
439 	*reg = (uint16_t)(*reg - 1);
440 }
441 
pop(uint32_t * reg)442 uint16_t unsp_device::pop(uint32_t *reg)
443 {
444 	*reg = (uint16_t)(*reg + 1);
445 	return (uint16_t)read16(*reg);
446 }
447 
trigger_fiq()448 inline void unsp_device::trigger_fiq()
449 {
450 	if (!m_core->m_enable_fiq || m_core->m_fiq)
451 		return;
452 
453 	m_core->m_fiq = 1;
454 
455 	push(m_core->m_r[REG_PC], &m_core->m_r[REG_SP]);
456 	push(m_core->m_r[REG_SR], &m_core->m_r[REG_SP]);
457 	m_core->m_r[REG_PC] = read16(0xfff6);
458 	m_core->m_r[REG_SR] = 0;
459 	standard_irq_callback(UNSP_FIQ_LINE);
460 }
461 
trigger_irq(int line)462 inline void unsp_device::trigger_irq(int line)
463 {
464 	if ((m_core->m_ine == 0 && m_core->m_irq == 1) || m_core->m_pri <= line || !m_core->m_enable_irq)
465 		return;
466 
467 	m_core->m_irq = 1;
468 
469 	push(m_core->m_r[REG_PC], &m_core->m_r[REG_SP]);
470 	push(m_core->m_r[REG_SR], &m_core->m_r[REG_SP]);
471 	if (m_core->m_ine)
472 	{
473 		push(get_fr(), &m_core->m_r[REG_SP]);
474 	}
475 
476 	if (m_core->m_ine)
477 		m_core->m_pri = line;
478 
479 	m_core->m_r[REG_PC] = read16(0xfff8 + line);
480 	m_core->m_r[REG_SR] = 0;
481 	standard_irq_callback(UNSP_IRQ0_LINE+line);
482 }
483 
check_irqs()484 void unsp_device::check_irqs()
485 {
486 	if (!m_core->m_sirq)
487 		return;
488 
489 	int highest_irq = -1;
490 	for (int i = 0; i <= 8; i++)
491 	{
492 		if (BIT(m_core->m_sirq, i))
493 		{
494 			highest_irq = i;
495 			break;
496 		}
497 	}
498 
499 	if (highest_irq == UNSP_FIQ_LINE)
500 		trigger_fiq();
501 	else
502 		trigger_irq(highest_irq - 1);
503 }
504 
505 
execute_one(const uint16_t op)506 inline void unsp_device::execute_one(const uint16_t op)
507 {
508 	const uint16_t op0 = (op >> 12) & 15;
509 	const uint16_t opa = (op >> 9) & 7;
510 	const uint16_t op1 = (op >> 6) & 7;
511 
512 	if (op0 == 0xf)
513 		return execute_fxxx_group(op);
514 
515 	if(op0 < 0xf && opa == 0x7 && op1 < 2)
516 		return execute_jumps(op);
517 
518 	if (op0 == 0xe)
519 		return execute_exxx_group(op);
520 
521 	execute_remaining(op);
522 }
523 
execute_run()524 void unsp_device::execute_run()
525 {
526 	if (m_enable_drc)
527 	{
528 		execute_run_drc();
529 		return;
530 	}
531 
532 #if UNSP_LOG_OPCODES
533 	unsp_disassembler dasm;
534 #endif
535 
536 	while (m_core->m_icount >= 0)
537 	{
538 		debugger_instruction_hook(UNSP_LPC);
539 		const uint32_t op = read16(UNSP_LPC);
540 
541 #if UNSP_LOG_REGS
542 		log_regs();
543 #endif
544 
545 #if UNSP_LOG_OPCODES
546 		if (m_log_ops)
547 		{
548 			std::stringstream strbuffer;
549 			dasm.disassemble(strbuffer, UNSP_LPC, op, read16(UNSP_LPC+1));
550 			logerror("%x: %s\n", UNSP_LPC, strbuffer.str().c_str());
551 		}
552 #endif
553 
554 		add_lpc(1);
555 
556 		execute_one(op);
557 
558 		if (op != 0x9a98)
559 		{
560 			check_irqs();
561 		}
562 	}
563 }
564 
565 
566 /*****************************************************************************/
567 
execute_set_input(int inputnum,int state)568 void unsp_device::execute_set_input(int inputnum, int state)
569 {
570 	set_state_unsynced(inputnum, state);
571 }
572 
get_csb()573 uint8_t unsp_device::get_csb()
574 {
575 	return 1 << ((UNSP_LPC >> 20) & 3);
576 }
577 
set_state_unsynced(int inputnum,int state)578 void unsp_device::set_state_unsynced(int inputnum, int state)
579 {
580 	m_core->m_sirq &= ~(1 << inputnum);
581 
582 	if(!state)
583 	{
584 		return;
585 	}
586 
587 	switch (inputnum)
588 	{
589 		case UNSP_IRQ0_LINE:
590 		case UNSP_IRQ1_LINE:
591 		case UNSP_IRQ2_LINE:
592 		case UNSP_IRQ3_LINE:
593 		case UNSP_IRQ4_LINE:
594 		case UNSP_IRQ5_LINE:
595 		case UNSP_IRQ6_LINE:
596 		case UNSP_IRQ7_LINE:
597 		case UNSP_FIQ_LINE:
598 			m_core->m_sirq |= (1 << inputnum);
599 			break;
600 		case UNSP_BRK_LINE:
601 			break;
602 	}
603 }
604 
get_ds()605 uint16_t unsp_device::get_ds()
606 {
607 	return (m_core->m_r[REG_SR] >> 10) & 0x3f;
608 }
609 
set_ds(uint16_t ds)610 void unsp_device::set_ds(uint16_t ds)
611 {
612 	m_core->m_r[REG_SR] &= 0x03ff;
613 	m_core->m_r[REG_SR] |= (ds & 0x3f) << 10;
614 }
615 
set_fr(uint16_t fr)616 void unsp_device::set_fr(uint16_t fr)
617 {
618 	m_core->m_aq = BIT(fr, 14);
619 	const uint32_t old_bank = m_core->m_bnk;
620 	m_core->m_bnk = BIT(fr, 13);
621 	if (m_core->m_bnk != old_bank)
622 	{
623 		std::swap<uint32_t>(m_core->m_r[REG_R1], m_core->m_secbank[REG_SR1]);
624 		std::swap<uint32_t>(m_core->m_r[REG_R2], m_core->m_secbank[REG_SR2]);
625 		std::swap<uint32_t>(m_core->m_r[REG_R3], m_core->m_secbank[REG_SR3]);
626 		std::swap<uint32_t>(m_core->m_r[REG_R4], m_core->m_secbank[REG_SR4]);
627 	}
628 	m_core->m_fra = BIT(fr, 12);
629 	m_core->m_fir_move = BIT(fr, 11);
630 	m_core->m_sb = (fr >> 7) & 0xf;
631 	m_core->m_enable_fiq = BIT(fr, 6);
632 	m_core->m_enable_irq = BIT(fr, 5);
633 	m_core->m_ine = BIT(fr, 4);
634 	m_core->m_pri = fr & 0xf;
635 }
636 
get_fr()637 uint16_t unsp_device::get_fr()
638 {
639 	uint16_t fr = m_core->m_aq << 14;
640 	fr |= m_core->m_bnk << 13;
641 	fr |= m_core->m_fra << 12;
642 	fr |= m_core->m_fir_move << 11;
643 	fr |= m_core->m_sb << 7;
644 	fr |= m_core->m_enable_fiq << 6;
645 	fr |= m_core->m_enable_irq << 5;
646 	fr |= m_core->m_ine << 4;
647 	fr |= m_core->m_pri;
648 	return fr;
649 }
650