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