|
|
1.1 root 1: //
2: // nono
1.1.1.2 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
7: #pragma once
8:
1.1.1.3 ! root 9: //
! 10: // 1回の(アラインド)物理アクセスを担当するマクロ。
! 11: // これらは続く _mmu テンプレートで使用する。
! 12: // goto を含むことに注意。gcc 拡張式(?)に注意。
! 13: // Translate* は Fetch, Read, Write の3種だが、Mainbus には
! 14: // Read, Write しかないことに注意。物理バスに FC0 と FC1、つまりプログラム
! 15: // 空間かどうかの情報は出していないため。
! 16: //
1.1 root 17:
1.1.1.3 ! root 18: #define FETCH(size) ({ \
! 19: bus.paddr = bus.laddr; \
! 20: if (use_mmu && TranslateFetch() == false) \
! 21: goto buserr; \
! 22: uint64 data_ = mainbus->__CONCAT(Read,size)(bus.paddr); \
! 23: if ((int64)data_ < 0) \
! 24: goto buserr; \
! 25: data_; /* これが戻り値 */ \
! 26: })
! 27:
! 28: #define READ(size) ({ \
! 29: bus.paddr = bus.laddr; \
! 30: if (use_mmu && TranslateRead() == false) \
! 31: goto buserr; \
! 32: uint64 data_ = mainbus->__CONCAT(Read,size)(bus.paddr); \
! 33: if ((int64)data_ < 0) \
! 34: goto buserr; \
! 35: data_; /* これが戻り値 */ \
! 36: })
! 37:
! 38: #define WRITE(size, data) ({ \
! 39: bus.paddr = bus.laddr; \
! 40: if (use_mmu && TranslateWrite() == false) \
! 41: goto buserr; \
! 42: int64 berr_ = mainbus->__CONCAT(Write,size)(bus.paddr, (data)); \
! 43: if (berr_ < 0) \
! 44: goto buserr; \
! 45: 0; /* 戻り値不要だけど一応 */ \
! 46: })
! 47:
! 48: //
! 49: // MMU を考慮した下請けテンプレート。
! 50: // 1回分のミスアラインドありのアクセスを担当。
! 51: //
! 52:
! 53: template<bool use_mmu> uint32
! 54: fetch_16_mmu()
! 55: {
! 56: uint64 data;
! 57:
! 58: data = FETCH(16);
! 59: // XXX バスエラー時に PC をインクリメントするタイミングは?
! 60: reg.pc += 2;
! 61:
! 62: return data;
! 63:
! 64: buserr:
! 65: bus.SET_SSW(use_mmu, M68K::SSW_SIZE_WORD);
! 66: throw M68K::EXCEP_BUSERR;
! 67: }
! 68:
! 69: template<bool use_mmu> uint32
! 70: fetch_32_mmu()
! 71: {
! 72: uint64 data;
! 73:
! 74: if ((bus.laddr & 3) == 0) {
! 75: data = FETCH(32);
! 76: } else {
! 77: uint64 h, l;
! 78:
! 79: h = FETCH(16);
! 80: bus.laddr += 2;
! 81:
! 82: l = FETCH(16);
! 83: data = (h << 16) | l;
! 84: }
! 85: // XXX バスエラー時に PC をインクリメントするタイミングは?
! 86: reg.pc += 4;
! 87: return data;
! 88:
! 89: buserr:
! 90: bus.SET_SSW(use_mmu, M68K::SSW_SIZE_LONG);
! 91: throw M68K::EXCEP_BUSERR;
1.1 root 92: }
93:
1.1.1.3 ! root 94: template<bool use_mmu> uint32
! 95: read_8_mmu()
1.1 root 96: {
1.1.1.3 ! root 97: uint64 data;
! 98:
! 99: data = READ(8);
! 100:
! 101: if (1)
! 102: putlog(2, "read_8 %08X -> %02X", bus.laddr, (uint32)data);
1.1 root 103: return data;
1.1.1.3 ! root 104:
! 105: buserr:
! 106: bus.SET_SSW(use_mmu, M68K::SSW_SIZE_BYTE);
! 107: throw M68K::EXCEP_BUSERR;
1.1 root 108: }
109:
1.1.1.3 ! root 110: template<bool use_mmu> uint32
! 111: read_16_mmu()
1.1 root 112: {
1.1.1.3 ! root 113: uint64 data;
! 114:
! 115: if ((bus.laddr & 1) == 0) {
! 116: data = READ(16);
! 117: } else {
! 118: uint64 h, l;
! 119:
! 120: h = READ(8);
! 121: bus.laddr += 1;
! 122:
! 123: l = READ(8);
! 124: data = (h << 8) | l;
! 125: }
! 126:
! 127: if (1)
! 128: putlog(2, "read_16 %08X -> %04X", bus.laddr, (uint32)data);
1.1 root 129: return data;
1.1.1.3 ! root 130:
! 131: buserr:
! 132: bus.SET_SSW(use_mmu, M68K::SSW_SIZE_WORD);
! 133: throw M68K::EXCEP_BUSERR;
! 134: }
! 135:
! 136: template<bool use_mmu> uint32
! 137: read_32_mmu()
! 138: {
! 139: uint64 data;
! 140:
! 141: if ((bus.laddr & 3) == 0) {
! 142: data = READ(32);
! 143: } else if ((bus.laddr & 1) == 0) {
! 144: uint64 h, l;
! 145:
! 146: h = READ(16);
! 147: bus.laddr += 2;
! 148:
! 149: l = READ(16);
! 150: data = (h << 16) | l;
! 151: } else {
! 152: uint64 h, m, l;
! 153:
! 154: h = READ(8);
! 155: bus.laddr += 1;
! 156:
! 157: m = READ(16);
! 158: bus.laddr += 2;
! 159:
! 160: l = READ(8);
! 161: data = (h << 24) | (m << 8) | l;
! 162: }
! 163:
! 164: if (1)
! 165: putlog(2, "read_32 %08X -> %08X", bus.laddr, (uint32)data);
! 166: return data;
! 167:
! 168: buserr:
! 169: bus.SET_SSW(use_mmu, M68K::SSW_SIZE_LONG);
! 170: throw M68K::EXCEP_BUSERR;
! 171: }
! 172:
! 173: template<bool use_mmu> void
! 174: write_8_mmu()
! 175: {
! 176: uint32 data = bus.data;
! 177:
! 178: if (1)
! 179: putlog(2, "write_8 %08X <- %02X", bus.laddr, data);
! 180:
! 181: WRITE(8, data);
! 182: return;
! 183:
! 184: buserr:
! 185: bus.SET_SSW(use_mmu, M68K::SSW_SIZE_BYTE);
! 186: throw M68K::EXCEP_BUSERR;
! 187: }
! 188:
! 189: template<bool use_mmu> void
! 190: write_16_mmu()
! 191: {
! 192: uint32 data = bus.data;
! 193:
! 194: if (1)
! 195: putlog(2, "write_16 %08X <- %04X", bus.laddr, data);
! 196:
! 197: if ((bus.laddr & 1) == 0) {
! 198: WRITE(16, data);
! 199: } else {
! 200: WRITE(8, data >> 8);
! 201:
! 202: bus.laddr += 1;
! 203: WRITE(8, data & 0xff);
! 204: }
! 205: return;
! 206:
! 207: buserr:
! 208: bus.SET_SSW(use_mmu, M68K::SSW_SIZE_WORD);
! 209: throw M68K::EXCEP_BUSERR;
! 210: }
! 211:
! 212: template<bool use_mmu> void
! 213: write_32_mmu()
! 214: {
! 215: uint32 data = bus.data;
! 216:
! 217: if (1)
! 218: putlog(2, "write_32 %08X <- %08X", bus.laddr, data);
! 219:
! 220: if ((bus.laddr & 3) == 0) {
! 221: WRITE(32, data);
! 222: } else if ((bus.laddr & 1) == 0) {
! 223: WRITE(16, data >> 16);
! 224:
! 225: bus.laddr += 2;
! 226: WRITE(16, data & 0xffff);
! 227: } else {
! 228: WRITE(8, data >> 24);
! 229:
! 230: bus.laddr += 1;
! 231: WRITE(16, (data >> 8) & 0xffff);
! 232:
! 233: bus.laddr += 2;
! 234: WRITE(8, data & 0xff);
! 235: }
! 236: return;
! 237:
! 238: buserr:
! 239: bus.SET_SSW(use_mmu, M68K::SSW_SIZE_LONG);
! 240: throw M68K::EXCEP_BUSERR;
1.1 root 241: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.