1 // license:BSD-3-Clause
2 // copyright-holders:Ville Linde
3 /******************************************************************************
4 
5     MB86235 UML recompiler core
6 
7 ******************************************************************************/
8 
9 #include "emu.h"
10 #include "mb86235.h"
11 #include "mb86235fe.h"
12 
13 #include "cpu/drcfe.h"
14 #include "cpu/drcuml.h"
15 #include "cpu/drcumlsh.h"
16 #include "debugger.h"
17 
18 #include "mb86235defs.h"
19 
20 
21 /*
22     TODO:
23     - check jump condition before parallel ALU/MUL (flags!)
24 
25 */
26 
27 
28 
29 
30 // map variables
31 #define MAPVAR_PC                       uml::M0
32 #define MAPVAR_CYCLES                   uml::M1
33 
34 // exit codes
35 #define EXECUTE_OUT_OF_CYCLES           0
36 #define EXECUTE_MISSING_CODE            1
37 #define EXECUTE_UNMAPPED_CODE           2
38 #define EXECUTE_RESET_CACHE             3
39 
40 
41 #define AR(reg)                 uml::mem(&m_core->ar[(reg)])
42 #define AA(reg)                 m_regmap[(reg)]
43 #define AB(reg)                 m_regmap[(reg)+8]
44 #define MA(reg)                 m_regmap[(reg)+16]
45 #define MB(reg)                 m_regmap[(reg)+24]
46 #define FLAGS_AZ                uml::mem(&m_core->flags.az)
47 #define FLAGS_AN                uml::mem(&m_core->flags.an)
48 #define FLAGS_AV                uml::mem(&m_core->flags.av)
49 #define FLAGS_AU                uml::mem(&m_core->flags.au)
50 #define FLAGS_AD                uml::mem(&m_core->flags.ad)
51 #define FLAGS_ZC                uml::mem(&m_core->flags.zc)
52 #define FLAGS_IL                uml::mem(&m_core->flags.il)
53 #define FLAGS_NR                uml::mem(&m_core->flags.nr)
54 #define FLAGS_ZD                uml::mem(&m_core->flags.zd)
55 #define FLAGS_MN                uml::mem(&m_core->flags.mn)
56 #define FLAGS_MZ                uml::mem(&m_core->flags.mz)
57 #define FLAGS_MV                uml::mem(&m_core->flags.mv)
58 #define FLAGS_MU                uml::mem(&m_core->flags.mu)
59 #define FLAGS_MD                uml::mem(&m_core->flags.md)
60 
61 #define PRP                     uml::mem(&m_core->prp)
62 #define PWP                     uml::mem(&m_core->pwp)
63 #define RPC                     uml::mem(&m_core->rpc)
64 #define LPC                     uml::mem(&m_core->lpc)
65 
66 #define AZ_CALC_REQUIRED        ((desc->regreq[1] & 0x1) || desc->flags & OPFLAG_IN_DELAY_SLOT)
67 #define AN_CALC_REQUIRED        ((desc->regreq[1] & 0x2) || desc->flags & OPFLAG_IN_DELAY_SLOT)
68 #define AV_CALC_REQUIRED        ((desc->regreq[1] & 0x4) || desc->flags & OPFLAG_IN_DELAY_SLOT)
69 #define AU_CALC_REQUIRED        ((desc->regreq[1] & 0x8) || desc->flags & OPFLAG_IN_DELAY_SLOT)
70 #define AD_CALC_REQUIRED        ((desc->regreq[1] & 0x10) || desc->flags & OPFLAG_IN_DELAY_SLOT)
71 #define ZC_CALC_REQUIRED        ((desc->regreq[1] & 0x20) || desc->flags & OPFLAG_IN_DELAY_SLOT)
72 #define IL_CALC_REQUIRED        ((desc->regreq[1] & 0x40) || desc->flags & OPFLAG_IN_DELAY_SLOT)
73 #define NR_CALC_REQUIRED        ((desc->regreq[1] & 0x80) || desc->flags & OPFLAG_IN_DELAY_SLOT)
74 #define ZD_CALC_REQUIRED        ((desc->regreq[1] & 0x100) || desc->flags & OPFLAG_IN_DELAY_SLOT)
75 #define MN_CALC_REQUIRED        ((desc->regreq[1] & 0x200) || desc->flags & OPFLAG_IN_DELAY_SLOT)
76 #define MZ_CALC_REQUIRED        ((desc->regreq[1] & 0x400) || desc->flags & OPFLAG_IN_DELAY_SLOT)
77 #define MV_CALC_REQUIRED        ((desc->regreq[1] & 0x800) || desc->flags & OPFLAG_IN_DELAY_SLOT)
78 #define MU_CALC_REQUIRED        ((desc->regreq[1] & 0x1000) || desc->flags & OPFLAG_IN_DELAY_SLOT)
79 #define MD_CALC_REQUIRED        ((desc->regreq[1] & 0x2000) || desc->flags & OPFLAG_IN_DELAY_SLOT)
80 
alloc_handle(uml::code_handle * & handleptr,const char * name)81 inline void mb86235_device::alloc_handle(uml::code_handle *&handleptr, const char *name)
82 {
83 	if (!handleptr)
84 		handleptr = m_drcuml->handle_alloc(name);
85 }
86 
87 
88 
cfunc_unimplemented(void * param)89 static void cfunc_unimplemented(void *param)
90 {
91 	mb86235_device *cpu = (mb86235_device *)param;
92 	cpu->unimplemented_op();
93 }
94 
cfunc_unimplemented_alu(void * param)95 static void cfunc_unimplemented_alu(void *param)
96 {
97 	mb86235_device *cpu = (mb86235_device *)param;
98 	cpu->unimplemented_alu();
99 }
100 
cfunc_unimplemented_control(void * param)101 static void cfunc_unimplemented_control(void *param)
102 {
103 	mb86235_device *cpu = (mb86235_device *)param;
104 	cpu->unimplemented_control();
105 }
106 
cfunc_unimplemented_double_xfer1(void * param)107 static void cfunc_unimplemented_double_xfer1(void *param)
108 {
109 	mb86235_device *cpu = (mb86235_device *)param;
110 	cpu->unimplemented_double_xfer1();
111 }
112 
cfunc_unimplemented_double_xfer2(void * param)113 static void cfunc_unimplemented_double_xfer2(void *param)
114 {
115 	mb86235_device *cpu = (mb86235_device *)param;
116 	cpu->unimplemented_double_xfer2();
117 }
118 
cfunc_pcs_overflow(void * param)119 static void cfunc_pcs_overflow(void *param)
120 {
121 	mb86235_device *cpu = (mb86235_device *)param;
122 	cpu->pcs_overflow();
123 }
124 
cfunc_pcs_underflow(void * param)125 static void cfunc_pcs_underflow(void *param)
126 {
127 	mb86235_device *cpu = (mb86235_device *)param;
128 	cpu->pcs_underflow();
129 }
130 
131 
132 
unimplemented_op()133 void mb86235_device::unimplemented_op()
134 {
135 	uint64_t op = m_core->arg64;
136 	printf("MB86235: PC=%08X: Unimplemented op %04X%08X\n", m_core->pc, (uint32_t)(op >> 32), (uint32_t)(op));
137 	fatalerror("MB86235: PC=%08X: Unimplemented op %04X%08X\n", m_core->pc, (uint32_t)(op >> 32), (uint32_t)(op));
138 }
139 
unimplemented_alu()140 void mb86235_device::unimplemented_alu()
141 {
142 	uint32_t op = m_core->arg0;
143 	printf("MB86235: PC=%08X: Unimplemented alu %02X\n", m_core->pc, op);
144 	fatalerror("MB86235: PC=%08X: Unimplemented alu %02X\n", m_core->pc, op);
145 }
146 
unimplemented_control()147 void mb86235_device::unimplemented_control()
148 {
149 	uint32_t cop = m_core->arg0;
150 	printf("MB86235: PC=%08X: Unimplemented control %02X\n", m_core->pc, cop);
151 	fatalerror("MB86235: PC=%08X: Unimplemented control %02X\n", m_core->pc, cop);
152 }
153 
unimplemented_double_xfer1()154 void mb86235_device::unimplemented_double_xfer1()
155 {
156 	uint64_t op = m_core->arg64;
157 	printf("MB86235: PC=%08X: Unimplemented double xfer1 %04X%08X\n", m_core->pc, (uint32_t)(op >> 32), (uint32_t)(op));
158 	fatalerror("MB86235: PC=%08X: Unimplemented double xfer1 %04X%08X\n", m_core->pc, (uint32_t)(op >> 32), (uint32_t)(op));
159 }
160 
unimplemented_double_xfer2()161 void mb86235_device::unimplemented_double_xfer2()
162 {
163 	uint64_t op = m_core->arg64;
164 	printf("MB86235: PC=%08X: Unimplemented double xfer2 %04X%08X\n", m_core->pc, (uint32_t)(op >> 32), (uint32_t)(op));
165 	fatalerror("MB86235: PC=%08X: Unimplemented double xfer2 %04X%08X\n", m_core->pc, (uint32_t)(op >> 32), (uint32_t)(op));
166 }
167 
pcs_overflow()168 void mb86235_device::pcs_overflow()
169 {
170 	printf("MB86235: PC=%08X: PCS overflow\n", m_core->pc);
171 	fatalerror("MB86235: PC=%08X: PCS overflow\n", m_core->pc);
172 }
173 
pcs_underflow()174 void mb86235_device::pcs_underflow()
175 {
176 	printf("MB86235: PC=%08X: PCS underflow\n", m_core->pc);
177 	fatalerror("MB86235: PC=%08X: PCS underflow\n", m_core->pc);
178 }
179 
180 
181 
182 
183 /*-------------------------------------------------
184 load_fast_iregs - load any fast integer
185 registers
186 -------------------------------------------------*/
187 
load_fast_iregs(drcuml_block & block)188 inline void mb86235_device::load_fast_iregs(drcuml_block &block)
189 {
190 	int regnum;
191 
192 	for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++)
193 	{
194 		if (m_regmap[regnum].is_int_register())
195 		{
196 		}
197 	}
198 }
199 
200 
201 /*-------------------------------------------------
202 save_fast_iregs - save any fast integer
203 registers
204 -------------------------------------------------*/
205 
save_fast_iregs(drcuml_block & block)206 void mb86235_device::save_fast_iregs(drcuml_block &block)
207 {
208 	int regnum;
209 
210 	for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++)
211 	{
212 		if (m_regmap[regnum].is_int_register())
213 		{
214 		}
215 	}
216 }
217 
218 
219 
220 
run_drc()221 void mb86235_device::run_drc()
222 {
223 	drcuml_state *drcuml = m_drcuml.get();
224 	int execute_result;
225 
226 	/* execute */
227 	do
228 	{
229 		execute_result = drcuml->execute(*m_entry);
230 
231 		/* if we need to recompile, do it */
232 		if (execute_result == EXECUTE_MISSING_CODE)
233 		{
234 			compile_block(m_core->pc);
235 		}
236 		else if (execute_result == EXECUTE_UNMAPPED_CODE)
237 		{
238 			fatalerror("Attempted to execute unmapped code at PC=%08X\n", m_core->pc);
239 		}
240 		else if (execute_result == EXECUTE_RESET_CACHE)
241 		{
242 			flush_cache();
243 		}
244 	} while (execute_result != EXECUTE_OUT_OF_CYCLES);
245 }
246 
compile_block(offs_t pc)247 void mb86235_device::compile_block(offs_t pc)
248 {
249 	compiler_state compiler = { 0 };
250 
251 	const opcode_desc *seqhead, *seqlast;
252 	const opcode_desc *desclist;
253 	bool override = false;
254 
255 	desclist = m_drcfe->describe_code(pc);
256 
257 	bool succeeded = false;
258 	while (!succeeded)
259 	{
260 		try
261 		{
262 			drcuml_block &block(m_drcuml->begin_block(4096));
263 
264 			for (seqhead = desclist; seqhead != nullptr; seqhead = seqlast->next())
265 			{
266 				const opcode_desc *curdesc;
267 				uint32_t nextpc;
268 
269 				/* determine the last instruction in this sequence */
270 				for (seqlast = seqhead; seqlast != nullptr; seqlast = seqlast->next())
271 					if (seqlast->flags & OPFLAG_END_SEQUENCE)
272 						break;
273 				assert(seqlast != nullptr);
274 
275 				/* if we don't have a hash for this mode/pc, or if we are overriding all, add one */
276 				if (override || m_drcuml->hash_exists(0, seqhead->pc))
277 					UML_HASH(block, 0, seqhead->pc);                                        // hash    mode,pc
278 
279 																							/* if we already have a hash, and this is the first sequence, assume that we */
280 																							/* are recompiling due to being out of sync and allow future overrides */
281 				else if (seqhead == desclist)
282 				{
283 					override = true;
284 					UML_HASH(block, 0, seqhead->pc);                                        // hash    mode,pc
285 				}
286 
287 				/* otherwise, redispatch to that fixed PC and skip the rest of the processing */
288 				else
289 				{
290 					UML_LABEL(block, seqhead->pc | 0x80000000);                             // label   seqhead->pc
291 					UML_HASHJMP(block, 0, seqhead->pc, *m_nocode);                          // hashjmp <0>,seqhead->pc,nocode
292 					continue;
293 				}
294 
295 				/* label this instruction, if it may be jumped to locally */
296 				if (seqhead->flags & OPFLAG_IS_BRANCH_TARGET)
297 					UML_LABEL(block, seqhead->pc | 0x80000000);                             // label   seqhead->pc
298 
299 																							/* iterate over instructions in the sequence and compile them */
300 				for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next())
301 					generate_sequence_instruction(block, compiler, curdesc);
302 
303 				/* if we need to return to the start, do it */
304 				if (seqlast->flags & OPFLAG_RETURN_TO_START)
305 					nextpc = pc;
306 				/* otherwise we just go to the next instruction */
307 				else
308 					nextpc = seqlast->pc + (seqlast->skipslots + 1);
309 
310 				/* count off cycles and go there */
311 				generate_update_cycles(block, compiler, nextpc, true);                     // <subtract cycles>
312 
313 				if (seqlast->next() == nullptr || seqlast->next()->pc != nextpc)
314 					UML_HASHJMP(block, 0, nextpc, *m_nocode);                               // hashjmp <mode>,nextpc,nocode
315 			}
316 
317 			block.end();
318 			succeeded = true;
319 		}
320 		catch (drcuml_block::abort_compilation &)
321 		{
322 			flush_cache();
323 		}
324 	}
325 }
326 
327 
328 
static_generate_entry_point()329 void mb86235_device::static_generate_entry_point()
330 {
331 	//uml::code_label const skip = 1;
332 	/* begin generating */
333 	drcuml_block &block(m_drcuml->begin_block(20));
334 
335 	/* forward references */
336 	alloc_handle(m_nocode, "nocode");
337 
338 	alloc_handle(m_entry, "entry");
339 	UML_HANDLE(block, *m_entry);                                                            // handle  entry
340 
341 	load_fast_iregs(block);                                                                 // <load fastregs>
342 
343 	/* generate a hash jump via the current mode and PC */
344 	UML_HASHJMP(block, 0, mem(&m_core->pc), *m_nocode);   // hashjmp <mode>,<pc>,nocode
345 
346 	block.end();
347 }
348 
349 
static_generate_nocode_handler()350 void mb86235_device::static_generate_nocode_handler()
351 {
352 	/* begin generating */
353 	drcuml_block &block(m_drcuml->begin_block(10));
354 
355 	/* generate a hash jump via the current mode and PC */
356 	alloc_handle(m_nocode, "nocode");
357 	UML_HANDLE(block, *m_nocode);                                                           // handle  nocode
358 	UML_GETEXP(block, I0);                                                                  // getexp  i0
359 	UML_MOV(block, mem(&m_core->pc), I0);                                                   // mov     [pc],i0
360 	save_fast_iregs(block);                                                                 // <save fastregs>
361 	UML_EXIT(block, EXECUTE_MISSING_CODE);                                                  // exit    EXECUTE_MISSING_CODE
362 
363 	block.end();
364 }
365 
static_generate_out_of_cycles()366 void mb86235_device::static_generate_out_of_cycles()
367 {
368 	/* begin generating */
369 	drcuml_block &block(m_drcuml->begin_block(10));
370 
371 	/* generate a hash jump via the current mode and PC */
372 	alloc_handle(m_out_of_cycles, "out_of_cycles");
373 	UML_HANDLE(block, *m_out_of_cycles);                                                    // handle  out_of_cycles
374 	UML_GETEXP(block, I0);                                                                  // getexp  i0
375 	UML_MOV(block, mem(&m_core->pc), I0);                                                   // mov     <pc>,i0
376 	save_fast_iregs(block);                                                                 // <save fastregs>
377 	UML_EXIT(block, EXECUTE_OUT_OF_CYCLES);                                                 // exit    EXECUTE_OUT_OF_CYCLES
378 
379 	block.end();
380 }
381 
clear_fifoin(void * param)382 void mb86235_device::clear_fifoin(void *param)
383 {
384 	mb86235_device *cpu = (mb86235_device *)param;
385 	cpu->m_fifoin->clear();
386 }
387 
clear_fifoout0(void * param)388 void mb86235_device::clear_fifoout0(void *param)
389 {
390 	mb86235_device *cpu = (mb86235_device *)param;
391 	cpu->m_fifoout0->clear();
392 }
393 
clear_fifoout1(void * param)394 void mb86235_device::clear_fifoout1(void *param)
395 {
396 	mb86235_device *cpu = (mb86235_device *)param;
397 	cpu->m_fifoout1->clear();
398 }
399 
read_fifoin(void * param)400 void mb86235_device::read_fifoin(void *param)
401 {
402 	mb86235_device *cpu = (mb86235_device *)param;
403 	cpu->m_cur_value = cpu->m_fifoin->pop();
404 }
405 
write_fifoout0(void * param)406 void mb86235_device::write_fifoout0(void *param)
407 {
408 	mb86235_device *cpu = (mb86235_device *)param;
409 	cpu->m_fifoout0->push(u32(cpu->m_cur_value));
410 }
411 
write_fifoout1(void * param)412 void mb86235_device::write_fifoout1(void *param)
413 {
414 	mb86235_device *cpu = (mb86235_device *)param;
415 	cpu->m_fifoout1->push(u32(cpu->m_cur_value));
416 }
417 
empty_fifoin(void * param)418 void mb86235_device::empty_fifoin(void *param)
419 {
420 	mb86235_device *cpu = (mb86235_device *)param;
421 	cpu->m_cur_value = cpu->m_fifoin->is_empty();
422 }
423 
full_fifoout0(void * param)424 void mb86235_device::full_fifoout0(void *param)
425 {
426 	mb86235_device *cpu = (mb86235_device *)param;
427 	cpu->m_cur_value = cpu->m_fifoout0->is_full();
428 }
429 
full_fifoout1(void * param)430 void mb86235_device::full_fifoout1(void *param)
431 {
432 	mb86235_device *cpu = (mb86235_device *)param;
433 	cpu->m_cur_value = cpu->m_fifoout1->is_full();
434 }
435 
static_generate_memory_accessors()436 void mb86235_device::static_generate_memory_accessors()
437 {
438 	uml::code_label label = 1;
439 
440 	{
441 		// A-Bus read handler
442 		// I0 = address
443 		// I1 = return data
444 		// I2 = trashed
445 		drcuml_block &block(m_drcuml->begin_block(128));
446 
447 		alloc_handle(m_read_abus, "read_abus");
448 		UML_HANDLE(block, *m_read_abus);
449 		UML_CMP(block, I0, 0x400);
450 		UML_JMPc(block, COND_GE, label);
451 		// internal A-RAM
452 		UML_READ(block, I1, I0, SIZE_DWORD, SPACE_DATA);
453 		UML_RET(block);
454 		// external
455 		UML_LABEL(block, label++);
456 		UML_AND(block, I0, I0, 0x3fff);
457 		UML_AND(block, I2, mem(&m_core->eb), ~0x3fff);
458 		UML_OR(block, I0, I0, I2);
459 		UML_READ(block, I1, I0, SIZE_DWORD, SPACE_DATA);
460 		UML_RET(block);
461 
462 		block.end();
463 	}
464 	{
465 		// A-Bus write handler
466 		// I0 = address
467 		// I1 = data
468 		// I2 = trashed
469 		drcuml_block &block(m_drcuml->begin_block(128));
470 
471 		alloc_handle(m_write_abus, "write_abus");
472 		UML_HANDLE(block, *m_write_abus);
473 		UML_CMP(block, I0, 0x400);
474 		UML_JMPc(block, COND_GE, label);
475 		// internal A-RAM
476 		UML_WRITE(block, I0, I1, SIZE_DWORD, SPACE_DATA);
477 		UML_RET(block);
478 		// external
479 		UML_LABEL(block, label++);
480 		UML_AND(block, I0, I0, 0x3fff);
481 		UML_AND(block, I2, mem(&m_core->eb), ~0x3fff);
482 		UML_OR(block, I0, I0, I2);
483 		UML_WRITE(block, I0, I1, SIZE_DWORD, SPACE_DATA);
484 		UML_RET(block);
485 
486 		block.end();
487 	}
488 }
489 
490 
flush_cache()491 void mb86235_device::flush_cache()
492 {
493 	/* empty the transient cache contents */
494 	m_drcuml->reset();
495 
496 	try
497 	{
498 		// generate the entry point and out-of-cycles handlers
499 		static_generate_entry_point();
500 		static_generate_nocode_handler();
501 		static_generate_out_of_cycles();
502 
503 		// generate exception handlers
504 
505 		// generate memory accessors
506 		static_generate_memory_accessors();
507 	}
508 	catch (drcuml_block::abort_compilation &)
509 	{
510 		fatalerror("Error generating MB86235 static handlers\n");
511 	}
512 }
513 
514 
515 
generate_sequence_instruction(drcuml_block & block,compiler_state & compiler,const opcode_desc * desc)516 void mb86235_device::generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
517 {
518 	/* add an entry for the log */
519 	//  if (m_drcuml->logging() && !(desc->flags & OPFLAG_VIRTUAL_NOOP))
520 	//      log_add_disasm_comment(block, desc->pc, desc->opptr.l[0]);
521 
522 	/* set the PC map variable */
523 	UML_MAPVAR(block, MAPVAR_PC, desc->pc);                                                 // mapvar  PC,desc->pc
524 
525 																							/* accumulate total cycles */
526 	compiler.cycles += desc->cycles;
527 
528 	/* update the icount map variable */
529 	UML_MAPVAR(block, MAPVAR_CYCLES, compiler.cycles);                                      // mapvar  CYCLES,compiler.cycles
530 
531 																							/* if we are debugging, call the debugger */
532 	if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
533 	{
534 		UML_MOV(block, mem(&m_core->pc), desc->pc);                                         // mov     [pc],desc->pc
535 		save_fast_iregs(block);                                                             // <save fastregs>
536 		UML_DEBUG(block, desc->pc);                                                         // debug   desc->pc
537 	}
538 
539 	/* if we hit an unmapped address, fatal error */
540 	if (desc->flags & OPFLAG_COMPILER_UNMAPPED)
541 	{
542 		UML_MOV(block, mem(&m_core->pc), desc->pc);                                         // mov     [pc],desc->pc
543 		save_fast_iregs(block);                                                             // <save fastregs>
544 		UML_EXIT(block, EXECUTE_UNMAPPED_CODE);                                             // exit    EXECUTE_UNMAPPED_CODE
545 	}
546 
547 	/* if this is an invalid opcode, generate the exception now */
548 	//  if (desc->flags & OPFLAG_INVALID_OPCODE)
549 	//      UML_EXH(block, *m_exception[EXCEPTION_PROGRAM], 0x80000);                           // exh    exception_program,0x80000
550 
551 	/* unless this is a virtual no-op, it's a regular instruction */
552 	if (!(desc->flags & OPFLAG_VIRTUAL_NOOP))
553 	{
554 		/* compile the instruction */
555 		if (!generate_opcode(block, compiler, desc))
556 		{
557 			UML_MOV(block, mem(&m_core->pc), desc->pc);                                     // mov     [pc],desc->pc
558 			UML_DMOV(block, mem(&m_core->arg64), desc->opptr.q[0]);                         // dmov    [arg64],*desc->opptr.q
559 			UML_CALLC(block, cfunc_unimplemented, this);                                    // callc   cfunc_unimplemented,ppc
560 		}
561 	}
562 }
563 
generate_update_cycles(drcuml_block & block,compiler_state & compiler,uml::parameter param,bool allow_exception)564 void mb86235_device::generate_update_cycles(drcuml_block &block, compiler_state &compiler, uml::parameter param, bool allow_exception)
565 {
566 	/* account for cycles */
567 	if (compiler.cycles > 0)
568 	{
569 		UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), MAPVAR_CYCLES);          // sub     icount,icount,cycles
570 		UML_MAPVAR(block, MAPVAR_CYCLES, 0);                                                // mapvar  cycles,0
571 		if (allow_exception)
572 			UML_EXHc(block, COND_S, *m_out_of_cycles, param);                               // exh     out_of_cycles,nextpc
573 	}
574 	compiler.cycles = 0;
575 }
576 
577 
generate_ea(drcuml_block & block,compiler_state & compiler,const opcode_desc * desc,int md,int arx,int ary,int disp)578 void mb86235_device::generate_ea(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, int md, int arx, int ary, int disp)
579 {
580 	// Calculates EA into register I0
581 
582 	switch (md)
583 	{
584 		case 0x0:   // @ARx
585 			UML_MOV(block, I0, AR(arx));
586 			break;
587 		case 0x1:   // @ARx++
588 			UML_MOV(block, I0, AR(arx));
589 			UML_ADD(block, AR(arx), AR(arx), 1);
590 			break;
591 		case 0x3:   // @ARx++disp12
592 			UML_ADD(block, I0, AR(arx), disp);
593 			UML_ADD(block, AR(arx), AR(arx), 1);
594 			break;
595 		case 0x4:   // @ARx+ARy
596 			UML_ADD(block, I0, AR(arx), AR(ary));
597 			break;
598 		case 0x5:   // @ARx+ARy++
599 			UML_ADD(block, I0, AR(arx), AR(ary));
600 			UML_ADD(block, AR(ary), AR(ary), 1);
601 			break;
602 		case 0xa:   // @ARx+disp12
603 			UML_ADD(block, I0, AR(arx), disp);
604 			break;
605 
606 		default:
607 			fatalerror("generate_ea: md = %02X, PC = %08X", md, desc->pc);
608 			break;
609 	}
610 }
611 
612 
613 
generate_reg_read(drcuml_block & block,compiler_state & compiler,const opcode_desc * desc,int reg,uml::parameter dst)614 void mb86235_device::generate_reg_read(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, int reg, uml::parameter dst)
615 {
616 	switch (reg)
617 	{
618 		case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
619 			// MA0-7
620 			UML_MOV(block, dst, MA(reg & 7));
621 			break;
622 
623 		case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
624 			// AA0-7
625 			UML_MOV(block, dst, AA(reg & 7));
626 			break;
627 
628 		case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
629 			// AR0-7
630 			UML_MOV(block, dst, AR(reg & 7));
631 			break;
632 
633 		case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
634 			// MB0-7
635 			UML_MOV(block, dst, MB(reg & 7));
636 			break;
637 
638 		case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
639 			// AB0-7
640 			UML_MOV(block, dst, AB(reg & 7));
641 			break;
642 
643 		case 0x30:  // PR
644 			UML_LOAD(block, dst, m_core->pr, PRP, SIZE_DWORD, SCALE_x4);
645 			break;
646 
647 		case 0x31:  // FI
648 			if (m_fifoin)
649 			{
650 				UML_CALLC(block, read_fifoin, this);
651 				UML_MOV(block, dst, mem(&m_cur_value));
652 			}
653 			else
654 				UML_MOV(block, dst, 0);
655 			break;
656 
657 		default:
658 			fatalerror("generate_reg_read: unimplemented register %02X at %08X", reg, desc->pc);
659 			break;
660 	}
661 }
662 
663 
generate_reg_write(drcuml_block & block,compiler_state & compiler,const opcode_desc * desc,int reg,uml::parameter src)664 void mb86235_device::generate_reg_write(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, int reg, uml::parameter src)
665 {
666 	switch (reg)
667 	{
668 		case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
669 			// MA0-7
670 			UML_MOV(block, MA(reg & 7), src);
671 			break;
672 
673 		case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
674 			// AA0-7
675 			UML_MOV(block, AA(reg & 7), src);
676 			break;
677 
678 		case 0x10:      // EB
679 			UML_MOV(block, mem(&m_core->eb), src);
680 			break;
681 
682 		case 0x13:      // EO
683 			UML_MOV(block, mem(&m_core->eo), src);
684 			break;
685 
686 		case 0x14:      // SP
687 			UML_MOV(block, mem(&m_core->sp), src);
688 			break;
689 
690 		case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
691 			// AR0-7
692 			UML_MOV(block, AR(reg & 7), src);
693 			break;
694 
695 		case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27:
696 			// MB0-7
697 			UML_MOV(block, MB(reg & 7), src);
698 			break;
699 
700 		case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f:
701 			// AB0-7
702 			UML_MOV(block, AB(reg & 7), src);
703 			break;
704 
705 		case 0x30:      // PR
706 			UML_STORE(block, m_core->pr, PWP, src, SIZE_DWORD, SCALE_x4);
707 			break;
708 
709 		case 0x32:      // FO0
710 			if (m_fifoout0)
711 			{
712 				UML_MOV(block, mem(&m_cur_value), src);
713 				UML_CALLC(block, write_fifoout0, this);
714 			}
715 			break;
716 
717 		case 0x34:      // PDR
718 			UML_MOV(block, mem(&m_core->pdr), src);
719 			break;
720 
721 		case 0x35:      // DDR
722 			UML_MOV(block, mem(&m_core->ddr), src);
723 			break;
724 
725 		case 0x36:      // PRP
726 			UML_MOV(block, PRP, src);
727 			break;
728 
729 		case 0x37:      // PWP
730 			UML_MOV(block, PWP, src);
731 			break;
732 
733 		default:
734 			fatalerror("generate_reg_write: unimplemented register %02X at %08X", reg, desc->pc);
735 			break;
736 	}
737 }
738 
has_register_clash(const opcode_desc * desc,int outreg)739 bool mb86235_device::has_register_clash(const opcode_desc *desc, int outreg)
740 {
741 	switch (outreg)
742 	{
743 		case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
744 			// MA0-7
745 			if (desc->regin[0] & (1 << (16 + (outreg & 7)))) return true;
746 			break;
747 		case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
748 			// MB0-7
749 			if (desc->regin[0] & (1 << (24 + (outreg & 7)))) return true;
750 			break;
751 		case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
752 			// AA0-7
753 			if (desc->regin[0] & (1 << (outreg & 7))) return true;
754 			break;
755 		case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
756 			// AB0-7
757 			if (desc->regin[0] & (1 << (8 + (outreg & 7)))) return true;
758 			break;
759 	}
760 	return false;
761 }
762 
aluop_has_result(int aluop)763 bool mb86235_device::aluop_has_result(int aluop)
764 {
765 	switch (aluop)
766 	{
767 		case 0x04:      // FCMP
768 		case 0x07:      // NOP
769 		case 0x14:      // CMP
770 			return false;
771 
772 		default:
773 			break;
774 	}
775 	return true;
776 }
777 
778 
779 
generate_opcode(drcuml_block & block,compiler_state & compiler,const opcode_desc * desc)780 bool mb86235_device::generate_opcode(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
781 {
782 	uint64_t opcode = desc->opptr.q[0];
783 
784 	bool fifoin_check = false;
785 	bool fifoout0_check = false;
786 	bool fifoout1_check = false;
787 
788 	// enable fifo in check if this opcode or the delay slot reads from FIFO
789 	if (desc->userflags & OP_USERFLAG_FIFOIN)
790 		fifoin_check = true;
791 	if (desc->delayslots > 0)
792 	{
793 		if (desc->delay.first()->userflags & OP_USERFLAG_FIFOIN)
794 			fifoin_check = true;
795 	}
796 
797 	// enable fifoout0 check if this opcode or the delay slot writes to FIFO0
798 	if (desc->userflags & OP_USERFLAG_FIFOOUT0)
799 		fifoout0_check = true;
800 	if (desc->delayslots > 0)
801 	{
802 		if (desc->delay.first()->userflags & OP_USERFLAG_FIFOOUT0)
803 			fifoout0_check = true;
804 	}
805 
806 	// enable fifoout1 check if this opcode or the delay slot writes to FIFO1
807 	if (desc->userflags & OP_USERFLAG_FIFOOUT1)
808 		fifoout1_check = true;
809 	if (desc->delayslots > 0)
810 	{
811 		if (desc->delay.first()->userflags & OP_USERFLAG_FIFOOUT1)
812 			fifoout1_check = true;
813 	}
814 
815 	// insert FIFO IN check if needed
816 	if (fifoin_check && m_fifoin)
817 	{
818 		uml::code_label const not_empty = compiler.labelnum++;
819 		UML_CALLC(block, empty_fifoin, this);
820 		UML_CMP(block, mem(&m_cur_value), 1);
821 		UML_JMPc(block, COND_NE, not_empty);
822 
823 		UML_MOV(block, mem(&m_core->icount), 0);
824 		UML_EXH(block, *m_out_of_cycles, desc->pc);
825 
826 		UML_LABEL(block, not_empty);
827 	}
828 
829 	// insert FIFO OUT0 check if needed
830 	if (fifoout0_check && m_fifoout0)
831 	{
832 		uml::code_label const not_full = compiler.labelnum++;
833 		UML_CALLC(block, full_fifoout0, this);
834 		UML_CMP(block, mem(&m_cur_value), 1);
835 		UML_JMPc(block, COND_NE, not_full);
836 
837 		UML_MOV(block, mem(&m_core->icount), 0);
838 		UML_EXH(block, *m_out_of_cycles, desc->pc);
839 
840 		UML_LABEL(block, not_full);
841 	}
842 
843 	// insert FIFO OUT1 check if needed
844 	if (fifoout1_check && m_fifoout1)
845 	{
846 		uml::code_label const not_full = compiler.labelnum++;
847 		UML_CALLC(block, full_fifoout1, this);
848 		UML_CMP(block, mem(&m_cur_value), 1);
849 		UML_JMPc(block, COND_NE, not_full);
850 
851 		UML_MOV(block, mem(&m_core->icount), 0);
852 		UML_EXH(block, *m_out_of_cycles, desc->pc);
853 
854 		UML_LABEL(block, not_full);
855 	}
856 
857 
858 	switch ((opcode >> 61) & 7)
859 	{
860 		case 0:     // ALU / MUL / double transfer (type 1)
861 		{
862 			bool alu_temp = has_register_clash(desc, (opcode >> 42) & 0x1f) && aluop_has_result((opcode >> 56) & 0x1f);
863 			bool mul_temp = has_register_clash(desc, (opcode >> 27) & 0x1f);
864 			generate_alu(block, compiler, desc, (opcode >> 42) & 0x7ffff, alu_temp);
865 			generate_mul(block, compiler, desc, (opcode >> 27) & 0x7fff, mul_temp);
866 			generate_double_xfer1(block, compiler, desc);
867 			if (alu_temp) UML_MOV(block, get_alu_output((opcode >> 42) & 0x1f), mem(&m_core->alutemp));
868 			if (mul_temp) UML_MOV(block, get_alu_output((opcode >> 27) & 0x1f), mem(&m_core->multemp));
869 			break;
870 		}
871 		case 1:     // ALU / MUL / transfer (type 1)
872 		{
873 			bool alu_temp = has_register_clash(desc, (opcode >> 42) & 0x1f) && aluop_has_result((opcode >> 56) & 0x1f);
874 			bool mul_temp = has_register_clash(desc, (opcode >> 27) & 0x1f);
875 			generate_alu(block, compiler, desc, (opcode >> 42) & 0x7ffff, alu_temp);
876 			generate_mul(block, compiler, desc, (opcode >> 27) & 0x7fff, mul_temp);
877 			generate_xfer1(block, compiler, desc);
878 			if (alu_temp) UML_MOV(block, get_alu_output((opcode >> 42) & 0x1f), mem(&m_core->alutemp));
879 			if (mul_temp) UML_MOV(block, get_alu_output((opcode >> 27) & 0x1f), mem(&m_core->multemp));
880 			break;
881 		}
882 		case 2:     // ALU / MUL / control
883 		{
884 			generate_pre_control(block, compiler, desc);
885 			generate_alu(block, compiler, desc, (opcode >> 42) & 0x7ffff, false);
886 			generate_mul(block, compiler, desc, (opcode >> 27) & 0x7fff, false);
887 			generate_control(block, compiler, desc);
888 			break;
889 		}
890 		case 4:     // ALU or MUL / double transfer (type 2)
891 		{
892 			bool comp_temp;
893 			if (opcode & ((uint64_t)(1) << 41))
894 			{
895 				comp_temp = has_register_clash(desc, (opcode >> 42) & 0x1f) && aluop_has_result((opcode >> 56) & 0x1f);
896 				generate_alu(block, compiler, desc, (opcode >> 42) & 0x7ffff, comp_temp);
897 			}
898 			else
899 			{
900 				comp_temp = has_register_clash(desc, (opcode >> 42) & 0x1f);
901 				generate_mul(block, compiler, desc, (opcode >> 42) & 0x7fff, comp_temp);
902 			}
903 			generate_double_xfer2(block, compiler, desc);
904 			if (comp_temp)
905 			{
906 				if (opcode & ((uint64_t)(1) << 41))
907 					UML_MOV(block, get_alu_output((opcode >> 42) & 0x1f), mem(&m_core->alutemp));
908 				else
909 					UML_MOV(block, get_alu_output((opcode >> 42) & 0x1f), mem(&m_core->multemp));
910 			}
911 			break;
912 		}
913 		case 5:     // ALU or MUL / transfer (type 2)
914 		{
915 			bool comp_temp;
916 			if (opcode & ((uint64_t)(1) << 41))
917 			{
918 				comp_temp = has_register_clash(desc, (opcode >> 42) & 0x1f) && aluop_has_result((opcode >> 56) & 0x1f);
919 				generate_alu(block, compiler, desc, (opcode >> 42) & 0x7ffff, comp_temp);
920 			}
921 			else
922 			{
923 				comp_temp = has_register_clash(desc, (opcode >> 42) & 0x1f);
924 				generate_mul(block, compiler, desc, (opcode >> 42) & 0x7fff, comp_temp);
925 			}
926 			generate_xfer2(block, compiler, desc);
927 			if (comp_temp)
928 			{
929 				if (opcode & ((uint64_t)(1) << 41))
930 					UML_MOV(block, get_alu_output((opcode >> 42) & 0x1f), mem(&m_core->alutemp));
931 				else
932 					UML_MOV(block, get_alu_output((opcode >> 42) & 0x1f), mem(&m_core->multemp));
933 			}
934 			break;
935 		}
936 		case 6:     // ALU or MUL / control
937 		{
938 			generate_pre_control(block, compiler, desc);
939 			if (opcode & ((uint64_t)(1) << 41))
940 				generate_alu(block, compiler, desc, (opcode >> 42) & 0x7ffff, false);
941 			else
942 				generate_mul(block, compiler, desc, (opcode >> 42) & 0x7fff, false);
943 			generate_control(block, compiler, desc);
944 			break;
945 		}
946 		case 7:     // transfer (type 3)
947 		{
948 			generate_xfer3(block, compiler, desc);
949 			break;
950 		}
951 
952 		default:
953 			return false;
954 	}
955 
956 	// update PR and PW if needed
957 	if ((desc->userflags & OP_USERFLAG_PR_MASK) != 0)
958 	{
959 		switch ((desc->userflags & OP_USERFLAG_PR_MASK) >> 8)
960 		{
961 			case 1:     // PR++
962 				UML_ADD(block, PRP, PRP, 1);
963 				UML_CMP(block, PRP, 24);
964 				UML_MOVc(block, COND_GE, PRP, 0);
965 				break;
966 			case 2:     // PR--
967 				UML_SUB(block, PRP, PRP, 1);
968 				UML_CMP(block, PRP, 0);
969 				UML_MOVc(block, COND_L, PRP, 23);
970 				break;
971 			case 3:     // PR#0
972 				UML_MOV(block, PRP, 0);
973 				break;
974 		}
975 	}
976 
977 	if ((desc->userflags & OP_USERFLAG_PW_MASK) != 0)
978 	{
979 		switch ((desc->userflags & OP_USERFLAG_PW_MASK) >> 10)
980 		{
981 			case 1:     // PW++
982 				UML_ADD(block, PWP, PWP, 1);
983 				UML_CMP(block, PWP, 24);
984 				UML_MOVc(block, COND_GE, PWP, 0);
985 				break;
986 			case 2:     // PW--
987 				UML_SUB(block, PWP, PWP, 1);
988 				UML_CMP(block, PWP, 0);
989 				UML_MOVc(block, COND_L, PWP, 23);
990 				break;
991 			case 3:     // PW#0
992 				UML_MOV(block, PWP, 0);
993 				break;
994 		}
995 	}
996 
997 	// handle repeat
998 	if (desc->userflags & OP_USERFLAG_REPEATED_OP)
999 	{
1000 		uml::code_label const no_repeat = compiler.labelnum++;
1001 		UML_SUB(block, RPC, RPC, 1);
1002 		UML_CMP(block, RPC, 0);
1003 		UML_JMPc(block, COND_LE, no_repeat);
1004 
1005 		generate_update_cycles(block, compiler, desc->pc, true);
1006 		if (desc->flags & OPFLAG_INTRABLOCK_BRANCH)
1007 			UML_JMP(block, desc->pc | 0x80000000);
1008 		else
1009 			UML_HASHJMP(block, 0, desc->pc, *m_nocode);
1010 
1011 		UML_LABEL(block, no_repeat);
1012 	}
1013 
1014 	return true;
1015 }
1016 
1017 
1018 
generate_alumul_input(drcuml_block & block,compiler_state & compiler,const opcode_desc * desc,int reg,uml::parameter dst,bool fp,bool mul)1019 void mb86235_device::generate_alumul_input(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, int reg, uml::parameter dst, bool fp, bool mul)
1020 {
1021 	switch (reg)
1022 	{
1023 		case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
1024 			if (mul)
1025 				UML_MOV(block, dst, MA(reg & 7));
1026 			else
1027 				UML_MOV(block, dst, AA(reg & 7));
1028 			break;
1029 
1030 		case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
1031 			if (mul)
1032 				UML_MOV(block, dst, MB(reg & 7));
1033 			else
1034 				UML_MOV(block, dst, AB(reg & 7));
1035 			break;
1036 
1037 		case 0x10:  // PR
1038 		case 0x11:  // PR++
1039 		case 0x12:  // PR--
1040 		case 0x13:  // PR#0
1041 			UML_LOAD(block, dst, m_core->pr, PRP, SIZE_DWORD, SCALE_x4);
1042 			break;
1043 
1044 		case 0x18:  // 0 / -1.0E+0
1045 			if (fp)
1046 				UML_MOV(block, dst, 0xbf800000);
1047 			else
1048 				UML_MOV(block, dst, 0);
1049 			break;
1050 
1051 		case 0x19:  // 1 / 0.0E+0
1052 			if (fp)
1053 				UML_MOV(block, dst, 0);
1054 			else
1055 				UML_MOV(block, dst, 1);
1056 			break;
1057 
1058 		case 0x1a:  // -1 / 0.5+0
1059 			if (fp)
1060 				UML_MOV(block, dst, 0x3f000000);
1061 			else
1062 				UML_MOV(block, dst, -1);
1063 			break;
1064 
1065 		case 0x1b:  // 1.0E+0
1066 			UML_MOV(block, dst, 0x3f800000);
1067 			break;
1068 
1069 		case 0x1c:  // 1.5E+0
1070 			UML_MOV(block, dst, 0x3fc00000);
1071 			break;
1072 
1073 		case 0x1d:  // 2.0E+0
1074 			UML_MOV(block, dst, 0x40000000);
1075 			break;
1076 
1077 		case 0x1e:  // 3.0E+0
1078 			UML_MOV(block, dst, 0x40400000);
1079 			break;
1080 
1081 		case 0x1f:  // 5.0E+0
1082 			UML_MOV(block, dst, 0x40a00000);
1083 			break;
1084 
1085 		default:
1086 			fatalerror("generate_alu_input: invalid register %02X", reg);
1087 	}
1088 }
1089 
get_alu_output(int reg)1090 uml::parameter mb86235_device::get_alu_output(int reg)
1091 {
1092 	switch (reg)
1093 	{
1094 		case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
1095 			return MA(reg & 7);
1096 		case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
1097 			return MB(reg & 7);
1098 		case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
1099 			return AA(reg & 7);
1100 		case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
1101 			return AB(reg & 7);
1102 	}
1103 	return uml::parameter(0);
1104 }
1105 
get_alu1_input(int reg)1106 uml::parameter mb86235_device::get_alu1_input(int reg)
1107 {
1108 	switch (reg)
1109 	{
1110 		case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
1111 			return AA(reg & 7);
1112 
1113 		case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
1114 			return AB(reg & 7);
1115 	}
1116 	return uml::parameter(0);
1117 }
1118 
get_mul1_input(int reg)1119 uml::parameter mb86235_device::get_mul1_input(int reg)
1120 {
1121 	switch (reg)
1122 	{
1123 		case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
1124 			return MA(reg & 7);
1125 
1126 		case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
1127 			return MB(reg & 7);
1128 	}
1129 	return uml::parameter(0);
1130 }
1131 
1132 
1133 
generate_alu(drcuml_block & block,compiler_state & compiler,const opcode_desc * desc,int aluop,bool alutemp)1134 void mb86235_device::generate_alu(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, int aluop, bool alutemp)
1135 {
1136 	int i1 = (aluop >> 10) & 0xf;
1137 	int i2 = (aluop >> 5) & 0x1f;
1138 	int io = aluop & 0x1f;
1139 	int op = (aluop >> 14) & 0x1f;
1140 
1141 	switch (op)
1142 	{
1143 		case 0x00:      // FADD
1144 			generate_alumul_input(block, compiler, desc, i2, uml::I0, true, false);
1145 			UML_FSCOPYI(block, F0, I0);
1146 			UML_FSCOPYI(block, F1, get_alu1_input(i1));
1147 			UML_FSADD(block, F0, F0, F1);
1148 			UML_ICOPYFS(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), F0);
1149 			if (AN_CALC_REQUIRED || AZ_CALC_REQUIRED)
1150 				UML_FSCMP(block, F0, mem(&m_core->fp0));
1151 			if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, FLAGS_AN);
1152 			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
1153 			// TODO: AV flag
1154 			// TODO: AU flag
1155 			// TODO: AD flag
1156 			break;
1157 
1158 		case 0x02:      // FSUB
1159 			generate_alumul_input(block, compiler, desc, i2, uml::I0, true, false);
1160 			UML_FSCOPYI(block, F0, I0);
1161 			UML_FSCOPYI(block, F1, get_alu1_input(i1));
1162 			UML_FSSUB(block, F0, F0, F1);
1163 			UML_ICOPYFS(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), F0);
1164 			if (AN_CALC_REQUIRED || AZ_CALC_REQUIRED)
1165 				UML_FSCMP(block, F0, mem(&m_core->fp0));
1166 			if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, FLAGS_AN);
1167 			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
1168 			// TODO: AV flag
1169 			// TODO: AU flag
1170 			// TODO: AD flag
1171 			break;
1172 
1173 		case 0x04:      // FCMP
1174 			generate_alumul_input(block, compiler, desc, i2, uml::I0, true, false);
1175 			UML_FSCOPYI(block, F0, I0);
1176 			UML_FSCOPYI(block, F1, get_alu1_input(i1));
1177 			UML_FSCMP(block, F0, F1);
1178 			if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, FLAGS_AN);
1179 			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
1180 			// TODO: AV flag
1181 			// TODO: AU flag
1182 			// TODO: AD flag
1183 			break;
1184 
1185 		case 0x05:      // FABS
1186 			UML_AND(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), get_alu1_input(i1), 0x7fffffff);
1187 			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
1188 			if (AN_CALC_REQUIRED) UML_MOV(block, FLAGS_AN, 0);
1189 			// TODO: AD flag
1190 			break;
1191 
1192 		case 0x06:      // FABC
1193 			generate_alumul_input(block, compiler, desc, i2, uml::I0, true, false);
1194 			UML_AND(block, I0, I0, 0x7fffffff);
1195 			UML_AND(block, I1, get_alu1_input(i1), 0x7fffffff);
1196 			UML_FSCOPYI(block, F0, I0);
1197 			UML_FSCOPYI(block, F1, I1);
1198 			UML_FSCMP(block, F0, F1);
1199 			if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, FLAGS_AN);
1200 			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
1201 			if (AU_CALC_REQUIRED) UML_MOV(block, FLAGS_AU, 1);
1202 			// TODO: AD flag
1203 			break;
1204 
1205 		case 0x07:      // NOP
1206 			break;
1207 
1208 		case 0x0d:      // CIF
1209 			generate_alumul_input(block, compiler, desc, i1, uml::I1, true, false);
1210 			UML_FSFRINT(block, F0, I1, SIZE_DWORD);
1211 			if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED)
1212 				UML_CMP(block, I1, 0);
1213 			if (AN_CALC_REQUIRED) UML_SETc(block, COND_L, FLAGS_AN);
1214 			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_E, FLAGS_AZ);
1215 			UML_ICOPYFS(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), F0);
1216 			break;
1217 
1218 		case 0x0e:      // CFI
1219 		{
1220 			uml::code_label const truncate = compiler.labelnum++;
1221 			uml::code_label const end = compiler.labelnum++;
1222 			UML_FSCOPYI(block, F0, get_alu1_input(i1));
1223 			UML_TEST(block, mem(&m_core->mod), 0x80);
1224 			UML_JMPc(block, COND_Z, truncate);
1225 			UML_FSTOINT(block, I0, F0, SIZE_DWORD, ROUND_ROUND);
1226 			UML_JMP(block, end);
1227 			UML_LABEL(block, truncate);
1228 			UML_FSTOINT(block, I0, F0, SIZE_DWORD, ROUND_TRUNC);
1229 			UML_LABEL(block, end);
1230 
1231 			UML_CMP(block, I0, 0xff800000);
1232 			UML_MOVc(block, COND_L, I0, 0xff800000);
1233 			if (AV_CALC_REQUIRED) UML_MOVc(block, COND_L, FLAGS_AV, 1);
1234 			UML_CMP(block, I0, 0x007fffff);
1235 			UML_MOVc(block, COND_G, I0, 0x007fffff);
1236 			if (AV_CALC_REQUIRED) UML_MOVc(block, COND_G, FLAGS_AV, 1);
1237 			if (AN_CALC_REQUIRED || AZ_CALC_REQUIRED)
1238 				UML_CMP(block, I0, 0);
1239 			if (AN_CALC_REQUIRED) UML_SETc(block, COND_L, FLAGS_AN);
1240 			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
1241 			UML_MOV(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), I0);
1242 			break;
1243 		}
1244 
1245 		case 0x10:      // ADD
1246 			generate_alumul_input(block, compiler, desc, i2, uml::I1, false, false);
1247 			UML_ADD(block, I0, I1, get_alu1_input(i1));
1248 			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
1249 			if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, FLAGS_AN);
1250 			UML_CMP(block, I0, 0xff800000);
1251 			UML_MOVc(block, COND_L, I0, 0xff800000);
1252 			if (AV_CALC_REQUIRED) UML_MOVc(block, COND_L, FLAGS_AV, 1);
1253 			UML_CMP(block, I0, 0x007fffff);
1254 			UML_MOVc(block, COND_G, I0, 0x007fffff);
1255 			if (AV_CALC_REQUIRED) UML_MOVc(block, COND_G, FLAGS_AV, 1);
1256 			UML_MOV(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), I0);
1257 			break;
1258 
1259 		case 0x12:      // SUB
1260 			generate_alumul_input(block, compiler, desc, i2, uml::I1, false, false);
1261 			UML_SUB(block, I0, I1, get_alu1_input(i1));
1262 			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
1263 			if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, FLAGS_AN);
1264 			UML_CMP(block, I0, 0xff800000);
1265 			UML_MOVc(block, COND_L, I0, 0xff800000);
1266 			if (AV_CALC_REQUIRED) UML_MOVc(block, COND_L, FLAGS_AV, 1);
1267 			UML_CMP(block, I0, 0x007fffff);
1268 			UML_MOVc(block, COND_G, I0, 0x007fffff);
1269 			if (AV_CALC_REQUIRED) UML_MOVc(block, COND_G, FLAGS_AV, 1);
1270 			UML_MOV(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), I0);
1271 			break;
1272 
1273 		case 0x14:      // CMP
1274 			generate_alumul_input(block, compiler, desc, i2, uml::I1, false, false);
1275 			UML_SUB(block, I0, I1, get_alu1_input(i1));
1276 			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
1277 			if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, FLAGS_AN);
1278 			if (AV_CALC_REQUIRED)
1279 			{
1280 				UML_CMP(block, I0, 0xff800000);
1281 				UML_MOVc(block, COND_L, FLAGS_AV, 1);
1282 				UML_CMP(block, I0, 0x007fffff);
1283 				UML_MOVc(block, COND_G, FLAGS_AV, 1);
1284 			}
1285 			break;
1286 
1287 		case 0x16:      // ATR
1288 			UML_MOV(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), get_alu1_input(i1));
1289 			break;
1290 
1291 		case 0x18:      // AND
1292 			generate_alumul_input(block, compiler, desc, i2, uml::I0, false, false);
1293 			UML_AND(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), I0, get_alu1_input(i1));
1294 			if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, FLAGS_AN);
1295 			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
1296 			if (AV_CALC_REQUIRED) UML_MOV(block, FLAGS_AV, 0);
1297 			if (AU_CALC_REQUIRED) UML_MOV(block, FLAGS_AU, 0);
1298 			break;
1299 
1300 		case 0x19:      // OR
1301 			generate_alumul_input(block, compiler, desc, i2, uml::I0, false, false);
1302 			UML_OR(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), I0, get_alu1_input(i1));
1303 			if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, FLAGS_AN);
1304 			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
1305 			if (AV_CALC_REQUIRED) UML_MOV(block, FLAGS_AV, 0);
1306 			if (AU_CALC_REQUIRED) UML_MOV(block, FLAGS_AU, 0);
1307 			break;
1308 
1309 		case 0x1a:      // XOR
1310 			generate_alumul_input(block, compiler, desc, i2, uml::I0, false, false);
1311 			UML_XOR(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), I0, get_alu1_input(i1));
1312 			if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, FLAGS_AN);
1313 			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_AZ);
1314 			if (AV_CALC_REQUIRED) UML_MOV(block, FLAGS_AV, 0);
1315 			if (AU_CALC_REQUIRED) UML_MOV(block, FLAGS_AU, 0);
1316 			break;
1317 
1318 		case 0x1c:      // LSR
1319 			generate_alumul_input(block, compiler, desc, i1, uml::I0, false, false);
1320 			UML_SHR(block, I0, I0, i2);
1321 			if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED)
1322 				UML_CMP(block, I0, 0);
1323 			if (AN_CALC_REQUIRED) UML_SETc(block, COND_L, FLAGS_AN);
1324 			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_E, FLAGS_AZ);
1325 			if (AV_CALC_REQUIRED) UML_MOV(block, FLAGS_AV, 0);
1326 			if (AU_CALC_REQUIRED) UML_MOV(block, FLAGS_AU, 0);
1327 			UML_MOV(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), I0);
1328 			break;
1329 
1330 		case 0x1d:      // LSL
1331 			generate_alumul_input(block, compiler, desc, i1, uml::I0, false, false);
1332 			UML_SHL(block, I0, I0, i2);
1333 			if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED)
1334 				UML_CMP(block, I0, 0);
1335 			if (AN_CALC_REQUIRED) UML_SETc(block, COND_L, FLAGS_AN);
1336 			if (AZ_CALC_REQUIRED) UML_SETc(block, COND_E, FLAGS_AZ);
1337 			if (AV_CALC_REQUIRED) UML_MOV(block, FLAGS_AV, 0);
1338 			if (AU_CALC_REQUIRED) UML_MOV(block, FLAGS_AU, 0);
1339 			UML_MOV(block, alutemp ? mem(&m_core->alutemp) : get_alu_output(io), I0);
1340 			break;
1341 
1342 		default:
1343 			UML_MOV(block, mem(&m_core->pc), desc->pc);
1344 			UML_MOV(block, mem(&m_core->arg0), op);
1345 			UML_CALLC(block, cfunc_unimplemented_alu, this);
1346 			break;
1347 	}
1348 }
1349 
generate_mul(drcuml_block & block,compiler_state & compiler,const opcode_desc * desc,int mulop,bool multemp)1350 void mb86235_device::generate_mul(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, int mulop, bool multemp)
1351 {
1352 	int i1 = (mulop >> 10) & 0xf;
1353 	int i2 = (mulop >> 5) & 0x1f;
1354 	int io = mulop & 0x1f;
1355 	int m = mulop & 0x4000;
1356 
1357 	if (m)
1358 	{
1359 		// FMUL
1360 		generate_alumul_input(block, compiler, desc, i2, uml::I1, true, true);
1361 		UML_FSCOPYI(block, F1, I1);
1362 		UML_FSCOPYI(block, F0, get_mul1_input(i1));
1363 		UML_FSMUL(block, F1, F0, F1);
1364 		if (MZ_CALC_REQUIRED || MN_CALC_REQUIRED)
1365 			UML_FSCMP(block, F1, mem(&m_core->fp0));
1366 		if (MZ_CALC_REQUIRED) UML_SETc(block, COND_E, FLAGS_MZ);
1367 		if (MN_CALC_REQUIRED) UML_SETc(block, COND_C, FLAGS_MN);
1368 		// TODO: MV flag
1369 		// TODO: MU flag
1370 		// TODO: MD flag
1371 		UML_ICOPYFS(block, multemp ? mem(&m_core->multemp) : get_alu_output(io), F1);
1372 	}
1373 	else
1374 	{
1375 		// MUL
1376 		generate_alumul_input(block, compiler, desc, i2, uml::I1, false, true);
1377 		UML_MULS(block, I0, I0, I1, get_mul1_input(i1));
1378 		if (MZ_CALC_REQUIRED) UML_SETc(block, COND_Z, FLAGS_MZ);
1379 		if (MN_CALC_REQUIRED) UML_SETc(block, COND_S, FLAGS_MN);
1380 		UML_CMP(block, I0, 0xff800000);
1381 		UML_MOVc(block, COND_L, I0, 0xff800000);
1382 		if (MV_CALC_REQUIRED) UML_MOVc(block, COND_L, FLAGS_MV, 1);
1383 		UML_CMP(block, I0, 0x007fffff);
1384 		UML_MOVc(block, COND_G, I0, 0x007fffff);
1385 		if (MV_CALC_REQUIRED) UML_MOVc(block, COND_G, FLAGS_MV, 1);
1386 		UML_MOV(block, multemp ? mem(&m_core->multemp) : get_alu_output(io), I0);
1387 	}
1388 }
1389 
1390 
generate_branch(drcuml_block & block,compiler_state & compiler,const opcode_desc * desc)1391 void mb86235_device::generate_branch(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
1392 {
1393 	// I0 = target pc for dynamic branches
1394 
1395 	compiler_state compiler_temp(compiler);
1396 
1397 	// save branch target
1398 	if (desc->targetpc == BRANCH_TARGET_DYNAMIC)
1399 	{
1400 		UML_MOV(block, mem(&m_core->jmpdest), I0);                                     // mov     [jmpdest],i0
1401 	}
1402 
1403 	// compile delay slots
1404 	generate_sequence_instruction(block, compiler_temp, desc->delay.first());
1405 
1406 	// update cycles and hash jump
1407 	if (desc->targetpc != BRANCH_TARGET_DYNAMIC)
1408 	{
1409 		generate_update_cycles(block, compiler_temp, desc->targetpc, true);
1410 		if (desc->flags & OPFLAG_INTRABLOCK_BRANCH)
1411 			UML_JMP(block, desc->targetpc | 0x80000000);                                // jmp      targetpc | 0x80000000
1412 		else
1413 			UML_HASHJMP(block, 0, desc->targetpc, *m_nocode);                           // hashjmp  0,targetpc,nocode
1414 	}
1415 	else
1416 	{
1417 		generate_update_cycles(block, compiler_temp, uml::mem(&m_core->jmpdest), true);
1418 		UML_HASHJMP(block, 0, mem(&m_core->jmpdest), *m_nocode);                        // hashjmp  0,jmpdest,nocode
1419 	}
1420 
1421 	// update compiler label
1422 	compiler.labelnum = compiler_temp.labelnum;
1423 
1424 	/* reset the mapvar to the current cycles and account for skipped slots */
1425 	compiler.cycles += desc->skipslots;
1426 	UML_MAPVAR(block, MAPVAR_CYCLES, compiler.cycles);                                  // mapvar  CYCLES,compiler.cycles
1427 }
1428 
1429 
generate_branch_target(drcuml_block & block,compiler_state & compiler,const opcode_desc * desc,int type,int ef2)1430 void mb86235_device::generate_branch_target(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, int type, int ef2)
1431 {
1432 	// Calculates dynamic targets into I0
1433 
1434 	switch (type)
1435 	{
1436 		case 0x0: break;
1437 		case 0x1: break;
1438 		case 0x2:           // ARx
1439 		{
1440 			int reg = (ef2 >> 6) & 7;
1441 			UML_MOV(block, I0, AR(reg));
1442 			break;
1443 		}
1444 		case 0x4:           // Axx
1445 		{
1446 			int reg = (ef2 >> 6) & 7;
1447 			if (ef2 & 0x400)
1448 				UML_MOV(block, I0, AB(reg));
1449 			else
1450 				UML_MOV(block, I0, AA(reg));
1451 			break;
1452 		}
1453 		default:
1454 			fatalerror("generate_branch_target: type %02X at %08X", type, desc->pc);
1455 			break;
1456 	}
1457 }
1458 
1459 
generate_condition(drcuml_block & block,compiler_state & compiler,const opcode_desc * desc,int cc,bool n,uml::code_label skip_label,bool condtemp)1460 void mb86235_device::generate_condition(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc, int cc, bool n, uml::code_label skip_label, bool condtemp)
1461 {
1462 	switch (cc)
1463 	{
1464 		case 0x00:      // MN
1465 			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_MN, 0);
1466 			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
1467 			break;
1468 		case 0x01:      // MZ
1469 			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_MZ, 0);
1470 			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
1471 			break;
1472 		case 0x02:      // MV
1473 			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_MV, 0);
1474 			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
1475 			break;
1476 		case 0x03:      // MU
1477 			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_MU, 0);
1478 			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
1479 			break;
1480 		case 0x04:      // ZD
1481 			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_ZD, 0);
1482 			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
1483 			break;
1484 		case 0x05:      // NR
1485 			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_NR, 0);
1486 			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
1487 			break;
1488 		case 0x06:      // IL
1489 			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_IL, 0);
1490 			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
1491 			break;
1492 		case 0x07:      // ZC
1493 			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_ZC, 0);
1494 			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
1495 			break;
1496 		case 0x08:      // AN
1497 			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_AN, 0);
1498 			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
1499 			break;
1500 		case 0x09:      // AZ
1501 			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_AZ, 0);
1502 			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
1503 			break;
1504 		case 0x0a:      // AV
1505 			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_AV, 0);
1506 			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
1507 			break;
1508 		case 0x0b:      // AU
1509 			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_AU, 0);
1510 			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
1511 			break;
1512 		case 0x0c:      // MD
1513 			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_MD, 0);
1514 			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
1515 			break;
1516 		case 0x0d:      // AD
1517 			UML_CMP(block, condtemp ? mem(&m_core->condtemp) : FLAGS_AD, 0);
1518 			UML_JMPc(block, n ? COND_NE : COND_E, skip_label);
1519 			break;
1520 		default:
1521 			fatalerror("generate_condition: unimplemented cc %02X at %08X", cc, desc->pc);
1522 			break;
1523 	}
1524 }
1525 
1526 
generate_control(drcuml_block & block,compiler_state & compiler,const opcode_desc * desc)1527 void mb86235_device::generate_control(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
1528 {
1529 	uint64_t op = desc->opptr.q[0];
1530 	int ef1 = (op >> 16) & 0x3f;
1531 	int ef2 = op & 0xffff;
1532 	int cop = (op >> 22) & 0x1f;
1533 //  int rel12 = (op & 0x800) ? (0xfffff000 | (op & 0xfff)) : (op & 0xfff);
1534 
1535 	switch (cop)
1536 	{
1537 		case 0x00:      // NOP
1538 			break;
1539 
1540 		case 0x03:      //
1541 			if (ef1 == 1)   // CLRFI
1542 			{
1543 				if (m_fifoin)
1544 					UML_CALLC(block, clear_fifoin, this);
1545 			}
1546 			else if (ef1 == 2)  // CLRFO
1547 			{
1548 				if (m_fifoout0)
1549 					UML_CALLC(block, clear_fifoout0, this);
1550 				if (m_fifoout1)
1551 					UML_CALLC(block, clear_fifoout1, this);
1552 			}
1553 			else if (ef1 == 3)  // CLRF
1554 			{
1555 				if (m_fifoin)
1556 					UML_CALLC(block, clear_fifoin, this);
1557 				if (m_fifoout0)
1558 					UML_CALLC(block, clear_fifoout0, this);
1559 				if (m_fifoout1)
1560 					UML_CALLC(block, clear_fifoout1, this);
1561 			}
1562 			break;
1563 
1564 		case 0x08:      // SETM #imm16
1565 			UML_MOV(block, mem(&m_core->mod), ef2);
1566 			break;
1567 
1568 		case 0x10:      // DBcc
1569 		{
1570 			uml::code_label const skip_label = compiler.labelnum++;
1571 
1572 			generate_branch_target(block, compiler, desc, (op >> 12) & 0xf, ef2);
1573 			generate_condition(block, compiler, desc, ef1, false, skip_label, true);
1574 			generate_branch(block, compiler, desc);
1575 			UML_LABEL(block, skip_label);
1576 			break;
1577 		}
1578 
1579 		case 0x11:      // DBNcc
1580 		{
1581 			uml::code_label const skip_label = compiler.labelnum++;
1582 
1583 			generate_branch_target(block, compiler, desc, (op >> 12) & 0xf, ef2);
1584 			generate_condition(block, compiler, desc, ef1, true, skip_label, true);
1585 			generate_branch(block, compiler, desc);
1586 			UML_LABEL(block, skip_label);
1587 			break;
1588 		}
1589 
1590 		case 0x12:      // DJMP
1591 		{
1592 			generate_branch_target(block, compiler, desc, (op >> 12) & 0xf, ef2);
1593 			generate_branch(block, compiler, desc);
1594 			break;
1595 		}
1596 
1597 		case 0x1a:      // DCALL
1598 		{
1599 			// push PC
1600 			uml::code_label const no_overflow = compiler.labelnum++;
1601 			UML_CMP(block, mem(&m_core->pcp), 4);
1602 			UML_JMPc(block, COND_L, no_overflow);
1603 			UML_MOV(block, mem(&m_core->pc), desc->pc);
1604 			UML_CALLC(block, cfunc_pcs_overflow, this);
1605 
1606 			UML_LABEL(block, no_overflow);
1607 			UML_STORE(block, m_core->pcs, mem(&m_core->pcp), desc->pc + 2, SIZE_DWORD, SCALE_x4);
1608 			UML_ADD(block, mem(&m_core->pcp), mem(&m_core->pcp), 1);
1609 
1610 			generate_branch_target(block, compiler, desc, (op >> 12) & 0xf, ef2);
1611 			generate_branch(block, compiler, desc);
1612 			break;
1613 		}
1614 
1615 		case 0x1b:      // DRET
1616 		{
1617 			// pop PC
1618 			uml::code_label const no_underflow = compiler.labelnum++;
1619 			UML_CMP(block, mem(&m_core->pcp), 0);
1620 			UML_JMPc(block, COND_G, no_underflow);
1621 			UML_MOV(block, mem(&m_core->pc), desc->pc);
1622 			UML_CALLC(block, cfunc_pcs_underflow, this);
1623 
1624 			UML_LABEL(block, no_underflow);
1625 			UML_SUB(block, mem(&m_core->pcp), mem(&m_core->pcp), 1);
1626 			UML_LOAD(block, I0, m_core->pcs, mem(&m_core->pcp), SIZE_DWORD, SCALE_x4);
1627 
1628 			generate_branch(block, compiler, desc);
1629 			break;
1630 		}
1631 
1632 		default:
1633 			UML_MOV(block, mem(&m_core->pc), desc->pc);
1634 			UML_MOV(block, mem(&m_core->arg0), cop);
1635 			UML_CALLC(block, cfunc_unimplemented_control, this);
1636 			break;
1637 	}
1638 }
1639 
generate_xfer1(drcuml_block & block,compiler_state & compiler,const opcode_desc * desc)1640 void mb86235_device::generate_xfer1(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
1641 {
1642 	uint64_t opcode = desc->opptr.q[0];
1643 
1644 	int dr = (opcode >> 12) & 0x7f;
1645 	int sr = (opcode >> 19) & 0x7f;
1646 	int md = opcode & 0xf;
1647 	int ary = (opcode >> 4) & 7;
1648 	int disp5 = (opcode >> 7) & 0x1f;
1649 	int trm = (opcode >> 26) & 1;
1650 //  int dir = (opcode >> 25) & 1;
1651 
1652 	if (trm == 0)
1653 	{
1654 		if (sr == 0x58)
1655 		{
1656 			// MOV1 #imm12, DR
1657 			generate_reg_write(block, compiler, desc, dr & 0x3f, uml::parameter(opcode & 0xfff));
1658 		}
1659 		else
1660 		{
1661 			if ((sr & 0x40) == 0)
1662 			{
1663 				generate_reg_read(block, compiler, desc, sr & 0x3f, uml::I1);
1664 			}
1665 			else
1666 			{
1667 				generate_ea(block, compiler, desc, md, sr & 7, ary, disp5);
1668 				if (sr & 0x20)  // RAM-B
1669 				{
1670 					UML_READ(block, I1, I0, SIZE_DWORD, SPACE_IO);
1671 				}
1672 				else // RAM-A
1673 				{
1674 					UML_CALLH(block, *m_read_abus);
1675 				}
1676 			}
1677 
1678 			if ((dr & 0x40) == 0)
1679 			{
1680 				generate_reg_write(block, compiler, desc, dr & 0x3f, uml::I1);
1681 			}
1682 			else
1683 			{
1684 				generate_ea(block, compiler, desc, md, dr & 7, ary, disp5);
1685 				if (dr & 0x20)  // RAM-B
1686 				{
1687 					UML_WRITE(block, I0, I1, SIZE_DWORD, SPACE_IO);
1688 				}
1689 				else // RAM-A
1690 				{
1691 					UML_CALLH(block, *m_write_abus);
1692 				}
1693 			}
1694 		}
1695 	}
1696 	else
1697 	{
1698 		// external transfer
1699 		fatalerror("generate_xfer1 MOV1 at %08X (%08X%08X)", desc->pc, (uint32_t)(opcode >> 32), (uint32_t)(opcode));
1700 	}
1701 }
1702 
generate_double_xfer1(drcuml_block & block,compiler_state & compiler,const opcode_desc * desc)1703 void mb86235_device::generate_double_xfer1(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
1704 {
1705 	UML_MOV(block, mem(&m_core->pc), desc->pc);
1706 	UML_DMOV(block, mem(&m_core->arg64), desc->opptr.q[0]);
1707 	UML_CALLC(block, cfunc_unimplemented_double_xfer1, this);
1708 }
1709 
generate_xfer2(drcuml_block & block,compiler_state & compiler,const opcode_desc * desc)1710 void mb86235_device::generate_xfer2(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
1711 {
1712 	uint64_t opcode = desc->opptr.q[0];
1713 
1714 	int op = (opcode >> 39) & 3;
1715 	int trm = (opcode >> 38) & 1;
1716 	int dir = (opcode >> 37) & 1;
1717 	int sr = (opcode >> 31) & 0x7f;
1718 	int dr = (opcode >> 24) & 0x7f;
1719 	int ary = (opcode >> 4) & 7;
1720 	int md = opcode & 0xf;
1721 
1722 	int disp14 = (opcode >> 7) & 0x3fff;
1723 	if (disp14 & 0x2000) disp14 |= 0xffffc000;
1724 
1725 	if (op == 0)    // MOV2
1726 	{
1727 		if (trm == 0)
1728 		{
1729 			if (sr == 0x58)
1730 			{
1731 				// MOV2 #imm24, DR
1732 				generate_reg_write(block, compiler, desc, dr & 0x3f, uml::parameter(opcode & 0xffffff));
1733 			}
1734 			else
1735 			{
1736 				if ((sr & 0x40) == 0)
1737 				{
1738 					generate_reg_read(block, compiler, desc, sr & 0x3f, uml::I1);
1739 				}
1740 				else
1741 				{
1742 					generate_ea(block, compiler, desc, md, sr & 7, ary, disp14);
1743 					if (sr & 0x20)  // RAM-B
1744 					{
1745 						UML_READ(block, I1, I0, SIZE_DWORD, SPACE_IO);
1746 					}
1747 					else // RAM-A
1748 					{
1749 						UML_CALLH(block, *m_read_abus);
1750 					}
1751 				}
1752 
1753 				if ((dr & 0x40) == 0)
1754 				{
1755 					generate_reg_write(block, compiler, desc, dr & 0x3f, uml::I1);
1756 				}
1757 				else
1758 				{
1759 					generate_ea(block, compiler, desc, md, dr & 7, ary, disp14);
1760 					if (dr & 0x20)  // RAM-B
1761 					{
1762 						UML_WRITE(block, I0, I1, SIZE_DWORD, SPACE_IO);
1763 					}
1764 					else // RAM-A
1765 					{
1766 						UML_CALLH(block, *m_write_abus);
1767 					}
1768 				}
1769 			}
1770 		}
1771 		else
1772 		{
1773 			// external transfer
1774 			if (dir == 0)
1775 			{
1776 				generate_reg_read(block, compiler, desc, dr & 0x3f, uml::I0);
1777 				UML_ADD(block, I1, mem(&m_core->eb), mem(&m_core->eo));
1778 				UML_ADD(block, I1, I1, disp14);
1779 				UML_WRITE(block, I1, I0, SIZE_DWORD, SPACE_DATA);
1780 			}
1781 			else
1782 			{
1783 				UML_ADD(block, I1, mem(&m_core->eb), mem(&m_core->eo));
1784 				UML_ADD(block, I1, I1, disp14);
1785 				UML_READ(block, I0, I1, SIZE_DWORD, SPACE_DATA);
1786 				generate_reg_write(block, compiler, desc, dr & 0x3f, uml::I0);
1787 			}
1788 
1789 			// update EO
1790 			UML_ADD(block, mem(&m_core->eo), mem(&m_core->eo), disp14);
1791 		}
1792 	}
1793 	else if (op == 2)   // MOV4
1794 	{
1795 		fatalerror("generate_xfer2 MOV4 at %08X (%08X%08X)", desc->pc, (uint32_t)(opcode >> 32), (uint32_t)(opcode));
1796 	}
1797 }
1798 
generate_double_xfer2(drcuml_block & block,compiler_state & compiler,const opcode_desc * desc)1799 void mb86235_device::generate_double_xfer2(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
1800 {
1801 	UML_MOV(block, mem(&m_core->pc), desc->pc);
1802 	UML_DMOV(block, mem(&m_core->arg64), desc->opptr.q[0]);
1803 	UML_CALLC(block, cfunc_unimplemented_double_xfer2, this);
1804 }
1805 
generate_xfer3(drcuml_block & block,compiler_state & compiler,const opcode_desc * desc)1806 void mb86235_device::generate_xfer3(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
1807 {
1808 	uint64_t opcode = desc->opptr.q[0];
1809 
1810 	uint32_t imm = (uint32_t)(opcode >> 27);
1811 	int dr = (opcode >> 19) & 0x7f;
1812 	int ary = (opcode >> 4) & 7;
1813 	int md = opcode & 0xf;
1814 
1815 	int disp = (opcode >> 7) & 0xfff;
1816 	if (disp & 0x800) disp |= 0xfffff800;
1817 
1818 	switch (dr >> 5)
1819 	{
1820 		case 0:
1821 		case 1:     // reg
1822 			generate_reg_write(block, compiler, desc, dr & 0x3f, uml::parameter(imm));
1823 			break;
1824 
1825 		case 2:     // RAM-A
1826 			generate_ea(block, compiler, desc, md, dr & 7, ary, disp);
1827 			UML_MOV(block, I1, imm);
1828 			UML_CALLH(block, *m_write_abus);
1829 			break;
1830 
1831 		case 3:     // RAM-B
1832 			generate_ea(block, compiler, desc, md, dr & 7, ary, disp);
1833 			UML_WRITE(block, I0, imm, SIZE_DWORD, SPACE_IO);
1834 			break;
1835 	}
1836 }
1837 
1838 
generate_pre_control(drcuml_block & block,compiler_state & compiler,const opcode_desc * desc)1839 void mb86235_device::generate_pre_control(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
1840 {
1841 	uint64_t op = desc->opptr.q[0];
1842 	int ef1 = (op >> 16) & 0x3f;
1843 	int ef2 = op & 0xffff;
1844 	int cop = (op >> 22) & 0x1f;
1845 
1846 	switch (cop)
1847 	{
1848 		case 0x10:      // DBcc
1849 		case 0x11:      // DBNcc
1850 		case 0x18:      // DCcc
1851 		case 0x19:      // DCNcc
1852 			switch (ef1)
1853 			{
1854 				case 0x00:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_MN); break;        // MN
1855 				case 0x01:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_MZ); break;        // MZ
1856 				case 0x02:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_MV); break;        // MV
1857 				case 0x03:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_MU); break;        // MU
1858 				case 0x04:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_ZD); break;        // ZD
1859 				case 0x05:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_NR); break;        // NR
1860 				case 0x06:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_IL); break;        // IL
1861 				case 0x07:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_ZC); break;        // ZC
1862 				case 0x08:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_AN); break;        // AN
1863 				case 0x09:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_AZ); break;        // AZ
1864 				case 0x0a:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_AV); break;        // AV
1865 				case 0x0b:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_AU); break;        // AU
1866 				case 0x0c:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_MD); break;        // MD
1867 				case 0x0d:  UML_MOV(block, mem(&m_core->condtemp), FLAGS_AD); break;        // AD
1868 				default:
1869 					fatalerror("generate_pre_control: unimplemented cc %02X at %08X", ef1, desc->pc);
1870 					break;
1871 			}
1872 			break;
1873 
1874 		case 0x14:      // DBBC ARx:y, rel12
1875 			// TODO: copy ARx
1876 			UML_MOV(block, mem(&m_core->condtemp), AR((ef2 >> 13) & 7));
1877 			break;
1878 
1879 		case 0x15:      // DBBS ARx:y, rel12
1880 			// TODO: copy ARx
1881 			UML_MOV(block, mem(&m_core->condtemp), AR((ef2 >> 13) & 7));
1882 			break;
1883 
1884 		default:
1885 			break;
1886 	}
1887 }
1888