1 // license:BSD-3-Clause
2 // copyright-holders:Olivier Galibert
3
4 #include "emu.h"
5 #include "debugger.h"
6 #include "mb86233.h"
7 #include "mb86233d.h"
8
9 /*
10 Driver based on the initial reverse-engineering of Elsemi, extended,
11 generalized and made to look more like a cpu since then thanks in
12 part to a "manual" that barely deserves the name.
13
14 The 86232 has 512 32-bits dwords of triple-port memory (1 write, 2
15 read). The 86233/86234 have instead two normal (1 read, 1 write,
16 non-simultaneous) independant ram banks, one of 256 dwords and one
17 of 512.
18
19 The ram banks are mapped at 0x000-0x0ff and 0x200-0x3ff (proven by
20 geometrizer code that clears the ram at startup). Move and load
21 instructions kind of target a specific ram, but do it by adding
22 0x200 to the address on one side of the other, which can then end up
23 anywhere. In particular model1 coprocessor has the output fifo at
24 0x400, which is sometimes hit by having x1 at 0x200 and using the
25 automatic 0x200 adder. Theorically external accesses to 100-1ff and
26 400+ seem to be routed externally, since they're used for the fifo
27 in model 1.
28
29 The cpu can theorically work in either floating point (32-bits ieee
30 flots) or fixed point (32/36/48 bits registers) modes. All sega
31 programs start by activating floating point and staying there, so
32 fixed point is not implemented.
33
34 An interrupt is used to update the rf0 (status? leds?) registers in
35 the coprocessor programs. It's on bit 1 of the mask (irq3?) and
36 vector 0x004. It's probably periodic, maybe on vblank. Note that
37 the copro programs never initialize the stack pointer. Interrupts
38 are not implemented at this point.
39
40 The 86233 and 86234 dies are slightly different in the die shots,
41 but there's no known programming-level difference at this point.
42 It's unclear whether some register-file linked functionality is
43 internal or external though (fifos, banking in model2/86234), so
44 there may lie the actual differences.
45 */
46
47
48 DEFINE_DEVICE_TYPE(MB86233, mb86233_device, "mb86233", "Fujitsu MB86233 (TGP)")
49 DEFINE_DEVICE_TYPE(MB86234, mb86234_device, "mb86234", "Fujitsu MB86234 (TGP)")
50
51
mb86233_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)52 mb86233_device::mb86233_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
53 : cpu_device(mconfig, type, tag, owner, clock)
54 , m_program_config("program", ENDIANNESS_LITTLE, 32, 16, -2)
55 , m_data_config("data", ENDIANNESS_LITTLE, 32, 16, -2)
56 , m_io_config("io", ENDIANNESS_LITTLE, 32, 16, -2)
57 , m_rf_config("rf", ENDIANNESS_LITTLE, 32, 4, -2)
58 {
59 }
60
mb86233_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)61 mb86233_device::mb86233_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
62 : mb86233_device(mconfig, MB86233, tag, owner, clock)
63 {
64 }
65
mb86234_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)66 mb86234_device::mb86234_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
67 : mb86233_device(mconfig, MB86234, tag, owner, clock)
68 {
69 }
70
memory_space_config() const71 device_memory_interface::space_config_vector mb86233_device::memory_space_config() const
72 {
73 return space_config_vector {
74 std::make_pair(AS_PROGRAM, &m_program_config),
75 std::make_pair(AS_DATA, &m_data_config),
76 std::make_pair(AS_IO, &m_io_config),
77 std::make_pair(AS_RF, &m_rf_config)
78 };
79 }
80
81
create_disassembler()82 std::unique_ptr<util::disasm_interface> mb86233_device::create_disassembler()
83 {
84 return std::make_unique<mb86233_disassembler>();
85 }
86
87
88
device_start()89 void mb86233_device::device_start()
90 {
91 space(AS_PROGRAM).cache(m_cache);
92 space(AS_PROGRAM).specific(m_program);
93 space(AS_DATA).specific(m_data);
94 space(AS_IO).specific(m_io);
95 space(AS_RF).specific(m_rf);
96
97 state_add(STATE_GENPC, "GENPC", m_pc);
98 state_add(STATE_GENPCBASE, "PC", m_ppc).noshow();
99 state_add(STATE_GENSP, "SP", m_sp);
100 state_add(STATE_GENFLAGS, "ST", m_st);
101
102 state_add(REG_A, "A", m_a);
103 state_add(REG_B, "B", m_b);
104 state_add(REG_D, "D", m_d);
105 state_add(REG_P, "P", m_p);
106 state_add(REG_R, "R", m_r);
107 state_add(REG_R, "RPC", m_rpc);
108 state_add(REG_C0, "C0", m_c0);
109 state_add(REG_C1, "C1", m_c1);
110 state_add(REG_B0, "B0", m_b0);
111 state_add(REG_B1, "B1", m_b1);
112 state_add(REG_X0, "X0", m_x0);
113 state_add(REG_X1, "X1", m_x1);
114 state_add(REG_I0, "I0", m_i0);
115 state_add(REG_I1, "I1", m_i1);
116 state_add(REG_SFT, "SFT", m_sft);
117 state_add(REG_VSM, "VSM", m_vsm);
118 state_add(REG_PCS0, "PCS0", m_pcs[0]);
119 state_add(REG_PCS1, "PCS1", m_pcs[1]);
120 state_add(REG_PCS2, "PCS2", m_pcs[2]);
121 state_add(REG_PCS3, "PCS3", m_pcs[3]);
122 state_add(REG_MASK, "MASK", m_mask);
123 state_add(REG_M, "M", m_m);
124
125 save_item(NAME(m_ppc));
126 save_item(NAME(m_pc));
127 save_item(NAME(m_st));
128 save_item(NAME(m_sp));
129 save_item(NAME(m_a));
130 save_item(NAME(m_b));
131 save_item(NAME(m_d));
132 save_item(NAME(m_p));
133 save_item(NAME(m_r));
134 save_item(NAME(m_rpc));
135 save_item(NAME(m_c0));
136 save_item(NAME(m_c1));
137 save_item(NAME(m_b0));
138 save_item(NAME(m_b1));
139 save_item(NAME(m_x0));
140 save_item(NAME(m_x1));
141 save_item(NAME(m_i0));
142 save_item(NAME(m_i1));
143 save_item(NAME(m_sft));
144 save_item(NAME(m_vsm));
145 save_item(NAME(m_vsmr));
146 save_item(NAME(m_pcs));
147 save_item(NAME(m_mask));
148 save_item(NAME(m_m));
149 save_item(NAME(m_gpio0));
150 save_item(NAME(m_gpio1));
151 save_item(NAME(m_gpio2));
152 save_item(NAME(m_gpio3));
153
154 save_item(NAME(m_alu_stmask));
155 save_item(NAME(m_alu_stset));
156 save_item(NAME(m_alu_r1));
157 save_item(NAME(m_alu_r2));
158
159 m_gpio0 = m_gpio1 = m_gpio2 = m_gpio3 = false;
160
161 set_icountptr(m_icount);
162 }
163
164
state_string_export(const device_state_entry & entry,std::string & str) const165 void mb86233_device::state_string_export(const device_state_entry &entry, std::string &str) const
166 {
167 }
168
WRITE_LINE_MEMBER(mb86233_device::gpio0_w)169 WRITE_LINE_MEMBER(mb86233_device::gpio0_w)
170 {
171 m_gpio0 = state;
172 }
173
WRITE_LINE_MEMBER(mb86233_device::gpio1_w)174 WRITE_LINE_MEMBER(mb86233_device::gpio1_w)
175 {
176 m_gpio1 = state;
177 }
178
WRITE_LINE_MEMBER(mb86233_device::gpio2_w)179 WRITE_LINE_MEMBER(mb86233_device::gpio2_w)
180 {
181 m_gpio2 = state;
182 }
183
WRITE_LINE_MEMBER(mb86233_device::gpio3_w)184 WRITE_LINE_MEMBER(mb86233_device::gpio3_w)
185 {
186 m_gpio3 = state;
187 }
188
device_reset()189 void mb86233_device::device_reset()
190 {
191 m_pc = 0;
192 m_ppc = 0;
193 m_st = F_ZRC|F_ZRD|F_ZX0|F_ZX1|F_ZX2|F_ZC0|F_ZC1;
194 m_sp = 0;
195
196 m_a = 0;
197 m_b = 0;
198 m_d = 0;
199 m_p = 0;
200 m_r = 1;
201 m_rpc = 1;
202 m_c0 = 1;
203 m_c1 = 1;
204 m_b0 = 0;
205 m_b1 = 0;
206 m_x0 = 0;
207 m_x1 = 0;
208 m_i0 = 0;
209 m_i1 = 0;
210 m_sft = 0;
211 m_vsm = 0;
212 m_vsmr = 7;
213 m_mask = 0;
214 m_m = 1;
215
216 m_alu_stmask = 0;
217 m_alu_stset = 0;
218 m_alu_r1 = 0;
219 m_alu_r2 = 0;
220
221 std::fill(std::begin(m_pcs), std::end(m_pcs), 0);
222
223 m_stall = false;
224 }
225
s24_32(u32 val)226 s32 mb86233_device::s24_32(u32 val)
227 {
228 if(val & 0x00800000)
229 return val | 0xff000000;
230 else
231 return val & 0x00ffffff;
232 }
233
set_exp(u32 val,u32 exp)234 u32 mb86233_device::set_exp(u32 val, u32 exp)
235 {
236 return (val & 0x807fffff) | ((exp & 0xff) << 23);
237 }
238
set_mant(u32 val,u32 mant)239 u32 mb86233_device::set_mant(u32 val, u32 mant)
240 {
241 return (val & 0x07f800000) | ((mant & 0x00800000) << 8) | (mant & 0x007fffff);
242 }
243
get_exp(u32 val)244 u32 mb86233_device::get_exp(u32 val)
245 {
246 return (val >> 23) & 0xff;
247 }
248
get_mant(u32 val)249 u32 mb86233_device::get_mant(u32 val)
250 {
251 return val & 0x80000000 ? val | 0x7f800000 : val & 0x807fffff;
252 }
253
pcs_push()254 void mb86233_device::pcs_push()
255 {
256 for(unsigned int i=3; i; i--)
257 m_pcs[i] = m_pcs[i-1];
258 m_pcs[0] = m_pc;
259 }
260
pcs_pop()261 void mb86233_device::pcs_pop()
262 {
263 m_pc = m_pcs[0];
264 for(unsigned int i=0; i != 3; i++)
265 m_pcs[i] = m_pcs[i+1];
266 }
267
testdz()268 void mb86233_device::testdz()
269 {
270 if(m_d)
271 m_st &= ~F_ZRD;
272 else
273 m_st |= F_ZRD;
274 if(m_d & 0x80000000)
275 m_st |= F_SGD;
276 else
277 m_st &= ~F_SGD;
278 }
279
alu_pre(u32 alu)280 void mb86233_device::alu_pre(u32 alu)
281 {
282 switch(alu) {
283 case 0x00: break; // no alu
284
285 case 0x01: {
286 // andd
287 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
288 m_alu_r1 = m_d & m_a;
289 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
290 break;
291 }
292
293 case 0x02: {
294 // orad
295 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
296 m_alu_r1 = m_d | m_a;
297 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
298 break;
299 }
300
301 case 0x03: {
302 // eord
303 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
304 m_alu_r1 = m_d ^ m_a;
305 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
306 break;
307 }
308
309 case 0x04: {
310 // notd
311 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
312 m_alu_r1 = ~m_d;
313 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
314 break;
315 }
316
317 case 0x05: {
318 // fcpd
319 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
320 u32 r = f2u(u2f(m_d) - u2f(m_a));
321 m_alu_stset = r ? r & 0x80000000 ? F_SGD : 0 : F_ZRD;
322 break;
323 }
324
325 case 0x06: {
326 // fmad
327 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
328 m_alu_r1 = f2u(u2f(m_d) + u2f(m_a));
329 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
330 break;
331 }
332
333 case 0x07: {
334 // fsbd
335 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
336 m_alu_r1 = f2u(u2f(m_d) - u2f(m_a));
337 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
338 break;
339 }
340
341 case 0x08: {
342 // fml
343 m_alu_stmask = 0;
344 m_alu_r1 = f2u(u2f(m_a) * u2f(m_b));
345 m_alu_stset = 0;
346 break;
347 }
348
349 case 0x09: {
350 // fmsd
351 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
352 m_alu_r1 = f2u(u2f(m_d) + u2f(m_p));
353 m_alu_r2 = f2u(u2f(m_a) * u2f(m_b));
354 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
355 break;
356 }
357
358 case 0x0a: {
359 // fmrd
360 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
361 m_alu_r1 = f2u(u2f(m_d) - u2f(m_p));
362 m_alu_r2 = f2u(u2f(m_a) * u2f(m_b));
363 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
364 break;
365 }
366
367 case 0x0b: {
368 // fabd
369 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
370 m_alu_r1 = m_d & 0x7fffffff;
371 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
372 break;
373 }
374
375 case 0x0c: {
376 // fsmd
377 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
378 m_alu_r1 = f2u(u2f(m_d) + u2f(m_p));
379 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
380 break;
381 }
382
383 case 0x0d: {
384 // fspd
385 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
386 m_alu_r1 = m_p;
387 m_alu_r2 = f2u(u2f(m_a) * u2f(m_b));
388 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
389 break;
390 }
391
392 case 0x0e: {
393 // cxfd
394 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
395 m_alu_r1 = f2u(s32(m_d));
396 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
397 break;
398 }
399
400 case 0x0f: {
401 // cfxd
402 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
403 switch((m_m >> 1) & 3) {
404 case 0: m_alu_r1 = s32(roundf(u2f(m_d))); break;
405 case 1: m_alu_r1 = s32(ceilf(u2f(m_d))); break;
406 case 2: m_alu_r1 = s32(floorf(u2f(m_d))); break;
407 case 3: m_alu_r1 = s32(u2f(m_d)); break;
408 }
409 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
410 break;
411 }
412
413 case 0x10: {
414 // fdvd
415 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
416 m_alu_r1 = f2u(u2f(m_d) / u2f(m_a));
417 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
418 break;
419 }
420
421 case 0x11: {
422 // fned
423 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
424 m_alu_r1 = m_d ? m_d ^ 0x80000000 : 0;
425 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
426 break;
427 }
428
429 case 0x13: {
430 // d = b + a
431 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
432 m_alu_r1 = f2u(u2f(m_b) + u2f(m_a));
433 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
434 break;
435 }
436
437 case 0x14: {
438 // d = b - a
439 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
440 m_alu_r1 = f2u(u2f(m_b) - u2f(m_a));
441 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
442 break;
443 }
444
445 case 0x16: {
446 // lsrd
447 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
448 m_alu_r1 = m_d >> m_sft;
449 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
450 break;
451 }
452
453 case 0x17: {
454 // lsld
455 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
456 m_alu_r1 = m_d << m_sft;
457 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
458 break;
459 }
460
461 case 0x18: {
462 // asrd
463 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
464 m_alu_r1 = s32(m_d) >> m_sft;
465 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
466 break;
467 }
468
469 case 0x19: {
470 // asld
471 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
472 m_alu_r1 = s32(m_d) << m_sft;
473 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
474 break;
475 }
476
477 case 0x1a: {
478 // addd
479 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
480 m_alu_r1 = m_d + m_a;
481 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
482 break;
483 }
484
485 case 0x1b: {
486 // subd
487 m_alu_stmask = F_ZRD|F_SGD|F_CPD|F_OVD|F_DVZD;
488 m_alu_r1 = m_d - m_a;
489 m_alu_stset = m_alu_r1 ? m_alu_r1 & 0x80000000 ? F_SGD : 0 : F_ZRD;
490 break;
491 }
492
493 default:
494 logerror("unhandled alu pre %02x\n", alu);
495 break;
496 }
497 }
498
alu_update_st()499 void mb86233_device::alu_update_st()
500 {
501 m_st = (m_st & ~m_alu_stmask) | m_alu_stset;
502 }
503
alu_post(u32 alu)504 void mb86233_device::alu_post(u32 alu)
505 {
506 switch(alu) {
507 case 0x00: break; // no alu
508
509 case 0x05:
510 // flags only
511 alu_update_st();
512 break;
513
514 case 0x01: case 0x02: case 0x03: case 0x04:
515 case 0x06: case 0x07: case 0x0b: case 0x0c:
516 case 0x0e: case 0x0f: case 0x10: case 0x11:
517 case 0x13: case 0x14: case 0x16: case 0x17:
518 case 0x18: case 0x19: case 0x1a: case 0x1b:
519 // d update
520 m_d = m_alu_r1;
521 alu_update_st();
522 break;
523
524 case 0x08:
525 // p update
526 m_p = m_alu_r1;
527 break;
528
529 case 0x09: case 0x0a: case 0xd:
530 // d, p update
531 m_d = m_alu_r1;
532 m_p = m_alu_r2;
533 alu_update_st();
534 break;
535
536 default:
537 logerror("unhandled alu post %02x\n", alu);
538 break;
539 }
540 }
541
ea_pre_0(u32 r)542 u16 mb86233_device::ea_pre_0(u32 r)
543 {
544 switch(r & 0x180) {
545 case 0x000: return r & 0x7f;
546 case 0x080: case 0x100: return (r & 0x7f) + m_b0 + m_x0;
547 case 0x180: {
548 switch(r & 0x60) {
549 case 0x00: return m_b0 + m_x0;
550 case 0x20: return m_x0;
551 case 0x40: return m_b0 + (m_x0 & m_vsmr);
552 case 0x60: return m_x0 & m_vsmr;
553 }
554 }
555 }
556 return 0;
557 }
558
ea_post_0(u32 r)559 void mb86233_device::ea_post_0(u32 r)
560 {
561 if(!(r & 0x100))
562 return;
563 if(!(r & 0x080))
564 m_x0 += m_i0;
565 else {
566 if(r & 0x10)
567 m_x0 += (r & 0xf) - 0x10;
568 else
569 m_x0 += r & 0xf;
570 }
571 }
572
ea_pre_1(u32 r)573 u16 mb86233_device::ea_pre_1(u32 r)
574 {
575 switch(r & 0x180) {
576 case 0x000: return r & 0x7f;
577 case 0x080: case 0x100: return (r & 0x7f) + m_b1 + m_x1;
578 case 0x180: {
579 switch(r & 0x60) {
580 case 0x00: return m_b1 + m_x1;
581 case 0x20: return m_x1;
582 case 0x40: return m_b1 + (m_x1 & m_vsmr);
583 case 0x60: return m_x1 & m_vsmr;
584 }
585 }
586 }
587 return 0;
588 }
589
ea_post_1(u32 r)590 void mb86233_device::ea_post_1(u32 r)
591 {
592 if(!(r & 0x100))
593 return;
594 if(!(r & 0x080))
595 m_x1 += m_i1;
596 else {
597 if(r & 0x10)
598 m_x1 += (r & 0xf) - 0x10;
599 else
600 m_x1 += r & 0xf;
601 }
602 }
603
read_reg(u32 r)604 u32 mb86233_device::read_reg(u32 r)
605 {
606 r &= 0x3f;
607 if(r >= 0x20 && r < 0x30)
608 return m_rf.read_dword(r & 0x1f);
609 switch(r) {
610 case 0x00: return m_b0;
611 case 0x01: return m_b1;
612 case 0x02: return m_x0;
613 case 0x03: return m_x1;
614
615 case 0x0c: return m_c0;
616 case 0x0d: return m_c1;
617
618 case 0x10: return m_a;
619 case 0x11: return get_exp(m_a);
620 case 0x12: return get_mant(m_a);
621 case 0x13: return m_b;
622 case 0x14: return get_exp(m_b);
623 case 0x15: return get_mant(m_b);
624 case 0x19: return m_d;
625 /* c */
626 case 0x1a: return get_exp(m_d);
627 case 0x1b: return get_mant(m_d);
628 case 0x1c: return m_p;
629 case 0x1d: return get_exp(m_p);
630 case 0x1e: return get_mant(m_p);
631 case 0x1f: return m_sft;
632
633 case 0x34: return m_rpc;
634
635 default:
636 logerror("unimplemented read_reg(%02x) (%x)\n", r, m_ppc);
637 return 0;
638 }
639 }
640
write_reg(u32 r,u32 v)641 void mb86233_device::write_reg(u32 r, u32 v)
642 {
643 r &= 0x3f;
644 if(r >= 0x20 && r < 0x30) {
645 m_rf.write_dword(r & 0x1f, v);
646 return;
647 }
648 switch(r) {
649 case 0x00: m_b0 = v; break;
650 case 0x01: m_b1 = v; break;
651 case 0x02: m_x0 = v; break;
652 case 0x03: m_x1 = v; break;
653
654 case 0x05: m_i0 = v; break;
655 case 0x06: m_i1 = v; break;
656
657 case 0x08: m_sp = v; break;
658
659 case 0x0a: m_vsm = v & 7; m_vsmr = (8 << m_vsm) - 1; break;
660
661 case 0x0c:
662 m_c0 = v;
663 if(m_c0 == 1)
664 m_st |= F_ZC0;
665 else
666 m_st &= ~F_ZC0;
667 break;
668
669 case 0x0d:
670 m_c1 = v;
671 if(m_c1 == 1)
672 m_st |= F_ZC1;
673 else
674 m_st &= ~F_ZC1;
675 break;
676
677 case 0x0f: break;
678
679 case 0x10: m_a = v; break;
680 case 0x11: m_a = set_exp(m_a, v); break;
681 case 0x12: m_a = set_mant(m_a, v); break;
682 case 0x13: m_b = v; break;
683 case 0x14: m_b = set_exp(m_b, v); break;
684 case 0x15: m_b = set_mant(m_b, v); break;
685 /* c */
686 case 0x19: m_d = v; testdz(); break;
687 case 0x1a: m_d = set_exp(m_d, v); testdz(); break;
688 case 0x1b: m_d = set_mant(m_d, v); testdz(); break;
689 case 0x1c: m_p = v; break;
690 case 0x1d: m_p = set_exp(m_p, v); break;
691 case 0x1e: m_p = set_mant(m_p, v); break;
692 case 0x1f: m_sft = v; break;
693
694 case 0x34: m_rpc = v; break;
695 case 0x3c: m_mask = v; break;
696
697 default:
698 logerror("unimplemented write_reg(%02x, %08x) (%x)\n", r, v, m_ppc);
699 break;
700 }
701 }
702
write_mem_internal_1(u32 r,u32 v,bool bank)703 void mb86233_device::write_mem_internal_1(u32 r, u32 v, bool bank)
704 {
705 u16 ea = ea_pre_1(r);
706 if(bank)
707 ea += 0x200;
708 m_data.write_dword(ea, v);
709 ea_post_1(r);
710 }
711
write_mem_io_1(u32 r,u32 v)712 void mb86233_device::write_mem_io_1(u32 r, u32 v)
713 {
714 u16 ea = ea_pre_1(r);
715 m_io.write_dword(ea, v);
716 ea_post_1(r);
717 }
718
execute_run()719 void mb86233_device::execute_run()
720 {
721 while(m_icount > 0) {
722 m_ppc = m_pc;
723 debugger_instruction_hook(m_ppc);
724 u32 opcode = m_cache.read_dword(m_pc++);
725
726 switch((opcode >> 26) & 0x3f) {
727 case 0x00: {
728 // lab
729 u32 r1 = opcode & 0x1ff;
730 u32 r2 = (opcode >> 9) & 0x1ff;
731 u32 alu = (opcode >> 21) & 0x1f;
732 u32 op = (opcode >> 18) & 0x7;
733
734 alu_pre(alu);
735
736 switch(op) {
737 case 0: case 1: {
738 // lab mem, mem (e)
739
740 u32 ea1 = ea_pre_0(r1);
741 u32 v1 = m_data.read_dword(ea1);
742 if(m_stall) goto do_stall;
743
744 u32 ea2 = ea_pre_1(r2);
745 u32 v2 = m_io.read_dword(ea2);
746 if(m_stall) goto do_stall;
747
748 ea_post_0(r1);
749 ea_post_1(r2);
750
751 m_a = v1;
752 m_b = v2;
753 break;
754 }
755
756 case 3: {
757 // lab mem, mem + 0x200
758
759 u32 ea1 = ea_pre_0(r1);
760 u32 v1 = m_data.read_dword(ea1);
761 if(m_stall) goto do_stall;
762
763 u32 ea2 = ea_pre_1(r2) + 0x200;
764 u32 v2 = m_data.read_dword(ea2);
765 if(m_stall) goto do_stall;
766
767 ea_post_0(r1);
768 ea_post_1(r2);
769
770 m_a = v1;
771 m_b = v2;
772 break;
773 }
774
775 case 4: {
776 // lab mem + 0x200, mem
777
778 u32 ea1 = ea_pre_0(r1) + 0x200;
779 u32 v1 = m_data.read_dword(ea1);
780 if(m_stall) goto do_stall;
781
782 u32 ea2 = ea_pre_1(r2);
783 u32 v2 = m_data.read_dword(ea2);
784 if(m_stall) goto do_stall;
785
786 ea_post_0(r1);
787 ea_post_1(r2);
788
789 m_a = v1;
790 m_b = v2;
791 break;
792 }
793
794 default:
795 logerror("unhandled lab subop %x\n", op);
796 logerror("%x\n", m_ppc);
797 break;
798
799 }
800
801 alu_post(alu);
802 break;
803 }
804
805
806 case 0x07: {
807 // ld / mov
808 u32 r1 = opcode & 0x1ff;
809 u32 r2 = (opcode >> 9) & 0x1ff;
810 u32 alu = (opcode >> 21) & 0x1f;
811 u32 op = (opcode >> 18) & 0x7;
812
813 alu_pre(alu);
814
815 switch(op) {
816 case 0: {
817 // mov mem, mem (e)
818 u32 ea = ea_pre_0(r1);
819 u32 v = m_data.read_dword(ea);
820 if(m_stall) goto do_stall;
821 ea_post_0(r1);
822 write_mem_io_1(r2, v);
823 break;
824 }
825
826 case 1: {
827 // mov mem, mem (e)
828 u32 ea = ea_pre_0(r1);
829 u32 v = m_data.read_dword(ea);
830 if(m_stall) goto do_stall;
831 ea_post_0(r1);
832 write_mem_io_1(r2, v);
833 break;
834 }
835
836 case 2: {
837 // mov mem (e), mem
838 u32 ea = ea_pre_0(r1);
839 u32 v = m_io.read_dword(ea);
840 if(m_stall) goto do_stall;
841 ea_post_0(r1);
842 write_mem_internal_1(r2, v, false);
843 break;
844 }
845
846 case 3: {
847 // mov mem, mem + 0x200
848 u32 ea = ea_pre_0(r1);
849 u32 v = m_data.read_dword(ea);
850 if(m_stall) goto do_stall;
851 ea_post_0(r1);
852 write_mem_internal_1(r2, v, true);
853 break;
854 }
855
856 case 4: {
857 // mov mem + 0x200, mem
858 u32 ea = ea_pre_0(r1) + 0x200;
859 u32 v = m_data.read_dword(ea);
860 if(m_stall) goto do_stall;
861 ea_post_0(r1);
862 write_mem_internal_1(r2, v, false);
863 break;
864 }
865
866 case 5: {
867 // mov mem (o), mem
868 u32 ea = ea_pre_0(r1);
869 u32 v = m_program.read_dword(ea);
870 if(m_stall) goto do_stall;
871 ea_post_0(r1);
872 write_mem_internal_1(r2, v, false);
873 break;
874 }
875
876 case 7: {
877 switch(r2 >> 6) {
878 case 0: {
879 // mov reg, mem
880 u32 v = read_reg(r2);
881 if(m_stall) goto do_stall;
882 write_mem_internal_1(r1, v, false);
883 break;
884 }
885
886 case 1: {
887 // mov reg, mem (e)
888 u32 v = read_reg(r2);
889 if(m_stall) goto do_stall;
890 write_mem_io_1(r1, v);
891 break;
892 }
893
894 case 2: {
895 // mov mem + 0x200, reg
896 u32 ea = ea_pre_1(r1) + 0x200;
897 u32 v = m_data.read_dword(ea);
898 if(m_stall) goto do_stall;
899 ea_post_1(r1);
900 write_reg(r2, v);
901 break;
902 }
903
904 case 3: {
905 // mov mem, reg
906 u32 ea = ea_pre_1(r1);
907 u32 v = m_data.read_dword(ea);
908 if(m_stall) goto do_stall;
909 ea_post_1(r1);
910 write_reg(r2, v);
911 break;
912 }
913
914 case 4: {
915 // mov mem (e), reg
916 u32 ea = ea_pre_1(r1);
917 u32 v = m_io.read_dword(ea);
918 if(m_stall) goto do_stall;
919 ea_post_1(r1);
920 write_reg(r2, v);
921 break;
922 }
923
924 case 5: {
925 // mov mem (o), reg
926 u32 ea = ea_pre_0(r1);
927 u32 v = m_program.read_dword(ea);
928 if(m_stall) goto do_stall;
929 ea_post_0(r1);
930 write_reg(r2, v);
931 break;
932 }
933
934 case 6: {
935 // mov reg, reg
936 u32 v = read_reg(r1);
937 if(m_stall) goto do_stall;
938 write_reg(r2, v);
939 break;
940 }
941
942 default:
943 logerror("unhandled ld/mov subop 7/%x (%x)\n", r2 >> 6, m_ppc);
944 break;
945 }
946 break;
947 }
948
949 default:
950 logerror("unhandled ld/mov subop %x (%x)\n", op, m_ppc);
951 break;
952 }
953
954 alu_post(alu);
955 break;
956 }
957
958 case 0x0d: {
959 // stm/clm
960 u32 sub2 = (opcode >> 17) & 7;
961
962 // Theorically has restricted alu too
963
964 switch(sub2) {
965 case 5:
966 // stmh
967 // bit 0 = floating point
968 // bit 1-2 = rounding mode
969 m_m = opcode;
970 break;
971
972 default:
973 logerror("unimplemented opcode 0d/%x (%x)\n", sub2, m_ppc);
974 break;
975 }
976 break;
977 }
978
979 case 0x0e: {
980 // lipl / lia / lib / lid
981 switch((opcode >> 24) & 0x3) {
982 case 0:
983 m_p = (m_p & 0xffffff000000) | (opcode & 0xffffff);
984 break;
985 case 1:
986 m_a = s24_32(opcode);
987 break;
988 case 2:
989 m_b = s24_32(opcode);
990 break;
991 case 3:
992 m_d = s24_32(opcode);
993 testdz();
994 break;
995 }
996 break;
997 }
998
999 case 0x0f: {
1000 // rep/clr0/clr1/set
1001 u32 alu = (opcode >> 20) & 0x1f;
1002 u32 sub2 = (opcode >> 17) & 7;
1003
1004 alu_pre(alu);
1005
1006 switch(sub2) {
1007 case 0:
1008 // clr0
1009 if(opcode & 0x0004) m_a = 0;
1010 if(opcode & 0x0008) m_b = 0;
1011 if(opcode & 0x0010) m_d = 0;
1012 break;
1013
1014 case 1:
1015 // clr1 - flags mapping unknown
1016 break;
1017
1018 case 2: {
1019 // rep
1020 u8 r = opcode & 0x8000 ? read_reg(opcode) : opcode;
1021 if(m_stall) goto do_stall;
1022 m_r = r;
1023 goto rep_start;
1024 }
1025
1026 case 3:
1027 // set - flags mapping unknown
1028 // 0800 = enable interrupt flag
1029 break;
1030
1031 default:
1032 logerror("unimplemented opcode 0f/%x (%x)\n", sub2, m_ppc);
1033 break;
1034 }
1035
1036 alu_post(alu);
1037 break;
1038 }
1039
1040 case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
1041 case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: {
1042 // ldi
1043 write_reg(opcode >> 24, s24_32(opcode));
1044 break;
1045 }
1046
1047 case 0x2f: case 0x3f: {
1048 // Conditional branch of every kind
1049 u32 cond = ( opcode >> 20 ) & 0x1f;
1050 u32 subtype = ( opcode >> 17 ) & 7;
1051 u32 data = opcode & 0xffff;
1052 bool invert = opcode & 0x40000000;
1053
1054 bool cond_passed = false;
1055
1056 switch(cond) {
1057 case 0x00: // zrd - d zero
1058 cond_passed = m_st & F_ZRD;
1059 break;
1060
1061 case 0x01: // ged - d >= 0
1062 cond_passed = !(m_st & F_SGD);
1063 break;
1064
1065 case 0x02: // led - d <= 0
1066 cond_passed = m_st & (F_ZRD | F_SGD);
1067 break;
1068
1069 case 0x0a: // gpio0
1070 cond_passed = m_gpio0;
1071 break;
1072
1073 case 0x0b: // gpio1
1074 cond_passed = m_gpio1;
1075 break;
1076
1077 case 0x0c: // gpio2
1078 cond_passed = m_gpio2;
1079 break;
1080
1081 case 0x10: // zc0 - c0 == 1
1082 cond_passed = !(m_st & F_ZC0);
1083 break;
1084
1085 case 0x11: // zc1 - c1 == 1
1086 cond_passed = !(m_st & F_ZC1);
1087 break;
1088
1089 case 0x12: // gpio3
1090 cond_passed = m_gpio3;
1091 break;
1092
1093 case 0x16: // alw - always
1094 cond_passed = true;
1095 break;
1096
1097 default:
1098 logerror("unimplemented condition %x (%x)\n", cond, m_ppc);
1099 break;
1100 }
1101 if(invert)
1102 cond_passed = !cond_passed;
1103
1104 if(cond_passed) {
1105 switch(subtype) {
1106 case 0: // brif #adr
1107 m_pc = data;
1108 break;
1109
1110 case 1: // brul
1111 if(opcode & 0x4000) {
1112 // brul reg
1113 u32 v = read_reg(opcode);
1114 if(m_stall) goto do_stall;
1115 m_pc = v;
1116 } else {
1117 // brul adr
1118 u32 ea = ea_pre_0(opcode);
1119 u32 v = m_data.read_dword(ea);
1120 if(m_stall) goto do_stall;
1121 ea_post_0(opcode);
1122 m_pc = v;
1123 }
1124 break;
1125
1126 case 2: // bsif #adr
1127 pcs_push();
1128 m_pc = data;
1129 break;
1130
1131 case 3: // bsul
1132 if(opcode & 0x4000) {
1133 // bsul reg
1134 u32 v = read_reg(opcode);
1135 if(m_stall) goto do_stall;
1136 pcs_push();
1137 m_pc = v;
1138 } else {
1139 // bsul adr
1140 u32 ea = ea_pre_0(opcode);
1141 u32 v = m_data.read_dword(ea);
1142 if(m_stall) goto do_stall;
1143 ea_post_0(opcode);
1144 pcs_push();
1145 m_pc = v;
1146 }
1147 break;
1148
1149 case 5: // rtif #adr
1150 pcs_pop();
1151 break;
1152
1153 case 6: { // ldif adr, rn
1154 u32 ea = ea_pre_0(opcode);
1155 u32 v = m_data.read_dword(ea);
1156 if(m_stall) goto do_stall;
1157 ea_post_0(opcode);
1158 write_reg(opcode >> 9, v);
1159 break;
1160 }
1161
1162 default:
1163 logerror("unimplemented branch subtype %x (%x)\n", subtype, m_ppc);
1164 break;
1165 }
1166 }
1167
1168 if(subtype < 2)
1169 switch(cond) {
1170 case 0x10:
1171 if(m_c0 != 1) {
1172 m_c0 --;
1173 if(m_c0 == 1)
1174 m_st |= F_ZC0;
1175 }
1176 break;
1177
1178 case 0x11:
1179 if(m_c1 != 1) {
1180 m_c1 --;
1181 if(m_c1 == 1)
1182 m_st |= F_ZC1;
1183 }
1184 break;
1185 }
1186
1187 break;
1188 }
1189
1190 default:
1191 logerror("unimplemented opcode type %02x (%x)\n", (opcode >> 26) & 0x3f, m_ppc);
1192 break;
1193 }
1194
1195 if(m_r != 1) {
1196 m_pc = m_ppc;
1197 m_r --;
1198 }
1199
1200 rep_start:
1201 if(0) {
1202 do_stall:
1203 m_pc = m_ppc;
1204 m_stall = false;
1205 }
1206 m_icount--;
1207 }
1208 }
1209