|
|
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.