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