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