OSDN Git Service

[VM][DEVICE] You should add "DECVICE::initialize()" to top of initialize().
[csp-qt/common_source_project-fm7.git] / source / src / vm / upd7810.cpp
1 /*
2         Skelton for retropc emulator
3
4         Origin : MESS 0.152
5         Author : Takeda.Toshiya
6         Date   : 2016.03.17-
7
8         [ uPD7810 ]
9 */
10
11 #include "upd7810.h"
12 #ifdef USE_DEBUGGER
13 #include "debugger.h"
14 #endif
15
16 #if defined(HAS_UPD7810)
17         #define CPU_MODEL upd7810
18 #elif defined(HAS_UPD7807)
19         #define CPU_MODEL upd7807
20 #elif defined(HAS_UPD7801)
21         #define CPU_MODEL upd7801
22 #elif defined(HAS_UPD78C05)
23         #define CPU_MODEL upd78c05
24 #elif defined(HAS_UPD78C06)
25         #define CPU_MODEL upd78c06
26 #elif defined(HAS_UPD7907)
27         #define CPU_MODEL upd7907
28 #endif
29
30 /* ----------------------------------------------------------------------------
31         MAME uPD7810
32 ---------------------------------------------------------------------------- */
33
34 #define PAIR pair_t
35 #define offs_t UINT16
36
37 /*****************************************************************************/
38 /* src/emu/devcpu.h */
39
40 // CPU interface functions
41 #define CPU_INIT_NAME(name)                     cpu_init_##name
42 #define CPU_INIT(name)                          void* CPU_INIT_NAME(name)()
43 #define CPU_INIT_CALL(name)                     CPU_INIT_NAME(name)()
44
45 #define CPU_RESET_NAME(name)                    cpu_reset_##name
46 #define CPU_RESET(name)                         void CPU_RESET_NAME(name)(upd7810_state *cpustate)
47 #define CPU_RESET_CALL(name)                    CPU_RESET_NAME(name)(cpustate)
48
49 #define CPU_EXECUTE_NAME(name)                  cpu_execute_##name
50 #define CPU_EXECUTE(name)                       int CPU_EXECUTE_NAME(name)(upd7810_state *cpustate)
51 #define CPU_EXECUTE_CALL(name)                  CPU_EXECUTE_NAME(name)(cpustate)
52
53 #define CPU_DISASSEMBLE_NAME(name)              cpu_disassemble_##name
54 #define CPU_DISASSEMBLE(name)                   int CPU_DISASSEMBLE_NAME(name)(_TCHAR *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, symbol_t *first_symbol)
55 #define CPU_DISASSEMBLE_CALL(name)              CPU_DISASSEMBLE_NAME(name)(buffer, pc, oprom, oprom, d_debugger->first_symbol)
56
57 /*****************************************************************************/
58 /* src/emu/didisasm.h */
59
60 // Disassembler constants
61 const UINT32 DASMFLAG_SUPPORTED     = 0x80000000;   // are disassembly flags supported?
62 const UINT32 DASMFLAG_STEP_OUT      = 0x40000000;   // this instruction should be the end of a step out sequence
63 const UINT32 DASMFLAG_STEP_OVER     = 0x20000000;   // this instruction should be stepped over by setting a breakpoint afterwards
64 const UINT32 DASMFLAG_OVERINSTMASK  = 0x18000000;   // number of extra instructions to skip when stepping over
65 const UINT32 DASMFLAG_OVERINSTSHIFT = 27;           // bits to shift after masking to get the value
66 const UINT32 DASMFLAG_LENGTHMASK    = 0x0000ffff;   // the low 16-bits contain the actual length
67
68 /*****************************************************************************/
69 /* src/emu/diexec.h */
70
71 // I/O line states
72 enum line_state
73 {
74         CLEAR_LINE = 0,                         // clear (a fired or held) line
75         ASSERT_LINE                             // assert an interrupt immediately
76 };
77
78 enum
79 {
80         UPD7810_INTF1  = 0,
81         UPD7810_INTF2  = 1,
82         UPD7810_INTF0  = 2,
83         UPD7810_INTFE1 = 4,
84         INPUT_LINE_NMI
85 };
86
87 #define logerror(...)
88 #define fatalerror(...)
89
90 #undef IN
91 #undef OUT
92
93 #include "mame/emu/cpu/upd7810/upd7810.c"
94 #ifdef USE_DEBUGGER
95 #undef _DOFF
96 #include "mame/emu/cpu/upd7810/7810dasm.c"
97 #endif
98
99 // main
100
101 void UPD7810::initialize()
102 {
103         DEVICE::initialize();
104         opaque = CPU_INIT_CALL(upd7810);
105         
106         upd7810_state *cpustate = (upd7810_state *)opaque;
107 #if defined(HAS_UPD7810)
108         cpustate->config.type = TYPE_7810;
109 #elif defined(HAS_UPD7807)
110         cpustate->config.type = TYPE_7807;
111 #elif defined(HAS_UPD7801)
112         cpustate->config.type = TYPE_7801;
113 #elif defined(HAS_UPD78C05)
114         cpustate->config.type = TYPE_78C05;
115 #elif defined(HAS_UPD78C06)
116         cpustate->config.type = TYPE_78C06;
117 #elif defined(HAS_UPD7907)
118         cpustate->config.type = TYPE_78C06;
119 #endif
120         cpustate->program = d_mem;
121         cpustate->io = d_io;
122         cpustate->outputs_to = (void*)&outputs_to;
123         cpustate->outputs_txd = (void*)&outputs_txd;
124 #ifdef USE_DEBUGGER
125         cpustate->emu = emu;
126         cpustate->debugger = d_debugger;
127         cpustate->program_stored = d_mem;
128         cpustate->io_stored = d_io;
129         
130         d_debugger->set_context_mem(d_mem);
131         d_debugger->set_context_io(d_io);
132 #endif
133 }
134
135 void UPD7810::release()
136 {
137         free(opaque);
138 }
139
140 void UPD7810::reset()
141 {
142         upd7810_state *cpustate = (upd7810_state *)opaque;
143         
144         CPU_RESET_CALL(CPU_MODEL);
145         
146         cpustate->program = d_mem;
147         cpustate->io = d_io;
148         cpustate->outputs_to = (void*)&outputs_to;
149         cpustate->outputs_txd = (void*)&outputs_txd;
150 #ifdef USE_DEBUGGER
151         cpustate->emu = emu;
152         cpustate->debugger = d_debugger;
153         cpustate->program_stored = d_mem;
154         cpustate->io_stored = d_io;
155 #endif
156         icount = 0;
157         busreq = false;
158 }
159
160 int UPD7810::run(int clock)
161 {
162         upd7810_state *cpustate = (upd7810_state *)opaque;
163         
164         if(clock == -1) {
165                 if(busreq) {
166                         // don't run cpu!
167                         return 1;
168                 } else {
169                         // run only one opcode
170                         return CPU_EXECUTE_CALL(upd7810);
171                 }
172         } else {
173                 icount += clock;
174                 int first_icount = icount;
175                 
176                 // run cpu while given clocks
177                 while(icount > 0 && !busreq) {
178                         icount -= CPU_EXECUTE_CALL(upd7810);
179                 }
180                 // if busreq is raised, spin cpu while remained clock
181                 if(icount > 0 && busreq) {
182                         icount = 0;
183                 }
184                 return first_icount - icount;
185         }
186 }
187
188 void UPD7810::write_signal(int id, uint32_t data, uint32_t mask)
189 {
190         upd7810_state *cpustate = (upd7810_state *)opaque;
191         
192         switch(id) {
193         case SIG_UPD7810_INTF1:
194                 set_irq_line(cpustate, UPD7810_INTF1, (data & mask) ? ASSERT_LINE : CLEAR_LINE);
195                 break;
196         case SIG_UPD7810_INTF2:
197                 set_irq_line(cpustate, UPD7810_INTF2, (data & mask) ? ASSERT_LINE : CLEAR_LINE);
198                 break;
199         case SIG_UPD7810_INTF0:
200                 set_irq_line(cpustate, UPD7810_INTF0, (data & mask) ? ASSERT_LINE : CLEAR_LINE);
201                 break;
202         case SIG_UPD7810_INTFE1:
203                 set_irq_line(cpustate, UPD7810_INTFE1, (data & mask) ? ASSERT_LINE : CLEAR_LINE);
204                 break;
205         case SIG_UPD7810_NMI:
206                 set_irq_line(cpustate, INPUT_LINE_NMI, (data & mask) ? ASSERT_LINE : CLEAR_LINE);
207                 break;
208         case SIG_CPU_BUSREQ:
209                 busreq = ((data & mask) != 0);
210                 break;
211         }
212 }
213
214 uint32_t UPD7810::get_pc()
215 {
216         upd7810_state *cpustate = (upd7810_state *)opaque;
217         return cpustate->ppc.w.l;
218 }
219
220 uint32_t UPD7810::get_next_pc()
221 {
222         upd7810_state *cpustate = (upd7810_state *)opaque;
223         return cpustate->pc.w.l;
224 }
225
226 #ifdef USE_DEBUGGER
227 void UPD7810::write_debug_data8(uint32_t addr, uint32_t data)
228 {
229         int wait;
230         d_mem->write_data8w(addr, data, &wait);
231 }
232
233 uint32_t UPD7810::read_debug_data8(uint32_t addr)
234 {
235         int wait;
236         return d_mem->read_data8w(addr, &wait);
237 }
238
239 void UPD7810::write_debug_io8(uint32_t addr, uint32_t data)
240 {
241         int wait;
242         d_io->write_io8w(addr, data, &wait);
243 }
244
245 uint32_t UPD7810::read_debug_io8(uint32_t addr) {
246         int wait;
247         return d_io->read_io8w(addr, &wait);
248 }
249
250 bool UPD7810::write_debug_reg(const _TCHAR *reg, uint32_t data)
251 {
252         upd7810_state *cpustate = (upd7810_state *)opaque;
253         
254         if(_tcsicmp(reg, _T("PC")) == 0) {
255                 PC = data;
256         } else if(_tcsicmp(reg, _T("SP")) == 0) {
257                 SP = data;
258         } else if(_tcsicmp(reg, _T("VA")) == 0) {
259                 VA = data;
260         } else if(_tcsicmp(reg, _T("BC")) == 0) {
261                 BC = data;
262         } else if(_tcsicmp(reg, _T("DE")) == 0) {
263                 DE = data;
264         } else if(_tcsicmp(reg, _T("HL")) == 0) {
265                 HL = data;
266         } else if(_tcsicmp(reg, _T("V")) == 0) {
267                 V = data;
268         } else if(_tcsicmp(reg, _T("A")) == 0) {
269                 A = data;
270         } else if(_tcsicmp(reg, _T("B")) == 0) {
271                 B = data;
272         } else if(_tcsicmp(reg, _T("C")) == 0) {
273                 C = data;
274         } else if(_tcsicmp(reg, _T("D")) == 0) {
275                 D = data;
276         } else if(_tcsicmp(reg, _T("E")) == 0) {
277                 E = data;
278         } else if(_tcsicmp(reg, _T("H")) == 0) {
279                 H = data;
280         } else if(_tcsicmp(reg, _T("L")) == 0) {
281                 L = data;
282         } else if(_tcsicmp(reg, _T("VA'")) == 0) {
283                 VA2 = data;
284         } else if(_tcsicmp(reg, _T("BC'")) == 0) {
285                 BC2 = data;
286         } else if(_tcsicmp(reg, _T("DE'")) == 0) {
287                 DE2 = data;
288         } else if(_tcsicmp(reg, _T("HL'")) == 0) {
289                 HL2 = data;
290         } else if(_tcsicmp(reg, _T("V'")) == 0) {
291                 V2 = data;
292         } else if(_tcsicmp(reg, _T("A'")) == 0) {
293                 A2 = data;
294         } else if(_tcsicmp(reg, _T("B'")) == 0) {
295                 B2 = data;
296         } else if(_tcsicmp(reg, _T("C'")) == 0) {
297                 C2 = data;
298         } else if(_tcsicmp(reg, _T("D'")) == 0) {
299                 D2 = data;
300         } else if(_tcsicmp(reg, _T("E'")) == 0) {
301                 E2 = data;
302         } else if(_tcsicmp(reg, _T("H'")) == 0) {
303                 H2 = data;
304         } else if(_tcsicmp(reg, _T("L'")) == 0) {
305                 L2 = data;
306         } else {
307                 return false;
308         }
309         return true;
310 }
311
312 void UPD7810::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
313 {
314 /*
315 VA = 0000  BC = 0000  DE = 0000 HL = 0000  PSW= 00 [Z SK HC L1 L0 CY]
316 VA'= 0000  BC'= 0000  DE'= 0000 HL'= 0000  SP = 0000  PC = 0000
317           (BC)= 0000 (DE)=0000 (HL)= 0000 (SP)= 0000 <DI>
318 */
319         upd7810_state *cpustate = (upd7810_state *)opaque;
320         int wait;
321         my_stprintf_s(buffer, buffer_len,
322         _T("VA = %04X  BC = %04X  DE = %04X HL = %04X  PSW= %02x [%s %s %s %s %s %s]\nVA'= %04X  BC'= %04X  DE'= %04X HL'= %04X  SP = %04X  PC = %04X\n          (BC)= %04X (DE)=%04X (HL)= %04X (SP)= %04X <%s>"),
323         VA, BC, DE, HL, PSW,
324         (PSW & Z) ? _T("Z") : _T("-"), (PSW & SK) ? _T("SK") : _T("--"), (PSW & HC) ? _T("HC") : _T("--"), (PSW & L1) ? _T("L1") : _T("--"), (PSW & L0) ? _T("L0") : _T("--"), (PSW & CY) ? _T("CY") : _T("--"),
325         VA2, BC2, DE2, HL2, SP, PC,
326         d_mem->read_data16w(BC, &wait), d_mem->read_data16w(DE, &wait), d_mem->read_data16w(HL, &wait), d_mem->read_data16w(SP, &wait),
327         IFF ? _T("EI") : _T("DI"));
328 }
329
330 // disassembler
331
332 int UPD7810::debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len)
333 {
334         uint8_t oprom[8];
335         uint8_t *opram = oprom;
336         
337         for(int i = 0; i < 8; i++) {
338                 int wait;
339                 oprom[i] = d_mem->read_data8w(pc + i, &wait);
340         }
341         return CPU_DISASSEMBLE_CALL(CPU_MODEL) & DASMFLAG_LENGTHMASK;
342 }
343 #endif
344
345 #define STATE_VERSION   3
346
347 void UPD7810::save_state(FILEIO* state_fio)
348 {
349         state_fio->FputUint32(STATE_VERSION);
350         state_fio->FputInt32(this_device_id);
351         
352         state_fio->Fwrite(opaque, sizeof(upd7810_state), 1);
353         state_fio->FputInt32(icount);
354         state_fio->FputBool(busreq);
355 }
356
357 bool UPD7810::load_state(FILEIO* state_fio)
358 {
359         if(state_fio->FgetUint32() != STATE_VERSION) {
360                 return false;
361         }
362         if(state_fio->FgetInt32() != this_device_id) {
363                 return false;
364         }
365         state_fio->Fread(opaque, sizeof(upd7810_state), 1);
366         icount = state_fio->FgetInt32();
367         busreq = state_fio->FgetBool();
368         
369         // post process
370         upd7810_state *cpustate = (upd7810_state *)opaque;
371         cpustate->program = d_mem;
372         cpustate->io = d_io;
373         cpustate->outputs_to = (void*)&outputs_to;
374         cpustate->outputs_txd = (void*)&outputs_txd;
375 #ifdef USE_DEBUGGER
376         cpustate->emu = emu;
377         cpustate->debugger = d_debugger;
378         cpustate->program_stored = d_mem;
379         cpustate->io_stored = d_io;
380 #endif
381         return true;
382 }