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