|
|
1.1 root 1: //
2: // nono
1.1.1.2 root 3: // Copyright (C) 2020 nono project
4: // Licensed under nono-license.txt
1.1 root 5: //
6:
7: // MPU (m88xx0)
8:
9: #include "mpu88xx0.h"
10: #include "config.h"
1.1.1.2 root 11: #include "sysctlr.h"
12:
1.1 root 13: // コンストラクタ
1.1.1.7 root 14: MPU88xx0Device::MPU88xx0Device()
1.1.1.8 root 15: : inherited("MPU(88xx0)")
1.1 root 16: {
1.1.1.7 root 17: cpu.reset(new m88kcpu());
1.1.1.4 root 18:
1.1.1.2 root 19: // LUNA88K では CMMU の ID は次のように割り振ってあるようだ。
20: // OpenBSD の sys/arch/luna68k/include/board.h より。
21: //
22: // Inst Data
23: // CPU#0 ID=7 ID=6
24: // CPU#1 ID=5 ID=4
25: // CPU#2 ID=3 ID=2
26: // CPU#3 ID=1 ID=0
27: //
28: // 厳密にはこれは LUNA88K のハードウェアがどういうコンフィグレーションで
29: // m88200 を使うかなので、ここではなくて vm_luna あたりのほうがいいかも
30: // しれんけど、あまり遠いのも面倒なので、とりあえずこの辺に。
31: // あとマルチプロセッサになったらまたその時考える。
32: cpu->cmmu[0].SetID(7);
33: cpu->cmmu[1].SetID(6);
34:
1.1.1.8 root 35: // レジスタモニター
36: monitor.func = (MonitorCallback_t)&MPU88xx0Device::MonitorUpdate;
37: monitor.SetSize(79, 18);
38: monitor.Regist(ID_MONITOR_MPUREG);
1.1 root 39: }
40:
41: // デストラクタ
42: MPU88xx0Device::~MPU88xx0Device()
43: {
44: }
45:
1.1.1.5 root 46: bool
47: MPU88xx0Device::Init()
48: {
49: // 親クラス
50: if (inherited::Init() == false) {
51: return false;
52: }
53: // MPU クロックは親 Init() で読み込んで、ここで cpu にセットする
54: cpu->SetClockSpeed(clock_khz);
55:
1.1.1.8 root 56: const ConfigItem& item = gConfig->Find("mpu-pseudo-stop");
57: cpu->pseudo_stop_enable = (bool)item.AsInt();
58:
1.1.1.5 root 59: return true;
60: }
61:
1.1.1.7 root 62: bool
63: MPU88xx0Device::PowerOn()
64: {
65: cpu->PowerOn();
66: return true;
67: }
68:
1.1 root 69: void
1.1.1.7 root 70: MPU88xx0Device::ResetHard()
1.1 root 71: {
1.1.1.5 root 72: cpu->RequestReset();
1.1 root 73: }
74:
1.1.1.6 root 75: // アクセス中の論理アドレスを取得
76: uint32
77: MPU88xx0Device::GetLaddr() const
78: {
79: m88200 *cmmu = m88200::GetBusMaster();
80: assert(cmmu);
81: return cmmu->GetLaddr();
82: }
83:
84: // アクセス中の物理アドレスを取得
85: uint32
86: MPU88xx0Device::GetPaddr() const
87: {
88: m88200 *cmmu = m88200::GetBusMaster();
89: assert(cmmu);
90: return cmmu->GetPaddr();
91: }
92:
1.1.1.4 root 93: // アクセスウェイトを加算
94: void
1.1.1.5 root 95: MPU88xx0Device::AddCycle(int32 cycle)
1.1.1.4 root 96: {
97: // 今アクセスしてきている(= バスマスターの) CMMU に対して加算する
98: m88200 *cmmu = m88200::GetBusMaster();
99: assert(cmmu);
100: cmmu->AddCycle(cycle);
101: }
102:
1.1.1.2 root 103: // Interrupt
104: void
1.1.1.5 root 105: MPU88xx0Device::Interrupt(int level)
1.1.1.2 root 106: {
1.1.1.5 root 107: cpu->Interrupt(level);
1.1.1.2 root 108: }
109:
1.1.1.9 ! root 110: // DOS call エミュレーションのコールバックを指定
! 111: void
! 112: MPU88xx0Device::SetFLineCallback(bool (*callback)(m88kcpu *, void *), void *arg)
! 113: {
! 114: cpu->SetFLineCallback(callback, arg);
! 115: }
! 116:
! 117: // MPU からのアクセスをエミュレート
! 118: uint64
! 119: MPU88xx0Device::Read8(uint32 addr)
! 120: {
! 121: return cpu->cmmu[1].load_8(addr);
! 122: }
! 123:
! 124: uint64
! 125: MPU88xx0Device::Read16(uint32 addr)
! 126: {
! 127: if ((addr & 1) == 0) {
! 128: return cpu->cmmu[1].load_16(addr);
! 129: } else {
! 130: uint64 h, l;
! 131: h = Read8(addr);
! 132: if ((int64)h < 0) {
! 133: return h;
! 134: }
! 135: l = Read8(addr + 1);
! 136: if ((int64)l < 0) {
! 137: return l;
! 138: }
! 139: return (h << 8) | l;
! 140: }
! 141: }
! 142:
! 143: uint64
! 144: MPU88xx0Device::Read32(uint32 addr)
! 145: {
! 146: if ((addr & 3) == 0) {
! 147: return cpu->cmmu[1].load_32(addr);
! 148: } else if ((addr & 1) == 0) {
! 149: uint64 h, l;
! 150: h = Read16(addr);
! 151: if ((int64)h < 0) {
! 152: return h;
! 153: }
! 154: l = Read16(addr + 2);
! 155: if ((int64)l < 0) {
! 156: return l;
! 157: }
! 158: return (h << 16) | l;
! 159: } else {
! 160: uint64 h, m, l;
! 161: h = Read8(addr);
! 162: if ((int64)h < 0) {
! 163: return h;
! 164: }
! 165: m = Read16(addr + 1);
! 166: if ((int64)m < 0) {
! 167: return m;
! 168: }
! 169: l = Read8(addr + 3);
! 170: if ((int64)l < 0) {
! 171: return l;
! 172: }
! 173: return (h << 24) | (m << 8) | l;
! 174: }
! 175: }
! 176:
! 177: uint64
! 178: MPU88xx0Device::Write8(uint32 addr, uint32 data)
! 179: {
! 180: return cpu->cmmu[1].store_8(addr, data & 0xff);
! 181: }
! 182:
! 183: uint64
! 184: MPU88xx0Device::Write16(uint32 addr, uint32 data)
! 185: {
! 186: if ((addr & 1) == 0) {
! 187: return cpu->cmmu[1].store_16(addr, data & 0xffff);
! 188: } else {
! 189: uint64 r;
! 190: r = Write8(addr, data >> 8);
! 191: if ((int64)r < 0) {
! 192: return r;
! 193: }
! 194: return Write8(addr + 1, data);
! 195: }
! 196: }
! 197:
! 198: uint64
! 199: MPU88xx0Device::Write32(uint32 addr, uint32 data)
! 200: {
! 201: if ((addr & 3) == 0) {
! 202: return cpu->cmmu[1].store_32(addr, data);
! 203: } else if ((addr & 1) == 0) {
! 204: uint64 r;
! 205: r = Write16(addr, data >> 16);
! 206: if ((int64)r < 0) {
! 207: return r;
! 208: }
! 209: return Write16(addr + 2, data);
! 210: } else {
! 211: uint64 r;
! 212: r = Write8(addr, data >> 24);
! 213: if ((int64)r < 0) {
! 214: return r;
! 215: }
! 216: r = Write16(addr + 1, data >> 8);
! 217: if ((int64)r < 0) {
! 218: return r;
! 219: }
! 220: return Write8(addr + 3, data);
! 221: }
! 222: }
! 223:
1.1 root 224: // モニター更新
1.1.1.3 root 225: void
1.1.1.8 root 226: MPU88xx0Device::MonitorUpdate(Monitor *, TextScreen& screen)
1.1 root 227: {
228: m88100reg reg;
229: int x;
230: int y;
231:
1.1.1.8 root 232: screen.Clear();
1.1 root 233:
234: // ローカルにコピー
235: reg = *cpu;
236:
237: //
238: for (int i = 0; i < countof(reg.r); i++) {
1.1.1.8 root 239: screen.Print((i / 8) * 14, i % 8, "r%-2d:%08x", i, reg.r[i]);
1.1 root 240: }
241:
242: // 制御レジスタ
243: x = 0;
244: y = 9;
1.1.1.8 root 245: screen.Print(x, y++, "pid (cr0):%08x(Arch=$%02x Ver=$%02x MC=%s)",
1.1 root 246: reg.pid,
247: (reg.pid >> 8) & 0xff,
1.1.1.2 root 248: (reg.pid >> 1) & 0x7f,
249: (reg.pid & 1) ? "Master" : "Checker");
1.1.1.8 root 250: screen.Print(x, y, "psr (cr1):%08x(", reg.psr);
251: screen.Puts(x + 19, y, TA::OnOff(reg.psr & m88100reg::PSR_SUPER), "S");
252: screen.Puts(x + 21, y,
1.1.1.2 root 253: ((reg.psr & m88100reg::PSR_BO_LE) ? "BO=LE" : "BO=BE"));
1.1.1.8 root 254: screen.Puts(x + 27, y, TA::OnOff(reg.psr & m88100reg::PSR_SER), "SER");
255: screen.Puts(x + 31, y, TA::OnOff(reg.psr & m88100reg::PSR_C), "Cy");
256: screen.Puts(x + 34, y, TA::OnOff(reg.psr & m88100reg::PSR_SFD1), "SFD1");
257: screen.Puts(x + 39, y, TA::OnOff(reg.psr & m88100reg::PSR_MXM), "MXM");
258: screen.Puts(x + 43, y, TA::OnOff(reg.psr & m88100reg::PSR_IND), "IND");
259: screen.Puts(x + 47, y, TA::OnOff(reg.psr & m88100reg::PSR_SFRZ), "SFRZ");
260: screen.Puts(x + 51, y, ")");
1.1.1.2 root 261: y++;
1.1.1.8 root 262: screen.Print(x, y, "epsr(cr2):%08x(", reg.epsr);
263: screen.Puts(x + 19, y, TA::OnOff(reg.epsr & m88100reg::PSR_SUPER), "S");
264: screen.Puts(x + 21, y,
1.1.1.2 root 265: ((reg.epsr& m88100reg::PSR_BO_LE) ? "BO=LE" : "BO=BE"));
1.1.1.8 root 266: screen.Puts(x + 27, y, TA::OnOff(reg.epsr & m88100reg::PSR_SER), "SER");
267: screen.Puts(x + 31, y, TA::OnOff(reg.epsr & m88100reg::PSR_C), "Cy");
268: screen.Puts(x + 34, y, TA::OnOff(reg.epsr & m88100reg::PSR_SFD1), "SFD1");
269: screen.Puts(x + 39, y, TA::OnOff(reg.epsr & m88100reg::PSR_MXM), "MXM");
270: screen.Puts(x + 43, y, TA::OnOff(reg.epsr & m88100reg::PSR_IND), "IND");
271: screen.Puts(x + 47, y, TA::OnOff(reg.epsr & m88100reg::PSR_SFRZ), "SFRZ");
272: screen.Puts(x + 51, y, ")");
1.1 root 273:
1.1.1.2 root 274: // 制御レジスタ(左中; *IP)
1.1 root 275: x = 0;
276: y = 12;
1.1.1.8 root 277: screen.Print(x, y + 0, "xip:%08x opX:%08x(%c%c)",
1.1 root 278: reg.xip, (uint32)reg.opX,
279: cpu->OpIsBusErr(reg.opX) ? 'B' : '-',
280: cpu->OpIsDelay(reg.opX) ? 'D' : '-');
1.1.1.8 root 281: screen.Print(x, y + 1, "nip:%08x opF:%08x(%c%c)",
1.1 root 282: reg.nip, (uint32)reg.opF,
283: cpu->OpIsBusErr(reg.opF) ? 'B' : '-',
284: cpu->OpIsDelay(reg.opF) ? 'D' : '-');
1.1.1.8 root 285: screen.Print(x, y + 2, "fip:%08x", reg.fip);
1.1 root 286:
287: // 制御レジスタ (S*IP)
288: x = 32;
289: for (int i = 0; i < 3; i++) {
1.1.1.8 root 290: screen.Print(x, y + i, "%s(cr%d):%08x:%c%c",
1.1 root 291: m88100reg::sipname[i], 4 + i,
292: (reg.cr[4 + i] & m88100reg::SIP_MASK),
293: (reg.cr[4 + i] & m88100reg::SIP_V) ? 'V' : '-',
294: (reg.cr[4 + i] & m88100reg::SIP_E) ? 'E' : '-');
295: }
296:
1.1.1.2 root 297: // 制御レジスタ(右中)
1.1 root 298: x = 55;
299: y = 9;
300: for (int i = 0; i < 4; i++) {
301: int rn = 17 + i;
1.1.1.8 root 302: screen.Print(x, y++, "sr%d(cr%d):%08x", i, rn, reg.cr[rn]);
1.1 root 303: }
1.1.1.8 root 304: screen.Print(x, y++, "ssbr(cr3):%08x", reg.ssbr);
305: screen.Print(x, y++, "vbr (cr7):%08x", reg.vbr);
1.1 root 306:
1.1.1.2 root 307: // MMU レジスタ(下段)
308: y = 15;
309: for (int i = 0; i <= 2; i++) {
310: int dt = 8 + i * 3;
311: int dd = 9 + i * 3;
312: int da = 10 + i * 3;
313:
1.1.1.8 root 314: screen.Print(0, y, "dmt%d(cr%-2d):%04x",
1.1.1.2 root 315: i, dt, (reg.cr[dt] & 0xffff));
1.1.1.8 root 316: screen.Puts(15, y, "(b,s,d,l,rx, s,en ,w,v)");
317: screen.Puts(16, y, (reg.cr[dt] & m88100reg::DM_BO) ? "B" : "-");
318: screen.Puts(18, y, (reg.cr[dt] & m88100reg::DM_DAS) ? "S" : "U");
319: screen.Puts(20, y, (reg.cr[dt] & m88100reg::DM_DOUB1) ? "D" : "-");
320: screen.Puts(22, y, (reg.cr[dt] & m88100reg::DM_LOCK) ? "L" : "-");
1.1.1.2 root 321: // カンマが自然に見えるようにここだけカンマも含めて前詰めで出力
1.1.1.8 root 322: screen.Print(25, y, "%d,",
1.1.1.2 root 323: (reg.cr[dt] & m88100reg::DM_DREG_MASK) >> 7);
1.1.1.8 root 324: screen.Puts(28, y, (reg.cr[dt] & m88100reg::DM_SIGNED) ? "S" : "-");
1.1.1.2 root 325: uint32 en = (reg.cr[dt] & m88100reg::DM_EN_MASK) >> 2;
1.1.1.8 root 326: screen.Puts(30, y, m88100reg::dmt_en_str[en]);
327: screen.Puts(35, y, (reg.cr[dt] & m88100reg::DM_WRITE) ? "W" : "-");
328: screen.Puts(37, y, (reg.cr[dt] & m88100reg::DM_VALID) ? "V" : "-");
1.1.1.2 root 329:
1.1.1.8 root 330: screen.Print(40, y, "dmd%d(cr%-2d):%08x", i, dd, reg.cr[dd]);
331: screen.Print(60, y, "dma%d(cr%2d):%08x", i, da, reg.cr[da]);
1.1.1.2 root 332: y++;
333: }
1.1 root 334: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.