|
|
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: #include "m88100.h"
8: #include "m88100excep.h"
9: #include "debugger.h"
1.1.1.11! root 10: #include "mpu88xx0.h"
1.1 root 11:
12: #define OP_DEF(name) void __CONCAT(m88kcpu::op_,name)()
13: #define OP_FUNC(name) __CONCAT(op_,name)()
14: #include "m88100ops.cpp"
15:
1.1.1.7 root 16: // 文字列を作る前にレベルを評価するためマクロ
17: #define cpulog(lv, fmt...) do { \
18: if (__predict_false(gMPU->loglevel >= (lv))) { \
19: gMPU->putlogn(fmt); \
20: } \
21: } while (0)
22:
1.1.1.11! root 23: // 電源オン
1.1.1.8 root 24: void
25: m88kcpu::PowerOn()
26: {
1.1.1.11! root 27: // サイクルを初期化。
! 28: used_cycle = 0;
! 29:
1.1.1.8 root 30: // 履歴は電源オン時だけ初期化。
31: // (LUNA88K は ROM が正常パスで CPU リセットを行ったりするので)
32: exhist.Clear();
33: brhist.Clear();
34:
35: // この後起きるリセット例外で xip を初期化する前に参照することになるので
36: // これだけここでも初期化しておく。
37: xip = 0;
38: }
39:
1.1 root 40: // リセット例外のようなもの?
1.1.1.11! root 41: uint64
1.1.1.5 root 42: m88kcpu::Reset()
1.1 root 43: {
1.1.1.11! root 44: uint64 cycle_start = used_cycle;
! 45:
1.1.1.8 root 46: // 例外履歴に記録 (例外発生はブランチ履歴にも記録)
47: // リセット例外も発生時の XIP を記録する。(LUNA88K の ROM 1.20)
48: exhist.AddEntry(xip | 1, 0, 0xfc000000 | 0);
49: brhist.AddEntry(xip | 1, 0, 0xfc000000 | 0);
50: // デバッガに通知 (例外ブレーク用)
51: debugger_notify_exception(0);
52:
1.1.1.5 root 53: // 内部の割り込み状態をクリア
54: intr_pending = 0;
1.1.1.11! root 55: ChangeState(CPU_STATE_NORMAL);
! 56:
! 57: // 実際どこかは分からんけど PSR 設定の前にリセットしておきたい
! 58: cmmu[0].Reset();
! 59: cmmu[1].Reset();
1.1.1.4 root 60:
61: // Table 6-8 (p6-47)
1.1 root 62: psr = 0x800003ff;
1.1.1.4 root 63: // XXX ただし SFU1 は未実装なので下げておく
1.1 root 64: psr &= ~PSR_SFD1;
65:
1.1.1.2 root 66: #if defined(TEST_INTERRUPT)
1.1.1.4 root 67: psr &= ~PSR_IND;
68: psr &= ~PSR_SFRZ;
1.1 root 69: #endif
70:
1.1.1.4 root 71: SetPSR();
1.1.1.2 root 72:
1.1.1.8 root 73: fip = 0;
1.1.1.7 root 74:
75: // レジスタのうち明記されてるものをクリア。
76: // 不定と明記されてるものはリセットでは触らないでおく。
77: // scoreboard: cleared
1.1 root 78: nip = 0;
79: xip = 0;
1.1.1.4 root 80: vbr = 0;
81: fpecr = 0;
82: fpcr = 0;
83: fpsr = 0;
1.1.1.7 root 84: // DMTx は bit0(Valid) をクリア。他は不定
85: dmt0 &= ~DM_VALID;
86: dmt1 &= ~DM_VALID;
87: dmt2 &= ~DM_VALID;
1.1.1.4 root 88:
1.1 root 89: fetch();
1.1.1.11! root 90:
! 91: return used_cycle - cycle_start;
1.1 root 92: }
93:
1.1.1.11! root 94: // 1命令実行する。
! 95: // 戻り値は消費したサイクル数。
! 96: int
! 97: m88kcpu::Exec()
1.1 root 98: {
1.1.1.11! root 99: uint64 cycle_start = used_cycle;
1.1.1.5 root 100:
1.1.1.11! root 101: {
1.1 root 102: // shift pipeline
103: opX = opF;
104: xip = nip;
105:
106: // prefetch next inst
107: fetch();
108:
109: // この時点で実行しようとする命令が opX に入っている
110:
111: if (OpIsBusErr(opX)) {
112: // プリフェッチしていた命令がバスエラー
113: Exception(M88K_EXCEP_INST);
1.1.1.11! root 114: goto exit;
1.1 root 115: }
116:
117: uint32 op12 = op32_to_12(opX);
118:
119: switch (op12) {
120: #include "m88100switch.inc"
121: default:
1.1.1.2 root 122: OP_FUNC(illegal);
123: break;
1.1 root 124: }
125:
1.1.1.11! root 126: if (intr_pending && IsIntrEnable()) {
1.1.1.10 root 127: // 割り込み処理要求が来ていて、
128: // 直前の命令が割り込みを禁止していなければ割り込み
1.1.1.5 root 129: // XXX 実際は違う気がする
1.1.1.7 root 130: cpulog(4, "INTR take");
1.1.1.5 root 131: ExceptionCore(M88K_EXCEP_INTERRUPT, ExceptionKind::INTR);
1.1.1.11! root 132: goto exit;
1.1 root 133: }
134:
1.1.1.5 root 135: used_cycle++;
1.1.1.2 root 136:
1.1 root 137: }
138:
1.1.1.6 root 139: exit:
1.1.1.11! root 140: return used_cycle - cycle_start;
1.1.1.5 root 141: }
142:
1.1.1.11! root 143: // STOP 状態で 1 命令実行する。
! 144: // 戻り値は消費したサイクル数。
! 145: int
! 146: m88kcpu::ExecPseudoStop()
1.1 root 147: {
1.1.1.11! root 148: instruction_in_stop++;
! 149: if (instruction_in_stop > 4) {
! 150: ChangeState(CPU_STATE_NORMAL);
! 151: }
1.1 root 152:
1.1.1.11! root 153: return Exec();
1.1.1.5 root 154: }
155:
1.1.1.11! root 156:
1.1 root 157: // 通常の例外。
1.1.1.2 root 158: // DataAccessException, エラー、割り込み、TRAP からは使わない。
1.1 root 159: // vec はベクタ番号。
160: void
161: m88kcpu::Exception(int vec)
162: {
163: ExceptionCore(vec, ExceptionKind::NORMAL);
164: }
165:
166: // 例外処理コア部分
167: // vec はベクタ番号。
168: void
169: m88kcpu::ExceptionCore(int vec, ExceptionKind cause)
170: {
1.1.1.4 root 171: uint syscall = 0;
172:
1.1.1.3 root 173: // 例外履歴に記録 (例外発生はブランチ履歴にも記録)
1.1.1.4 root 174: // OpenBSD システムコールなら番号もついでに記録。
175: // システムコール番号は tb0 発行時点で r13 にセットされている。
176: // ただし 0 番は syscall(2) (間接システムコール) で、実際の番号は r2。
177: // 198番 __syscall(2) だと r2:r3 (なので実質 r3)。
178: if (vec == 450) {
179: syscall = r[13];
180: if (syscall == 0) {
181: syscall = r[2];
182: } else if (syscall == 198) {
183: syscall = r[3];
184: }
185: syscall &= 0xfff;
186: }
1.1.1.5 root 187: uint32 from = xip | (IsSuper() ? 1 : 0);
188: uint32 inst = 0xfc000000 | (syscall << 12) | vec;
189: exhist.AddEntry(from, 0, inst);
190: brhist.AddEntry(from, 0, inst);
1.1.1.3 root 191: // デバッガに通知 (例外ブレーク用)
1.1.1.4 root 192: debugger_notify_exception(vec);
193:
194: // 命令中で起きる例外はとりあえず全部2クロック追加? (Table.7-5)
195: if (cause != ExceptionKind::INTR) {
1.1.1.5 root 196: AddCycle(2);
1.1.1.4 root 197: }
1.1.1.3 root 198:
1.1 root 199: if (psr & PSR_SFRZ) {
200: if (cause != ExceptionKind::TRAP) {
1.1.1.7 root 201: cpulog(2, "SFRZ Error Exception");
1.1 root 202: vec = M88K_EXCEP_ERROR;
203: cause = ExceptionKind::ERROR;
204: }
205: } else {
1.1.1.7 root 206: cpulog(2, "Exception %x", vec);
1.1.1.2 root 207: if (vec != 1) {
1.1.1.7 root 208: cpulog(1, "Exception %x x=%x n=%x f=%x", vec, xip, nip, fip);
1.1.1.2 root 209: }
1.1 root 210: sxip = xip;
211: snip = nip;
1.1.1.7 root 212: sfip = fip;
1.1 root 213:
214: sxip |= SIP_V;
215: snip |= SIP_V;
1.1.1.4 root 216: sfip |= SIP_V;
1.1 root 217:
218: if (OpIsBusErr(opX)) {
219: sxip |= SIP_E; // E bit
220: }
221: if (OpIsBusErr(opF)) {
222: snip |= SIP_E; // E bit
223: }
224:
225: if (vec == M88K_EXCEP_UNIMPL_OP) {
226: sxip &= ~SIP_V;
227: }
228: }
229:
1.1.1.2 root 230: if (cause != ExceptionKind::DATA) {
231: // データアクセス例外以外は、
232: // データパイプラインはフラッシュ状態とする。
233: // ほんとうは違う。かも。
234: dmt0 = 0;
235: } else {
236: // xip: ld/st/xmem
237: // nip: next
238: // fip: fetch
239:
240: // rom1.2 は DAE が起きると、
241:
242: // ROM挙動 CPU の RTE 挙動
243: // sfip = sxip
244: // sxip -> ~V (INVALID) CPU はそもそも sxip を評価しない
245: // snip = 0 (INVALID) CPU はこれを nop 相当に処理する
246: // rte
247:
248: // してくる。そのまま読むと命令を再実行しようとしているように
249: // 読めるが、再実行すると無限ループになってしまう。
250: // DAE の時点で xip が進んでいることを期待して利用している?
251:
252: // openbsd は
253: // xmem の write バスエラーを検知すると命令を再実行するために
254: // fip = nip, nip = xip して rte する。ということは xip = xmem に
255: // なっていることを期待している。
256:
257: // というわけで
258: // ld で DataAccessException のときは、実CPUはすでに次の命令を
259: // 実行している?
260: // もう少し考えると、スコアボードでレジスタの干渉がなければ、
261: // 実行している?
262:
263: // 仕方がないのでハックでごまかす。
264: // rte のほうも参照のこと。
265:
266: if (IsSuper() && xip >= 0x41000000 && xip < 0x42000000) {
267: // 遅延例外機構がないので、ROM 合わせのハック。
268: sxip = snip;
269: }
270: }
271:
1.1 root 272: epsr = psr;
1.1.1.2 root 273: SetPSR(psr | PSR_SUPER | PSR_SFD1 | PSR_IND | PSR_SFRZ);
1.1 root 274:
275: fip = vbr + (vec << 3);
276: fetch();
1.1.1.3 root 277: // ここでベクタに飛ぶのだが、ベクタ内の2命令でおそらく必ずもう一度
278: // 分岐してそっちでも履歴が残るので、ここでブランチ履歴を残すのは
279: // ちょっと冗長という気もする。
280:
1.1 root 281: if (OpIsBusErr(opF)) {
282: if (cause == ExceptionKind::ERROR) {
283: // double bus fault
284: // 実機は無限ループ状態
285: PANIC("Infinite ERROR (double bus fault)");
286: } else {
287: ExceptionCore(M88K_EXCEP_ERROR, ExceptionKind::ERROR);
288: }
289: }
290: }
291:
1.1.1.10 root 292: inline uint32
1.1.1.5 root 293: m88kcpu::Calcdmt(uint32 flag)
294: {
295: return
296: ((psr & PSR_BO_LE) ? DM_BO : 0)
297: | ((IsSuper() && !(flag & DM_USR)) ? DM_DAS : 0)
298: | DM_VALID;
299: }
300:
1.1 root 301: // データアクセス例外(Read)
1.1.1.5 root 302: // ld.b, ld.h, ld.hu, ld 用
1.1 root 303: void
1.1.1.5 root 304: m88kcpu::ReadDataException32(uint32 addr, uint32 flag)
1.1 root 305: {
306: // ミスアラインドはこの例外より前にチェックされていて、
307: // ここにはアラインドしかこない。
308: dma0 = addr & ~0x3;
1.1.1.5 root 309: dmt0 = Calcdmt(flag)
1.1 root 310: | (FLD_D << 7)
311: | (flag & DM_SIGNED)
312: | ((flag & DM_EN_MASK) >> (addr & 0x03))
1.1.1.5 root 313: ;
314: dmt1 &= ~DM_VALID;
315: dmt2 &= ~DM_VALID;
1.1.1.7 root 316: cpulog(1, "ReadDAE xip=%x addr=%x", xip, addr);
1.1.1.2 root 317: ExceptionCore(M88K_EXCEP_DATA, ExceptionKind::DATA);
1.1 root 318: }
319:
1.1.1.5 root 320: // データアクセス例外(Read)
321: // ld.d 用
322: void
323: m88kcpu::ReadDataException64(uint32 addr, uint32 flag)
324: {
325: // ミスアラインドはこの例外より前にチェックされていて、
326: // ここにはアラインドしかこない。
327: dma0 = addr;
328: dmt0 = Calcdmt(flag)
329: | DM_DOUB1 // ダブルワードの第1アクセスのときセット
330: | (FLD_D << 7)
331: | DM_EN_MASK // 32ビット有効
332: ;
333:
334: dma1 = dma0 + 4;
335: dmt1 = Calcdmt(flag)
336: | (FLD_D2 << 7)
337: | DM_EN_MASK // 32ビット有効
338: ;
339:
340: dmt2 &= ~DM_VALID;
341:
342: if ((flag & DM_DOUB1) == 0) {
343: // .d の2ワード目がバスエラー。第1ワードのアクセスは成功した。
1.1.1.11! root 344: // DMx0 が例外を起こしたアクセスを示す。
! 345: // Manual 6.7.3
! 346: dma0 = dma1;
! 347: dmt0 = dmt1;
! 348: dmt1 &= ~DM_VALID;
1.1.1.5 root 349: }
350:
1.1.1.7 root 351: cpulog(1, "ReadDAE64 xip=%x addr=%x", xip, addr);
1.1.1.5 root 352: ExceptionCore(M88K_EXCEP_DATA, ExceptionKind::DATA);
353: }
354:
1.1 root 355: // データアクセス例外(Write)
1.1.1.5 root 356: // st.b, st.h, st.hu, st 用
1.1 root 357: void
1.1.1.5 root 358: m88kcpu::WriteDataException32(uint32 addr, uint32 flag)
1.1 root 359: {
360: // ミスアラインドはこの例外より前にチェックされていて、
361: // ここにはアラインドしかこない。
362: dma0 = addr & ~0x3;
1.1.1.5 root 363: dmt0 = Calcdmt(flag)
1.1 root 364: | (FLD_D << 7)
365: | ((flag & DM_EN_MASK) >> (addr & 0x03))
366: | DM_WRITE
1.1.1.5 root 367: ;
368: dmd0 = rD;
1.1 root 369:
1.1.1.5 root 370: dmt1 &= ~DM_VALID;
371: dmt2 &= ~DM_VALID;
1.1.1.7 root 372: cpulog(1, "WriteDAE xip=%x addr=%x", xip, addr);
1.1.1.2 root 373: ExceptionCore(M88K_EXCEP_DATA, ExceptionKind::DATA);
374: }
375:
1.1.1.5 root 376: // データアクセス例外(Write)
377: // st.d 用
378: void
379: m88kcpu::WriteDataException64(uint32 addr, uint32 flag)
380: {
381: // ミスアラインドはこの例外より前にチェックされていて、
382: // ここにはアラインドしかこない。
383: dma0 = addr & ~0x3;
384: dmt0 = Calcdmt(flag)
385: | DM_DOUB1 // ダブルワードの第1アクセスのときセット
386: | (FLD_D << 7)
387: | DM_EN_MASK
388: | DM_WRITE
389: ;
390: dmd0 = rD;
391:
392: dma1 = dma0 + 4;
393: dmt1 = Calcdmt(flag)
394: | (FLD_D2 << 7)
395: | DM_EN_MASK
396: | DM_WRITE
397: ;
398: dmd1 = rD2;
399:
400: dmt2 &= ~DM_VALID;
401:
402: if ((flag & DM_DOUB1) == 0) {
403: // .d の2ワード目がバスエラー。第1ワードのアクセスは成功した。
1.1.1.11! root 404: // DMx0 が例外を起こしたアクセスを示す。
! 405: // Manual 6.7.3
! 406: dma0 = dma1;
! 407: dmt0 = dmt1;
! 408: dmd0 = dmd1;
! 409: dmt1 &= ~DM_VALID;
1.1.1.5 root 410: }
411:
1.1.1.7 root 412: cpulog(1, "WriteDAE64 xip=%x addr=%x", xip, addr);
1.1.1.5 root 413: ExceptionCore(M88K_EXCEP_DATA, ExceptionKind::DATA);
414: }
415:
1.1.1.2 root 416: // データアクセス例外(xmem)
1.1.1.5 root 417: // xmem には .d は無い
1.1.1.2 root 418: void
1.1.1.5 root 419: m88kcpu::XmemDataException(uint32 addr, uint32 flag)
1.1.1.2 root 420: {
421: dma0 = addr & ~0x3;
1.1.1.5 root 422: dmt0 = Calcdmt(flag)
423: | DM_LOCK // xmem でセット
1.1.1.2 root 424: | (FLD_D << 7)
425: | (flag & DM_SIGNED)
426: | ((flag & DM_EN_MASK) >> (addr & 0x03))
1.1.1.5 root 427: ;
1.1.1.2 root 428:
1.1.1.5 root 429: dma1 = dma0;
430: dmt1 = Calcdmt(flag)
431: | DM_LOCK // xmem でセット
1.1.1.2 root 432: | (FLD_D << 7)
433: | (flag & DM_SIGNED)
434: | ((flag & DM_EN_MASK) >> (addr & 0x03))
435: | DM_WRITE
1.1.1.5 root 436: ;
437: dmd1 = rD;
1.1.1.2 root 438:
1.1.1.5 root 439: dmt2 &= ~DM_VALID;
1.1.1.2 root 440:
441: // ミスアラインドはこの例外より前にチェックされていて、
442: // ここにはアラインドしかこない。
443: if (cmmu[1].fault_code != m88200::FAULT_CODE_BUSERR
444: || cmmu[1].acc_read) {
445: // アドレス変換フォルトまたは read 時点
446: // nop
1.1 root 447: } else {
1.1.1.2 root 448: // xmem の write 時点
1.1.1.5 root 449: dmt0 &= ~DM_VALID;
1.1 root 450: }
1.1.1.2 root 451:
1.1.1.7 root 452: cpulog(1, "xmemDAE xip=%x addr=%x", xip, addr);
1.1.1.2 root 453: ExceptionCore(M88K_EXCEP_DATA, ExceptionKind::DATA);
1.1 root 454: }
455:
1.1.1.10 root 456: // FPxS レジスタをセット
1.1.1.5 root 457: void
1.1.1.10 root 458: m88kcpu::SetFPxS(uint32& h, uint32& l, double src, uint32 ts)
1.1.1.5 root 459: {
1.1.1.10 root 460: // FPHS[12]、FPLS[12] は以下の構造
461: //
462: // 3 2 1 0
463: // 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
464: // +-+---------------------+---------------------------------------+
465: // |S| Exponent(11bit) | High Order 20 bits of Mantissa | FPHSn
466: // +-+---------------------+---------------------------------------+
467: //
468: // +---------------------------------------------------------------+
469: // | Low Order bits of Mantissa, or Integer | FPLSn
470: // +---------------------------------------------------------------+
471: //
472: // ts が 1 (double) の場合は IEEE754 double と同じ。
473: // ts が 0 (single) の場合は float を double にキャスト (拡大変換) した
474: // ものではないことに注意。
475: // S(符号ビット)はそのまま。float の Mantissa (23bit) のうち上位 20bit
476: // を FPHSn に、残り 3bit を FPLSn の上位 3bit に。ここまではいい。
477: // Exponent は float の指数部(8bit、バイアス=127) の値を *そのまま*
478: // 符号拡張(?)する。
479: // (float)1.0 は 1.0 * 2^0 なのでバイアス込みの指数部は 127、
480: // (float)2.0 は 1.0 * 2^1 なのでバイアス込みの指数部は 128。
481: // バイアス込みにした値は符号なし数のはずだが、ここではこれを 11bit に
482: // 符号拡張して FPHSn の Exponent 部に格納するようだ。取り出す際に下位
483: // 8bit しか取り出さなければ害はないし、符号拡張する方がハードウェア的に
484: // 都合がよかったとかだろうか。
485: // 仮に普通に double に変換すると double の指数部バイアスは 1023 なので
486: // バイアス込みの指数部は先程の例だとそれぞれ 1023、1024 になるが
487: // これではないということ。
488:
489: union64 u;
490: u.q = d2u(src);
491: if (ts == 0) {
492: // single
493:
494: uint32 exp;
495: // src は普通の double なのでこの指数部を取り出す
496: uint32 double_biased = (u.h >> 20) & 0x7ff;
497: if (double_biased == 0x7ff) {
498: // Inf, NAN
499: exp = 0x7ff00000;
500: } else {
501: // double のバイアスを外して float のバイアスを足す
502: int float_biased = (double_biased - 1023) + 127;
503: // この 8bit 値を 11bit に符号拡張して所定の位置へ
504: exp = ((int32)(float_biased << 24)) >> 4;
505: exp &= 0x7ff00000;
506: }
507:
508: h = (u.h & 0x800fffff) | exp;
509: l = u.l;
510: } else {
511: // double
512: h = u.h;
513: l = u.l;
514: }
515: }
516:
517: // FPR[HL] レジスタに double 値をセット
518: // - それ以外のフィールドは保存する XXX ここでクリアしてもいいか?
519: // - XXX Guard, Round, Sticky (, AddOne) はまだない
520: void
521: m88kcpu::SetFPRx(double src)
522: {
523: union64 u;
524: uint32 exp;
525:
526: u.q = d2u(src);
527:
528: // Sign は FPRH
529: fprh &= ~(FPRH_SIGN | FPRH_MANT); // Mantissa もついでにクリア
530: fprh |= u.h & 0x80000000;
531:
532: // Exp は FPIT。
533: // double は 11bit だが FPIT::RESEXP は 12bit なので 1bit 符号拡張する。
534: // 符号付き数(正確には負数)の右シフトは実装依存だが gcc, clang は
535: // 算術右シフトになる。
536: //
537: // 3 2
538: // 1 0 9 8 7 6 5 4 3 2 1 0 9
539: // +-+---------------------+-
540: // double |S| Exponent(11bit) |
541: // +-+---------------------+-
542: //
543: // +---------------------+-+-
544: // u.h<<1 | Exponent(11bit) |X|
545: // +---------------------+-+-
546: //
547: // +-----------------------+-
548: // exp>>1 | Exponent(12bit) |
549: // +-----------------------+-
550: exp = u.h << 1;
551: exp = (int32)exp >> 1;
552: fpit &= ~FPIT_RESEXP;
553: fpit |= exp & FPIT_RESEXP;
554:
555: // Mantissa は FPRH, FPRL
556: // 上位側(FPRH)には最上位(実数桁)の隠しビットを含む。
557: fprh |= (u.h & 0x000fffff);
558: fprh |= FPRH_1;
559: fprl = u.l;
560: }
561:
562: // FP Precise 例外。浮動小数点数1つの場合。
563: void
564: m88kcpu::FPPreciseException(uint32 cause, double s2)
565: {
566: SetFPS2(s2, m88100opf_FP_T2(opX));
567: FPPreciseException(cause);
568: }
569:
570: // FP Precise 例外。浮動小数点数2つの場合。
571: void
572: m88kcpu::FPPreciseException(uint32 cause, double s1, double s2)
573: {
574: SetFPS1(s1, m88100opf_FP_T1(opX));
575: SetFPS2(s2, m88100opf_FP_T2(opX));
576: FPPreciseException(cause);
577: }
578:
579: // FP Precise 例外。
580: void
581: m88kcpu::FPPreciseException(uint32 cause)
582: {
583: assert(cause == FPECR_FIOV ||
584: cause == FPECR_FUNIMP ||
585: cause == FPECR_FPRV ||
586: cause == FPECR_FROP ||
587: cause == FPECR_FDVZ);
588:
589: fpecr = cause;
590:
591: // FPPT(FP Precise operation Type Register)
592: fppt = opX & 0xffe0; // Opcode, T1, T2, TD は opX と同じ位置
593: fppt |= m88100opf_D(opX); // DEST
594:
595: Exception(M88K_EXCEP_SFU1_PRECISE);
596: }
597:
598: // FP Imprecise 例外。
599: void
600: m88kcpu::FPImpreciseException(uint32 cause)
601: {
602: assert(cause == FPECR_FUNF ||
603: cause == FPECR_FOVF ||
604: cause == FPECR_FINX);
605:
606: fpecr = cause;
607:
608: // FPIT(FP Imprecise operation Type Register)
609: fpit &= FPIT_RESEXP;
610: fpit |= opX & FPIT_OPCODE;
611: fpit |= (opX & 0x00000020) << 5; // DESTSIZ
612: fpit |= (fpcr & 0x0000001f) << 5; // EFINV,EFDVZ,EFUNF,EFOVR,EFINX
613: fpit |= m88100opf_D(opX); // DEST
614:
615: // FPRH(FP Result High Register)
616: fprh &= ~FPRH_RNDMODE;
617: fprh |= (fpcr & FPCR_RM) << 14;
1.1.1.5 root 618:
1.1.1.10 root 619: Exception(M88K_EXCEP_SFU1_IMPRECISE);
1.1.1.5 root 620: }
621:
1.1 root 622: void
1.1.1.5 root 623: m88kcpu::Interrupt(int level)
1.1 root 624: {
1.1.1.5 root 625: // level は 0 か 1。
626: intr_pending = level;
1.1.1.11! root 627:
! 628: if (intr_pending && IsIntrEnable() && (cpu_state == CPU_STATE_STOP)) {
! 629: // 割り込みを受け付けたら STOP 解除。
! 630: ChangeState(CPU_STATE_NORMAL);
! 631: }
1.1 root 632: }
633:
634: void
635: m88kcpu::fpu_unimpl()
636: {
637: printf("%s\n", __func__);
1.1.1.10 root 638: FPPreciseException(FPECR_FUNIMP);
1.1 root 639: }
1.1.1.2 root 640:
641: OP_DEF(illegal)
642: {
643: // 本来は不当命令例外?
1.1.1.7 root 644: cpulog(0, "Illegal instruction %08x", (uint32)opX);
1.1.1.2 root 645: }
1.1.1.11! root 646:
! 647: void
! 648: m88kcpu::ChangeState(uint32 new_state)
! 649: {
! 650: if (new_state == CPU_STATE_STOP) {
! 651: instruction_in_stop = 0;
! 652: }
! 653:
! 654: if (cpu_state != new_state) {
! 655: cpu_state = new_state;
! 656: // スケジューラに通知
! 657: dev->NotifyCPUMode(cpu_state);
! 658: }
! 659: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.