|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2023 nono project
4: // Licensed under nono-license.txt
5: //
6:
7: // キャッシュ
8:
9: #include "mpu680x0.h"
10: #include "m68030cache.h"
11:
12: // 命令キャッシュから指定のアドレスをワードフェッチ。
13: // ここでは PC を進めたりはしない。
14: // バスエラーが起きると例外 M68K::EXCEP_BUSERR をスローする。
15: uint32
16: MPU680x0Device::fetch_16_cache(uint32 addr)
17: {
18: putlog(2, "%s addr=%08x", __func__, addr);
19: // addr を含むロングワードを読み込んでから、上位か下位だけ返す。
20: uint32 data = fetch_32_cache_aligned(addr & ~3);
21: if ((addr & 2) == 0) {
22: return data >> 16;
23: } else {
24: return data & 0xffff;
25: }
26: }
27:
28: // 命令キャッシュから指定のアドレス (ミスアライン可) をロングワードフェッチ。
29: // ここでは PC を進めたりはしない。
30: // バスエラーが起きると例外 M68K::EXCEP_BUSERR をスローする。
31: uint32
32: MPU680x0Device::fetch_32_cache(uint32 addr)
33: {
34: putlog(2, "%s addr=%08x", __func__, addr);
35: if ((addr & 2) == 0) {
36: return fetch_32_cache_aligned(addr);
37: } else {
38: uint32 data;
39: data = fetch_16_cache(addr) << 16;
40: data |= fetch_16_cache(addr + 2);
41: return data;
42: }
43: }
44:
45: // 命令キャッシュから指定のアドレスをロングワードフェッチ。
46: // addr の下位2ビットは無視される。
47: // ここでは PC を進めたりはしない。
48: uint32
49: MPU680x0Device::fetch_32_cache_aligned(uint32 addr)
50: {
51: putlog(2, "%s addr=%08x", __func__, addr);
52: uint32 tag = (addr & 0xffffff00) | (IsSuper() ? 1 : 0);
53: uint32 idx = (addr & 0x000000f0) >> 4;
54:
55: auto& l = icache->line[idx];
56: if (l.tag != tag) {
57: // タグが一致しなければ、1ライン充填。
58: // XXX 可能ならバースト転送?
59: putlog(2, "%s line[%d] invalidate", __func__, idx);
60:
61: l.tag = tag;
62: l.valid_all = 0;
63: // XXX 未実装
64: // FALLTHROUGH
65: }
66:
67: // タグが一致した
68: uint32 sel = (addr & 0x0000000c) >> 2;
69: if (l.valid[sel] == 0) {
70: // シングル充填。
71: uint32 data = fetch_32_bus((addr & 0xfffffff0) + (sel << 2));
72: if (__predict_true(bus.ci == false)) {
73: l.data[sel] = data;
74: l.valid[sel] = 1;
75: putlog(2, "%s line[%d][%d] <- %08x", __func__, idx, sel, data);
76: } else {
77: putlog(2, "%s line[%d][%d] = %08x (CI)", __func__, idx, sel, data);
78: }
79: return data;
80: }
81:
82: // エントリが有効
83: putlog(2, "%s line[%d][%d] -> %08x", __func__, idx, sel, l.data[sel]);
84: return l.data[sel];
85: }
86:
87: #if 0
88: uint32
89: MPU680x0Device::read_8_cache(busaddr addr)
90: {
91: printf("%s not implemented\n", __func__);
92: return -1;
93: }
94:
95: uint32
96: MPU680x0Device::read_16_cache(busaddr addr)
97: {
98: printf("%s not implemented\n", __func__);
99: return -1;
100: }
101:
102: uint32
103: MPU680x0Device::read_32_cache(busaddr addr)
104: {
105: printf("%s not implemented\n", __func__);
106: return -1;
107: }
108:
109: void
110: MPU680x0Device::write_8_cache(busaddr addr, uint32 data)
111: {
112: printf("%s not implemented\n", __func__);
113: }
114:
115: void
116: MPU680x0Device::write_16_cache(busaddr addr, uint32 data)
117: {
118: printf("%s not implemented\n", __func__);
119: }
120:
121: void
122: MPU680x0Device::write_32_cache(busaddr addr, uint32 data)
123: {
124: printf("%s not implemented\n", __func__);
125: }
126: #endif
127:
128: // CACR レジスタ書き込み
129: void
130: MPU680x0Device::SetCACR(uint32 newval)
131: {
132: newval &= M68K::CACR_MASK;
133: uint32 oldval = reg.cacr;
134: uint32 chgval = oldval ^ newval;
135:
136: // EI
137: if ((chgval & M68K::CACR_EI) != 0) {
138: if ((newval & M68K::CACR_EI) != 0) {
139: // 命令キャッシュ有効
140: icache_enable = true;
141: putlog(1, "I-Cache enabled");
142: } else {
143: // 命令キャッシュ無効
144: icache_enable = false;
145: putlog(1, "I-Cache disabled");
146: }
147: }
148:
149: // FI
150: if ((chgval & M68K::CACR_FI) != 0) {
151: icache_freeze = (newval & M68K::CACR_FI);
152: }
153:
154: // CEI
155: if ((chgval & M68K::CACR_CEI) != 0) {
156: // CAAR の b7-2 で示されるロングワードを無効にする。
157: uint32 idx = (reg.cacr & 0x000000f0) >> 4;
158: uint32 num = (reg.cacr & 0x0000000c) >> 2;
159: auto& l = icache->line[idx];
160: l.valid[num] = 0;
161:
162: newval &= ~M68K::CACR_CEI;
163: }
164:
165: // CI
166: if ((chgval & M68K::CACR_CI) != 0) {
167: // 命令キャッシュの全エントリをクリア。
168: for (auto& l : icache->line) {
169: l.valid_all = 0;
170: }
171:
172: newval &= ~M68K::CACR_CI;
173: }
174:
175: // データキャッシュは未実装。
176: newval &= ~(M68K::CACR_CD | M68K::CACR_CED);
177:
178: // とりあえずレジスタイメージも保存。
179: reg.cacr = newval;
180: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.