OSDN Git Service

[VM][PC9801][MEMBUS] Split update_bios() to functions.
[csp-qt/common_source_project-fm7.git] / source / src / vm / upd71071.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2007.08.14 -
6
7         [ uPD71071 ]
8 */
9
10 #include "upd71071.h"
11 #include "debugger.h"
12
13 void UPD71071::initialize()
14 {
15         DEVICE::initialize();
16         _SINGLE_MODE_DMA = osd->check_feature(_T("SINGLE_MODE_DMA"));
17         _USE_DEBUGGER    = osd->check_feature(_T("USE_DEBUGGER"));
18         for(int i = 0; i < 4; i++) {
19                 dma[i].areg = dma[i].bareg = 0;
20                 dma[i].creg = dma[i].bcreg = 0;
21         }
22         if(_USE_DEBUGGER) {
23                 if(d_debugger != NULL) {
24                         d_debugger->set_device_name(_T("Debugger (uPD71071 DMAC)"));
25                         d_debugger->set_context_mem(this);
26                         d_debugger->set_context_io(vm->dummy);
27                 }
28         }
29 }
30
31 void UPD71071::reset()
32 {
33         for(int i = 0; i < 4; i++) {
34                 dma[i].mode = 0x04;
35         }
36         b16 = selch = base = 0;
37         cmd = tmp = 0;
38         req = sreq = tc = 0;
39         mask = 0x0f;
40 }
41
42 void UPD71071::write_io8(uint32_t addr, uint32_t data)
43 {
44         switch(addr & 0x0f) {
45         case 0x00:
46                 if(data & 1) {
47                         // dma reset
48                         for(int i = 0; i < 4; i++) {
49                                 dma[i].mode = 0x04;
50                         }
51                         selch = base = 0;
52                         cmd = tmp = 0;
53                         sreq = tc = 0;
54                         mask = 0x0f;
55                 }
56                 b16 = data & 2;
57                 break;
58         case 0x01:
59                 selch = data & 3;
60                 base = data & 4;
61                 break;
62         case 0x02:
63                 dma[selch].bcreg = (dma[selch].bcreg & 0xff00) | data;
64 //              if(!base) {
65                         dma[selch].creg = (dma[selch].creg & 0xff00) | data;
66 //              }
67                 break;
68         case 0x03:
69                 dma[selch].bcreg = (dma[selch].bcreg & 0x00ff) | (data << 8);
70 //              if(!base) {
71                         dma[selch].creg = (dma[selch].creg & 0x00ff) | (data << 8);
72 //              }
73                 break;
74         case 0x04:
75                 dma[selch].bareg = (dma[selch].bareg & 0xffff00) | data;
76 //              if(!base) {
77                         dma[selch].areg = (dma[selch].areg & 0xffff00) | data;
78 //              }
79                 break;
80         case 0x05:
81                 dma[selch].bareg = (dma[selch].bareg & 0xff00ff) | (data << 8);
82 //              if(!base) {
83                         dma[selch].areg = (dma[selch].areg & 0xff00ff) | (data << 8);
84 //              }
85                 break;
86         case 0x06:
87                 dma[selch].bareg = (dma[selch].bareg & 0x00ffff) | (data << 16);
88 //              if(!base) {
89                         dma[selch].areg = (dma[selch].areg & 0x00ffff) | (data << 16);
90 //              }
91                 break;
92         case 0x08:
93                 cmd = (cmd & 0xff00) | data;
94                 break;
95         case 0x09:
96                 cmd = (cmd & 0xff) | (data << 8);
97                 break;
98         case 0x0a:
99                 dma[selch].mode = data;
100                 break;
101         case 0x0e:
102                 if(((sreq = data) != 0) && !(_SINGLE_MODE_DMA)) {
103 //#ifndef SINGLE_MODE_DMA
104                         do_dma();
105 //#endif
106                 }
107                 break;
108         case 0x0f:
109                 mask = data;
110                 break;
111         }
112 }
113
114 uint32_t UPD71071::read_io8(uint32_t addr)
115 {
116         uint32_t val;
117         
118         switch(addr & 0x0f) {
119         case 0x00:
120                 return b16;
121         case 0x01:
122                 return (base << 2) | (1 << selch);
123         case 0x02:
124                 if(base) {
125                         return dma[selch].bcreg & 0xff;
126                 } else {
127                         return dma[selch].creg & 0xff;
128                 }
129         case 0x03:
130                 if(base) {
131                         return (dma[selch].bcreg >> 8) & 0xff;
132                 } else {
133                         return (dma[selch].creg >> 8) & 0xff;
134                 }
135         case 0x04:
136                 if(base) {
137                         return dma[selch].bareg & 0xff;
138                 } else {
139                         return dma[selch].areg & 0xff;
140                 }
141         case 0x05:
142                 if(base) {
143                         return (dma[selch].bareg >> 8) & 0xff;
144                 } else {
145                         return (dma[selch].areg >> 8) & 0xff;
146                 }
147         case 0x06:
148                 if(base) {
149                         return (dma[selch].bareg >> 16) & 0xff;
150                 } else {
151                         return (dma[selch].areg >> 16) & 0xff;
152                 }
153         case 0x08:
154                 return cmd & 0xff;
155         case 0x09:
156                 return (cmd >> 8) & 0xff;
157         case 0x0a:
158                 return dma[selch].mode;
159         case 0x0b:
160                 val = (req << 4) | tc;
161                 tc = 0;
162                 return val;
163         case 0x0c:
164                 return tmp & 0xff;
165         case 0x0d:
166                 return (tmp >> 8) & 0xff;
167         case 0x0e:
168                 return sreq;
169         case 0x0f:
170                 return mask;
171         }
172         return 0xff;
173 }
174
175 void UPD71071::write_signal(int id, uint32_t data, uint32_t mask)
176 {
177         uint8_t bit = 1 << (id & 3);
178         
179         if(data & mask) {
180                 if(!(req & bit)) {
181                         req |= bit;
182 //#ifndef SINGLE_MODE_DMA
183                         if(!_SINGLE_MODE_DMA) do_dma();
184 //#endif
185                 }
186         } else {
187                 req &= ~bit;
188         }
189 }
190
191 void UPD71071::write_via_debugger_data8(uint32_t addr, uint32_t data)
192 {
193         d_mem->write_dma_data8(addr, data);
194 }
195
196 uint32_t UPD71071::read_via_debugger_data8(uint32_t addr)
197 {
198         return d_mem->read_dma_data8(addr);
199 }
200
201 void UPD71071::write_via_debugger_data16(uint32_t addr, uint32_t data)
202 {
203         d_mem->write_dma_data16(addr, data);
204 }
205
206 uint32_t UPD71071::read_via_debugger_data16(uint32_t addr)
207 {
208         return d_mem->read_dma_data16(addr);
209 }
210
211 // note: if SINGLE_MODE_DMA is defined, do_dma() is called in every machine cycle
212
213 uint32_t UPD71071::read_signal(int ch)
214 {
215         if((ch >= (SIG_UPD71071_IS_TRANSFERING + 0)) && (ch < (SIG_UPD71071_IS_TRANSFERING + 4))) {
216                 bool _nch = ch - SIG_UPD71071_IS_TRANSFERING;
217                 if((cmd & 0x04) != 0) return 0x00; // Not transfering
218                 if((dma[_nch].creg == 0)) return 0x00; //
219                 return 0xffffffff;
220         } else if((ch >= (SIG_UPD71071_IS_16BITS_TRANSFER + 0)) && (ch < (SIG_UPD71071_IS_16BITS_TRANSFER + 4))) {
221                 bool _nch = ch - SIG_UPD71071_IS_16BITS_TRANSFER;
222                 return ((dma[_nch].mode & 1) != 0) ? 0xffffffff : 0;
223         }
224         return 0;
225 }
226                         
227 void UPD71071::do_dma()
228 {
229         // check DDMA
230         if(cmd & 4) {
231                 return;
232         }
233         
234         // run dma
235         for(int c = 0; c < 4; c++) {
236                 uint8_t bit = 1 << c;
237                 if(((req | sreq) & bit) && !(mask & bit)) {
238                         // execute dma
239                         while((req | sreq) & bit) {
240                                 // Will check WORD transfer mode for FM-Towns.(mode.bit0 = '1).
241                                 if((dma[c].mode & 0x01) == 1) {
242                                         // 8bit transfer mode
243                                         if((dma[c].mode & 0x0c) == 0x00) {
244                                                 // verify
245                                                 uint32_t val = dma[c].dev->read_dma_io16(0);
246                                                 // update temporary register
247                                                 tmp = val;
248                                         } else if((dma[c].mode & 0x0c) == 0x04) {
249                                                 // io -> memory
250                                                 uint32_t val;
251                                                 val = dma[c].dev->read_dma_io16(0);
252                                                 write_signals(&outputs_wrote_mem_word, dma[c].areg);
253                                                 if(_USE_DEBUGGER) {
254                                                         if(d_debugger != NULL && d_debugger->now_device_debugging) {
255                                                                 d_debugger->write_via_debugger_data16(dma[c].areg, val);
256                                                         } else {
257                                                                 this->write_via_debugger_data16(dma[c].areg, val);
258                                                         }
259                                                 } else {
260                                                                 this->write_via_debugger_data16(dma[c].areg, val);
261                                                 }
262                                                         
263                                                 // update temporary register
264                                                 tmp = val;
265                                         } else if((dma[c].mode & 0x0c) == 0x08) {
266                                                 // memory -> io
267                                                 uint32_t val;
268                                                 if(_USE_DEBUGGER) {
269                                                         if(d_debugger != NULL && d_debugger->now_device_debugging) {
270                                                                 val = d_debugger->read_via_debugger_data16(dma[c].areg);
271                                                         } else {
272                                                                 val = this->read_via_debugger_data16(dma[c].areg);
273                                                         }
274                                                 } else {
275                                                                 val = this->read_via_debugger_data16(dma[c].areg);
276                                                 }                                                       
277                                                 dma[c].dev->write_dma_io16(0, val);
278                                                 // update temporary register
279                                                 tmp = val;
280                                         }
281                                         if(dma[c].mode & 0x20) {
282                                                 dma[c].areg = (dma[c].areg - 2) & 0xffffff;
283                                         } else {
284                                                 dma[c].areg = (dma[c].areg + 2) & 0xffffff;
285                                         }
286                                         if(dma[c].creg-- == 0) {  // OK?
287                                                 // TC
288                                                 if(dma[c].mode & 0x10) {
289                                                         // auto initialize
290                                                         dma[c].areg = dma[c].bareg;
291                                                         dma[c].creg = dma[c].bcreg;
292                                                 } else {
293                                                         mask |= bit;
294                                                 }
295                                                 req &= ~bit;
296                                                 sreq &= ~bit;
297                                                 tc |= bit;
298                                                 
299                                                 write_signals(&outputs_tc, 0xffffffff);
300                                         } else if(_SINGLE_MODE_DMA) {
301                                                 if((dma[c].mode & 0xc0) == 0x40) {
302                                                         // single mode
303                                                         break;
304                                                 }
305                                         }
306                                 } else {
307                                         // 8bit transfer mode
308                                         if((dma[c].mode & 0x0c) == 0x00) {
309                                                 // verify
310                                                 uint32_t val = dma[c].dev->read_dma_io8(0);
311                                                 // update temporary register
312                                                 tmp = (tmp >> 8) | (val << 8);
313                                         } else if((dma[c].mode & 0x0c) == 0x04) {
314                                                 // io -> memory
315                                                 uint32_t val;
316                                                 val = dma[c].dev->read_dma_io8(0);
317                                                 write_signals(&outputs_wrote_mem_byte, dma[c].areg);
318                                                 if(_USE_DEBUGGER) {
319                                                         if(d_debugger != NULL && d_debugger->now_device_debugging) {
320                                                                 d_debugger->write_via_debugger_data8(dma[c].areg, val);
321                                                         } else {
322                                                                 this->write_via_debugger_data8(dma[c].areg, val);
323                                                         }
324                                                 } else {
325                                                         this->write_via_debugger_data8(dma[c].areg, val);
326                                                 }                                                       
327                                                 // update temporary register
328                                                 tmp = (tmp >> 8) | (val << 8);
329                                         } else if((dma[c].mode & 0x0c) == 0x08) {
330                                                 // memory -> io
331                                                 uint32_t val;
332                                                 if(_USE_DEBUGGER) {
333                                                         if(d_debugger != NULL && d_debugger->now_device_debugging) {
334                                                                 val = d_debugger->read_via_debugger_data8(dma[c].areg);
335                                                         } else {
336                                                                 val = this->read_via_debugger_data8(dma[c].areg);
337                                                         }
338                                                 } else {
339                                                         val = this->read_via_debugger_data8(dma[c].areg);
340                                                 }
341                                                 dma[c].dev->write_dma_io8(0, val);
342                                                 // update temporary register
343                                                 tmp = (tmp >> 8) | (val << 8);
344                                         }
345                                         if(dma[c].mode & 0x20) {
346                                                 dma[c].areg = (dma[c].areg - 1) & 0xffffff;
347                                         } else {
348                                                 dma[c].areg = (dma[c].areg + 1) & 0xffffff;
349                                         }
350                                 }
351                                 if(dma[c].creg-- == 0) {
352                                         // TC
353                                         if(dma[c].mode & 0x10) {
354                                                 // auto initialize
355                                                 dma[c].areg = dma[c].bareg;
356                                                 dma[c].creg = dma[c].bcreg;
357                                         } else {
358                                                 mask |= bit;
359                                         }
360                                         req &= ~bit;
361                                         sreq &= ~bit;
362                                         tc |= bit;
363                                         
364                                         write_signals(&outputs_tc, 0xffffffff);
365 //#ifdef SINGLE_MODE_DMA
366                                 } else if(_SINGLE_MODE_DMA) {
367                                         if((dma[c].mode & 0xc0) == 0x40) {
368                                                 // single mode
369                                                 break;
370                                         }
371 //#endif
372                                 }
373                         }
374                 }
375         }
376 //#ifdef SINGLE_MODE_DMA
377         if(_SINGLE_MODE_DMA) {
378                 if(d_dma) {
379                         d_dma->do_dma();
380                 }
381         }
382 //#endif
383 }
384
385 bool UPD71071::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
386 {
387 /*
388 CH0 AREG=FFFF CREG=FFFF BAREG=FFFF BCREG=FFFF REQ=1 MASK=1 MODE=FF MEM->I/O
389 CH1 AREG=FFFF CREG=FFFF BAREG=FFFF BCREG=FFFF REQ=1 MASK=1 MODE=FF I/O->MEM
390 CH2 AREG=FFFF CREG=FFFF BAREG=FFFF BCREG=FFFF REQ=1 MASK=1 MODE=FF VERIFY
391 CH3 AREG=FFFF CREG=FFFF BAREG=FFFF BCREG=FFFF REQ=1 MASK=1 MODE=FF INVALID
392 */
393         static const _TCHAR *dir[4] = {
394                 _T("VERIFY"), _T("I/O->MEM"), _T("MEM->I/O"), _T("INVALID")
395         };
396         my_stprintf_s(buffer, buffer_len,
397         _T("CH0 AREG=%04X CREG=%04X BAREG=%04X BCREG=%04X REQ=%d MASK=%d MODE=%02X %s\n")
398         _T("CH1 AREG=%04X CREG=%04X BAREG=%04X BCREG=%04X REQ=%d MASK=%d MODE=%02X %s\n")
399         _T("CH2 AREG=%04X CREG=%04X BAREG=%04X BCREG=%04X REQ=%d MASK=%d MODE=%02X %s\n")
400         _T("CH3 AREG=%04X CREG=%04X BAREG=%04X BCREG=%04X REQ=%d MASK=%d MODE=%02X %s"),
401         dma[0].areg, dma[0].creg, dma[0].bareg, dma[0].bcreg, ((req | sreq) >> 0) & 1, (mask >> 0) & 1, dma[0].mode, dir[(dma[0].mode >> 2) & 3],
402         dma[1].areg, dma[1].creg, dma[1].bareg, dma[1].bcreg, ((req | sreq) >> 1) & 1, (mask >> 1) & 1, dma[1].mode, dir[(dma[1].mode >> 2) & 3],
403         dma[2].areg, dma[2].creg, dma[2].bareg, dma[2].bcreg, ((req | sreq) >> 2) & 1, (mask >> 2) & 1, dma[2].mode, dir[(dma[2].mode >> 2) & 3],
404         dma[3].areg, dma[3].creg, dma[3].bareg, dma[3].bcreg, ((req | sreq) >> 3) & 1, (mask >> 3) & 1, dma[3].mode, dir[(dma[3].mode >> 2) & 3]);
405         return true;
406 }
407
408 #define STATE_VERSION   1
409
410 bool UPD71071::process_state(FILEIO* state_fio, bool loading)
411 {
412         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
413                 return false;
414         }
415         if(!state_fio->StateCheckInt32(this_device_id)) {
416                 return false;
417         }
418         for(int i = 0; i < 4; i++) {
419                 state_fio->StateValue(dma[i].areg);
420                 state_fio->StateValue(dma[i].bareg);
421                 state_fio->StateValue(dma[i].creg);
422                 state_fio->StateValue(dma[i].bcreg);
423                 state_fio->StateValue(dma[i].mode);
424         }
425         state_fio->StateValue(b16);
426         state_fio->StateValue(selch);
427         state_fio->StateValue(base);
428         state_fio->StateValue(cmd);
429         state_fio->StateValue(tmp);
430         state_fio->StateValue(req);
431         state_fio->StateValue(sreq);
432         state_fio->StateValue(mask);
433         state_fio->StateValue(tc);
434         return true;
435 }
436