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