1 // license:BSD-3-Clause
2 // copyright-holders:Angelo Salese, ElSemi, Ville Linde
3 /********************************************************************************
4  *
5  * MB86235 "TGPx4" (c) Fujitsu
6  *
7  * Written by Angelo Salese & ElSemi
8  *
9  * TODO:
10  * - rewrite ALU integer/floating point functions, use templates etc;
11  * - move post-opcodes outside of the execute_op() function, like increment_prp()
12  *    (needed if opcode uses fifo in/out);
13  * - rewrite fifo hookups, remove them from the actual opcodes.
14  * - use a phase system for the execution, like do_alu() being separated
15  *    from control();
16  * - illegal delay slots unsupported, and no idea about what is supposed to happen;
17  * - externalize PDR / DDR (error LED flags on Model 2);
18  * - instruction cycles;
19  * - pipeline (four instruction executed per cycle!)
20  *
21  ********************************************************************************/
22 
23 #include "emu.h"
24 #include "mb86235.h"
25 #include "mb86235fe.h"
26 #include "mb86235d.h"
27 
28 #include "debugger.h"
29 
30 
31 #define ENABLE_DRC      0
32 
33 
34 #define CACHE_SIZE                      (1 * 1024 * 1024)
35 #define COMPILE_BACKWARDS_BYTES         128
36 #define COMPILE_FORWARDS_BYTES          512
37 #define COMPILE_MAX_INSTRUCTIONS        ((COMPILE_BACKWARDS_BYTES/4) + (COMPILE_FORWARDS_BYTES/4))
38 #define COMPILE_MAX_SEQUENCE            64
39 
40 
41 
42 DEFINE_DEVICE_TYPE(MB86235, mb86235_device, "mb86235", "Fujitsu MB86235 \"TGPx4\"")
43 
44 
internal_abus(address_map & map)45 void mb86235_device::internal_abus(address_map &map)
46 {
47 	map(0x000000, 0x0003ff).ram();
48 }
49 
internal_bbus(address_map & map)50 void mb86235_device::internal_bbus(address_map &map)
51 {
52 	map(0x000000, 0x0003ff).ram();
53 }
54 
55 
56 
57 /* Execute cycles */
execute_run()58 void mb86235_device::execute_run()
59 {
60 #if ENABLE_DRC
61 	run_drc();
62 #else
63 	uint64_t opcode;
64 	while(m_core->icount > 0)
65 	{
66 		uint32_t curpc;
67 
68 		curpc = check_previous_op_stall() ? m_core->cur_fifo_state.pc : m_core->pc;
69 
70 		debugger_instruction_hook(curpc);
71 		opcode = m_pcache.read_qword(curpc);
72 
73 		m_core->ppc = curpc;
74 
75 		if(m_core->delay_slot == true)
76 		{
77 			m_core->pc = m_core->delay_pc;
78 			m_core->delay_slot = false;
79 		}
80 		else
81 			handle_single_step_execution();
82 
83 		execute_op(opcode >> 32, opcode & 0xffffffff);
84 
85 		m_core->icount--;
86 	}
87 
88 #endif
89 }
90 
91 
device_start()92 void mb86235_device::device_start()
93 {
94 	space(AS_PROGRAM).cache(m_pcache);
95 	space(AS_PROGRAM).specific(m_program);
96 	space(AS_DATA).specific(m_dataa);
97 	space(AS_IO).specific(m_datab);
98 
99 	m_core = (mb86235_internal_state *)m_cache.alloc_near(sizeof(mb86235_internal_state));
100 	memset(m_core, 0, sizeof(mb86235_internal_state));
101 
102 
103 #if ENABLE_DRC
104 	// init UML generator
105 
106 	uint32_t umlflags = 0;
107 	m_drcuml = std::make_unique<drcuml_state>(*this, m_cache, umlflags, 1, 24, 0);
108 
109 	// add UML symbols
110 	m_drcuml->symbol_add(&m_core->pc, sizeof(m_core->pc), "pc");
111 	m_drcuml->symbol_add(&m_core->icount, sizeof(m_core->icount), "icount");
112 
113 	for (int i = 0; i < 8; i++)
114 	{
115 		char buf[10];
116 		sprintf(buf, "aa%d", i);
117 		m_drcuml->symbol_add(&m_core->aa[i], sizeof(m_core->aa[i]), buf);
118 		sprintf(buf, "ab%d", i);
119 		m_drcuml->symbol_add(&m_core->ab[i], sizeof(m_core->ab[i]), buf);
120 		sprintf(buf, "ma%d", i);
121 		m_drcuml->symbol_add(&m_core->ma[i], sizeof(m_core->ma[i]), buf);
122 		sprintf(buf, "mb%d", i);
123 		m_drcuml->symbol_add(&m_core->mb[i], sizeof(m_core->mb[i]), buf);
124 		sprintf(buf, "ar%d", i);
125 		m_drcuml->symbol_add(&m_core->ar[i], sizeof(m_core->ar[i]), buf);
126 	}
127 
128 	m_drcuml->symbol_add(&m_core->flags.az, sizeof(m_core->flags.az), "flags_az");
129 	m_drcuml->symbol_add(&m_core->flags.an, sizeof(m_core->flags.an), "flags_an");
130 	m_drcuml->symbol_add(&m_core->flags.av, sizeof(m_core->flags.av), "flags_av");
131 	m_drcuml->symbol_add(&m_core->flags.au, sizeof(m_core->flags.au), "flags_au");
132 	m_drcuml->symbol_add(&m_core->flags.ad, sizeof(m_core->flags.ad), "flags_ad");
133 	m_drcuml->symbol_add(&m_core->flags.zc, sizeof(m_core->flags.zc), "flags_zc");
134 	m_drcuml->symbol_add(&m_core->flags.il, sizeof(m_core->flags.il), "flags_il");
135 	m_drcuml->symbol_add(&m_core->flags.nr, sizeof(m_core->flags.nr), "flags_nr");
136 	m_drcuml->symbol_add(&m_core->flags.zd, sizeof(m_core->flags.zd), "flags_zd");
137 	m_drcuml->symbol_add(&m_core->flags.mn, sizeof(m_core->flags.mn), "flags_mn");
138 	m_drcuml->symbol_add(&m_core->flags.mz, sizeof(m_core->flags.mz), "flags_mz");
139 	m_drcuml->symbol_add(&m_core->flags.mv, sizeof(m_core->flags.mv), "flags_mv");
140 	m_drcuml->symbol_add(&m_core->flags.mu, sizeof(m_core->flags.mu), "flags_mu");
141 	m_drcuml->symbol_add(&m_core->flags.md, sizeof(m_core->flags.md), "flags_md");
142 
143 
144 	m_drcuml->symbol_add(&m_core->arg0, sizeof(m_core->arg0), "arg0");
145 	m_drcuml->symbol_add(&m_core->arg1, sizeof(m_core->arg1), "arg1");
146 	m_drcuml->symbol_add(&m_core->arg2, sizeof(m_core->arg2), "arg2");
147 	m_drcuml->symbol_add(&m_core->arg3, sizeof(m_core->arg3), "arg3");
148 	m_drcuml->symbol_add(&m_core->alutemp, sizeof(m_core->alutemp), "alutemp");
149 	m_drcuml->symbol_add(&m_core->multemp, sizeof(m_core->multemp), "multemp");
150 
151 	m_drcuml->symbol_add(&m_core->pcp, sizeof(m_core->pcp), "pcp");
152 
153 
154 	m_drcfe = std::make_unique<mb86235_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, COMPILE_MAX_SEQUENCE);
155 
156 	for (int i = 0; i < 8; i++)
157 	{
158 		m_regmap[i] = uml::mem(&m_core->aa[i]);
159 		m_regmap[i + 8] = uml::mem(&m_core->ab[i]);
160 		m_regmap[i + 16] = uml::mem(&m_core->ma[i]);
161 		m_regmap[i + 24] = uml::mem(&m_core->mb[i]);
162 	}
163 #endif
164 
165 	// Register state for debugger
166 	state_add(MB86235_PC, "PC", m_core->pc).formatstr("%08X");
167 	state_add(MB86235_AR0, "AR0", m_core->ar[0]).formatstr("%08X");
168 	state_add(MB86235_AR1, "AR1", m_core->ar[1]).formatstr("%08X");
169 	state_add(MB86235_AR2, "AR2", m_core->ar[2]).formatstr("%08X");
170 	state_add(MB86235_AR3, "AR3", m_core->ar[3]).formatstr("%08X");
171 	state_add(MB86235_AR4, "AR4", m_core->ar[4]).formatstr("%08X");
172 	state_add(MB86235_AR5, "AR5", m_core->ar[5]).formatstr("%08X");
173 	state_add(MB86235_AR6, "AR6", m_core->ar[6]).formatstr("%08X");
174 	state_add(MB86235_AR7, "AR7", m_core->ar[7]).formatstr("%08X");
175 	state_add(MB86235_AA0, "AA0", m_core->aa[0]).formatstr("%08X");
176 	state_add(MB86235_AA1, "AA1", m_core->aa[1]).formatstr("%08X");
177 	state_add(MB86235_AA2, "AA2", m_core->aa[2]).formatstr("%08X");
178 	state_add(MB86235_AA3, "AA3", m_core->aa[3]).formatstr("%08X");
179 	state_add(MB86235_AA4, "AA4", m_core->aa[4]).formatstr("%08X");
180 	state_add(MB86235_AA5, "AA5", m_core->aa[5]).formatstr("%08X");
181 	state_add(MB86235_AA6, "AA6", m_core->aa[6]).formatstr("%08X");
182 	state_add(MB86235_AA7, "AA7", m_core->aa[7]).formatstr("%08X");
183 	state_add(MB86235_AB0, "AB0", m_core->ab[0]).formatstr("%08X");
184 	state_add(MB86235_AB1, "AB1", m_core->ab[1]).formatstr("%08X");
185 	state_add(MB86235_AB2, "AB2", m_core->ab[2]).formatstr("%08X");
186 	state_add(MB86235_AB3, "AB3", m_core->ab[3]).formatstr("%08X");
187 	state_add(MB86235_AB4, "AB4", m_core->ab[4]).formatstr("%08X");
188 	state_add(MB86235_AB5, "AB5", m_core->ab[5]).formatstr("%08X");
189 	state_add(MB86235_AB6, "AB6", m_core->ab[6]).formatstr("%08X");
190 	state_add(MB86235_AB7, "AB7", m_core->ab[7]).formatstr("%08X");
191 	state_add(MB86235_MA0, "MA0", m_core->ma[0]).formatstr("%08X");
192 	state_add(MB86235_MA1, "MA1", m_core->ma[1]).formatstr("%08X");
193 	state_add(MB86235_MA2, "MA2", m_core->ma[2]).formatstr("%08X");
194 	state_add(MB86235_MA3, "MA3", m_core->ma[3]).formatstr("%08X");
195 	state_add(MB86235_MA4, "MA4", m_core->ma[4]).formatstr("%08X");
196 	state_add(MB86235_MA5, "MA5", m_core->ma[5]).formatstr("%08X");
197 	state_add(MB86235_MA6, "MA6", m_core->ma[6]).formatstr("%08X");
198 	state_add(MB86235_MA7, "MA7", m_core->ma[7]).formatstr("%08X");
199 	state_add(MB86235_MB0, "MB0", m_core->mb[0]).formatstr("%08X");
200 	state_add(MB86235_MB1, "MB1", m_core->mb[1]).formatstr("%08X");
201 	state_add(MB86235_MB2, "MB2", m_core->mb[2]).formatstr("%08X");
202 	state_add(MB86235_MB3, "MB3", m_core->mb[3]).formatstr("%08X");
203 	state_add(MB86235_MB4, "MB4", m_core->mb[4]).formatstr("%08X");
204 	state_add(MB86235_MB5, "MB5", m_core->mb[5]).formatstr("%08X");
205 	state_add(MB86235_MB6, "MB6", m_core->mb[6]).formatstr("%08X");
206 	state_add(MB86235_MB7, "MB7", m_core->mb[7]).formatstr("%08X");
207 	state_add(MB86235_ST,  "ST", m_core->st).formatstr("%08X");
208 
209 	state_add(MB86235_EB,  "EB",  m_core->eb).formatstr("%08X");
210 	state_add(MB86235_EO,  "EO",  m_core->eo).formatstr("%08X");
211 	state_add(MB86235_SP,  "SP",  m_core->sp).formatstr("%08X");
212 	state_add(MB86235_RPC, "RPC", m_core->rpc).formatstr("%08X");
213 	state_add(MB86235_LPC, "LPC", m_core->lpc).formatstr("%08X");
214 	state_add(MB86235_PDR, "PDR", m_core->pdr).formatstr("%08X");
215 	state_add(MB86235_DDR, "DDR", m_core->ddr).formatstr("%08X");
216 	state_add(MB86235_MOD, "MOD", m_core->mod).formatstr("%04X");
217 	state_add(MB86235_PRP, "PRP", m_core->prp).formatstr("%02X");
218 	state_add(MB86235_PWP, "PWP", m_core->pwp).formatstr("%02X");
219 	state_add(STATE_GENPC, "GENPC", m_core->pc ).noshow();
220 	state_add(STATE_GENPCBASE, "CURPC", m_core->pc).noshow();
221 
222 	set_icountptr(m_core->icount);
223 
224 	m_core->fp0 = 0.0f;
225 	save_pointer(NAME(m_core->pr), 24);
226 }
227 
device_reset()228 void mb86235_device::device_reset()
229 {
230 #if ENABLE_DRC
231 	flush_cache();
232 #endif
233 
234 	m_core->pc = 0;
235 	m_core->delay_pc = 0;
236 	m_core->ppc = 0;
237 	m_core->delay_slot = false;
238 }
239 
240 #if 0
241 void mb86235_cpu_device::execute_set_input(int irqline, int state)
242 {
243 	switch(irqline)
244 	{
245 		case MB86235_INT_INTRM:
246 			m_intrm_pending = (state == ASSERT_LINE);
247 			m_intrm_state = state;
248 			break;
249 		case MB86235_RESET:
250 			if (state == ASSERT_LINE)
251 				m_reset_pending = 1;
252 			m_reset_state = state;
253 			break;
254 		case MB86235_INT_INTR:
255 			if (state == ASSERT_LINE)
256 				m_intr_pending = 1;
257 			m_intr_state = state;
258 			break;
259 	}
260 }
261 #endif
262 
mb86235_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)263 mb86235_device::mb86235_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
264 	: cpu_device(mconfig, MB86235, tag, owner, clock)
265 	, m_program_config("program", ENDIANNESS_LITTLE, 64, 32, -3)
266 	, m_dataa_config("data_a", ENDIANNESS_LITTLE, 32, 24, -2, address_map_constructor(FUNC(mb86235_device::internal_abus), this))
267 	, m_datab_config("data_b", ENDIANNESS_LITTLE, 32, 10, -2, address_map_constructor(FUNC(mb86235_device::internal_bbus), this))
268 	, m_fifoin(*this, finder_base::DUMMY_TAG)
269 	, m_fifoout0(*this, finder_base::DUMMY_TAG)
270 	, m_fifoout1(*this, finder_base::DUMMY_TAG)
271 	, m_cache(CACHE_SIZE + sizeof(mb86235_internal_state))
272 	, m_drcuml(nullptr)
273 	, m_drcfe(nullptr)
274 {
275 }
276 
~mb86235_device()277 mb86235_device::~mb86235_device()
278 {
279 }
280 
memory_space_config() const281 device_memory_interface::space_config_vector mb86235_device::memory_space_config() const
282 {
283 	return space_config_vector {
284 		std::make_pair(AS_PROGRAM, &m_program_config),
285 		std::make_pair(AS_DATA,    &m_dataa_config),
286 		std::make_pair(AS_IO,      &m_datab_config)
287 	};
288 }
289 
state_string_export(const device_state_entry & entry,std::string & str) const290 void mb86235_device::state_string_export(const device_state_entry &entry, std::string &str) const
291 {
292 	switch (entry.index())
293 	{
294 		case STATE_GENFLAGS:
295 			str = string_format("?");
296 			break;
297 	}
298 }
299 
create_disassembler()300 std::unique_ptr<util::disasm_interface> mb86235_device::create_disassembler()
301 {
302 	return std::make_unique<mb86235_disassembler>();
303 }
304