|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2024 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: #include "mpu680x0.h"
8: #include "m68040mmu.h"
9:
10: uint32
11: MPU68040Device::fetch_2()
12: {
13: busaddr addr = busaddr(reg.pc) | fc_inst | BusAddr::Size2;
14: busdata bd = read_data(addr);
15: reg.pc += 2;
16: return bd.Data();
17: }
18:
19: uint32
20: MPU68040Device::fetch_4()
21: {
22: busaddr addr = busaddr(reg.pc) | fc_inst | BusAddr::Size4;
23: busdata bd = read_data(addr);
24: reg.pc += 4;
25: return bd.Data();
26: }
27:
28: // read_1,2,4() の共通部分。ミスアライン可。
29: // バスエラーが起きると例外 M68K::EXCEP_BUSERR をスローする。
30: uint32
31: MPU68040Device::read_data(busaddr addr)
32: {
33: busdata data = read_nocache(addr);
34: if (__predict_false(data.IsBusErr())) {
35: bus.laddr = addr;
36: throw M68K::EXCEP_BUSERR;
37: }
38: return data.Data();
39: }
40:
41: // キャッシュ無効時の読み込み。ミスアライン可。
42: // バスエラーも busdata を返す。
43: busdata
44: MPU68040Device::read_nocache(busaddr addr)
45: {
46: // デバイスは、addr の下位ビットによらず、自身のデバイスのポートサイズ分
47: // のデータと、その応答サイズ(自分のポートサイズ) を Size フィールドに
48: // セットして返してくる。
49: //
50: // MPU(68040) は、A1-A0、残りバイト数、デバイスの応答サイズの情報から
51: // 受け取ったデータバスのうち適切なところを切り出して使う。
52:
53: bool span_page = false;
54: uint32 data = 0;
55: for (;;) {
56: bus.laddr = addr;
1.1.1.2 ! root 57: busaddr paddr = TranslateRead(addr);
! 58: if (__predict_false(paddr.IsBusErr())) {
1.1 root 59: bus.atcfault = true;
60: // ATC フォールトが2ページ目で起きたか。
61: bus.atcfault2 = span_page;
62: return BusData::BusErr;
63: }
1.1.1.2 ! root 64: bus.ci = paddr.IsCInhibit();
! 65: busdata bd = read_phys(paddr);
1.1 root 66: if (__predict_false(bd.IsBusErr())) {
67: return bd;
68: }
69:
70: uint32 reqsize = addr.GetSize();
71: // デバイスのポートサイズ(応答サイズ)
72: uint32 portsize = bd.GetSize();
73: // 今回のアドレスオフセット
74: uint32 offset = addr.Addr() & (portsize - 1);
75: uint32 datasize = portsize - offset;
76: uint32 tmp = bd.Data();
77: // 下詰めされたデータに対するマスク
78: uint32 mask = 0xffffffffU >> ((4 - datasize) * 8);
79: // 今回必要なところ
80: tmp &= mask;
81: if (datasize == reqsize) {
82: data |= tmp;
83: break;
84: } else if (datasize > reqsize) {
85: tmp >>= (datasize - reqsize) * 8;
86: data |= tmp;
87: break;
88: } else {
89: tmp <<= (reqsize - datasize) * 8;
90: data |= tmp;
91: }
92:
93: uint32 oldaddr = addr.Addr();
94: addr += datasize;
95: reqsize -= datasize;
96: addr.ChangeSize(reqsize);
97:
98: if (__predict_false(((addr.Addr() ^ oldaddr) & ~mmu_tc->page_mask))) {
99: span_page = true;
100: }
101: }
102: return data;
103: }
104:
105: // write_1,2,4() の共通部分。ミスアライン可。
106: // バスエラーが起きると例外 M68K::EXCEP_BUSERR をスローする。
107: void
108: MPU68040Device::write_data(busaddr addr, uint32 data)
109: {
110: busaddr origaddr = addr;
111: uint32 origdata = data;
112:
113: bool span_page = false;
114: for (;;) {
115: bus.laddr = addr;
1.1.1.2 ! root 116: busaddr paddr = TranslateWrite(addr);
! 117: if (__predict_false(paddr.IsBusErr())) {
1.1 root 118: bus.atcfault = true;
119: // ATC フォールトが2ページ目で起きたか。
120: bus.atcfault2 = span_page;
121: break;
122: }
1.1.1.2 ! root 123: bus.ci = paddr.IsCInhibit();
! 124: busdata bd = write_phys(paddr, data);
1.1 root 125: if (__predict_false(bd.IsBusErr())) {
126: break;
127: }
128: uint32 reqsize = addr.GetSize();
129: uint32 portsize = bd.GetSize();
130: uint32 offset = addr.Addr() & (portsize - 1);
131: uint32 datasize = portsize - offset;
132: if (datasize >= reqsize) {
133: // ここが成功して終了。
134: return;
135: }
136:
137: addr += datasize;
138: reqsize -= datasize;
139: addr.ChangeSize(reqsize);
140: data &= (1U << (reqsize * 8)) - 1;
141:
142: if (((addr.Addr() ^ origaddr.Addr()) & ~mmu_tc->page_mask) != 0) {
143: span_page = true;
144: }
145: }
146:
147: // 報告するのは先頭のアドレス。
1.1.1.2 ! root 148: bus.laddr = origaddr;
1.1 root 149: bus.data = origdata;
150: throw M68K::EXCEP_BUSERR;
151: }
152:
153: // CACR レジスタ書き込み。
154: void
155: MPU68040Device::SetCACR(uint32 data)
156: {
157: // とりあえず
158: reg.cacr = data & M68040::CACR_MASK;
159: }
160:
161: // リセット例外の CPU 固有部分。
162: void
163: MPU68040Device::ResetCache()
164: {
165: SetCACR(0);
166: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.