|
|
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: bus.size = addr.GetSize(); ! 37: throw M68K::EXCEP_BUSERR; ! 38: } ! 39: return data.Data(); ! 40: } ! 41: ! 42: // キャッシュ無効時の読み込み。ミスアライン可。 ! 43: // バスエラーも busdata を返す。 ! 44: busdata ! 45: MPU68040Device::read_nocache(busaddr addr) ! 46: { ! 47: // デバイスは、addr の下位ビットによらず、自身のデバイスのポートサイズ分 ! 48: // のデータと、その応答サイズ(自分のポートサイズ) を Size フィールドに ! 49: // セットして返してくる。 ! 50: // ! 51: // MPU(68040) は、A1-A0、残りバイト数、デバイスの応答サイズの情報から ! 52: // 受け取ったデータバスのうち適切なところを切り出して使う。 ! 53: ! 54: bool span_page = false; ! 55: uint32 data = 0; ! 56: for (;;) { ! 57: bus.laddr = addr; ! 58: bus.paddr = addr; ! 59: if (__predict_false(TranslateRead() == false)) { ! 60: bus.atcfault = true; ! 61: // ATC フォールトが2ページ目で起きたか。 ! 62: bus.atcfault2 = span_page; ! 63: return BusData::BusErr; ! 64: } ! 65: busdata bd = read_phys(); ! 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; ! 116: bus.paddr = addr; ! 117: if (__predict_false(TranslateWrite() == false)) { ! 118: bus.atcfault = true; ! 119: // ATC フォールトが2ページ目で起きたか。 ! 120: bus.atcfault2 = span_page; ! 121: break; ! 122: } ! 123: busdata bd = write_phys(data); ! 124: if (__predict_false(bd.IsBusErr())) { ! 125: break; ! 126: } ! 127: uint32 reqsize = addr.GetSize(); ! 128: uint32 portsize = bd.GetSize(); ! 129: uint32 offset = addr.Addr() & (portsize - 1); ! 130: uint32 datasize = portsize - offset; ! 131: if (datasize >= reqsize) { ! 132: // ここが成功して終了。 ! 133: return; ! 134: } ! 135: ! 136: addr += datasize; ! 137: reqsize -= datasize; ! 138: addr.ChangeSize(reqsize); ! 139: data &= (1U << (reqsize * 8)) - 1; ! 140: ! 141: if (((addr.Addr() ^ origaddr.Addr()) & ~mmu_tc->page_mask) != 0) { ! 142: span_page = true; ! 143: } ! 144: } ! 145: ! 146: // 報告するのは先頭のアドレス。 ! 147: bus.laddr.ChangeAddr(origaddr.Addr()); ! 148: bus.size = origaddr.GetSize(); ! 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.