|
|
1.1 root 1: //
2: // nono
1.1.1.3 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
1.1.1.3 root 6:
1.1.1.4 root 7: #include "mpu680x0.h"
1.1 root 8:
1.1.1.5 ! root 9: // 現在の FC での通常アクセス (MPU 内部から使用する)
! 10: // ミスアライン可。
! 11: // バスエラーが起きると例外 M68K::EXCEP_BUSERR をスローする。
! 12: // uint32 fetch_{16,32}()
! 13: // uint32 read_{8,16,32}(laddr)
! 14: // void write_{8,16,32}(laddr, data)
1.1 root 15:
1.1.1.5 ! root 16: // reg.pc からワードをフェッチし reg.pc を進める。
! 17: uint32
! 18: MPU680x0Device::fetch_16()
1.1 root 19: {
1.1.1.5 ! root 20: uint32 data;
! 21:
! 22: if (__predict_true(icache_enable)) {
! 23: data = fetch_16_cache(reg.pc);
1.1 root 24: } else {
1.1.1.5 ! root 25: data = fetch_16_bus(reg.pc);
1.1 root 26: }
1.1.1.5 ! root 27: reg.pc += 2;
! 28:
! 29: return data;
1.1 root 30: }
31:
1.1.1.5 ! root 32: // reg.pc からロングワード(ミスアライン可)をフェッチし reg.pc を進める。
! 33: uint32
! 34: MPU680x0Device::fetch_32()
1.1 root 35: {
1.1.1.5 ! root 36: uint32 data;
! 37:
! 38: if (__predict_true(icache_enable)) {
! 39: data = fetch_32_cache(reg.pc);
1.1 root 40: } else {
1.1.1.5 ! root 41: if ((reg.pc & 2) == 0) {
! 42: data = fetch_32_bus(reg.pc);
! 43: } else {
! 44: data = fetch_16_bus(reg.pc) << 16;
! 45: data |= fetch_16_bus(reg.pc + 2);
! 46: }
1.1 root 47: }
1.1.1.5 ! root 48: reg.pc += 4;
! 49:
! 50: return data;
1.1 root 51: }
52:
1.1.1.5 ! root 53: uint32
! 54: MPU680x0Device::read_8(uint32 addr)
1.1 root 55: {
1.1.1.5 ! root 56: busaddr laddr(addr, fc_data | busaddr::R);
! 57: return read_8_fc(laddr);
1.1 root 58: }
59:
1.1.1.5 ! root 60: uint32
! 61: MPU680x0Device::read_16(uint32 addr)
1.1 root 62: {
1.1.1.5 ! root 63: busaddr laddr(addr, fc_data | busaddr::R);
! 64: return read_16_fc(laddr);
1.1 root 65: }
66:
1.1.1.5 ! root 67: uint32
! 68: MPU680x0Device::read_32(uint32 addr)
1.1 root 69: {
1.1.1.5 ! root 70: busaddr laddr(addr, fc_data | busaddr::R);
! 71: return read_32_fc(laddr);
1.1 root 72: }
73:
1.1.1.5 ! root 74: void
! 75: MPU680x0Device::write_8(uint32 addr, uint32 data)
1.1 root 76: {
1.1.1.5 ! root 77: busaddr laddr(addr, fc_data | busaddr::W);
! 78: write_8_fc(laddr, data);
1.1 root 79: }
80:
1.1.1.5 ! root 81: void
! 82: MPU680x0Device::write_16(uint32 addr, uint32 data)
1.1 root 83: {
1.1.1.5 ! root 84: busaddr laddr(addr, fc_data | busaddr::W);
! 85: write_16_fc(laddr, data);
1.1 root 86: }
87:
1.1.1.5 ! root 88: void
! 89: MPU680x0Device::write_32(uint32 addr, uint32 data)
1.1 root 90: {
1.1.1.5 ! root 91: busaddr laddr(addr, fc_data | busaddr::W);
! 92: write_32_fc(laddr, data);
1.1 root 93: }
94:
1.1.1.5 ! root 95: // FC 指定アクセス (MPU コアから使用する)
! 96: // ミスアライン可。
! 97: // バスエラーが起きると例外 M68K::EXCEP_BUSERR をスローする。
! 98: // uint32 read_{8,16,32}_fc(busaddr)
! 99: // void write_{8,16,32}_fc(busaddr, data)
! 100: // (fetch は常に現在の FC でアクセスするので FC 指定版は不要)
1.1 root 101:
102: uint32
1.1.1.5 ! root 103: MPU680x0Device::read_8_fc(busaddr addr)
1.1 root 104: {
1.1.1.5 ! root 105: uint32 data;
1.1 root 106:
1.1.1.5 ! root 107: if (1) {
! 108: data = read_8_bus(addr);
! 109: }
! 110:
! 111: return data;
1.1 root 112: }
113:
114: uint32
1.1.1.5 ! root 115: MPU680x0Device::read_16_fc(busaddr addr)
1.1 root 116: {
1.1.1.5 ! root 117: uint32 data;
! 118:
! 119: if (1) {
! 120: // バスアクセスは要整列。
! 121: if (__predict_true((addr & 1) == 0)) {
! 122: data = read_16_bus(addr);
! 123: } else {
! 124: data = read_8_bus(addr) << 8;
! 125: addr += 1;
! 126: data |= read_8_bus(addr);
! 127: }
! 128: }
! 129:
! 130: return data;
1.1 root 131: }
132:
133: uint32
1.1.1.5 ! root 134: MPU680x0Device::read_32_fc(busaddr addr)
1.1 root 135: {
1.1.1.5 ! root 136: uint32 data;
! 137:
! 138: if (1) {
! 139: // バスアクセスは要整列。
! 140: if (__predict_true((addr & 3) == 0)) {
! 141: data = read_32_bus(addr);
! 142: } else if (__predict_true((addr & 1) == 0)) {
! 143: data = read_16_bus(addr) << 16;
! 144: addr += 2;
! 145: data |= read_16_bus(addr);
! 146: } else {
! 147: data = read_8_bus(addr) << 24;
! 148: addr += 1;
! 149: data |= read_16_bus(addr) << 8;
! 150: addr += 2;
! 151: data |= read_8_bus(addr);
! 152: }
! 153: }
! 154:
! 155: return data;
1.1 root 156: }
157:
1.1.1.5 ! root 158: void
! 159: MPU680x0Device::write_8_fc(busaddr addr, uint32 data)
1.1 root 160: {
1.1.1.5 ! root 161: if (1) {
! 162: write_8_bus(addr, data);
! 163: }
1.1 root 164: }
165:
166: void
1.1.1.5 ! root 167: MPU680x0Device::write_16_fc(busaddr addr, uint32 data)
1.1 root 168: {
1.1.1.5 ! root 169: if (1) {
! 170: // バスアクセスは要整列。
! 171: if (__predict_true((addr & 1) == 0)) {
! 172: write_16_bus(addr, data);
! 173: } else {
! 174: write_8_bus(addr, data >> 8);
! 175: addr += 1;
! 176: write_8_bus(addr, data & 0xff);
! 177: }
! 178: }
1.1 root 179: }
180:
181: void
1.1.1.5 ! root 182: MPU680x0Device::write_32_fc(busaddr addr, uint32 data)
1.1 root 183: {
1.1.1.5 ! root 184: if (1) {
! 185: // バスアクセスは要整列。
! 186: if (__predict_true((addr & 3) == 0)) {
! 187: write_32_bus(addr, data);
! 188: } else if (__predict_true((addr & 1) == 0)) {
! 189: write_16_bus(addr, data >> 16);
! 190: addr += 2;
! 191: write_16_bus(addr, data & 0xffff);
! 192: } else {
! 193: write_8_bus(addr, data >> 24);
! 194: addr += 1;
! 195: write_16_bus(addr, (data >> 8) & 0xffff);
! 196: addr += 2;
! 197: write_8_bus(addr, data & 0xff);
! 198: }
! 199: }
1.1 root 200: }
201:
1.1.1.5 ! root 202: // 外部バスアクセス (MMU を含む)
! 203: // ミスアライン不可。
! 204: // バスエラーが起きると例外 M68K::EXCEP_BUSERR をスローする。
! 205: // uint32 fetch_{16,32}_bus()
! 206: // uint32 read_{8,16,32}_bus(busaddr)
! 207: // void write_{8,16,32}_bus(busaddr, data)
! 208:
! 209: // goto を含むことに注意。gcc 拡張式(?) に注意。
! 210: #define FETCH(size) ({ \
! 211: bus.laddr.Set(addr, fc_inst); \
! 212: bus.paddr = bus.laddr; \
! 213: bus.ci = false; \
! 214: if (__predict_true(mmu_enable)) { \
! 215: if (__predict_false(TranslateFetch() == false)) \
! 216: goto buserr; \
! 217: } \
! 218: busdata bd_ = mainbus->__CONCAT(Read,size)(bus.paddr); \
! 219: if (bd_.IsBusErr()) \
! 220: goto buserr; \
! 221: bd_; /* これが戻り値 */ \
! 222: })
! 223: #define READ(size) ({ \
! 224: bus.laddr = addr; \
! 225: bus.paddr = addr; \
! 226: bus.ci = false; \
! 227: if (__predict_true(mmu_enable)) { \
! 228: if (__predict_false(TranslateRead() == false)) \
! 229: goto buserr; \
! 230: } \
! 231: busdata bd_ = mainbus->__CONCAT(Read,size)(bus.paddr); \
! 232: if (bd_.IsBusErr()) \
! 233: goto buserr; \
! 234: bd_; /* これが戻り値 */ \
! 235: })
! 236: #define WRITE(size, data_) ({ \
! 237: bus.laddr = addr; \
! 238: bus.paddr = addr; \
! 239: bus.ci = false; \
! 240: if (__predict_true(mmu_enable)) { \
! 241: if (__predict_false(TranslateWrite() == false)) \
! 242: goto buserr; \
! 243: } \
! 244: busdata bd_ = mainbus->__CONCAT(Write,size)(bus.paddr, data_); \
! 245: if (bd_.IsBusErr()) \
! 246: goto buserr; \
! 247: bd_; /* これが戻り値 */ \
! 248: })
! 249:
! 250: uint32
! 251: MPU680x0Device::fetch_16_bus(uint32 addr)
1.1 root 252: {
1.1.1.5 ! root 253: busdata bd;
! 254:
! 255: bd = FETCH(16);
! 256: buswait += bd.GetWait();
! 257: return bd.Data();
! 258:
! 259: buserr:
! 260: bus.size = M68K::SSW_SIZE_WORD;
! 261: throw M68K::EXCEP_BUSERR;
1.1 root 262: }
263:
1.1.1.5 ! root 264: uint32
! 265: MPU680x0Device::fetch_32_bus(uint32 addr)
! 266: {
! 267: busdata bd;
! 268:
! 269: bd = FETCH(32);
! 270: buswait += bd.GetWait();
! 271: return bd.Data();
! 272:
! 273: buserr:
! 274: bus.size = M68K::SSW_SIZE_LONG;
! 275: throw M68K::EXCEP_BUSERR;
! 276: }
1.1 root 277:
278: uint32
1.1.1.5 ! root 279: MPU680x0Device::read_8_bus(busaddr addr)
1.1 root 280: {
1.1.1.5 ! root 281: busdata data;
! 282:
! 283: data = READ(8);
! 284: putlog(2, "read_8 %08x -> %02x", bus.laddr.Addr(), data.Data());
! 285: buswait += data.GetWait();
! 286: return data.Data();
! 287:
! 288: buserr:
! 289: bus.size = M68K::SSW_SIZE_BYTE;
! 290: throw M68K::EXCEP_BUSERR;
1.1 root 291: }
292:
293: uint32
1.1.1.5 ! root 294: MPU680x0Device::read_16_bus(busaddr addr)
1.1 root 295: {
1.1.1.5 ! root 296: busdata data;
! 297:
! 298: data = READ(16);
! 299: putlog(2, "read_16 %08x -> %04x", bus.laddr.Addr(), data.Data());
! 300: buswait += data.GetWait();
! 301: return data.Data();
! 302:
! 303: buserr:
! 304: bus.size = M68K::SSW_SIZE_WORD;
! 305: throw M68K::EXCEP_BUSERR;
1.1 root 306: }
307:
308: uint32
1.1.1.5 ! root 309: MPU680x0Device::read_32_bus(busaddr addr)
1.1 root 310: {
1.1.1.5 ! root 311: busdata data;
! 312:
! 313: data = READ(32);
! 314: putlog(2, "read_32 %08x -> %08x", bus.laddr.Addr(), data.Data());
! 315: buswait += data.GetWait();
! 316: return data.Data();
! 317:
! 318: buserr:
! 319: bus.size = M68K::SSW_SIZE_LONG;
! 320: throw M68K::EXCEP_BUSERR;
1.1 root 321: }
322:
323: void
1.1.1.5 ! root 324: MPU680x0Device::write_8_bus(busaddr addr, uint32 data)
1.1 root 325: {
1.1.1.5 ! root 326: busdata rd;
! 327:
! 328: rd = WRITE(8, data);
! 329: putlog(2, "write_8 %08x <- %02x", bus.laddr.Addr(), data);
! 330: buswait += rd.GetWait();
! 331: return;
! 332:
! 333: buserr:
! 334: bus.size = M68K::SSW_SIZE_BYTE;
! 335: throw M68K::EXCEP_BUSERR;
1.1 root 336: }
337:
338: void
1.1.1.5 ! root 339: MPU680x0Device::write_16_bus(busaddr addr, uint32 data)
1.1 root 340: {
1.1.1.5 ! root 341: busdata rd;
! 342:
! 343: rd = WRITE(16, data);
! 344: putlog(2, "write_16 %08x <- %04x", bus.laddr.Addr(), data);
! 345: buswait += rd.GetWait();
! 346: return;
! 347:
! 348: buserr:
! 349: bus.size = M68K::SSW_SIZE_WORD;
! 350: throw M68K::EXCEP_BUSERR;
1.1 root 351: }
352:
353: void
1.1.1.5 ! root 354: MPU680x0Device::write_32_bus(busaddr addr, uint32 data)
1.1 root 355: {
1.1.1.5 ! root 356: busdata rd;
! 357:
! 358: rd = WRITE(32, data);
! 359: putlog(2, "write_32 %08x <- %08x", bus.laddr.Addr(), data);
! 360: buswait += rd.GetWait();
! 361: return;
! 362:
! 363: buserr:
! 364: bus.size = M68K::SSW_SIZE_LONG;
! 365: throw M68K::EXCEP_BUSERR;
1.1 root 366: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.