|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2022 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: //
8: // HD647180 I/O アクセス
9: //
10:
11: #include "mpu64180.h"
12: #include "hd647180.h"
13: #include "pio.h"
14: #include "scheduler.h"
15: #include "xpbus.h"
16:
17: //#define ENABLE_SERIAL_LOG
18: //#define ENABLE_SSG_LOG
19:
20: uint32
21: MPU64180Device::ReadIO(uint32 addr)
22: {
23: CYCLE(iowait);
24:
25: // 内蔵 I/O
26: if (io_address <= addr && addr < io_address + 0x80) {
27: return ReadInternalIO(addr - io_address);
28: }
29:
30: return ReadExternalIO(addr);
31: }
32:
33: uint32
34: MPU64180Device::ReadInternalIO(uint32 offset)
35: {
36: uint32 data = -1;
37:
38: switch (offset) {
39: case 0x00: // IO_CNTLA0
40: case 0x01: // IO_CNTLA1
41: data = 0x10;
42: #if defined(ENABLE_SERIAL_LOG)
43: putlog(0, "%s -> $%02x (NOT IMPLEMENTED)",
44: IOName(offset).c_str(), data);
45: #endif
46: return data;
47: case 0x02: // IO_CNTLB0
48: case 0x03: // IO_CNTLB1
49: break;
50: case 0x04: // IO_STAT0
51: case 0x05: // IO_STAT1
52: data = 0x02;
53: #if defined(ENABLE_SERIAL_LOG)
54: putlog(0, "%s -> $%02x (NOT IMPLEMENTED)",
55: IOName(offset).c_str(), data);
56: #endif
57: return data;
58: case 0x06: // IO_TDR0
59: case 0x07: // IO_TDR1
60: case 0x08: // IO_TSR0
61: case 0x09: // IO_TSR1
62: case 0x0a: // IO_CNTR
63: case 0x0b: // IO_TRDR
64: break;
65:
66: case 0x0c: // IO_TMDR0L
67: data = ReadTMDRL(0);
68: break;
69: case 0x0d: // IO_TMDR0H
70: data = ReadTMDRH(0);
71: break;
72: case 0x0e: // IO_RLDR0L
73: data = PeekRLDRL(0);
74: break;
75: case 0x0f: // IO_RLDR0H
76: data = PeekRLDRH(0);
77: break;
78: case 0x10: // IO_TCR
79: data = ReadTCR();
80: break;
81: case 0x14: // IO_TMDR1L
82: data = ReadTMDRL(1);
83: break;
84: case 0x15: // IO_TMDR1H
85: data = ReadTMDRH(1);
86: break;
87: case 0x16: // IO_RLDR1L
88: data = PeekRLDRH(0);
89: break;
90: case 0x17: // IO_RLDR1H
91: data = PeekRLDRH(1);
92: break;
93: case 0x18: // IO_FRC
94: data = PeekFRC();
95: break;
96:
97: case 0x20: // IO_SAR0L
98: case 0x21: // IO_SAR0H
99: case 0x22: // IO_SAR0B
100: case 0x23: // IO_DAR0L
101: case 0x24: // IO_DAR0H
102: case 0x25: // IO_DAR0B
103: case 0x26: // IO_BCR0L
104: case 0x27: // IO_BCR0H
105: case 0x28: // IO_MAR1L
106: case 0x29: // IO_MAR1H
107: case 0x2a: // IO_MAR1B
108: case 0x2b: // IO_IAR1L
109: case 0x2c: // IO_IAR1H
110: case 0x2e: // IO_BCR1L
111: case 0x2f: // IO_BCR1H
112: case 0x30: // IO_DSTAT
113: case 0x31: // IO_DMODE
114: break;
115: case 0x32: // IO_DCNTL
116: data = PeekDCNTL();
117: break;
118:
119: case 0x33: // IO_IL
120: data = PeekIL();
121: break;
122: case 0x34: // IO_ITC
123: data = PeekITC();
124: break;
125: case 0x36: // IO_RCR
126: data = PeekRCR();
127: break;
128:
129: case 0x38: // IO_CBR
130: data = PeekCBR();
131: break;
132:
133: case 0x39: // IO_BBR
134: data = PeekBBR();
135: break;
136:
137: case 0x3a: // IO_CBAR
138: data = PeekCBAR();
139: break;
140:
141: case 0x3e: // IO_OMCR
142: break;
143: case 0x3f: // IO_ICR
144: data = PeekICR();
145: break;
146:
147: case 0x40: // IO_T2FRCL
148: case 0x41: // IO_T2FRCH
149: case 0x42: // IO_T2OCR1L
150: case 0x43: // IO_T2OCR1H
151: case 0x44: // IO_T2OCR2L
152: case 0x45: // IO_T2OCR2H
153: case 0x46: // IO_T2ICRL
154: case 0x47: // IO_T2ICRH
155: case 0x48: // IO_T2CSR1
156: case 0x49: // IO_T2CSR2
157: break;
158:
159: case 0x50: // IO_CCSR
160: break;
161: case 0x51: // IO_RMCR
162: data = PeekRMCR();
163: break;
164:
165: case 0x53: // IO_DERA
166: break;
167: case 0x60: // IO_IODRA
168: data = 0xff;
169: #if defined(ENABLE_SERIAL_LOG)
170: putlog(0, "%s -> $%02x (NOT IMPLEMENTED)",
171: IOName(offset).c_str(), data);
172: #endif
173: return data;
174: case 0x61: // IO_IODRB
175: case 0x62: // IO_IODRC
176: case 0x63: // IO_IODRD
177: case 0x64: // IO_IODRE
178: case 0x65: // IO_IODRF
179: case 0x66: // IO_IDRG
180: case 0x70: // IO_DDRA
181: case 0x71: // IO_DDRB
182: case 0x72: // IO_DDRC
183: case 0x73: // IO_DDRD
184: case 0x74: // IO_DDRE
185: case 0x75: // IO_DDRF
186: break;
187:
188: default:
189: break;
190: }
191:
192: // 表示して値を返す部分はだいたいほぼ共通なので。
193: if ((int32)data < 0) {
194: // data が (32bitで) 負なら未実装ポート。
195: data = 0xff;
196: putlog(0, "ReadInternalIO %s -> $%02x (NOT IMPLEMENTED)",
197: IOName(offset).c_str(), data);
198: } else {
199: putlog(2, "%s -> $%02x", IOName(offset).c_str(), data);
200: }
201: return data;
202: }
203:
204: uint32
205: MPU64180Device::ReadExternalIO(uint32 addr)
206: {
207: uint32 data = -1;
208:
209: // LUNA の外部 I/O はアドレスの上位バイト不問
210: switch (addr & 0xff) {
211: case 0x82: // SSG
212: case 0x83: // SSG
213: #if !defined(ENABLE_SSG_LOG)
214: data = 0xff;
215: #endif
216: break;
217:
218: case 0x90: // INT0 ネゲート
219: // 読み込みでも (というかアクセスがあっただけで) ネゲート。
220: putlog(1, "%s Negate INT0", IOName(addr).c_str());
221: NegateINT0();
222: // 実際何が読めるかは不明だが。
223: return 0xff;
224:
225: case 0xa0: // レベル5 割り込み要求
226: case 0xb0: // レベル1 割り込み要求
227: // 読み込みでも割り込み上げそうだがとりあえず未実装へ回しておく。
228: break;
229:
230: default:
231: break;
232: }
233:
234: // 表示して値を返す部分はだいたいほぼ共通なので。
235: if ((int32)data < 0) {
236: // data が (32bitで) 負なら未実装ポート。
237: data = 0xff;
238: putlog(0, "ReadExternalIO %s -> $%02x (NOT IMPLEMENTED)",
239: IOName(addr).c_str(), data);
240: } else {
241: putlog(2, "%s -> $%02x", IOName(addr).c_str(), data);
242: }
243: return data;
244: }
245:
246: uint32
247: MPU64180Device::ReadTMDRL(int ch)
248: {
249: auto& t = timer[ch];
250:
251: // TDR 読み出しで割り込みフラグクリアの実績を解除
252: t.tif &= ~0x02;
253: ChangeTimerInterrupt();
254:
255: // L の読み出しで count を tmp にラッチ
256: t.tmpcount = t.count;
257:
258: // でラッチした L を読み出す
259: return t.tmpcount & 0xff;
260: }
261:
262: uint32
263: MPU64180Device::ReadTMDRH(int ch)
264: {
265: auto& t = timer[ch];
266:
267: // TDR 読み出しで割り込みフラグクリアの実績を解除
268: t.tif &= ~0x02;
269: ChangeTimerInterrupt();
270:
271: // L 読み出し時にラッチしたやつを読み出す。
272: return t.tmpcount >> 8;
273: }
274:
275: uint32
276: MPU64180Device::ReadTCR()
277: {
278: // TCR 読み出しで割り込みフラグクリアの実績を解除
279: timer[0].tif &= ~0x01;
280: timer[1].tif &= ~0x01;
281: ChangeTimerInterrupt();
282:
283: return PeekTCR();
284: }
285:
286: uint32
287: MPU64180Device::WriteIO(uint32 addr, uint32 data)
288: {
289: CYCLE(iowait);
290:
291: // 内蔵 I/O
292: if (io_address <= addr && addr < io_address + 0x80) {
293: return WriteInternalIO(addr - io_address, data);
294: }
295:
296: return WriteExternalIO(addr, data);
297: }
298:
299: uint32
300: MPU64180Device::WriteInternalIO(uint32 offset, uint32 data)
301: {
302: switch (offset) {
303: case 0x00: // IO_CNTLA0
304: case 0x01: // IO_CNTLA1
305: #if defined(USE_XPSERIAL)
306: putlog(0, "%s <- $%02x (NOT IMPLEMENTED)",
307: IOName(offset).c_str(), data);
308: #endif
309: return 0;
310: case 0x02: // IO_CNTLB0
311: case 0x03: // IO_CNTLB1
312: case 0x04: // IO_STAT0
313: case 0x05: // IO_STAT1
314: case 0x06: // IO_TDR0
315: case 0x07: // IO_TDR1
316: case 0x08: // IO_TSR0
317: case 0x09: // IO_TSR1
318: case 0x0a: // IO_CNTR
319: case 0x0b: // IO_TRDR
320: break;
321:
322: case 0x0c: // IO_TMDR0L
323: return WriteTMDRL(0, data);
324: case 0x0d: // IO_TMDR0H
325: return WriteTMDRH(0, data);
326: case 0x0e: // IO_RLDR0L
327: return WriteRLDRL(0, data);
328: case 0x0f: // IO_RLDR0H
329: return WriteRLDRH(0, data);
330: case 0x10: // IO_TCR
331: return WriteTCR(data);
332: case 0x14: // IO_TMDR1L
333: return WriteTMDRL(1, data);
334: case 0x15: // IO_TMDR1H
335: return WriteTMDRH(1, data);
336: case 0x16: // IO_RLDR1L
337: return WriteRLDRL(1, data);
338: case 0x17: // IO_RLDR1H
339: return WriteRLDRH(1, data);
340: case 0x18: // IO_FRC
341: // 書き込みは出来るけど、してはいけないっぽい。
342: // たぶん現在値が変わるだけだと思うけど未対応。
343: break;
344:
345: case 0x20: // IO_SAR0L
346: case 0x21: // IO_SAR0H
347: case 0x22: // IO_SAR0B
348: case 0x23: // IO_DAR0L
349: case 0x24: // IO_DAR0H
350: case 0x25: // IO_DAR0B
351: case 0x26: // IO_BCR0L
352: case 0x27: // IO_BCR0H
353: case 0x28: // IO_MAR1L
354: case 0x29: // IO_MAR1H
355: case 0x2a: // IO_MAR1B
356: case 0x2b: // IO_IAR1L
357: case 0x2c: // IO_IAR1H
358: case 0x2e: // IO_BCR1L
359: case 0x2f: // IO_BCR1H
360: case 0x30: // IO_DSTAT
361: case 0x31: // IO_DMODE
362: break;
363: case 0x32: // IO_DCNTL
364: return WriteDCNTL(data);
365: break;
366:
367: case 0x33: // IO_IL
368: return WriteIL(data);
369: case 0x34: // IO_ITC
370: return WriteITC(data);
371: case 0x36: // IO_RCR
372: return WriteRCR(data);
373:
374: case 0x38: // IO_CBR
375: return WriteCBR(data);
376: case 0x39: // IO_BBR
377: return WriteBBR(data);
378: case 0x3a: // IO_CBAR
379: return WriteCBAR(data);
380:
381: case 0x3e: // IO_OMCR
382: break;
383: case 0x3f: // IO_ICR
384: return WriteICR(data);
385:
386: case 0x40: // IO_T2FRCL
387: case 0x41: // IO_T2FRCH
388: case 0x42: // IO_T2OCR1L
389: case 0x43: // IO_T2OCR1H
390: case 0x44: // IO_T2OCR2L
391: case 0x45: // IO_T2OCR2H
392: case 0x46: // IO_T2ICRL
393: case 0x47: // IO_T2ICRH
394: case 0x48: // IO_T2CSR1
395: case 0x49: // IO_T2CSR2
396: break;
397:
398: case 0x50: // IO_CCSR
399: break;
400: case 0x51: // IO_RMCR
401: return WriteRMCR(data);
402:
403: case 0x53: // IO_DERA
404: case 0x60: // IO_IODRA
405: case 0x61: // IO_IODRB
406: case 0x62: // IO_IODRC
407: case 0x63: // IO_IODRD
408: case 0x64: // IO_IODRE
409: case 0x65: // IO_IODRF
410: case 0x66: // IO_IDRG
411: case 0x70: // IO_DDRA
412: case 0x71: // IO_DDRB
413: case 0x72: // IO_DDRC
414: case 0x73: // IO_DDRD
415: case 0x74: // IO_DDRE
416: case 0x75: // IO_DDRF
417: break;
418:
419: default:
420: break;
421: }
422:
423: putlog(0, "WriteInternalIO %s <- $%02x (NOT IMPLEMENTED)",
424: IOName(offset).c_str(), data);
425: return 0;
426: }
427:
428: uint32
429: MPU64180Device::WriteExternalIO(uint32 addr, uint32 data)
430: {
431: // LUNA の外部 I/O はアドレスの上位バイト不問
432: switch (addr & 0xff) {
433: case 0x82: // SSG
434: case 0x83: // SSG
435: #if !defined(ENABLE_SSG_LOG)
436: return 0;
437: #endif
438: break;
439:
440: case 0x90: // INT0 ネゲート
441: putlog(1, "%s Negate INT0", IOName(addr).c_str());
442: NegateINT0();
443: return 0;
444:
445: case 0xa0: // レベル5 割り込み要求
446: putlog(1, "%s Interrupt High", IOName(addr).c_str());
447: pio0->InterruptXPHigh();
448: return 0;
449:
450: case 0xb0: // レベル1 割り込み要求
451: putlog(1, "%s Interrupt Low", IOName(addr).c_str());
452: pio0->InterruptXPLow();
453: return 0;
454:
455: default:
456: break;
457: }
458:
459: putlog(0, "WriteExternalIO %s <- $%02x (NOT IMPLEMENTED)",
460: IOName(addr).c_str(), data);
461: return 0;
462: }
463:
464: uint32
465: MPU64180Device::WriteTMDRL(int ch, uint32 data)
466: {
467: auto& t = timer[ch];
468: if (t.running) {
469: // タイマー動作中の更新は inhibited と書いてあるけど、実際どうなる?
470: putlog(0, "Writing %s <- $%02x while timer is running! (ignored)",
471: IOName(HD647180::IO_TMDRL(ch)).c_str(), data);
472: } else {
473: t.count = (t.count & 0xff00) | data;
474: putlog(1, "%s <- $%02x (TMDR%d = $%04x)",
475: IOName(HD647180::IO_TMDRL(ch)).c_str(), data, ch, t.count);
476: }
477: return 0;
478: }
479:
480: uint32
481: MPU64180Device::WriteTMDRH(int ch, uint32 data)
482: {
483: auto& t = timer[ch];
484: if (t.running) {
485: // タイマー動作中の更新は inhibited と書いてあるけど、実際どうなる?
486: putlog(0, "Writing %s <- $%02x while timer is running! (ignored)",
487: IOName(HD647180::IO_TMDRH(ch)).c_str(), data);
488: } else {
489: t.count = (data << 8) | (t.count & 0x00ff);
490: putlog(1, "%s <- $%02x (TMDR%d = $%04x)",
491: IOName(HD647180::IO_TMDRH(ch)).c_str(), data, ch, t.count);
492: }
493: return 0;
494: }
495:
496: uint32
497: MPU64180Device::WriteRLDRL(int ch, uint32 data)
498: {
499: // 動作中にも変更可能
500: auto& t = timer[ch];
501: t.reload = (t.reload & 0xff00) | data;
502: putlog(1, "%s <- $%02x (RLDR%d = $%04x)",
503: IOName(HD647180::IO_RLDRL(ch)).c_str(), data, ch, t.reload);
504: return 0;
505: }
506:
507: uint32
508: MPU64180Device::WriteRLDRH(int ch, uint32 data)
509: {
510: // 動作中にも変更可能
511: auto& t = timer[ch];
512: t.reload = (data << 8) | (t.reload & 0x00ff);
513: putlog(1, "%s <- $%02x (RLDR%d = $%04x)",
514: IOName(HD647180::IO_RLDRH(ch)).c_str(), data, ch, t.reload);
515: return 0;
516: }
517:
518: uint32
519: MPU64180Device::WriteTCR(uint32 data)
520: {
521: std::array<bool, 2> new_tde;
522: std::string msg;
523:
524: timer[1].intr_enable = (data & 0x20);
525: timer[0].intr_enable = (data & 0x10);
526: // intr_enable を変更したので ChangeTimerInterrupt() を呼ぶのは
527: // 最後に行っている。
528:
529: timer_toc = (data >> 2) & 3;
530:
531: new_tde[1] = (data & 0x02);
532: new_tde[0] = (data & 0x01);
533: msg = string_format("TIE1=%d TIE0=%d TOC=$%d",
534: (timer[1].intr_enable ? 1 : 0),
535: (timer[0].intr_enable ? 1 : 0),
536: timer_toc);
537:
538: for (int ch = 0; ch < timer.size(); ch++) {
539: auto& t = timer[ch];
540: if (t.running == false && new_tde[ch] == true) {
541: // カウントダウン開始
542: t.count = t.reload;
543: t.running = true;
544: MakeActiveTimer();
545: msg += string_format(" Timer%d=Start", ch);
546: EnableTimer();
547: } else if (t.running == true && new_tde[ch] == false) {
548: // カウントダウン停止
549:
550: // ここではタイマーの状態を停止にするだけでよい。
551: // タイマーイベントの中で running が落ちてたら停止してくれる。
552: t.running = false;
553: MakeActiveTimer();
554: msg += string_format(" Timer%d=Stop", ch);
555: } else {
556: // 変化なし
557: }
558: }
559:
560: putlog(1, "%s <- $%02x: %s",
561: IOName(HD647180::IO_TCR).c_str(), data, msg.c_str());
562:
563: // ログの順序的に書き込みログの後で変更する
564: ChangeTimerInterrupt();
565:
566: return 0;
567: }
568:
569: uint32
570: MPU64180Device::WriteDCNTL(uint32 data)
571: {
572: // メモリウェイト 0,1,2,3
573: memwait = (data >> 6) & 3;
574:
575: // I/O ウェイトは 0,2,3,4
576: iowait = (data >> 4) & 3;
577: if (iowait != 0)
578: iowait++;
579:
580: // 下位4ビット分は未実装
581: dcntl = data & 0x0f;
582: return 0;
583: }
584:
585: uint32
586: MPU64180Device::WriteIL(uint32 data)
587: {
588: // 書き込み時にマスクする
589: intvec_low = data & 0xe0;
590: return 0;
591: }
592:
593: uint32
594: MPU64180Device::WriteITC(uint32 data)
595: {
596: itc_trap = (data & 0x80);
597: // UFO は ReadOnly
598: itc_ite2 = (data & 0x04);
599: itc_ite1 = (data & 0x02);
600: itc_ite0 = (data & 0x01);
601:
602: // XXX 割り込み変わったら何かする?
603:
604: return 0;
605: }
606:
607: uint32
608: MPU64180Device::WriteRCR(uint32 data)
609: {
610: // 未実装
611: rcr = data | 0x3c;
612:
613: if ((rcr & 0x80)) {
614: // Refresh Enable は未実装。無効にするなら表示不要。
615: putlog(0, "%s <- $%02x: Refresh Enable (NOT IMPLEMENTED)",
616: IOName(HD647180::IO_RCR).c_str(), data);
617: } else {
618: // ログレベル 1 なら全部表示
619: putlog(1, "%s <- $%02x (NOT IMPLEMENTED)",
620: IOName(HD647180::IO_RCR).c_str(), data);
621: }
622: return 0;
623: }
624:
625: uint32
626: MPU64180Device::WriteCBR(uint32 data)
627: {
628: int lv;
629: uint32 new_base = data << 12;
630: if (commbase != new_base) {
631: lv = 1;
632: commbase = new_base;
633: } else {
634: lv = 2;
635: }
636: putlog(lv, "%s <- $%02x: Common Base Addr=$%05x",
637: IOName(HD647180::IO_CBR).c_str(), data, commbase);
638: return 0;
639: }
640:
641: uint32
642: MPU64180Device::WriteBBR(uint32 data)
643: {
644: int lv;
645: uint32 new_base = data << 12;
646: if (bankbase != new_base) {
647: lv = 1;
648: bankbase = new_base;
649: } else {
650: lv = 2;
651: }
652: putlog(lv, "%s <- $%02x: Bank Base Addr=$%05x",
653: IOName(HD647180::IO_BBR).c_str(), data, bankbase);
654: return 0;
655: }
656:
657: uint32
658: MPU64180Device::WriteCBAR(uint32 data)
659: {
660: int lv;
661: uint32 new_comm = (data & 0xf0) << 8;
662: uint32 new_bank = (data & 0x0f) << 12;
663: if (commarea != new_comm || bankarea != new_bank) {
664: lv = 1;
665: commarea = new_comm;
666: bankarea = new_bank;
667: } else {
668: lv = 2;
669: }
670: putlog(lv, "%s <- $%02x: CommArea=$%04x BankArea=$%04x",
671: IOName(HD647180::IO_CBAR).c_str(), data, commarea, bankarea);
672: return 0;
673: }
674:
675: uint32
676: MPU64180Device::WriteICR(uint32 data)
677: {
678: io_address = data & 0x80;
679: putlog(1, "%s <- $%02x: I/O Address=$%02x",
680: IOName(HD647180::IO_ICR).c_str(), data, io_address);
681:
682: // IOSTP は未実装
683: if ((data & 0x20) != 0) {
684: putlog(0, "%s IOSTP (NOT IMPLEMENTED)");
685: }
686: return 0;
687: }
688:
689: uint32
690: MPU64180Device::WriteRMCR(uint32 data)
691: {
692: xpbus->SetRMCR(data);
693: putlog(1, "%s <- $%02x: RAM address=$%05x",
694: IOName(HD647180::IO_RMCR).c_str(), data, xpbus->GetXPRAMAddr());
695: return 0;
696: }
697:
698: uint32
699: MPU64180Device::PeekIO(uint32 addr)
700: {
701: // 内蔵 I/O
702: if (io_address <= addr && addr < io_address + 0x80) {
703: return PeekInternalIO(addr - io_address);
704: }
705:
706: return PeekExternalIO(addr);
707: }
708:
709: uint32
710: MPU64180Device::PeekInternalIO(uint32 offset)
711: {
712: switch (offset) {
713: case 0x00: // IO_CNTLA0
714: case 0x01: // IO_CNTLA1
715: case 0x02: // IO_CNTLB0
716: case 0x03: // IO_CNTLB1
717: case 0x04: // IO_STAT0
718: case 0x05: // IO_STAT1
719: case 0x06: // IO_TDR0
720: case 0x07: // IO_TDR1
721: case 0x08: // IO_TSR0
722: case 0x09: // IO_TSR1
723: case 0x0a: // IO_CNTR
724: case 0x0b: // IO_TRDR
725: break;
726:
727: case 0x0c: // IO_TMDR0L
728: return PeekTMDRL(0);
729: case 0x0d: // IO_TMDR0H
730: return PeekTMDRH(0);
731: case 0x0e: // IO_RLDR0L
732: return PeekRLDRL(0);
733: case 0x0f: // IO_RLDR0H
734: return PeekRLDRH(0);
735: case 0x10: // IO_TCR
736: return PeekTCR();
737: case 0x14: // IO_TMDR1L
738: return PeekTMDRL(1);
739: case 0x15: // IO_TMDR1H
740: return PeekTMDRH(1);
741: case 0x16: // IO_RLDR1L
742: return PeekRLDRL(1);
743: case 0x17: // IO_RLDR1H
744: return PeekRLDRH(1);
745: case 0x18: // IO_FRC
746: return PeekFRC();
747:
748: case 0x20: // IO_SAR0L
749: case 0x21: // IO_SAR0H
750: case 0x22: // IO_SAR0B
751: case 0x23: // IO_DAR0L
752: case 0x24: // IO_DAR0H
753: case 0x25: // IO_DAR0B
754: case 0x26: // IO_BCR0L
755: case 0x27: // IO_BCR0H
756: case 0x28: // IO_MAR1L
757: case 0x29: // IO_MAR1H
758: case 0x2a: // IO_MAR1B
759: case 0x2b: // IO_IAR1L
760: case 0x2c: // IO_IAR1H
761: case 0x2e: // IO_BCR1L
762: case 0x2f: // IO_BCR1H
763: case 0x30: // IO_DSTAT
764: case 0x31: // IO_DMODE
765: break;
766: case 0x32: // IO_DCNTL
767: return PeekDCNTL();
768:
769: case 0x33: // IO_IL
770: return PeekIL();
771: case 0x34: // IO_ITC
772: return PeekITC();
773: case 0x36: // IO_RCR
774: return PeekRCR();
775:
776: case 0x38: // IO_CBR
777: return PeekCBR();
778: case 0x39: // IO_BBR
779: return PeekBBR();
780: case 0x3a: // IO_CBAR
781: return PeekCBAR();
782:
783: case 0x3e: // IO_OMCR
784: break;
785: case 0x3f: // IO_ICR
786: return PeekICR();
787:
788: case 0x40: // IO_T2FRCL
789: case 0x41: // IO_T2FRCH
790: case 0x42: // IO_T2OCR1L
791: case 0x43: // IO_T2OCR1H
792: case 0x44: // IO_T2OCR2L
793: case 0x45: // IO_T2OCR2H
794: case 0x46: // IO_T2ICRL
795: case 0x47: // IO_T2ICRH
796: case 0x48: // IO_T2CSR1
797: case 0x49: // IO_T2CSR2
798: break;
799:
800: case 0x50: // IO_CCSR
801: break;
802: case 0x51: // IO_RMCR
803: return xpbus->GetRMCR();
804:
805: case 0x53: // IO_DERA
806: case 0x60: // IO_IODRA
807: case 0x61: // IO_IODRB
808: case 0x62: // IO_IODRC
809: case 0x63: // IO_IODRD
810: case 0x64: // IO_IODRE
811: case 0x65: // IO_IODRF
812: case 0x66: // IO_IDRG
813: case 0x70: // IO_DDRA
814: case 0x71: // IO_DDRB
815: case 0x72: // IO_DDRC
816: case 0x73: // IO_DDRD
817: case 0x74: // IO_DDRE
818: case 0x75: // IO_DDRF
819: break;
820:
821: default:
822: break;
823: }
824: return 0xff;
825: }
826:
827: uint32
828: MPU64180Device::PeekExternalIO(uint32 addr)
829: {
830: // LUNA の外部 I/O はアドレスの上位バイト不問
831: switch (addr & 0xff) {
832: case 0x82: // SSG
833: case 0x83: // SSG
834: break;
835:
836: case 0x90: // INT0 ネゲート
837: break;
838:
839: case 0xa0: // レベル5 割り込み要求
840: case 0xb0: // レベル1 割り込み要求
841: break;
842:
843: default:
844: break;
845: }
846: return 0xff;
847: }
848:
849: uint32
850: MPU64180Device::PeekTMDRL(int ch) const
851: {
852: return timer[ch].count & 0xff;
853: }
854:
855: uint32
856: MPU64180Device::PeekTMDRH(int ch) const
857: {
858: return timer[ch].count >> 8;
859: }
860:
861: uint32
862: MPU64180Device::PeekRLDRL(int ch) const
863: {
864: return timer[ch].reload & 0xff;
865: }
866:
867: uint32
868: MPU64180Device::PeekRLDRH(int ch) const
869: {
870: return timer[ch].reload >> 8;
871: }
872:
873: uint32
874: MPU64180Device::PeekTCR() const
875: {
876: uint32 data = (timer_toc << 2);
877:
878: if (timer[1].tif != 0)
879: data |= 0x80;
880: if (timer[0].tif != 0)
881: data |= 0x40;
882: if (timer[1].intr_enable)
883: data |= 0x20;
884: if (timer[0].intr_enable)
885: data |= 0x10;
886: if (timer[1].running)
887: data |= 0x02;
888: if (timer[0].running)
889: data |= 0x01;
890:
891: return data;
892: }
893:
894: uint32
895: MPU64180Device::PeekFRC() const
896: {
897: if (opmode == OpMode::Reset) {
898: return 0xff;
899: } else {
900: // Free Running Counter はリセット時に 0FFH で、
901: // そこから 10φ ごとに1ずつ減っていく。
902: // そのため、リセット時の時刻を覚えておき、経過時間から計算する。
903: uint64 time = scheduler->GetVirtTime() - timer_epoch;
904: return 0xff - (uint8)(time / (clock_nsec * 10));
905: }
906: }
907:
908: uint32
909: MPU64180Device::PeekDCNTL() const
910: {
911: uint32 data;
912:
913: data = (memwait << 6);
914: if (iowait != 0) {
915: data |= (iowait - 1) << 4;
916: }
917: data |= dcntl;
918:
919: return data;
920: }
921:
922: uint32
923: MPU64180Device::PeekIL() const
924: {
925: return intvec_low;
926: }
927:
928: uint32
929: MPU64180Device::PeekITC() const
930: {
931: uint32 data = 0x38;
932: if (itc_trap)
933: data |= 0x80;
934: if (itc_ufo)
935: data |= 0x40;
936: if (itc_ite2)
937: data |= 0x04;
938: if (itc_ite1)
939: data |= 0x02;
940: if (itc_ite0)
941: data |= 0x01;
942: return data;
943: }
944:
945: uint32
946: MPU64180Device::PeekRCR() const
947: {
948: return rcr;
949: }
950:
951: uint32
952: MPU64180Device::PeekCBR() const
953: {
954: return (commbase >> 12) & 0xff;
955: }
956:
957: uint32
958: MPU64180Device::PeekBBR() const
959: {
960: return (bankbase >> 12) & 0xff;
961: }
962:
963: uint32
964: MPU64180Device::PeekCBAR() const
965: {
966: uint32 data;
967:
968: data = (commarea >> 8) & 0xf0;
969: data |= (bankarea >> 12) & 0x0f;
970:
971: return data;
972: }
973:
974: uint32
975: MPU64180Device::PeekICR() const
976: {
977: // IOSTP は未実装
978: return io_address | 0x5f;
979: }
980:
981: uint32
982: MPU64180Device::PeekRMCR() const
983: {
984: return xpbus->GetRMCR();
985: }
986:
987: // アドレス (とあれば名前) を返す。
988: /*static*/ std::string
989: MPU64180Device::IOName(uint32 addr)
990: {
991: std::string buf;
992:
993: if (addr < 0x100) {
994: buf = string_format("%02XH", addr);
995: } else {
996: buf = string_format("%04XH", addr);
997: }
998:
999: if (addr < ionames.size() && ionames[addr] != NULL) {
1000: buf += '(';
1001: buf += ionames[addr];
1002: buf += ')';
1003: }
1004: return buf;
1005: }
1006:
1007: /*static*/ std::vector<const char *>
1008: MPU64180Device::ionames = {
1009: "CNTLA0", // 00
1010: "CNTLA1", // 01
1011: "CNTLB0", // 02
1012: "CNTLB1", // 03
1013: "STAT0", // 04
1014: "STAT1", // 05
1015: "TDR0", // 06
1016: "TDR1", // 07
1017: "TSR0", // 08
1018: "TSR1", // 09
1019: "CNTR", // 0a
1020: "TRDR", // 0b
1021: "TMDR0L", // 0c
1022: "TMDR0H", // 0d
1023: "RLDR0L", // 0e
1024: "RLDR0H", // 0f
1025:
1026: "TCR", // 10
1027: NULL, // 11
1028: NULL, // 12
1029: NULL, // 13
1030: "TMDR1L", // 14
1031: "TMDR1H", // 15
1032: "RLDR1L", // 16
1033: "RLDR1H", // 17
1034: "FRFC", // 18
1035: NULL, // 19
1036: NULL, // 1a
1037: NULL, // 1b
1038: NULL, // 1c
1039: NULL, // 1d
1040: NULL, // 1e
1041: NULL, // 1f
1042:
1043: "SAR0L", // 20
1044: "SAR0H", // 21
1045: "SAR0B", // 22
1046: "DAR0L", // 23
1047: "DAR0H", // 24
1048: "DAR0B", // 25
1049: "BCR0L", // 26
1050: "BCR0H", // 27
1051: "MAR1L", // 28
1052: "MAR1H", // 29
1053: "MAR1B", // 2a
1054: "IAR1L", // 2b
1055: "IAR1H", // 2c
1056: NULL, // 2d
1057: "BCR1L", // 2e
1058: "BCR1H", // 2f
1059:
1060: "DSTAT", // 30
1061: "DMODE", // 31
1062: "DCNTL", // 32
1063: "IL", // 33
1064: "ITC", // 34
1065: NULL, // 35
1066: "RCR", // 36
1067: NULL, // 37
1068: "CBR", // 38
1069: "BBR", // 39
1070: "CBAR", // 3a
1071: NULL, // 3b
1072: NULL, // 3c
1073: NULL, // 3d
1074: "OMCR", // 3e
1075: "ICR", // 3f
1076:
1077: "T2FRCL", // 40
1078: "T2FRCH", // 41
1079: "T2OCR1L", // 42
1080: "T2OCR1H", // 43
1081: "T2OCR2L", // 44
1082: "T2OCR2H", // 45
1083: "T2ICRL", // 46
1084: "T2ICRH", // 47
1085: "T2CSR1", // 48
1086: "T2CSR2", // 49
1087: NULL, // 4a
1088: NULL, // 4b
1089: NULL, // 4c
1090: NULL, // 4d
1091: NULL, // 4e
1092: NULL, // 4f
1093:
1094: "CCSR", // 50
1095: "RMCR", // 51
1096: NULL, // 52
1097: "DERA", // 53
1098: NULL, // 54
1099: NULL, // 55
1100: NULL, // 56
1101: NULL, // 57
1102: NULL, // 58
1103: NULL, // 59
1104: NULL, // 5a
1105: NULL, // 5b
1106: NULL, // 5c
1107: NULL, // 5d
1108: NULL, // 5e
1109: NULL, // 5f
1110:
1111: "IODRA", // 60
1112: "IODRB", // 61
1113: "IODRC", // 62
1114: "IODRD", // 63
1115: "IODRE", // 64
1116: "IODRF", // 65
1117: "IDRG", // 66
1118: NULL, // 67
1119: NULL, // 68
1120: NULL, // 69
1121: NULL, // 6a
1122: NULL, // 6b
1123: NULL, // 6c
1124: NULL, // 6d
1125: NULL, // 6e
1126: NULL, // 6f
1127:
1128: "DDRA", // 70
1129: "DDRB", // 71
1130: "DDRC", // 72
1131: "DDRD", // 73
1132: "DDRE", // 74
1133: "DDRF", // 75
1134: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.