|
|
1.1 ! root 1: // ! 2: // nono ! 3: // Copyright (C) 2020 nono project ! 4: // Licensed under nono-license.txt ! 5: // ! 6: ! 7: // ! 8: // メインバス ! 9: // ! 10: ! 11: #include "mainbus.h" ! 12: #include "mainram.h" ! 13: ! 14: // コンストラクタ ! 15: MainbusDevice::MainbusDevice() ! 16: : inherited(OBJ_MAINBUS) ! 17: { ! 18: } ! 19: ! 20: // デストラクタ ! 21: MainbusDevice::~MainbusDevice() ! 22: { ! 23: } ! 24: ! 25: uint64 ! 26: MainbusDevice::Read8(uint32 addr) ! 27: { ! 28: uint64 data; ! 29: ! 30: if (addr < direct_ram_size) { ! 31: data = MainRAMDevice::mainram[HLB(addr)]; ! 32: } else { ! 33: IODevice *dev = devtable[addr >> 24]; ! 34: data = dev->Read8(addr); ! 35: } ! 36: return data; ! 37: } ! 38: ! 39: uint64 ! 40: MainbusDevice::Read16(uint32 addr) ! 41: { ! 42: uint64 data; ! 43: ! 44: if (__predict_false((addr & 1) != 0)) ! 45: VMPANIC("unaligned access $%08x", addr); ! 46: ! 47: if (addr < direct_ram_size) { ! 48: data = *(uint16 *)&MainRAMDevice::mainram[HLW(addr)]; ! 49: } else { ! 50: IODevice *dev = devtable[addr >> 24]; ! 51: data = dev->Read16(addr); ! 52: } ! 53: return data; ! 54: } ! 55: ! 56: uint64 ! 57: MainbusDevice::Read32(uint32 addr) ! 58: { ! 59: uint64 data; ! 60: ! 61: if (__predict_false((addr & 3) != 0)) ! 62: VMPANIC("unaligned access $%08x", addr); ! 63: ! 64: if (addr < direct_ram_size) { ! 65: data = *(uint32 *)&MainRAMDevice::mainram[addr]; ! 66: } else { ! 67: IODevice *dev = devtable[addr >> 24]; ! 68: data = dev->Read32(addr); ! 69: } ! 70: return data; ! 71: } ! 72: ! 73: uint64 ! 74: MainbusDevice::Write8(uint32 addr, uint32 data) ! 75: { ! 76: if (addr < direct_ram_size) { ! 77: MainRAMDevice::mainram[HLB(addr)] = data; ! 78: return 0; ! 79: } else { ! 80: IODevice *dev = devtable[addr >> 24]; ! 81: return dev->Write8(addr, data); ! 82: } ! 83: } ! 84: ! 85: uint64 ! 86: MainbusDevice::Write16(uint32 addr, uint32 data) ! 87: { ! 88: if (__predict_false((addr & 1) != 0)) ! 89: VMPANIC("unaligned access $%08x", addr); ! 90: ! 91: if (addr < direct_ram_size) { ! 92: *(uint16 *)&MainRAMDevice::mainram[HLW(addr)] = data; ! 93: return 0; ! 94: } else { ! 95: IODevice *dev = devtable[addr >> 24]; ! 96: return dev->Write16(addr, data); ! 97: } ! 98: } ! 99: ! 100: uint64 ! 101: MainbusDevice::Write32(uint32 addr, uint32 data) ! 102: { ! 103: if (__predict_false((addr & 3) != 0)) ! 104: VMPANIC("unaligned access $%08x", addr); ! 105: ! 106: if (addr < direct_ram_size) { ! 107: *(uint32 *)&MainRAMDevice::mainram[addr] = data; ! 108: return 0; ! 109: } else { ! 110: IODevice *dev = devtable[addr >> 24]; ! 111: return dev->Write32(addr, data); ! 112: } ! 113: } ! 114: ! 115: uint64 ! 116: MainbusDevice::Peek8(uint32 addr) ! 117: { ! 118: uint64 data; ! 119: ! 120: if (addr < direct_ram_size) { ! 121: data = MainRAMDevice::mainram[HLB(addr)]; ! 122: } else { ! 123: IODevice *dev = devtable[addr >> 24]; ! 124: data = dev->Peek8(addr); ! 125: } ! 126: return data; ! 127: } ! 128: ! 129: // これだけオーバーライドではないので注意。 ! 130: uint64 ! 131: MainbusDevice::Peek32(uint32 addr) ! 132: { ! 133: uint64 data; ! 134: ! 135: if (__predict_false((addr & 3) != 0)) ! 136: VMPANIC("unaligned access $%08x", addr); ! 137: ! 138: if (addr < direct_ram_size) { ! 139: data = *(uint32 *)&MainRAMDevice::mainram[addr]; ! 140: } else { ! 141: IODevice *dev = devtable[addr >> 24]; ! 142: data = dev->Peek8(addr++) << 24; ! 143: data |= dev->Peek8(addr++) << 16; ! 144: data |= dev->Peek8(addr++) << 8; ! 145: data |= dev->Peek8(addr); ! 146: } ! 147: return data; ! 148: } ! 149: ! 150: // このアドレスを担当する次段の IODevice を返す (IOContainerDevice 用) ! 151: IODevice * ! 152: MainbusDevice::GetDevice(uint32 addr) const ! 153: { ! 154: return devtable[addr >> 24]; ! 155: } ! 156: ! 157: // デバイスをセットする。すでにあれば更新する。 ! 158: // idx は devtable[] のインデックス (16MB 単位)。 ! 159: /*static*/ void ! 160: MainbusDevice::SetDevice(int idx, IODevice *dev) ! 161: { ! 162: assert(idx < devtable.size()); ! 163: ! 164: devtable[idx] = dev; ! 165: } ! 166: ! 167: // デバイステーブルの src から len 個を dst にコピーする。(ミラーを作る) ! 168: /*static*/ void ! 169: MainbusDevice::CopyDevtable(int dst, int src, int len) ! 170: { ! 171: memcpy(&devtable[dst], &devtable[src], sizeof(devtable[0]) * len); ! 172: } ! 173: ! 174: // Mainbus は1つしかないので、スタティック変数にしておく。 ! 175: /*static*/ std::array<IODevice *, 256> MainbusDevice::devtable; ! 176: ! 177: // RAM へのアクセスは、アクセスアドレスが direct_ram_size 未満なら ram[] を ! 178: // 直接アクセスし、そうでなければデバイスクラス経由でアクセスする。 ! 179: // 高速モードでは RAM デバイスを経由すること自体とその中でアクセスウェイトを ! 180: // 計算する分を回避したい。 ! 181: /*static*/ int MainbusDevice::direct_ram_size;
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.