|
|
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:
1.1.1.2 root 7: // LUNA88K の ROM エミュレーション
8:
9: // IODevice
10: // |
11: // +----------+----------+
12: // v v
13: // ROMDevice Luna88KPROMEmuDeivce (ROM エミュレーション)
14: // |
15: // v
16: // PROMDevice (実ROM)
17:
18: #include "romemu_luna88k.h"
1.1 root 19: #include "aout.h"
20: #include "bt454.h"
21: #include "mainapp.h"
22: #include "memorystream.h"
23: #include "ram.h"
24: #include "spc.h"
25:
26: // コンストラクタ
27: Luna88kPROMEmuDevice::Luna88kPROMEmuDevice()
28: {
1.1.1.4 ! root 29: logname = "prom";
! 30: devname = "PROM";
! 31:
1.1 root 32: devaddr = baseaddr;
1.1.1.2 root 33: devlen = 256 * 1024;
34:
35: romdatalen = 1024; // サイズは適当
36: romdata.reset(new uint8 [romdatalen]);
1.1 root 37: }
38:
39: // デストラクタ
40: Luna88kPROMEmuDevice::~Luna88kPROMEmuDevice()
41: {
42: }
43:
44: bool
45: Luna88kPROMEmuDevice::Init()
46: {
1.1.1.2 root 47: MemoryStreamBE ms(romdata.get());
1.1 root 48:
49: // リセットベクタは本来2ワードだけだが他のベクタは使わないので
50: // 直接コードを書く。
51: uint32 hi = ROMIO_IPL >> 16;
52: uint32 lo = ROMIO_IPL & 0xffff;
53: ms.Write32(0x5c400000 | hi); // or.u r2, r0, (ROMIO_IPL >> 16)
54: ms.Write32(0x58420000 | lo); // or r2, r2, (ROMIO_IPL & 0xffff)
55: ms.Write32(0xf4221400); // ld r1, r2, r0
56: ms.Write32(0xf400c001); // jmp r1
57:
58: return true;
59: }
60:
61: void
62: Luna88kPROMEmuDevice::ResetHard()
63: {
64: ipl_done = false;
65: }
66:
67: // アドレスデコーダ
68: inline uint64
69: Luna88kPROMEmuDevice::Decoder(uint32 addr) const
70: {
1.1.1.2 root 71: // 折り返しなし
1.1 root 72: return addr - baseaddr;
73: }
74:
75: uint64
1.1.1.2 root 76: Luna88kPROMEmuDevice::Read8(uint32 addr)
77: {
78: // LUNA88K で Read8 呼ばれるんだっけ?
79:
80: uint64 offset = Decoder(addr) & (devlen - 1);
81:
82: // 謎の IO 空間は(ロング)ワードアクセスのみ
83: if (offset < romdatalen) {
84: return romdata[offset];
85: } else {
86: return 0xff;
87: }
88: }
89:
90: uint64
91: Luna88kPROMEmuDevice::Read16(uint32 addr)
92: {
93: // LUNA88K で Read16 呼ばれるんだっけ?
94:
95: uint64 offset = Decoder(addr) & (devlen - 1);
96:
97: // 謎の IO 空間は(ロング)ワードアクセスのみ
98: if (offset < romdatalen) {
99: return be16toh(*(uint16 *)(&romdata[offset]));
100: } else {
101: return 0xffff;
102: }
103: }
104:
105: uint64
1.1 root 106: Luna88kPROMEmuDevice::Read32(uint32 addr)
107: {
108: uint64 offset = Decoder(addr);
109:
110: // (ロング)ワードアクセスでだけ謎の I/O 空間が見える
111: switch (offset) {
112: case ROMIO_IPL - baseaddr:
113: if (!ipl_done)
114: return IPL();
115: break;
116: }
117:
1.1.1.2 root 118: offset &= (devlen - 1);
119: if (offset < romdatalen) {
120: return be32toh(*(uint32 *)(&romdata[offset]));
121: } else {
122: return 0xffffffff;
123: }
124: }
125:
126: uint64
127: Luna88kPROMEmuDevice::Write8(uint32 addr, uint32 data)
128: {
129: return 0;
130: }
131:
132: uint64
133: Luna88kPROMEmuDevice::Write16(uint32 addr, uint32 data)
134: {
135: return 0;
136: }
137:
138: uint64
139: Luna88kPROMEmuDevice::Write32(uint32 addr, uint32 data)
140: {
141: return 0;
142: }
143:
144: uint64
145: Luna88kPROMEmuDevice::Peek8(uint32 addr)
146: {
147: uint64 offset = Decoder(addr) & (devlen - 1);
148:
149: if (offset < romdatalen) {
150: return romdata[offset];
151: } else {
152: return 0xff;
153: }
1.1 root 154: }
155:
156: // 起動時の処理を行う。
157: // 成功すればエントリポイント、失敗すれば 0 を返す。
158: uint32
159: Luna88kPROMEmuDevice::IPL()
160: {
161: uint32 entry = 0;
162:
163: ipl_done = true;
164:
165: // ベクタテーブルを rte で埋めておく
166: for (int i = 0; i < 512; i++) {
167: gRAM->Write32(i * 8, 0xf400fc00 /* rte */);
168: }
169:
170: // ROM の機能テーブル
171: // 0x00001100 からあるようだ
172: // 0x0000110c GETC()
173: // 0x00001110 PUTC(c)
174: // 0x00001114 ビットマッププレーンの有効状態が入っている。
175: // bit0: plane0 有効
176: // bit1..7: plane1..7 有効
177: gRAM->Write32(0x0000110c, 0x00001300);
178: gRAM->Write32(0x00001110, 0x00001400);
179: gRAM->Write32(0x00001114, 0x00000001);
180:
181: // ROM GETC エミュレータ
182: gRAM->Write32(0x00001300, 0xfc000c00); // internal inst getc
183: gRAM->Write32(0x00001304, 0xf400c001); // jmp r1
184:
185: // ROM PUTC エミュレータ
186: gRAM->Write32(0x00001400, 0xfc001000); // internal inst putc
187: gRAM->Write32(0x00001404, 0xf400c001); // jmp r1
188:
1.1.1.3 root 189: // XXX このへん romemu_luna と同じところは共通化したほうがいい
190:
1.1 root 191: // 初期パレット
1.1.1.3 root 192: // 偶数番は白(R/G/B=15/15/15)、奇数番は黒(0/0/0)。
193: uint8 val = 0xf0;
194: gBT454->Write8(0, 0); // select palette
1.1.1.2 root 195: for (int i = 0; i < 16; i++) {
1.1.1.3 root 196: gBT454->Write8(1, val); // R
197: gBT454->Write8(1, val); // G
198: gBT454->Write8(1, val); // B
199: val ^= 0xf0;
1.1.1.2 root 200: }
1.1 root 201:
202: // SCSI
203: // BDID の書き込みによってホストデバイスがバスにアタッチされる構造なので。
204: gSPC->Write8(SPC::BDID, 7);
205:
206: if (gMainApp.host_file) {
207: // ホストのファイルを読み込んでエントリポイントアドレスを
208: // この Read アクセスの読み出し値として返す。
209: entry = gRAM->LoadFile(gMainApp.host_file, AOUT_MID_M88K);
1.1.1.3 root 210: if (entry == 0) {
211: // XXX まだコンソールがなくて停止できないのでとりあえず終了
212: exit(1);
213: }
1.1 root 214: }
215:
216: return entry;
217: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.