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