|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2017 [email protected]
4: //
5: // 論理アクセス
6: //
7:
8: //
9: // 1回の(アラインド)物理アクセスを担当するマクロ。
10: // これらは続く _mmu テンプレートで使用する。
11: // goto を含むことに注意。gcc 拡張式(?)に注意。
1.1.1.2 ! root 12: // mmu_translate_* は fetch, read, write の3種だが、vm_phys_ は
1.1 root 13: // read, write しかないことに注意。物理バスに FC0 と FC1、つまりプログラム
14: // 空間かどうかの情報は出していないため。
15: //
16:
17: #define FETCH(size) ({ \
18: cpu->bus.paddr = cpu->bus.laddr; \
19: if (use_mmu && m68030_mmu_translate_fetch(cpu) == false) \
20: goto buserr; \
1.1.1.2 ! root 21: uint64 data_ = vm_phys_read_##size(cpu->bus.paddr); \
1.1 root 22: if ((int64)data_ < 0) \
23: goto buserr; \
24: data_; /* これが戻り値 */ \
25: })
26:
27: #define READ(size) ({ \
28: cpu->bus.paddr = cpu->bus.laddr; \
29: if (use_mmu && m68030_mmu_translate_read(cpu) == false) \
30: goto buserr; \
1.1.1.2 ! root 31: uint64 data_ = vm_phys_read_##size(cpu->bus.paddr); \
1.1 root 32: if ((int64)data_ < 0) \
33: goto buserr; \
34: data_; /* これが戻り値 */ \
35: })
36:
37: #define WRITE(size, data) ({ \
38: cpu->bus.paddr = cpu->bus.laddr; \
39: if (use_mmu && m68030_mmu_translate_write(cpu) == false) \
40: goto buserr; \
1.1.1.2 ! root 41: int64 berr_ = vm_phys_write_##size(cpu->bus.paddr, (data)); \
1.1 root 42: if (berr_ < 0) \
43: goto buserr; \
44: 0; /* 戻り値不要だけど一応 */ \
45: })
46:
47: // バスエラー時に SSW をセットする。
48: // m68030_*_NN_mmu() 関数の下請け。
49: static inline void
50: SET_SSW(m68kcpu *cpu, bool use_mmu, uint size)
51: {
52: // サイズを設定
53: cpu->bus.ssw &= ~SSW_SIZE_MASK;
54: cpu->bus.ssw |= size;
55:
56: if (use_mmu) {
57: // データアクセスなら再試行のため DataFault ビットをセット。
58: // 命令アクセスなら RB をセット。
59: if ((cpu->bus.ssw & FC_DATA)) {
60: cpu->bus.ssw |= SSW_DF;
61: } else {
62: cpu->bus.ssw |= SSW_RB;
63: }
64: }
65: }
66:
67: //
68: // MMU を考慮した下請けテンプレート。
69: // 1回分のミスアラインドありのアクセスを担当。
70: //
71:
72: template<bool use_mmu> uint32
73: m68030_fetch_16_mmu(m68kcpu *cpu)
74: {
75: uint64 data;
76:
77: data = FETCH(16);
78: // XXX バスエラー時に PC をインクリメントするタイミングは?
79: RegPC += 2;
80:
81: return data;
82:
83: buserr:
84: SET_SSW(cpu, use_mmu, SSW_SIZE_WORD);
85: throw M68K_EXCEP_BUSERR;
86: }
87:
88: template<bool use_mmu> uint32
89: m68030_fetch_32_mmu(m68kcpu *cpu)
90: {
91: uint64 data;
92:
93: if ((cpu->bus.laddr & 3) == 0) {
94: data = FETCH(32);
95: } else {
96: uint64 h, l;
97:
98: h = FETCH(16);
99: cpu->bus.laddr += 2;
100:
101: l = FETCH(16);
102: data = (h << 16) | l;
103: }
104: // XXX バスエラー時に PC をインクリメントするタイミングは?
105: RegPC += 4;
106: return data;
107:
108: buserr:
109: SET_SSW(cpu, use_mmu, SSW_SIZE_LONG);
110: throw M68K_EXCEP_BUSERR;
111: }
112:
113: template<bool use_mmu> uint32
114: m68030_read_8_mmu(m68kcpu *cpu)
115: {
116: uint64 data;
117:
118: data = READ(8);
119:
120: if (1)
121: cpulog(2, "m68030_read_8 %08X -> %02X", cpu->bus.laddr, (uint32)data);
122: return data;
123:
124: buserr:
125: SET_SSW(cpu, use_mmu, SSW_SIZE_BYTE);
126: throw M68K_EXCEP_BUSERR;
127: }
128:
129: template<bool use_mmu> uint32
130: m68030_read_16_mmu(m68kcpu *cpu)
131: {
132: uint64 data;
133:
134: if ((cpu->bus.laddr & 1) == 0) {
135: data = READ(16);
136: } else {
137: uint64 h, l;
138:
139: h = READ(8);
140: cpu->bus.laddr += 1;
141:
142: l = READ(8);
143: data = (h << 8) | l;
144: }
145:
146: if (1)
147: cpulog(2, "m68030_read_16 %08X -> %04X", cpu->bus.laddr, (uint32)data);
148: return data;
149:
150: buserr:
151: SET_SSW(cpu, use_mmu, SSW_SIZE_WORD);
152: throw M68K_EXCEP_BUSERR;
153: }
154:
155: template<bool use_mmu> uint32
156: m68030_read_32_mmu(m68kcpu *cpu)
157: {
158: uint64 data;
159:
160: if ((cpu->bus.laddr & 3) == 0) {
161: data = READ(32);
162: } else if ((cpu->bus.laddr & 1) == 0) {
163: uint64 h, l;
164:
165: h = READ(16);
166: cpu->bus.laddr += 2;
167:
168: l = READ(16);
169: data = (h << 16) | l;
170: } else {
171: uint64 h, m, l;
172:
173: h = READ(8);
174: cpu->bus.laddr += 1;
175:
176: m = READ(16);
177: cpu->bus.laddr += 2;
178:
179: l = READ(8);
180: data = (h << 24) | (m << 8) | l;
181: }
182:
183: if (1)
184: cpulog(2, "m68030_read_32 %08X -> %08X", cpu->bus.laddr, (uint32)data);
185: return data;
186:
187: buserr:
188: SET_SSW(cpu, use_mmu, SSW_SIZE_LONG);
189: throw M68K_EXCEP_BUSERR;
190: }
191:
192: template<bool use_mmu> void
193: m68030_write_8_mmu(m68kcpu *cpu)
194: {
195: uint32 data = cpu->bus.data;
196:
197: if (1)
198: cpulog(2, "m68030_write_8 %08X <- %02X", cpu->bus.laddr, data);
199:
200: WRITE(8, data);
201: return;
202:
203: buserr:
204: SET_SSW(cpu, use_mmu, SSW_SIZE_BYTE);
205: throw M68K_EXCEP_BUSERR;
206: }
207:
208: template<bool use_mmu> void
209: m68030_write_16_mmu(m68kcpu *cpu)
210: {
211: uint32 data = cpu->bus.data;
212:
213: if (1)
214: cpulog(2, "m68030_write_16 %08X <- %04X", cpu->bus.laddr, data);
215:
216: if ((cpu->bus.laddr & 1) == 0) {
217: WRITE(16, data);
218: } else {
219: WRITE(8, data >> 8);
220:
221: cpu->bus.laddr += 1;
222: WRITE(8, data & 0xff);
223: }
224: return;
225:
226: buserr:
227: SET_SSW(cpu, use_mmu, SSW_SIZE_WORD);
228: throw M68K_EXCEP_BUSERR;
229: }
230:
231: template<bool use_mmu> void
232: m68030_write_32_mmu(m68kcpu *cpu)
233: {
234: uint32 data = cpu->bus.data;
235:
236: if (1)
237: cpulog(2, "m68030_write_32 %08X <- %08X", cpu->bus.laddr, data);
238:
239: if ((cpu->bus.laddr & 3) == 0) {
240: WRITE(32, data);
241: } else if ((cpu->bus.laddr & 1) == 0) {
242: WRITE(16, data >> 16);
243:
244: cpu->bus.laddr += 2;
245: WRITE(16, data & 0xffff);
246: } else {
247: WRITE(8, data >> 24);
248:
249: cpu->bus.laddr += 1;
250: WRITE(16, (data >> 8) & 0xffff);
251:
252: cpu->bus.laddr += 2;
253: WRITE(8, data & 0xff);
254: }
255: return;
256:
257: buserr:
258: SET_SSW(cpu, use_mmu, SSW_SIZE_LONG);
259: throw M68K_EXCEP_BUSERR;
260: }
261:
262: // m68030_{fetch,read,write}_NN() と m68030_{read,write}_NN_fc() の共通部分。
263: // fetch には FC 指定版はないので分ける必要は本来ないけど対称性のため。
264: // cpu->bus に必要な情報はセットされている。
265: // _bus 接尾辞はバスアクセスというより bus 構造体を使ったアクセスという感じ。
266:
267: static inline uint32
268: m68030_fetch_16_bus(m68kcpu *cpu)
269: {
270: if (cpu->mmu_enable) {
271: return m68030_fetch_16_mmu<true>(cpu);
272: } else {
273: return m68030_fetch_16_mmu<false>(cpu);
274: }
275: }
276:
277: static inline uint32
278: m68030_fetch_32_bus(m68kcpu *cpu)
279: {
280: if (cpu->mmu_enable) {
281: return m68030_fetch_32_mmu<true>(cpu);
282: } else {
283: return m68030_fetch_32_mmu<false>(cpu);
284: }
285: }
286:
287: static uint32
288: m68030_read_8_bus(m68kcpu *cpu)
289: {
290: if(1)cpulog(2, "%s $%08x", __func__, cpu->bus.laddr);
291: if (cpu->mmu_enable) {
292: return m68030_read_8_mmu<true>(cpu);
293: } else {
294: return m68030_read_8_mmu<false>(cpu);
295: }
296: }
297:
298: static uint32
299: m68030_read_16_bus(m68kcpu *cpu)
300: {
301: if(1)cpulog(2, "%s $%08x", __func__, cpu->bus.laddr);
302: if (cpu->mmu_enable) {
303: return m68030_read_16_mmu<true>(cpu);
304: } else {
305: return m68030_read_16_mmu<false>(cpu);
306: }
307: }
308:
309: static uint32
310: m68030_read_32_bus(m68kcpu *cpu)
311: {
312: if(1)cpulog(2, "%s $%08x", __func__, cpu->bus.laddr);
313: if (cpu->mmu_enable) {
314: return m68030_read_32_mmu<true>(cpu);
315: } else {
316: return m68030_read_32_mmu<false>(cpu);
317: }
318: }
319:
320: static void
321: m68030_write_8_bus(m68kcpu *cpu)
322: {
323: if(1)cpulog(2, "%s $%08x", __func__, cpu->bus.laddr);
324: if (cpu->mmu_enable) {
325: m68030_write_8_mmu<true>(cpu);
326: } else {
327: m68030_write_8_mmu<false>(cpu);
328: }
329: }
330:
331: static void
332: m68030_write_16_bus(m68kcpu *cpu)
333: {
334: if(1)cpulog(2, "%s $%08x", __func__, cpu->bus.laddr);
335: if (cpu->mmu_enable) {
336: m68030_write_16_mmu<true>(cpu);
337: } else {
338: m68030_write_16_mmu<false>(cpu);
339: }
340: }
341:
342: static void
343: m68030_write_32_bus(m68kcpu *cpu)
344: {
345: if(1)cpulog(2, "%s $%08x", __func__, cpu->bus.laddr);
346: if (cpu->mmu_enable) {
347: m68030_write_32_mmu<true>(cpu);
348: } else {
349: m68030_write_32_mmu<false>(cpu);
350: }
351: }
352:
353: //
354: // CPU 内部からのメモリアクセスは常にこの8つ (またはこれを呼び出すヘルパー
355: // 関数) を呼ぶこと。
356: // uint32 m68030_fetch_{16,32}(cpu)
357: // uint32 m68030_read_{8,16,32}(cpu, laddr)
358: // void m68030_write_{8,16,32}(cpu, laddr, data)
359: //
360:
361: uint32
362: m68030_fetch_16(m68kcpu *cpu)
363: {
364: cpu->bus.ssw = SSW_BUS_R | cpu->bus.fc2 | FC_PROG;
365: cpu->bus.laddr = RegPC;
366: return m68030_fetch_16_bus(cpu);
367: }
368:
369: uint32
370: m68030_fetch_32(m68kcpu *cpu)
371: {
372: cpu->bus.ssw = SSW_BUS_R | cpu->bus.fc2 | FC_PROG;
373: cpu->bus.laddr = RegPC;
374: return m68030_fetch_32_bus(cpu);
375: }
376:
377: uint32
378: m68030_read_8(m68kcpu *cpu, uint32 addr)
379: {
380: cpu->bus.ssw = SSW_BUS_R | cpu->bus.fc2 | FC_DATA;
381: cpu->bus.laddr = addr;
382: return m68030_read_8_bus(cpu);
383: }
384:
385: uint32
386: m68030_read_16(m68kcpu *cpu, uint32 addr)
387: {
388: cpu->bus.ssw = SSW_BUS_R | cpu->bus.fc2 | FC_DATA;
389: cpu->bus.laddr = addr;
390: return m68030_read_16_bus(cpu);
391: }
392:
393: uint32
394: m68030_read_32(m68kcpu *cpu, uint32 addr)
395: {
396: cpu->bus.ssw = SSW_BUS_R | cpu->bus.fc2 | FC_DATA;
397: cpu->bus.laddr = addr;
398: return m68030_read_32_bus(cpu);
399: }
400:
401: void
402: m68030_write_8(m68kcpu *cpu, uint32 addr, uint32 data)
403: {
404: cpu->bus.ssw = SSW_BUS_W | cpu->bus.fc2 | FC_DATA;
405: cpu->bus.laddr = addr;
406: cpu->bus.data = data;
407: m68030_write_8_bus(cpu);
408: }
409:
410: void
411: m68030_write_16(m68kcpu *cpu, uint32 addr, uint32 data)
412: {
413: cpu->bus.ssw = SSW_BUS_W | cpu->bus.fc2 | FC_DATA;
414: cpu->bus.laddr = addr;
415: cpu->bus.data = data;
416: m68030_write_16_bus(cpu);
417: }
418:
419: void
420: m68030_write_32(m68kcpu *cpu, uint32 addr, uint32 data)
421: {
422: cpu->bus.ssw = SSW_BUS_W | cpu->bus.fc2 | FC_DATA;
423: cpu->bus.laddr = addr;
424: cpu->bus.data = data;
425: m68030_write_32_bus(cpu);
426: }
427:
428: //
429: // MOVES 用の FC 指定版。
430: // 通常アクセスが現在の FC 空間に対してだが、
431: // こちらは SFC/DFC で指定された FC 空間に対してアクセスする。
432: //
433:
434: uint32
435: m68030_read_8_fc(m68kcpu *cpu, uint32 addr)
436: {
437: cpu->bus.ssw = SSW_BUS_R | RegSFC;
438: cpu->bus.laddr = addr;
439: return m68030_read_8_bus(cpu);
440: }
441:
442: uint32
443: m68030_read_16_fc(m68kcpu *cpu, uint32 addr)
444: {
445: cpu->bus.ssw = SSW_BUS_R | RegSFC;
446: cpu->bus.laddr = addr;
447: return m68030_read_16_bus(cpu);
448: }
449:
450: uint32
451: m68030_read_32_fc(m68kcpu *cpu, uint32 addr)
452: {
453: cpu->bus.ssw = SSW_BUS_R | RegSFC;
454: cpu->bus.laddr = addr;
455: return m68030_read_32_bus(cpu);
456: }
457:
458: void
459: m68030_write_8_fc(m68kcpu *cpu, uint32 addr, uint32 data)
460: {
461: cpu->bus.ssw = SSW_BUS_W | RegDFC;
462: cpu->bus.laddr = addr;
463: cpu->bus.data = data;
464: m68030_write_8_bus(cpu);
465: }
466:
467: void
468: m68030_write_16_fc(m68kcpu *cpu, uint32 addr, uint32 data)
469: {
470: cpu->bus.ssw = SSW_BUS_W | RegDFC;
471: cpu->bus.laddr = addr;
472: cpu->bus.data = data;
473: m68030_write_16_bus(cpu);
474: }
475:
476: void
477: m68030_write_32_fc(m68kcpu *cpu, uint32 addr, uint32 data)
478: {
479: cpu->bus.ssw = SSW_BUS_W | RegDFC;
480: cpu->bus.laddr = addr;
481: cpu->bus.data = data;
482: m68030_write_32_bus(cpu);
483: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.