|
|
1.1 root 1: //
2: // nono
3: // Copyright (C) 2020 [email protected]
4: //
5:
6: #pragma once
7:
8: #include "header.h"
9: #include "bus.h"
10: #include <atomic>
11:
12: // 外部リクエストフラグ
13: // XXX m680x0 側にもよく似たものがあってどうしたもんか
14: #define CPU_REQ_TRACE (0x00000004) // デバッガ有効
15: #define CPU_REQ_PROMPT (0x00000008) // デバッガプロンプト
16: #define CPU_REQ_RELEASE (0x00000010) // 命令後に CPU 実行中断
17: #define CPU_REQ_INTR (0x00000020) // 命令後に割り込みチェック
18:
19: class m88200
20: {
21: public:
22: m88200();
23: virtual ~m88200();
24:
25: public:
26: uint64 load_8(uint32 addr) {
27: return vm_phys_read_8(addr);
28: }
29: uint64 load_16(uint32 addr) {
30: return vm_phys_read_16(addr);
31: }
32: uint64 load_32(uint32 addr) {
33: return vm_phys_read_32(addr);
34: }
35: uint64 store_8(uint32 addr, uint32 data) {
36: return vm_phys_write_8(addr, data);
37: }
38: uint64 store_16(uint32 addr, uint32 data) {
39: return vm_phys_write_16(addr, data);
40: }
41: uint64 store_32(uint32 addr, uint32 data) {
42: return vm_phys_write_32(addr, data);
43: }
44:
45: uint32 idr = 0;
46: //:
47: };
48:
49: // m88100 レジスタイメージを保持する構造体。
50: // この構造体はコピーや比較をするので、ポインタとかは置かないこと。
51: struct m88100reg
52: {
53: // PID(cr0)
54: static const uint32 PID_REV_MASK = 0x0000ff00; // 0 = MC88100
55: static const uint32 PID_VER_MASK = 0x000000fe;
56: static const uint32 PID_MASTER = 0x00000001;
57: // PSR(cr1)
58: static const uint32 PSR_SUPER = 0x80000000;
59: static const uint32 PSR_BO_LE = 0x40000000; // ByteOrder(Little)
60: static const uint32 PSR_SER = 0x20000000;
61: static const uint32 PSR_C = 0x10000000; // Carry
62: static const uint32 PSR_SFD1 = 0x00000008; // SFU1 Disable
63: static const uint32 PSR_MXM = 0x00000004; // MisalignedAccessEnable
64: static const uint32 PSR_IND = 0x00000002; // Interrupt Disable
65: static const uint32 PSR_SFRZ = 0x00000001; // Shadow Freeze
66:
67: // 例外処理で使用される S*IP
68: static const uint32 SIP_MASK = 0xfffffffcU;
69: static const uint32 SIP_V = 0x00000002;
70: static const uint32 SIP_E = 0x00000001;
71:
72: // DMTn、データ例外
73: static const uint32 DM_BO = 0x00008000;
74: static const uint32 DM_DAS = 0x00004000;
75: static const uint32 DM_DOUB1 = 0x00002000;
76: static const uint32 DM_LOCK = 0x00001000;
77: static const uint32 DM_DREG_MASK = 0x00000f80;
78: static const uint32 DM_SIGNED = 0x00000040;
79: static const uint32 DM_EN3 = 0x00000020;
80: static const uint32 DM_EN2 = 0x00000010;
81: static const uint32 DM_EN1 = 0x00000008;
82: static const uint32 DM_EN0 = 0x00000004;
83: static const uint32 DM_EN_MASK = (DM_EN0 | DM_EN1 | DM_EN2 | DM_EN3);
84: static const uint32 DM_WRITE = 0x00000002;
85: static const uint32 DM_VALID = 0x00000001;
86: // 内部識別フラグ
87: static const uint32 DM_SIZE_B = (1U << 16) | DM_EN3;
88: static const uint32 DM_SIZE_H = (1U << 17) | DM_EN3 | DM_EN2;
89: static const uint32 DM_SIZE_W = (1U << 18) | DM_EN_MASK;
90: static const uint32 DM_USR = (1U << 20);
91: static const uint32 DM_BU = DM_SIZE_B;
92: static const uint32 DM_B = DM_SIZE_B | DM_SIGNED;
93: static const uint32 DM_HU = DM_SIZE_H;
94: static const uint32 DM_H = DM_SIZE_H | DM_SIGNED;
95: static const uint32 DM_W = DM_SIZE_W;
96: static const uint32 DM_D1 = DM_SIZE_W | DM_DOUB1;
97: static const uint32 DM_D2 = DM_SIZE_W;
98:
99: // 頻繁にアクセスしそうな変数はオフセットの若いほうに持ってきておく。
100:
101: // 実行中の命令
102: uint64 opX = 0;
103: // プリフェッチ命令
104: uint64 opF = 0;
105:
106: uint32 xip = 0;
107: uint32 nip = 0;
108: uint32 fip = 0;
109:
110: uint32 r[32] {};
111: union {
112: uint32 cr[21] {};
113: struct {
114: uint32 pid; // cr0
115: uint32 psr; // cr1
116: uint32 epsr; // cr2
117: uint32 ssbr; // cr3
118: uint32 sxip; // cr4
119: uint32 snip; // cr5
120: uint32 sfip; // cr6
121: uint32 vbr; // cr7
122: uint32 dmt0; // cr8
123: uint32 dmd0; // cr9
124: uint32 dma0; // cr10
125: uint32 dmt1; // cr11
126: uint32 dmd1; // cr12
127: uint32 dma1; // cr13
128: uint32 dmt2; // cr14
129: uint32 dmd2; // cr15
130: uint32 dma2; // cr16
131: uint32 sr[4]; // cr17,18,19,20
132: };
133: };
134: union {
135: uint32 fcr[11] {};
136: struct {
137: uint32 fpecr; // fcr0
138: uint32 fphs1; // fcr1
139: uint32 fpls1; // fcr2
140: uint32 fphs2; // fcr3
141: uint32 fpls2; // fcr4
142: uint32 fppt; // fcr5
143: uint32 fprh; // fcr6
144: uint32 fprl; // fcr7
145: uint32 fpit; // fcr8
146: uint32 fpsr; // fcr62 [9]
147: uint32 fpcr; // fcr63 [10]
148: };
149: };
150:
151: // 直近のデータアクセスアドレス
152: uint32 lastaddr;
153:
154: // スーパーバイザ/ユーザモードなら true
155: bool IsSuper() const { return (psr & PSR_SUPER) != 0; }
156: bool IsUser() const { return (psr & PSR_SUPER) == 0; }
157:
158: // MXM (Misaligned Access Enable) なら true
159: bool IsMXM() const { return (psr & PSR_MXM) != 0; }
160:
161: // キャリーフラグが立っていれば 1 を返す
162: uint32 GetCY() const { return (psr >> 28) & 1; }
163: // キャリーフラグをセットする。cy は最下位ビットのみ参照する
164: void SetCY(uint cy) {
165: psr &= ~PSR_C;
166: psr |= ((cy & 1) << 28);
167: }
168:
169: static const char * const sipname[3];
170: };
171:
172: class m88kcpu : public m88100reg
173: {
174: public:
175: m88kcpu();
176: virtual ~m88kcpu();
177:
178: public:
179: void Reset(uint32 reset_vector);
180: uint32 Run(uint64 request);
181: void Release();
182:
183: uint64 total_cycle = 0; // 積算実行サイクル数
184:
185: void Interrupt();
186:
187: public:
188: // [0] 命令バス
189: // [1] データバス
190: m88200 cmmu[2];
191:
192: uint64 fetch() {
193: nip = fip;
194: opF = cmmu[0].load_32(fip);
195: fip += 4;
196: return opF;
197: }
198:
199: // op が>=0ならバスエラーは起きていない
200: // そのときに DELAYSLOT bit が 0 ならば通常
201: // bit32 が 1 ならば遅延スロット命令
202: // op が負数ならバスエラーが起きた
203: // そのときに DELAYSLOT bit が 1 ならば通常バスエラー
204: // bit32 が 0 ならば遅延スロットでのバスエラー
205: // バスエラーかどうかのチェックのほうが回数が多いため、
206: // バスエラー優先にしたい。
207:
208:
209: bool OpIsBusErr(uint64 op) const {
210: return (int64)op < 0;
211: }
212: bool OpIsDelay(uint64 op) const {
213: return (OpIsBusErr(op) ? ~op : op) & DELAYSLOT;
214: }
215:
216: // クラス外部からの xip 取得
217: uint32 Getxip() const {
218: return xip;
219: }
220:
221: enum ExceptionKind
222: {
223: NORMAL,
224: ERROR,
225: INTR,
226: TRAP,
227: };
228:
229: void Exception(int vec);
230: void ExceptionCore(int vec, ExceptionKind cause);
231: void ReadDataException(uint32 addr, uint32 flag);
232: void WriteDataException(uint32 addr, uint32 data, uint32 flag);
233:
234: // FPU
235: bool IsFPUEnable() { return !(psr & PSR_SFD1); }
236: void fpu_unimpl();
237:
238: std::atomic<uint32> atomic_reqflag {}; // リクエストフラグ
239:
240: private:
241: const uint64 DELAYSLOT = 1ULL << 62;
242:
243: // OpSetDelay を一つの op に対して複数回呼ばないでください
244: uint64 OpSetDelay(uint64 op) const {
245: return op ^ DELAYSLOT;
246: }
247:
248: // ブランチ処理用
249: void EnterBranch();
250: void ExitBranch();
251: void ExitDelayBranch();
252: // ロードストア命令用の下処理
253: bool ldst_usr(uint32 size, uint32& usr);
254: uint32 ldst_scale(uint32 size);
255: bool ldst_align(uint32 size, uint32& addr);
256:
257: #define OP_PROTO(name) void __CONCAT(op_,name)()
258: #include "m88100ops.h"
259: #undef OP_PROTO
260:
261: void op_unimpl() {
262: printf("unimplemented op XIP=%08x opX=%08x\n", xip, (uint32)opX);
263: }
264: };
265:
266: // とりあえず
267: static inline uint32
268: op32_to_12(uint32 op)
269: {
270: uint32 op12 = ((op >> 20) & 0x0fc0) | ((op >> 10) & 0x003f);
271: return op12;
272: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.