|
|
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: #include "m88100acc.h"
1.1.1.5 root 8: #include <cfenv>
9: #include <cmath>
1.1.1.2 root 10:
1.1 root 11: // 命令のフィールド取り出し
1.1.1.2 root 12: #define FLD_D m88100opf_D(opX)
13: #define FLD_S1 m88100opf_S1(opX)
14: #define FLD_S2 m88100opf_S2(opX)
15: #define FLD_CR m88100opf_CR(opX)
16: #define B5 m88100opf_B5(opX)
17: #define M5 m88100opf_M5(opX)
18: #define W5 m88100opf_W5(opX)
19: #define O5 m88100opf_O5(opX)
20: #define IMM16 m88100opf_IMM16(opX)
21: #define VEC9 m88100opf_VEC9(opX)
1.1 root 22:
23: // 符号拡張・シフト済みのディスプレースメント
24: // XXX: (負数の右シフト)GCC only
25: #define D16 (((int32)(int16)opX) << 2)
26: #define D26 (((int32)(opX << 6) >> 4))
27: #define IsCO ((opX >> 8) & 1)
28: #define IsCI ((opX >> 9) & 1)
29:
30: // レジスタアクセス
31: #define rD (r[FLD_D])
32: #define rS1 (r[FLD_S1])
33: #define rS2 (r[FLD_S2])
1.1.1.4 root 34: // ダブルワードの2ワード目
1.1.1.5 root 35: #define FLD_D2 ((FLD_D + 1) & 0x1f)
36: #define rD2 (r[FLD_D2])
1.1 root 37:
1.1.1.5 root 38: // FP フィールド
39: #define FP_T1 m88100opf_FP_T1(opX)
40: #define FP_T2 m88100opf_FP_T2(opX)
41: #define FP_TD m88100opf_FP_TD(opX)
42:
1.1.1.11! root 43: // XXX t(サイズ)が原因で Reserved Operand になった時の S1, S2 はどうなる?
1.1.1.5 root 44: #define FP_GET(v, t, n) \
45: do { \
46: if (t == 0) { \
47: v = u2f(r[n]); \
48: } else if (t == 1) { \
1.1.1.11! root 49: v = u2d(((uint64)r[n] << 32) | r[(n + 1) & 31]); \
1.1.1.5 root 50: } else { \
1.1.1.11! root 51: FPPreciseException(FPECR_FROP); \
1.1.1.5 root 52: return; \
53: } \
54: } while (0)
55:
56: #define FP_SET(t, n, v) \
57: do { \
58: if (t == 0) { \
59: r[n] = f2u(v); \
60: } else if (t == 1) { \
61: uint64 tmp = d2u(v); \
62: r[n] = tmp >> 32; \
1.1.1.11! root 63: if (__predict_true(n != 31)) \
! 64: r[n + 1] = (uint32)tmp; \
1.1.1.5 root 65: } else { \
1.1.1.11! root 66: FPPreciseException(FPECR_FROP); \
1.1.1.5 root 67: return; \
68: } \
69: } while (0)
1.1 root 70:
71: // ブランチ命令入り口
72: inline void
1.1.1.4 root 73: m88kcpu::EnterBranch(uint32 toaddr)
1.1.1.2 root 74: {
1.1.1.9 root 75: // ジャンプ先アドレスの下位2bitはマスクされる
76: toaddr &= ~3;
1.1.1.2 root 77: // ブランチヒストリに登録しつつ、
78: // ブランチヒストリからブランチ状況を取得
1.1.1.5 root 79: auto e = brhist.AddEntry(xip | (IsSuper() ? 1 : 0), toaddr, opX);
1.1.1.2 root 80: fip = toaddr;
81:
82: // STOP 検出。
83: // m88k には STOP 状態 (何もせず割り込みだけ待つ状態。m68k の STOP 命令
84: // による STOP 状態に相当するもの) は存在せず、割り込みが起きるまで NOP
85: // 相当の命令を無限ループで実行し続ける方法が一般的にとられる。
86: // 実機であれば (電力が無駄なこと以外は) これで特段困らないかも知れないが
87: // エミュレータ (特に高速モード) ではこのような無限ループはホストの CPU
88: // がぶん回る状況になるため避けたい。そのためこの無限ループを検出したい。
89: // ただし特定の(または定番の)命令列があるわけではなく、任意の無限ループが
90: // 用いられているため、汎用的に自動検出する必要がある。
91:
92: // ループの 1 回目のブランチで初期化して、
93: // 2 回目のブランチで STOP だったかどうかをチェックする。
94: // 3 回目以降の場合は STOP でなかったので、もうチェックする必要はない。
95:
96: // m68k の STOP 命令が特権命令なので、それに倣ってここでも特権状態のみを
97: // 対象とする。
98:
99: // 通常のブランチで来る回数がはるかに多いと考えられるので、
100: // 先にカウント数をチェック対象かどうか調べる。
101: if (e.count < 3 && IsSuper()) {
102: if (e.count == 1) {
103: // 新規ブランチ
104: // 初期化
105: nop_counter = 0;
1.1.1.8 root 106: } else if (pseudo_stop_enable) {
107: // 疑似 STOP 状態有効のときに、
1.1.1.2 root 108: // e.count == 2 のときだけ STOP の検証をすれば良い。
109:
110: // d はブランチ間の命令数
111: uint32 d = (xip - toaddr) / sizeof(uint32);
112: // 遅延ブランチなら 1 命令余分に実行するはずなので 1 足す
1.1.1.9 root 113: if ((opX & (1 << 26)) != 0) {
1.1.1.2 root 114: d++;
115: }
116: // ブランチ間の命令がすべて NOP なら STOP ということにする。
117: if (nop_counter == d) {
118: atomic_reqflag |= CPU_REQ_STOP;
119: }
1.1.1.8 root 120:
121: // OpenBSD 6.6 では
122: // L1: tb1 #1 r0, #0xff
123: // ld r13, r21, #0x168
124: // bcnd.n eq0, r13, L1
125: // or r2, r25, #0x5ea0
126: // の命令列が使用されている。
127: // これについては tb1 で実装してある。
1.1.1.2 root 128: }
129: // STOP ではなかったら、あとは放置していい
130: }
131: }
132:
1.1 root 133: // 通常(即時)ブランチ出口
134: inline void
135: m88kcpu::ExitBranch()
136: {
137: // re-fetch branched instruction
138: fetch();
139: }
140:
141: // 遅延ブランチ出口
1.1.1.4 root 142: // 速度を稼ぐため、ビット反転だけでこれを区別しているので、
143: // 同じ op 中で複数回呼び出さないこと。
1.1 root 144: inline void
145: m88kcpu::ExitDelayBranch()
146: {
1.1.1.4 root 147: opF ^= DELAYSLOT;
1.1 root 148: }
149:
150: // ロードストアユニットの usr の処理。
151: // 正常なら true を返す (ので呼び出し側は実行継続)、
152: // 例外が起きたら処理して false を返すので呼び出し側は即リターンすること。
153: inline bool
1.1.1.2 root 154: m88kcpu::ldst_usr(uint32& usr)
1.1 root 155: {
156: usr = (opX & (1 << 8)) ? DM_USR : 0;
157: if (IsUser() && usr) {
158: Exception(M88K_EXCEP_PRIV);
159: return false;
160: }
161: return true;
162: }
163:
1.1.1.2 root 164: // MEMO: ロードストアでの usr の処理で、CMMU に対して
165: // usr を引数ではなくSetSuper() の呼び出しで渡すようにしている。
166: // データのロードストアだけがあるのなら usr を引数で渡すほうが
167: // 効率的だが、CMMU は 命令/データで同じものを使うため、
168: // 命令 CMMU では 100% 無駄な引数の引き渡しが必要になってしまう。
169: // そして命令アクセスのほうが何倍も比率が多い。
170: // .usr 指定は比率としてはレアなので、状態変更メソッドによる
171: // 方法にしてみた。
172:
1.1 root 173: // ロードストアユニットの scale の処理。addr を返す。
174: inline uint32
175: m88kcpu::ldst_scale(uint32 size)
176: {
1.1.1.9 root 177: if ((opX & (1 << 9)) != 0) {
1.1 root 178: return rS1 + rS2 * size;
179: } else {
180: return rS1 + rS2;
181: }
182: }
183:
184: // ロードストアユニットの align の処理。
185: // 正常なら true を返す (ので呼び出し側は実行継続)、
186: // 例外が起きたら処理して false を返すので呼び出し側は即リターンすること。
187: inline bool
188: m88kcpu::ldst_align(uint32 size, uint32& addr)
189: {
1.1.1.9 root 190: if ((addr & (size - 1)) != 0) {
1.1 root 191: if (IsMXM()) {
192: addr &= ~(size - 1);
193: } else {
194: Exception(M88K_EXCEP_MISALIGNED);
195: return false;
196: }
197: }
198: return true;
199: }
200:
201: // ロードストアユニットの usr と scale の処理 (呼び出し用マクロ)
202: #define LDST_USR_SCALE(size) do { \
1.1.1.2 root 203: if (ldst_usr(usr) == false) \
1.1 root 204: return; \
205: addr = ldst_scale(size); \
206: } while (0)
207:
208: // ロードストアユニットの align の処理 (呼び出し用マクロ)
209: #define LDST_ALIGN(size) do { \
210: if (ldst_align(size, addr) == false) \
211: return; \
212: } while (0)
213:
214: // ロードストアユニットのまとめたもの
215: #define LDST_USR_SCALE_ALIGN(size) do { \
216: LDST_USR_SCALE(size); \
217: LDST_ALIGN(size); \
218: } while (0)
219:
220: // 幅規制付き算術左シフト
221: static inline uint32
222: ASL(uint32 a, int n)
223: {
224: if (n <= 0)
225: return a;
226: if (n >= 32)
227: return 0;
228: return a << n;
229: }
230:
231: // 幅規制付き算術右シフト
232: static inline uint32
233: ASR(uint32 a, int n)
234: {
235: if (n <= 0)
236: return a;
237: if (n >= 32)
238: return (int32)a < 0 ? -1 : 0;
239: // XXX: 負数の右シフト
240: return (int32)a >> n;
241: }
242:
243: // 幅規制付き論理右シフト
244: static inline uint32
245: LSR(uint32 a, int n)
246: {
247: if (n <= 0)
248: return a;
249: if (n >= 32)
250: return 0;
251: return a >> n;
252: }
253:
254:
255: // 右ローテート
256: static inline uint32
257: ROR(uint32 a, int n)
258: {
259: // TODO: 各種コンパイラごとにビルトインがあったりなかったりするらしい
260: n &= 31;
261: if (n == 0) {
262: return a;
263: } else {
264: return (a >> n) | (a << (32 - n));
265: }
266: }
267:
268: // add でのオーバーフロー条件
269: static inline bool
270: isovf_add(uint32 s1, uint32 s2, uint32 res)
271: {
272: return (int32)((s1 ^ res) & (s2 ^ res)) < 0;
273: }
274: // sub でのオーバーフロー条件
275: static inline bool
276: isovf_sub(uint32 s1, uint32 s2, uint32 res)
277: {
278: return (int32)((s1 ^ s2) & (s1 ^ res)) < 0;
279: }
280:
281: // bcnd のやつ
282: static inline int
283: acc_cnd(uint32 r)
284: {
285: int rv;
1.1.1.9 root 286: if ((r & 0x80000000) != 0) {
1.1 root 287: if (r == 0x80000000) {
288: rv = 0x8;
289: } else {
290: rv = 0x4;
291: }
292: } else {
293: if (r == 0) {
294: rv = 0x2;
295: } else {
296: rv = 0x1;
297: }
298: }
299: return rv;
300: }
301:
302: // bitfield
303: static inline uint32
304: acc_bf(int w, int ofs)
305: {
306: uint32 m;
307: if (w == 0) {
308: m = 0xFFFFFFFFU;
309: } else {
310: m = ~(0xFFFFFFFFU << w);
311: }
312: return m << ofs;
313: }
314:
1.1.1.11! root 315: // m88100 FPCR の RndMode (0..3) から <cfenv> の丸めモード値への変換。
! 316: // 大抵ここに渡す前に 3 で AND しているはずなので範囲外は考慮しない。
! 317: static int rm_to_round[4] = {
! 318: FE_TONEAREST,
! 319: FE_TOWARDZERO,
! 320: FE_DOWNWARD,
! 321: FE_UPWARD,
! 322: };
! 323:
! 324:
1.1 root 325: // ここから命令定義
326:
327: // 000000_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
328: OP_DEF(xmem_bu_imm)
329: {
330: uint32 addr;
331: uint64 tmp;
332:
333: addr = rS1 + IMM16;
334: LDST_ALIGN(1);
335:
1.1.1.5 root 336: AddCycle(4); // Table.7-3
1.1.1.4 root 337:
1.1 root 338: lastaddr = addr;
1.1.1.6 root 339: tmp = cmmu[1].xmem_8(addr, rD & 0xff);
1.1 root 340: if ((int64)tmp < 0) {
1.1.1.5 root 341: XmemDataException(addr, DM_BU | DM_LOCK);
1.1 root 342: return;
343: }
344: if (FLD_D == 0)
345: return;
346: rD = tmp;
347: }
348:
349: // 000001_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
350: OP_DEF(xmem_w_imm)
351: {
352: uint32 addr;
353: uint64 tmp;
354:
355: addr = rS1 + IMM16;
356: LDST_ALIGN(4);
357:
1.1.1.5 root 358: AddCycle(4); // Table.7-3
1.1.1.4 root 359:
1.1 root 360: lastaddr = addr;
1.1.1.2 root 361: tmp = cmmu[1].xmem_32(addr, rD);
1.1 root 362: if ((int64)tmp < 0) {
1.1.1.5 root 363: XmemDataException(addr, DM_W | DM_LOCK);
1.1 root 364: return;
365: }
366: if (FLD_D == 0)
367: return;
368: rD = tmp;
369: }
370:
371: // 000010_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
372: OP_DEF(ld_hu_imm)
373: {
374: uint32 addr;
1.1.1.4 root 375: uint64 data;
1.1 root 376:
377: addr = rS1 + IMM16;
378: LDST_ALIGN(2);
379:
1.1.1.5 root 380: AddCycle(3); // Table.7-3
1.1.1.4 root 381:
1.1 root 382: lastaddr = addr;
1.1.1.4 root 383: data = cmmu[1].load_16(addr);
384: if ((int64)data < 0) {
1.1.1.5 root 385: ReadDataException32(addr, DM_HU);
1.1 root 386: return;
387: }
388: if (FLD_D == 0)
389: return;
1.1.1.4 root 390: rD = data;
1.1 root 391: }
392:
393: // 000011_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
394: OP_DEF(ld_bu_imm)
395: {
396: uint32 addr;
1.1.1.4 root 397: uint64 data;
1.1 root 398:
399: addr = rS1 + IMM16;
400: LDST_ALIGN(1);
401:
1.1.1.5 root 402: AddCycle(3); // Table.7-3
1.1.1.4 root 403:
1.1 root 404: lastaddr = addr;
1.1.1.4 root 405: data = cmmu[1].load_8(addr);
406: if ((int64)data < 0) {
1.1.1.5 root 407: ReadDataException32(addr, DM_BU);
1.1 root 408: return;
409: }
410: if (FLD_D == 0)
411: return;
1.1.1.4 root 412: rD = data;
1.1 root 413: }
414:
415: // 000100_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
416: OP_DEF(ld_d_imm)
417: {
418: uint32 addr;
1.1.1.4 root 419: uint64 data1, data2;
1.1 root 420:
421: addr = rS1 + IMM16;
422: LDST_ALIGN(8);
423:
1.1.1.5 root 424: AddCycle(4); // Table.7-3
1.1.1.4 root 425:
1.1 root 426: lastaddr = addr;
1.1.1.4 root 427: data1 = cmmu[1].load_32(addr);
428: if ((int64)data1 < 0) {
1.1.1.5 root 429: ReadDataException64(addr, DM_D1);
1.1 root 430: return;
431: }
432: addr += 4;
1.1.1.4 root 433: data2 = cmmu[1].load_32(addr);
434: if ((int64)data2 < 0) {
1.1.1.5 root 435: ReadDataException64(addr, DM_D2);
1.1 root 436: return;
437: }
438:
1.1.1.4 root 439: rD = data1;
440: rD2 = data2;
1.1 root 441: r[0] = 0;
442: }
443:
444: // 000101_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
445: OP_DEF(ld_w_imm)
446: {
447: uint32 addr;
1.1.1.4 root 448: uint64 data;
1.1 root 449:
450: addr = rS1 + IMM16;
451: LDST_ALIGN(4);
452:
1.1.1.5 root 453: AddCycle(3); // Table.7-3
1.1.1.4 root 454:
1.1 root 455: lastaddr = addr;
1.1.1.4 root 456: data = cmmu[1].load_32(addr);
457: if ((int64)data < 0) {
1.1.1.5 root 458: ReadDataException32(addr, DM_W);
1.1 root 459: return;
460: }
461: if (FLD_D == 0)
462: return;
1.1.1.4 root 463: rD = data;
1.1 root 464: }
465:
466: // 000110_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
467: OP_DEF(ld_h_imm)
468: {
469: uint32 addr;
1.1.1.4 root 470: uint64 data;
1.1 root 471:
472: addr = rS1 + IMM16;
473: LDST_ALIGN(2);
474:
1.1.1.5 root 475: AddCycle(3); // Table.7-3
1.1.1.4 root 476:
1.1 root 477: lastaddr = addr;
1.1.1.4 root 478: data = cmmu[1].load_16(addr);
479: if ((int64)data < 0) {
1.1.1.5 root 480: ReadDataException32(addr, DM_H);
1.1 root 481: return;
482: }
483: if (FLD_D == 0)
484: return;
1.1.1.4 root 485: rD = (uint32)(int32)(int16)data;
1.1 root 486: }
487:
488: // 000111_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
489: OP_DEF(ld_b_imm)
490: {
491: uint32 addr;
1.1.1.4 root 492: uint64 data;
1.1 root 493:
494: addr = rS1 + IMM16;
495: LDST_ALIGN(1);
496:
1.1.1.5 root 497: AddCycle(3); // Table.7-3
1.1.1.4 root 498:
1.1 root 499: lastaddr = addr;
1.1.1.4 root 500: data = cmmu[1].load_8(addr);
501: if ((int64)data < 0) {
1.1.1.5 root 502: ReadDataException32(addr, DM_B);
1.1 root 503: return;
504: }
505: if (FLD_D == 0)
506: return;
1.1.1.4 root 507: rD = (uint32)(int32)(int8)data;
1.1 root 508: }
509:
510: // 001000_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
511: OP_DEF(st_d_imm)
512: {
513: uint32 addr;
1.1.1.4 root 514: uint64 rv;
1.1 root 515:
516: addr = rS1 + IMM16;
517: LDST_ALIGN(8);
518:
1.1.1.5 root 519: AddCycle(1 + 4); // Table.7-3
1.1.1.4 root 520:
1.1 root 521: lastaddr = addr;
1.1.1.4 root 522: rv = cmmu[1].store_32(addr, rD);
523: if ((int64)rv < 0) {
1.1.1.5 root 524: WriteDataException64(addr, DM_D1);
1.1 root 525: return;
526: }
527: addr += 4;
1.1.1.4 root 528: rv = cmmu[1].store_32(addr, rD2);
529: if ((int64)rv < 0) {
1.1.1.5 root 530: WriteDataException64(addr, DM_D2);
1.1 root 531: return;
532: }
533: }
534:
535: // 001001_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
536: OP_DEF(st_w_imm)
537: {
538: uint32 addr;
1.1.1.4 root 539: uint64 rv;
1.1 root 540:
541: addr = rS1 + IMM16;
542: LDST_ALIGN(4);
543:
1.1.1.5 root 544: AddCycle(3); // Table.7-3
1.1.1.4 root 545:
1.1 root 546: lastaddr = addr;
1.1.1.4 root 547: rv = cmmu[1].store_32(addr, rD);
548: if ((int64)rv < 0) {
1.1.1.5 root 549: WriteDataException32(addr, DM_W);
1.1 root 550: return;
551: }
552: }
553:
554: // 001010_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
555: OP_DEF(st_h_imm)
556: {
557: uint32 addr;
1.1.1.4 root 558: uint64 rv;
1.1 root 559:
560: addr = rS1 + IMM16;
561: LDST_ALIGN(2);
562:
1.1.1.5 root 563: AddCycle(3); // Table.7-3
1.1.1.4 root 564:
1.1 root 565: lastaddr = addr;
1.1.1.5 root 566: rv = cmmu[1].store_16(addr, rD & 0xffff);
1.1.1.4 root 567: if ((int64)rv < 0) {
1.1.1.5 root 568: WriteDataException32(addr, DM_H);
1.1 root 569: return;
570: }
571: }
572:
573: // 001011_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
574: OP_DEF(st_b_imm)
575: {
576: uint32 addr;
1.1.1.4 root 577: uint64 rv;
1.1 root 578:
579: addr = rS1 + IMM16;
580: LDST_ALIGN(1);
581:
1.1.1.5 root 582: AddCycle(3); // Table.7-3
1.1.1.4 root 583:
1.1 root 584: lastaddr = addr;
1.1.1.5 root 585: rv = cmmu[1].store_8(addr, rD & 0xff);
1.1.1.4 root 586: if ((int64)rv < 0) {
1.1.1.5 root 587: WriteDataException32(addr, DM_B);
1.1 root 588: return;
589: }
590: }
591:
592: // 001100_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
593: OP_DEF(lda_d_imm)
594: {
595: if (FLD_D == 0)
596: return;
597: rD = rS1 + IMM16;
598: }
599:
600: // 001101_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
601: OP_DEF(lda_w_imm)
602: {
603: if (FLD_D == 0)
604: return;
605: rD = rS1 + IMM16;
606: }
607:
608: // 001110_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
609: OP_DEF(lda_h_imm)
610: {
611: if (FLD_D == 0)
612: return;
613: rD = rS1 + IMM16;
614: }
615:
616: // 001111_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
617: OP_DEF(lda_b_imm)
618: {
619: if (FLD_D == 0)
620: return;
621: rD = rS1 + IMM16;
622: }
623:
624: // 010000_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
625: OP_DEF(and_imm)
626: {
627: if (FLD_D == 0)
628: return;
629: rD = rS1 & (IMM16 | 0xffff0000U);
630: }
631:
632: // 010001_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
633: OP_DEF(and_u_imm)
634: {
635: if (FLD_D == 0)
636: return;
637: rD = rS1 & ((IMM16 << 16) | 0x0000ffffU);
638: }
639:
640: // 010010_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
641: OP_DEF(mask_imm)
642: {
643: if (FLD_D == 0)
644: return;
645: rD = rS1 & IMM16;
646: }
647:
648: // 010011_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
649: OP_DEF(mask_u_imm)
650: {
651: if (FLD_D == 0)
652: return;
653: rD = rS1 & (IMM16 << 16);
654: }
655:
656: // 010100_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
657: OP_DEF(xor_imm)
658: {
659: if (FLD_D == 0)
660: return;
661: rD = rS1 ^ IMM16;
662: }
663:
664: // 010101_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
665: OP_DEF(xor_u_imm)
666: {
667: if (FLD_D == 0)
668: return;
669: rD = rS1 ^ (IMM16 << 16);
670: }
671:
672: // 010110_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
673: OP_DEF(or_imm)
674: {
675: if (FLD_D == 0)
676: return;
677: rD = rS1 | IMM16;
678: }
679:
680: // 010111_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
681: OP_DEF(or_u_imm)
682: {
683: if (FLD_D == 0)
684: return;
685: rD = rS1 | (IMM16 << 16);
686: }
687:
688: // 011000_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
689: OP_DEF(addu_imm)
690: {
691: if (FLD_D == 0)
692: return;
693: rD = rS1 + IMM16;
694: }
695:
696: // 011001_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
697: OP_DEF(subu_imm)
698: {
699: if (FLD_D == 0)
700: return;
701: rD = rS1 - IMM16;
702: }
703:
704: // 011010_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
705: OP_DEF(divu_imm)
706: {
707: if (!IsFPUEnable()) {
708: fpu_unimpl();
709: return;
710: }
1.1.1.4 root 711:
1.1.1.5 root 712: AddCycle(38); // Table.7-6 (ただしざっくり)
1.1.1.4 root 713:
1.1 root 714: if (IMM16 == 0) {
715: Exception(M88K_EXCEP_INT_DIV);
716: return;
717: }
718: if (FLD_D == 0)
719: return;
720: rD = rS1 / IMM16;
721: }
722:
723: // 011011_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
724: OP_DEF(mul_imm)
725: {
726: if (!IsFPUEnable()) {
727: fpu_unimpl();
728: return;
729: }
1.1.1.4 root 730:
1.1.1.5 root 731: AddCycle(4); // Table.7-6 (ただしざっくり)
1.1.1.4 root 732:
1.1 root 733: if (FLD_D == 0)
734: return;
735: rD = rS1 * IMM16;
736: }
737:
738: // 011100_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
739: OP_DEF(add_imm)
740: {
741: uint32 imm = IMM16;
742: uint32 res = rS1 + imm;
743: if (isovf_add(rS1, imm, res)) {
744: Exception(M88K_EXCEP_INT_OVF);
745: return;
746: }
747: if (FLD_D == 0)
748: return;
749: rD = res;
750: }
751:
752: // 011101_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
753: OP_DEF(sub_imm)
754: {
755: uint32 imm = IMM16;
756: uint32 res = rS1 - imm;
757: if (isovf_sub(rS1, imm, res)) {
758: Exception(M88K_EXCEP_INT_OVF);
759: return;
760: }
761: if (FLD_D == 0)
762: return;
763: rD = res;
764: }
765:
766: // 011110_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
767: OP_DEF(div_imm)
768: {
769: if (!IsFPUEnable()) {
770: fpu_unimpl();
771: return;
772: }
1.1.1.4 root 773:
1.1.1.5 root 774: AddCycle(38); // Table.7-6 (ただしざっくり)
1.1.1.4 root 775:
1.1.1.2 root 776: if ((int32)rS1 < 0 || IMM16 == 0) {
1.1 root 777: Exception(M88K_EXCEP_INT_DIV);
778: return;
779: }
780: if (FLD_D == 0)
781: return;
782: rD = rS1 / IMM16;
783: }
784:
785: // 011111_DDDDDSSSSS_nnnnnn_nnnnnnnnnn
786: OP_DEF(cmp_imm)
787: {
788: if (FLD_D == 0)
789: return;
790: rD = acc_cmp(rS1, IMM16);
791: }
792:
793: // 100000_DDDDDzzzzz_01000n_nnnnnzzzzz
794: OP_DEF(ldcr)
795: {
796: if (IsUser()) {
797: Exception(M88K_EXCEP_PRIV);
798: return;
799: }
800: if (FLD_CR > countof(cr)) {
1.1.1.11! root 801: // 制御レジスタ番号が範囲外の時は
! 802: // 88100 では undocumented、
! 803: // 88110 では Unimplemented Opcode 例外。
1.1 root 804: Exception(M88K_EXCEP_UNIMPL_OP);
805: return;
806: }
807: if (FLD_D == 0)
808: return;
809: rD = cr[FLD_CR];
810: }
811:
812: // 100000_DDDDDzzzzz_01001n_nnnnnzzzzz
813: OP_DEF(fldcr)
814: {
815: int n = FLD_CR;
816:
1.1.1.11! root 817: // 88100 88110(Only for reference)
! 818: // Super User Super User
! 819: // ----- ----- ----- -----
! 820: // FCR0 read FPRV read FPRV
! 821: // FCR1..8 read FPRV FUNIMP FPRV
! 822: // FCR9..61 read0 FPRV FUNIMP FPRV
! 823: // FCR62,63 read read read read
1.1 root 824:
825: if (n >= 62) {
826: n = n - 62 + 9;
1.1.1.11! root 827: } else {
! 828: if (IsUser()) {
! 829: FPPreciseException(FPECR_FPRV);
! 830: return;
! 831: }
! 832: if (n > 8) {
! 833: rD = 0;
! 834: return;
! 835: }
1.1 root 836: }
837: if (FLD_D == 0)
838: return;
1.1.1.11! root 839:
! 840: // XXX 内部がバグってなければ読み出す時にマスクする必要はないが、一応
! 841: rD = fcr[n] & fcr_mask[n];
1.1 root 842: }
843:
844: // 100000_zzzzzSSSSS_10000n_nnnnnsssss
845: OP_DEF(stcr)
846: {
847: if (IsUser()) {
848: Exception(M88K_EXCEP_PRIV);
849: return;
850: }
851: if (FLD_CR > countof(cr)) {
1.1.1.11! root 852: // 制御レジスタ番号が範囲外の時は
! 853: // 88100 では undocumented、
! 854: // 88110 では Unimplemented Opcode 例外。
1.1 root 855: Exception(M88K_EXCEP_UNIMPL_OP);
856: return;
857: }
858: cr[FLD_CR] = rS1;
1.1.1.2 root 859: if (FLD_CR == 1) {
1.1.1.4 root 860: SetPSR();
1.1.1.2 root 861: }
1.1 root 862: }
863:
864: // 100000_zzzzzSSSSS_10001n_nnnnnsssss
865: OP_DEF(fstcr)
866: {
867: int n = FLD_CR;
868:
1.1.1.11! root 869: // 88100 88110(Only for reference)
! 870: // Super User Super User
! 871: // ----- ----- ----- -----
! 872: // FCR0 write FPRV write FPRV
! 873: // FCR1..8 noop FPRV FUNIMP FPRV
! 874: // FCR9..61 noop FPRV FUNIMP FPRV
! 875: // FCR62,63 write write write write
! 876:
! 877: if (n >= 62) {
! 878: n = n - 62 + 9;
! 879: } else {
! 880: if (IsUser()) {
! 881: FPPreciseException(FPECR_FPRV);
! 882: return;
! 883: }
! 884: // FCR1..8(読み込み専用レジスタ)、9..61(未実装レジスタ) ともに noop
! 885: if (n > 0) {
1.1 root 886: return;
887: }
888: }
889:
1.1.1.11! root 890: fcr[n] = rS1 & fcr_mask[n];
1.1 root 891:
1.1.1.11! root 892: // FPCR が変更されたら、ホストの丸めモードも更新
! 893: if (n == 10) {
! 894: uint32 rm = (fpcr >> 14) & 3;
! 895: std::fesetround(rm_to_round[rm]);
1.1 root 896: }
897: }
898:
899: // 100000_DDDDDSSSSS_11000n_nnnnnsssss
900: OP_DEF(xcr)
901: {
902: uint32 tmp;
903:
904: if (IsUser()) {
905: Exception(M88K_EXCEP_PRIV);
906: return;
907: }
908: if (FLD_CR > countof(cr)) {
1.1.1.11! root 909: // 制御レジスタ番号が範囲外の時は
! 910: // 88100 では undocumented、
! 911: // 88110 では Unimplemented Opcode 例外。
1.1 root 912: Exception(M88K_EXCEP_UNIMPL_OP);
913: return;
914: }
915: tmp = rS1;
916: rD = cr[FLD_CR];
917: cr[FLD_CR] = tmp;
1.1.1.2 root 918: if (FLD_CR == 1) {
1.1.1.4 root 919: SetPSR();
1.1.1.2 root 920: }
1.1 root 921: r[0] = 0;
922: }
923:
924: // 100000_DDDDDSSSSS_11001n_nnnnnsssss
925: OP_DEF(fxcr)
926: {
1.1.1.11! root 927: uint n = FLD_CR;
1.1 root 928:
1.1.1.11! root 929: // 88100 88110(Only for reference)
! 930: // Super User Super User
! 931: // ----- ----- ----- -----
! 932: // FCR0 xchg FPRV xchg FPRV
! 933: // FCR1..8 read FPRV FUNIMP FPRV
! 934: // FCR9..61 read0 FPRV FUNIMP FPRV
! 935: // FCR62,63 xchg xchg xchg xchg
1.1 root 936:
1.1.1.11! root 937: if (IsUser() && n < 62) {
! 938: FPPreciseException(FPECR_FPRV);
1.1 root 939: return;
940: }
941:
1.1.1.11! root 942: if (n == 0) {
! 943: goto exchange;
! 944: } else if (__predict_false(n < 9)) {
! 945: // FCR1..8 は読み込み専用レジスタなので、読み出す側のみ
! 946: rD = fcr[n] & fcr_mask[n];
! 947: r[0] = 0;
! 948: return;
! 949: } else if (__predict_false(n < 62)) {
! 950: // FCR9..61 は未実装レジスタなので、0 が読み出せるのみ
! 951: rD = 0;
! 952: return;
! 953: } else {
1.1 root 954: n = n - 62 + 9;
955: }
1.1.1.11! root 956:
! 957: exchange:
! 958: uint32 tmp = rS1;
! 959: rD = fcr[n] & fcr_mask[n];
! 960: fcr[n] = tmp & fcr_mask[n];
! 961:
1.1 root 962: r[0] = 0;
963: }
964:
965: // 100001_DDDDDSSSSS_00000n_nnnnnsssss
966: OP_DEF(fmul)
967: {
1.1.1.5 root 968: // 暫定
969: double s1;
970: double s2;
971:
972: if (FLD_D == 0) {
1.1.1.11! root 973: FPPreciseException(FPECR_FUNIMP);
1.1.1.5 root 974: return;
975: }
976:
977: FP_GET(s1, FP_T1, FLD_S1);
978: FP_GET(s2, FP_T2, FLD_S2);
979: FP_SET(FP_TD, FLD_D, s1 * s2);
1.1 root 980: }
981:
982: // 100001_DDDDD00000_001000_000nnsssss
983: OP_DEF(flt)
984: {
1.1.1.5 root 985: // 暫定
986: if (FLD_D == 0) {
1.1.1.11! root 987: FPPreciseException(FPECR_FUNIMP);
1.1.1.5 root 988: return;
989: }
990:
1.1.1.10 root 991: FP_SET(FP_TD, FLD_D, (double)(int32)rS2);
1.1 root 992: }
993:
1.1.1.5 root 994:
1.1 root 995: // 100001_DDDDDSSSSS_00101n_nnnnnsssss
996: OP_DEF(fadd)
997: {
1.1.1.5 root 998: // 暫定
999: double s1;
1000: double s2;
1001:
1002: if (FLD_D == 0) {
1.1.1.11! root 1003: FPPreciseException(FPECR_FUNIMP);
1.1.1.5 root 1004: return;
1005: }
1006:
1007: FP_GET(s1, FP_T1, FLD_S1);
1008: FP_GET(s2, FP_T2, FLD_S2);
1009: FP_SET(FP_TD, FLD_D, s1 + s2);
1.1 root 1010: }
1011:
1012: // 100001_DDDDDSSSSS_00110n_nnnnnsssss
1013: OP_DEF(fsub)
1014: {
1.1.1.5 root 1015: // 暫定
1016: double s1;
1017: double s2;
1018:
1019: if (FLD_D == 0) {
1.1.1.11! root 1020: FPPreciseException(FPECR_FUNIMP);
1.1.1.5 root 1021: return;
1022: }
1023:
1024: FP_GET(s1, FP_T1, FLD_S1);
1025: FP_GET(s2, FP_T2, FLD_S2);
1026: FP_SET(FP_TD, FLD_D, s1 - s2);
1.1 root 1027: }
1028:
1029: // 100001_DDDDDSSSSS_00111n_nnnnnsssss
1030: OP_DEF(fcmp)
1031: {
1.1.1.5 root 1032: double s1;
1033: double s2;
1034:
1035: if (FLD_D == 0) {
1.1.1.11! root 1036: FPPreciseException(FPECR_FUNIMP);
1.1.1.5 root 1037: return;
1038: }
1039:
1040: FP_GET(s1, FP_T1, FLD_S1);
1041: FP_GET(s2, FP_T2, FLD_S2);
1.1.1.11! root 1042:
! 1043: // XXX テストが出来てないので Inf と非正規化数は未対応
! 1044: // 非正規化数もここのはず
! 1045: if (std::isnan(s1) || std::isnan(s2) ||
! 1046: std::isinf(s1) || std::isinf(s2) )
! 1047: {
! 1048: FPPreciseException(FPECR_FROP, s1, s2);
! 1049: return;
! 1050: }
! 1051:
! 1052: //
! 1053: // 31 .. 12 11 10 9 8 7 6 5 4 3 2 1 0
! 1054: // +---- ---+----+----+----+----+----+----+----+----+----+----+----+----+
! 1055: // | 0 | ob | in | ib | ou | ge | lt | le | gt | ne | eq | cp | nc |
! 1056: // +---- ---+----+----+----+----+----+----+----+----+----+----+----+----+
! 1057:
! 1058: uint32 res = 0;
! 1059: if (s2 >= 0) {
! 1060: if (s1 <= 0 || s2 <= s1) res |= 0x0800; // ob
! 1061: if (0 < s1 && s1 < s2) res |= 0x0400; // in
! 1062: if (0 <= s1 && s1 <= s2) res |= 0x0200; // ib
! 1063: if (s1 < 0 || s2 < s1) res |= 0x0100; // ou
! 1064: }
! 1065: if (s1 >= s2) res |= 0x0080; // ge
! 1066: if (s1 < s2) res |= 0x0040; // lt
! 1067: if (s1 <= s2) res |= 0x0020; // le
! 1068: if (s1 > s2) res |= 0x0010; // gt
! 1069: if (s1 != s2) res |= 0x0008; // ne
! 1070: if (s1 == s2) res |= 0x0004; // eq
! 1071: // cp; if and only if the two operands are comparable
! 1072: if (!std::isnan(s1) && !std::isnan(s2)) {
! 1073: res |= 0x0002;
! 1074: }
! 1075: // nc; if, and only if, the two operands are not comparable
! 1076: if (std::isnan(s1) || std::isnan(s2)) {
! 1077: res |= 0x0001;
! 1078: }
! 1079:
! 1080: rD = res;
1.1 root 1081: }
1082:
1.1.1.11! root 1083: // int, nint, trnc 命令の共通部
! 1084: void
! 1085: m88kcpu::ops_int(int rndmode)
! 1086: {
! 1087: double src;
! 1088: double res;
! 1089: int exponent;
1.1.1.5 root 1090:
1091: if (FLD_D == 0) {
1.1.1.11! root 1092: FPPreciseException(FPECR_FUNIMP);
1.1.1.5 root 1093: return;
1094: }
1095:
1.1.1.11! root 1096: if (FP_T2 == 0) {
! 1097: float f;
! 1098: FP_GET(f, FP_T2, FLD_S2);
! 1099: src = f;
! 1100: } else {
! 1101: FP_GET(src, FP_T2, FLD_S2);
! 1102: }
! 1103:
! 1104: int saved_rndmode = std::fegetround();
1.1.1.5 root 1105:
1.1.1.11! root 1106: std::fesetround(rndmode);
! 1107: res = std::nearbyint(src);
! 1108: std::fesetround(saved_rndmode);
! 1109:
! 1110: exponent = 0;
! 1111: std::frexp(res, &exponent);
! 1112: if (std::isinf(res) || std::isnan(res) || exponent >= 30) {
! 1113: // 整数で表現出来ない(かも知れない)ので例外
! 1114: FPPreciseException(FPECR_FIOV, src);
! 1115: return;
1.1.1.5 root 1116: }
1.1.1.11! root 1117: rD = (uint32)(int32)res;
! 1118: }
! 1119:
! 1120: // 100001_DDDDD00000_010010_0nn00sssss
! 1121: OP_DEF(int)
! 1122: {
! 1123: // 現在のモードのまま (ちょっと無駄だけど…)
! 1124: ops_int(std::fegetround());
1.1 root 1125: }
1126:
1127: // 100001_DDDDD00000_010100_0nn00sssss
1128: OP_DEF(nint)
1129: {
1.1.1.11! root 1130: ops_int(FE_TONEAREST);
1.1 root 1131: }
1132:
1133: // 100001_DDDDD00000_010110_0nn00sssss
1134: OP_DEF(trnc)
1135: {
1.1.1.11! root 1136: ops_int(FE_TOWARDZERO);
1.1 root 1137: }
1138:
1139: // 100001_DDDDDSSSSS_01110n_nnnnnsssss
1140: OP_DEF(fdiv)
1141: {
1.1.1.5 root 1142: // 暫定
1143: double s1;
1144: double s2;
1145:
1146: if (FLD_D == 0) {
1.1.1.11! root 1147: FPPreciseException(FPECR_FUNIMP);
1.1.1.5 root 1148: return;
1149: }
1150:
1151: FP_GET(s1, FP_T1, FLD_S1);
1152: FP_GET(s2, FP_T2, FLD_S2);
1153: FP_SET(FP_TD, FLD_D, s1 / s2);
1.1 root 1154: }
1155:
1156: // 110000_nnnnnnnnnn_nnnnnn_nnnnnnnnnn
1157: OP_DEF(br)
1158: {
1.1.1.5 root 1159: AddCycle(1); // Table.7-5
1.1.1.4 root 1160: EnterBranch(xip + D26);
1.1 root 1161: ExitBranch();
1162: }
1163:
1164: // 110001_nnnnnnnnnn_nnnnnn_nnnnnnnnnn
1165: OP_DEF(br_n)
1166: {
1.1.1.5 root 1167: AddCycle(0); // Table.7-5
1.1.1.4 root 1168: EnterBranch(xip + D26);
1.1 root 1169: ExitDelayBranch();
1170: }
1171:
1172: // 110010_nnnnnnnnnn_nnnnnn_nnnnnnnnnn
1173: OP_DEF(bsr)
1174: {
1.1.1.5 root 1175: AddCycle(1); // Table.7-5
1.1.1.4 root 1176: EnterBranch(xip + D26);
1.1 root 1177: r[1] = nip;
1178: ExitBranch();
1179: }
1180:
1181: // 110011_nnnnnnnnnn_nnnnnn_nnnnnnnnnn
1182: OP_DEF(bsr_n)
1183: {
1.1.1.5 root 1184: AddCycle(0); // Table.7-5
1.1.1.4 root 1185: EnterBranch(xip + D26);
1.1 root 1186: r[1] = nip + 4;
1187: ExitDelayBranch();
1188: }
1189:
1190: // 110100_nnnnnSSSSS_nnnnnn_nnnnnnnnnn
1191: OP_DEF(bb0)
1192: {
1193: if ((rS1 & (1 << B5)) == 0) {
1.1.1.5 root 1194: AddCycle(1); // Table.7-5
1.1.1.4 root 1195: EnterBranch(xip + D16);
1.1 root 1196: ExitBranch();
1197: }
1198: }
1199:
1200: // 110101_nnnnnSSSSS_nnnnnn_nnnnnnnnnn
1201: OP_DEF(bb0_n)
1202: {
1203: if ((rS1 & (1 << B5)) == 0) {
1.1.1.4 root 1204: EnterBranch(xip + D16);
1.1 root 1205: ExitDelayBranch();
1206: }
1207: }
1208:
1209: // 110110_nnnnnSSSSS_nnnnnn_nnnnnnnnnn
1210: OP_DEF(bb1)
1211: {
1212: if ((rS1 & (1 << B5)) != 0) {
1.1.1.5 root 1213: AddCycle(1); // Table.7-5
1.1.1.4 root 1214: EnterBranch(xip + D16);
1.1 root 1215: ExitBranch();
1216: }
1217: }
1218:
1219: // 110111_nnnnnSSSSS_nnnnnn_nnnnnnnnnn
1220: OP_DEF(bb1_n)
1221: {
1222: if ((rS1 & (1 << B5)) != 0) {
1.1.1.4 root 1223: EnterBranch(xip + D16);
1.1 root 1224: ExitDelayBranch();
1225: }
1226: }
1227:
1228: // 111010_MMMMMSSSSS_nnnnnn_nnnnnnnnnn
1229: OP_DEF(bcnd)
1230: {
1.1.1.9 root 1231: if ((acc_cnd(rS1) & M5) != 0) {
1.1.1.5 root 1232: AddCycle(1); // Table.7-5
1.1.1.4 root 1233: EnterBranch(xip + D16);
1.1 root 1234: ExitBranch();
1235: }
1236: }
1237:
1238: // 111011_MMMMMSSSSS_nnnnnn_nnnnnnnnnn
1239: OP_DEF(bcnd_n)
1240: {
1.1.1.9 root 1241: if ((acc_cnd(rS1) & M5) != 0) {
1.1.1.4 root 1242: EnterBranch(xip + D16);
1.1 root 1243: ExitDelayBranch();
1244: }
1245: }
1246:
1247: // 111100_DDDDDSSSSS_100000_wwwwwooooo
1248: OP_DEF(clr_1)
1249: {
1250: if (FLD_D == 0)
1251: return;
1252: rD = rS1 & ~acc_bf(W5, O5);
1253: }
1254:
1255: // 111100_DDDDDSSSSS_100010_wwwwwooooo
1256: OP_DEF(set_1)
1257: {
1258: if (FLD_D == 0)
1259: return;
1260: rD = rS1 | acc_bf(W5, O5);
1261: }
1262:
1263: // 111100_DDDDDSSSSS_100100_wwwwwooooo
1264: OP_DEF(ext_1)
1265: {
1266: int w, o, left;
1267: uint32 tmp;
1268:
1269: if (FLD_D == 0)
1270: return;
1271: w = W5;
1272: if (w == 0)
1273: w = 32;
1274: o = O5;
1275: left = 32 - w - o;
1276: tmp = ASL(rS1, left);
1277: tmp = ASR(tmp, left);
1278: rD = ASR(tmp, o);
1279: }
1280:
1281: // 111100_DDDDDSSSSS_100110_wwwwwooooo
1282: OP_DEF(extu_1)
1283: {
1284: int w, o, left;
1285: uint32 tmp;
1286:
1287: if (FLD_D == 0)
1288: return;
1289: w = W5;
1290: if (w == 0)
1291: w = 32;
1292: o = O5;
1293: left = 32 - w - o;
1294: tmp = ASL(rS1, left);
1295: tmp = LSR(tmp, left);
1296: rD = tmp >> o;
1297: }
1298:
1299: // 111100_DDDDDSSSSS_101000_wwwwwooooo
1300: OP_DEF(mak_1)
1301: {
1302: if (FLD_D == 0)
1303: return;
1304: rD = (rS1 << O5) & acc_bf(W5, O5);
1305: }
1306:
1307: // 111100_DDDDDSSSSS_101010_zzzzzooooo
1308: OP_DEF(rot_1)
1309: {
1310: if (FLD_D == 0)
1311: return;
1312: rD = ROR(rS1, O5);
1313: }
1314:
1315: // 111100_bbbbbSSSSS_110100_0vvvvvvvvv
1316: OP_DEF(tb0)
1317: {
1318: if (IsUser() && VEC9 < 128) {
1319: Exception(M88K_EXCEP_PRIV);
1320: return;
1321: }
1322: if ((rS1 & (1 << B5)) == 0) {
1323: ExceptionCore(VEC9, ExceptionKind::TRAP);
1324: }
1325: }
1326:
1327: // 111100_bbbbbSSSSS_110110_0vvvvvvvvv
1328: OP_DEF(tb1)
1329: {
1330: if (IsUser() && VEC9 < 128) {
1331: Exception(M88K_EXCEP_PRIV);
1332: return;
1333: }
1334: if ((rS1 & (1 << B5)) != 0) {
1335: ExceptionCore(VEC9, ExceptionKind::TRAP);
1.1.1.8 root 1336: } else if (pseudo_stop_enable) {
1337:
1338: // OpenBSD の STOP エミュレーション。
1339: // OpenBSD 6.6 では
1340: // L1: tb1 #1 r0, #0xff
1341: // ld r13, r21, #0x168
1342: // bcnd.n eq0, r13, L1
1343: // or r2, r25, #0x5ea0
1344: // の命令列が使用されている。
1345: // tb1 は volatile 変数をアクセスするための同期命令として
1346: // gcc により出力されている。スーパバイザが volatile を
1347: // 観測するために同じアドレスの tb1 に直接ブランチで 3 回飛び込んで
1348: // きたら、それは割り込みか別プロセッサか I/O による変更を待っている
1349: // はずなので STOP と判断してみる。
1350: // o. 3回、という数字に確たる理由はない。
1351: // o. 念の為、16バイト(4命令)後方以内からのブランチに限定しておく。
1352:
1353: if (IsSuper() && VEC9 == 0xff) {
1354: const auto& e = brhist.entry[brhist.top];
1355: if (e.count == 3
1356: && e.to == xip
1357: && e.from - e.to < 16) {
1358: atomic_reqflag |= CPU_REQ_STOP;
1359: }
1360: }
1.1 root 1361: }
1362: }
1363:
1364: // 111100_MMMMMSSSSS_111010_0vvvvvvvvv
1365: OP_DEF(tcnd)
1366: {
1367: if (IsUser() && VEC9 < 128) {
1368: Exception(M88K_EXCEP_PRIV);
1369: return;
1370: }
1.1.1.9 root 1371: if ((acc_cnd(rS1) & M5) != 0) {
1.1 root 1372: ExceptionCore(VEC9, ExceptionKind::TRAP);
1373: }
1374: }
1375:
1376: // 111101_DDDDDSSSSS_000000_xU000sssss
1377: OP_DEF(xmem_bu)
1378: {
1379: uint64 tmp;
1380: uint32 addr;
1381: uint32 usr;
1382:
1383: LDST_USR_SCALE_ALIGN(1);
1384:
1.1.1.5 root 1385: AddCycle(4); // Table.7-3
1.1.1.4 root 1386:
1.1 root 1387: lastaddr = addr;
1.1.1.2 root 1388:
1389: // 例外安全のために都度 S/U ビットを制御
1390: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.6 root 1391: tmp = cmmu[1].xmem_8(addr, rD & 0xff);
1.1.1.2 root 1392: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1.1 root 1393: if ((int64)tmp < 0) {
1.1.1.5 root 1394: XmemDataException(addr, DM_BU | DM_LOCK | usr);
1.1 root 1395: return;
1396: }
1397: if (FLD_D == 0)
1398: return;
1399: rD = tmp;
1400: }
1401:
1402: // 111101_DDDDDSSSSS_000001_xU000sssss
1403: OP_DEF(xmem_w)
1404: {
1405: uint64 tmp;
1406: uint32 addr;
1407: uint32 usr;
1408:
1409: LDST_USR_SCALE_ALIGN(4);
1410:
1.1.1.5 root 1411: AddCycle(4); // Table.7-3
1.1.1.4 root 1412:
1.1 root 1413: lastaddr = addr;
1.1.1.2 root 1414:
1415: // 例外安全のために都度 S/U ビットを制御
1416: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1417: tmp = cmmu[1].xmem_32(addr, rD);
1418: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1.1 root 1419: if ((int64)tmp < 0) {
1.1.1.5 root 1420: XmemDataException(addr, DM_W | DM_LOCK | usr);
1.1 root 1421: return;
1422: }
1.1.1.2 root 1423:
1.1 root 1424: if (FLD_D == 0)
1425: return;
1426: rD = tmp;
1427: }
1428:
1429: // 111101_DDDDDSSSSS_000010_xU000sssss
1430: OP_DEF(ld_hu)
1431: {
1.1.1.4 root 1432: uint64 data;
1.1 root 1433: uint32 addr;
1434: uint32 usr;
1435:
1436: LDST_USR_SCALE_ALIGN(2);
1437:
1.1.1.5 root 1438: AddCycle(3); // Table.7-3
1.1.1.4 root 1439:
1.1 root 1440: lastaddr = addr;
1.1.1.2 root 1441:
1442: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1443: data = cmmu[1].load_16(addr);
1.1.1.2 root 1444: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1445:
1.1.1.4 root 1446: if ((int64)data < 0) {
1.1.1.5 root 1447: ReadDataException32(addr, DM_HU | usr);
1.1 root 1448: return;
1449: }
1450: if (FLD_D == 0)
1451: return;
1.1.1.4 root 1452: rD = data;
1.1 root 1453: }
1454:
1455: // 111101_DDDDDSSSSS_000011_xU000sssss
1456: OP_DEF(ld_bu)
1457: {
1.1.1.4 root 1458: uint64 data;
1.1 root 1459: uint32 addr;
1460: uint32 usr;
1461:
1462: LDST_USR_SCALE_ALIGN(1);
1463:
1.1.1.5 root 1464: AddCycle(3); // Table.7-3
1.1.1.4 root 1465:
1.1 root 1466: lastaddr = addr;
1.1.1.2 root 1467:
1468: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1469: data = cmmu[1].load_8(addr);
1.1.1.2 root 1470: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1471:
1.1.1.4 root 1472: if ((int64)data < 0) {
1.1.1.5 root 1473: ReadDataException32(addr, DM_BU | usr);
1.1 root 1474: return;
1475: }
1476: if (FLD_D == 0)
1477: return;
1.1.1.4 root 1478: rD = data;
1.1 root 1479: }
1480:
1481: // 111101_DDDDDSSSSS_000100_xU000sssss
1482: OP_DEF(ld_d)
1483: {
1.1.1.4 root 1484: uint64 data1, data2;
1.1 root 1485: uint32 addr;
1486: uint32 usr;
1487:
1488: LDST_USR_SCALE_ALIGN(8);
1489:
1.1.1.5 root 1490: AddCycle(4); // Table.7-3
1.1.1.4 root 1491:
1.1 root 1492: lastaddr = addr;
1.1.1.2 root 1493:
1494: // 例外安全のために都度 S/U ビットを制御
1495: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1496: data1 = cmmu[1].load_32(addr);
1.1.1.2 root 1497: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1498:
1.1.1.4 root 1499: if ((int64)data1 < 0) {
1.1.1.5 root 1500: ReadDataException64(addr, DM_D1 | usr);
1.1 root 1501: return;
1502: }
1503: addr += 4;
1.1.1.2 root 1504:
1505: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1506: data2 = cmmu[1].load_32(addr);
1.1.1.2 root 1507: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1508:
1.1.1.4 root 1509: if ((int64)data2 < 0) {
1.1.1.5 root 1510: ReadDataException64(addr, DM_D2 | usr);
1.1 root 1511: return;
1512: }
1.1.1.4 root 1513: rD = data1;
1514: rD2 = data2;
1.1 root 1515: r[0] = 0;
1516: }
1517:
1518: // 111101_DDDDDSSSSS_000101_xU000sssss
1519: OP_DEF(ld_w)
1520: {
1.1.1.4 root 1521: uint64 data;
1.1 root 1522: uint32 addr;
1523: uint32 usr;
1524:
1525: LDST_USR_SCALE_ALIGN(4);
1526:
1.1.1.5 root 1527: AddCycle(3); // Table.7-3
1.1.1.4 root 1528:
1.1 root 1529: lastaddr = addr;
1.1.1.2 root 1530:
1531: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1532: data = cmmu[1].load_32(addr);
1.1.1.2 root 1533: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1534:
1.1.1.4 root 1535: if ((int64)data < 0) {
1.1.1.5 root 1536: ReadDataException32(addr, DM_W | usr);
1.1 root 1537: return;
1538: }
1539: if (FLD_D == 0)
1540: return;
1.1.1.4 root 1541: rD = data;
1.1 root 1542: }
1543:
1544: // 111101_DDDDDSSSSS_000110_xU000sssss
1545: OP_DEF(ld_h)
1546: {
1.1.1.4 root 1547: uint64 data;
1.1 root 1548: uint32 addr;
1549: uint32 usr;
1550:
1551: LDST_USR_SCALE_ALIGN(2);
1552:
1.1.1.5 root 1553: AddCycle(3); // Table.7-3
1.1.1.4 root 1554:
1.1 root 1555: lastaddr = addr;
1.1.1.2 root 1556:
1557: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1558: data = cmmu[1].load_16(addr);
1.1.1.2 root 1559: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1560:
1.1.1.4 root 1561: if ((int64)data < 0) {
1.1.1.5 root 1562: ReadDataException32(addr, DM_H | usr);
1.1 root 1563: return;
1564: }
1565: if (FLD_D == 0)
1566: return;
1.1.1.4 root 1567: rD = (uint32)(int32)(int16)data;
1.1 root 1568: }
1569:
1570: // 111101_DDDDDSSSSS_000111_xU000sssss
1571: OP_DEF(ld_b)
1572: {
1.1.1.4 root 1573: uint64 data;
1.1 root 1574: uint32 addr;
1575: uint32 usr;
1576:
1577: LDST_USR_SCALE_ALIGN(1);
1578:
1.1.1.5 root 1579: AddCycle(3); // Table.7-3
1.1.1.4 root 1580:
1.1 root 1581: lastaddr = addr;
1.1.1.2 root 1582:
1583: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1584: data = cmmu[1].load_8(addr);
1.1.1.2 root 1585: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1586:
1.1.1.4 root 1587: if ((int64)data < 0) {
1.1.1.5 root 1588: ReadDataException32(addr, DM_B | usr);
1.1 root 1589: return;
1590: }
1591: if (FLD_D == 0)
1592: return;
1.1.1.4 root 1593: rD = (uint32)(int32)(int8)data;
1.1 root 1594: }
1595:
1596: // 111101_DDDDDSSSSS_001000_xU000sssss
1597: OP_DEF(st_d)
1598: {
1.1.1.4 root 1599: uint64 rv;
1.1 root 1600: uint32 addr;
1601: uint32 usr;
1602:
1603: LDST_USR_SCALE_ALIGN(8);
1604:
1.1.1.5 root 1605: AddCycle(1 + 4); // Table.7-3
1.1.1.4 root 1606:
1.1 root 1607: lastaddr = addr;
1.1.1.2 root 1608:
1609: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1610: rv = cmmu[1].store_32(addr, rD);
1.1.1.2 root 1611: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1612:
1.1.1.4 root 1613: if ((int64)rv < 0) {
1.1.1.5 root 1614: WriteDataException64(addr, DM_D1 | usr);
1.1 root 1615: return;
1616: }
1.1.1.2 root 1617:
1.1 root 1618: addr += 4;
1.1.1.2 root 1619:
1620: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1621: rv = cmmu[1].store_32(addr, rD2);
1.1.1.2 root 1622: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1623:
1.1.1.4 root 1624: if ((int64)rv < 0) {
1.1.1.5 root 1625: WriteDataException64(addr, DM_D2 | usr);
1.1 root 1626: return;
1627: }
1628: }
1629:
1630: // 111101_DDDDDSSSSS_001001_xU000sssss
1631: OP_DEF(st_w)
1632: {
1.1.1.4 root 1633: uint64 rv;
1.1 root 1634: uint32 addr;
1635: uint32 usr;
1636:
1637: LDST_USR_SCALE_ALIGN(4);
1638:
1.1.1.5 root 1639: AddCycle(3); // Table.7-3
1.1.1.4 root 1640:
1.1 root 1641: lastaddr = addr;
1.1.1.2 root 1642:
1643: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1644: rv = cmmu[1].store_32(addr, rD);
1.1.1.2 root 1645: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1646:
1.1.1.4 root 1647: if ((int64)rv < 0) {
1.1.1.5 root 1648: WriteDataException32(addr, DM_W | usr);
1.1 root 1649: return;
1650: }
1651: }
1652:
1653: // 111101_DDDDDSSSSS_001010_xU000sssss
1654: OP_DEF(st_h)
1655: {
1.1.1.4 root 1656: uint64 rv;
1.1 root 1657: uint32 addr;
1658: uint32 usr;
1659:
1660: LDST_USR_SCALE_ALIGN(2);
1661:
1.1.1.5 root 1662: AddCycle(3); // Table.7-3
1.1.1.4 root 1663:
1.1 root 1664: lastaddr = addr;
1.1.1.2 root 1665:
1666: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.5 root 1667: rv = cmmu[1].store_16(addr, rD & 0xffff);
1.1.1.2 root 1668: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1669:
1.1.1.4 root 1670: if ((int64)rv < 0) {
1.1.1.5 root 1671: WriteDataException32(addr, DM_H | usr);
1.1 root 1672: return;
1673: }
1674: }
1675:
1676: // 111101_DDDDDSSSSS_001011_xU000sssss
1677: OP_DEF(st_b)
1678: {
1.1.1.4 root 1679: uint64 rv;
1.1 root 1680: uint32 addr;
1681: uint32 usr;
1682:
1683: LDST_USR_SCALE_ALIGN(1);
1684:
1.1.1.5 root 1685: AddCycle(3); // Table.7-3
1.1.1.4 root 1686:
1.1 root 1687: lastaddr = addr;
1.1.1.2 root 1688:
1689: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.5 root 1690: rv = cmmu[1].store_8(addr, rD & 0xff);
1.1.1.2 root 1691: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1692:
1.1.1.4 root 1693: if ((int64)rv < 0) {
1.1.1.5 root 1694: WriteDataException32(addr, DM_B | usr);
1.1 root 1695: return;
1696: }
1697: }
1698:
1699: // 111101_DDDDDSSSSS_001100_xU000sssss
1700: OP_DEF(lda_d)
1701: {
1702: uint32 addr;
1703: uint32 usr;
1704:
1705: LDST_USR_SCALE(8);
1706:
1707: if (FLD_D == 0)
1708: return;
1709: rD = addr;
1710: }
1711:
1712: // 111101_DDDDDSSSSS_001101_xU000sssss
1713: OP_DEF(lda_w)
1714: {
1715: uint32 addr;
1716: uint32 usr;
1717:
1718: LDST_USR_SCALE(4);
1719:
1720: if (FLD_D == 0)
1721: return;
1722: rD = addr;
1723: }
1724:
1725: // 111101_DDDDDSSSSS_001110_xU000sssss
1726: OP_DEF(lda_h)
1727: {
1728: uint32 addr;
1729: uint32 usr;
1730:
1731: LDST_USR_SCALE(2);
1732:
1733: if (FLD_D == 0)
1734: return;
1735: rD = addr;
1736: }
1737:
1738: // 111101_DDDDDSSSSS_001111_xU000sssss
1739: OP_DEF(lda_b)
1740: {
1741: uint32 addr;
1742: uint32 usr;
1743:
1744: LDST_USR_SCALE(1);
1745:
1746: if (FLD_D == 0)
1747: return;
1748: rD = addr;
1749: }
1750:
1751: // 111101_DDDDDSSSSS_010000_00000sssss
1752: OP_DEF(and)
1753: {
1754: if (FLD_D == 0)
1755: return;
1756: rD = rS1 & rS2;
1757: }
1758:
1759: // 111101_DDDDDSSSSS_010001_00000sssss
1760: OP_DEF(and_c)
1761: {
1762: if (FLD_D == 0)
1763: return;
1764: rD = rS1 & ~rS2;
1765: }
1766:
1767: // 111101_DDDDDSSSSS_010100_00000sssss
1768: OP_DEF(xor)
1769: {
1770: if (FLD_D == 0)
1771: return;
1772: rD = rS1 ^ rS2;
1773: }
1774:
1775: // 111101_DDDDDSSSSS_010101_00000sssss
1776: OP_DEF(xor_c)
1777: {
1778: if (FLD_D == 0)
1779: return;
1780: rD = rS1 ^ ~rS2;
1781: }
1782:
1783: // 111101_DDDDDSSSSS_010110_00000sssss
1784: OP_DEF(or)
1785: {
1.1.1.2 root 1786: if (FLD_D == 0) {
1787: nop_counter++;
1.1 root 1788: return;
1.1.1.2 root 1789: }
1.1 root 1790: rD = rS1 | rS2;
1791: }
1792:
1793: // 111101_DDDDDSSSSS_010111_00000sssss
1794: OP_DEF(or_c)
1795: {
1796: if (FLD_D == 0)
1797: return;
1798: rD = rS1 | ~rS2;
1799: }
1800:
1801: // 111101_DDDDDSSSSS_011000_nn000sssss
1802: OP_DEF(addu)
1803: {
1.1.1.2 root 1804: uint64 res = (uint64)rS1 + rS2;
1.1 root 1805: if (IsCI) {
1806: res += GetCY();
1807: }
1808: if (IsCO) {
1.1.1.4 root 1809: SetCY(res >> 32);
1.1 root 1810: }
1811: if (FLD_D == 0)
1812: return;
1813: rD = res;
1814: }
1815:
1816: // 111101_DDDDDSSSSS_011001_nn000sssss
1817: OP_DEF(subu)
1818: {
1.1.1.9 root 1819: // sub* 命令の CY ビットはボローが発生*していない*時セット。
1.1.1.2 root 1820:
1821: // 1 の補数をとって足す。
1822: uint64 res = (uint64)rS1 + (~rS2);
1.1 root 1823: if (IsCI) {
1.1.1.2 root 1824: res += GetCY();
1825: } else {
1826: res += 1;
1.1 root 1827: }
1828: if (IsCO) {
1.1.1.4 root 1829: SetCY(res >> 32);
1.1 root 1830: }
1831: if (FLD_D == 0)
1832: return;
1833: rD = res;
1834: }
1835:
1836: // 111101_DDDDDSSSSS_011010_zz000sssss
1837: OP_DEF(divu)
1838: {
1839: if (!IsFPUEnable()) {
1840: fpu_unimpl();
1841: return;
1842: }
1.1.1.4 root 1843:
1.1.1.5 root 1844: AddCycle(38); // Table.7-6 (ただしざっくり)
1.1.1.4 root 1845:
1.1 root 1846: if (rS2 == 0) {
1847: Exception(M88K_EXCEP_INT_DIV);
1848: return;
1849: }
1850: if (FLD_D == 0)
1851: return;
1852: rD = rS1 / rS2;
1853: }
1854:
1855: // 111101_DDDDDSSSSS_011011_zz000sssss
1856: OP_DEF(mul)
1857: {
1858: if (!IsFPUEnable()) {
1859: fpu_unimpl();
1860: return;
1861: }
1.1.1.4 root 1862:
1.1.1.5 root 1863: AddCycle(4); // Table.7-6 (ただしざっくり)
1.1.1.4 root 1864:
1.1 root 1865: if (FLD_D == 0)
1866: return;
1867: rD = rS1 * rS2;
1868: }
1869:
1870: // 111101_DDDDDSSSSS_011100_nn000sssss
1871: OP_DEF(add)
1872: {
1.1.1.2 root 1873: uint64 res = (uint64)rS1 + rS2;
1.1 root 1874: if (IsCI) {
1875: res += GetCY();
1876: }
1877: if (isovf_add(rS1, rS2, res)) {
1878: Exception(M88K_EXCEP_INT_OVF);
1879: return;
1880: }
1.1.1.9 root 1881:
1882: // rD, Cy の更新は例外が起きなかった時だけ (p.6-19)
1883: if (IsCO) {
1884: SetCY(res >> 32);
1885: }
1.1 root 1886: if (FLD_D == 0)
1887: return;
1888: rD = res;
1889: }
1890:
1891: // 111101_DDDDDSSSSS_011101_nn000sssss
1892: OP_DEF(sub)
1893: {
1.1.1.9 root 1894: // sub* 命令の CY ビットはボローが発生*していない*時セット。
1.1.1.2 root 1895:
1896: // 1 の補数をとって足す。
1897: uint64 res = (uint64)rS1 + (~rS2);
1.1 root 1898: if (IsCI) {
1.1.1.2 root 1899: res += GetCY();
1900: } else {
1901: res += 1;
1.1 root 1902: }
1903: if (isovf_sub(rS1, rS2, res)) {
1904: Exception(M88K_EXCEP_INT_OVF);
1905: return;
1906: }
1.1.1.9 root 1907:
1908: // rD, Cy の更新は例外が起きなかった時だけ (p.6-19)
1909: if (IsCO) {
1910: SetCY(res >> 32);
1911: }
1.1 root 1912: if (FLD_D == 0)
1913: return;
1914: rD = res;
1915: }
1916:
1917: // 111101_DDDDDSSSSS_011110_zz000sssss
1918: OP_DEF(div)
1919: {
1920: if (!IsFPUEnable()) {
1921: fpu_unimpl();
1922: return;
1923: }
1.1.1.4 root 1924:
1.1.1.5 root 1925: AddCycle(38); // Table.7-6 (ただしざっくり)
1.1.1.4 root 1926:
1.1.1.2 root 1927: if ((int32)rS1 < 0 || (int32)rS2 <= 0) {
1.1 root 1928: Exception(M88K_EXCEP_INT_DIV);
1929: return;
1930: }
1931: if (FLD_D == 0)
1932: return;
1933: rD = rS1 / rS2;
1934: }
1935:
1936: // 111101_DDDDDSSSSS_011111_zz000sssss
1937: OP_DEF(cmp)
1938: {
1939: if (FLD_D == 0)
1940: return;
1941: rD = acc_cmp(rS1, rS2);
1942: }
1943:
1944: // 111101_DDDDDSSSSS_100000_00000sssss
1945: OP_DEF(clr_2)
1946: {
1947: if (FLD_D == 0)
1948: return;
1949: rD = rS1 & ~acc_bf((rS2 >> 5) & 0x1f, rS2 & 0x1f);
1950: }
1951:
1952: // 111101_DDDDDSSSSS_100010_00000sssss
1953: OP_DEF(set_2)
1954: {
1955: if (FLD_D == 0)
1956: return;
1957: rD = rS1 | acc_bf((rS2 >> 5) & 0x1f, rS2 & 0x1f);
1958: }
1959:
1960: // 111101_DDDDDSSSSS_100100_00000sssss
1961: OP_DEF(ext_2)
1962: {
1963: int w, o, left;
1964: uint32 tmp;
1965:
1966: if (FLD_D == 0)
1967: return;
1968: w = (rS2 >> 5) & 0x1f;
1969: if (w == 0)
1970: w = 32;
1971: o = (rS2 ) & 0x1f;
1972: left = 32 - w - o;
1973: tmp = ASL(rS1, left);
1974: tmp = ASR(tmp, left);
1975: rD = ASR(tmp, o);
1976: }
1977:
1978: // 111101_DDDDDSSSSS_100110_00000sssss
1979: OP_DEF(extu_2)
1980: {
1981: int w, o, left;
1982: uint32 tmp;
1983:
1984: if (FLD_D == 0)
1985: return;
1986: w = (rS2 >> 5) & 0x1f;
1987: if (w == 0)
1988: w = 32;
1989: o = (rS2 ) & 0x1f;
1990: left = 32 - w - o;
1991: tmp = ASL(rS1, left);
1992: tmp = LSR(tmp, left);
1993: rD = tmp >> o;
1994: }
1995:
1996: // 111101_DDDDDSSSSS_101000_00000sssss
1997: OP_DEF(mak_2)
1998: {
1999: if (FLD_D == 0)
2000: return;
2001: int w = (rS2 >> 5) & 0x1f;
2002: int o = (rS2 ) & 0x1f;
2003: rD = (rS1 << o) & acc_bf(w, o);
2004: }
2005:
2006: // 111101_DDDDDSSSSS_101010_00000sssss
2007: OP_DEF(rot_2)
2008: {
2009: if (FLD_D == 0)
2010: return;
2011: int o = (rS2 ) & 0x1f;
2012: rD = ROR(rS1, o);
2013: }
2014:
2015: // 111101_zzzzzzzzzz_110000_00000sssss
2016: OP_DEF(jmp)
2017: {
1.1.1.5 root 2018: AddCycle(1); // Table.7-5
1.1.1.4 root 2019: EnterBranch(rS2);
1.1 root 2020: ExitBranch();
2021: }
2022:
2023: // 111101_zzzzzzzzzz_110001_00000sssss
2024: OP_DEF(jmp_n)
2025: {
1.1.1.5 root 2026: AddCycle(0); // Table.7-5
1.1.1.4 root 2027: EnterBranch(rS2);
1.1 root 2028: ExitDelayBranch();
2029: }
2030:
2031: // 111101_zzzzzzzzzz_110010_00000sssss
2032: OP_DEF(jsr)
2033: {
1.1.1.5 root 2034: AddCycle(1); // Table.7-5
1.1.1.4 root 2035: EnterBranch(rS2);
1.1 root 2036: r[1] = nip;
2037: ExitBranch();
2038: }
2039:
2040: // 111101_zzzzzzzzzz_110011_00000sssss
2041: OP_DEF(jsr_n)
2042: {
1.1.1.5 root 2043: AddCycle(0); // Table.7-5
1.1.1.4 root 2044: EnterBranch(rS2);
1.1 root 2045: r[1] = nip + 4;
2046: ExitDelayBranch();
2047: }
2048:
1.1.1.2 root 2049: // 111101_DDDDDzzzzz_111010_00000sssss
2050: OP_DEF(ff1)
2051: {
2052: int i;
2053: uint32 m = 0x80000000U;
2054:
2055: if (FLD_D == 0)
2056: return;
2057:
2058: if (rS2 == 0) {
2059: rD = 32;
2060: } else {
2061: for (i = 31; i >= 0; i--, m >>= 1) {
2062: if ((rS2 & m) != 0) {
2063: break;
2064: }
2065: }
2066: rD = i;
2067: }
2068:
2069: }
2070:
2071: // 111101_DDDDDzzzzz_111011_00000sssss
2072: OP_DEF(ff0)
2073: {
2074: int i;
2075: uint32 m = 0x80000000U;
2076:
2077: if (FLD_D == 0)
2078: return;
2079:
2080: if (rS2 == 0xffffffffU) {
2081: rD = 32;
2082: } else {
2083: for (i = 31; i >= 0; i--, m >>= 1) {
2084: if ((rS2 & m) == 0) {
2085: break;
2086: }
2087: }
2088: rD = i;
2089: }
2090: }
2091:
1.1 root 2092: // 111101_zzzzzzzzzz_111111_0000000000
2093: OP_DEF(rte)
2094: {
1.1.1.5 root 2095: AddCycle(2); // Table.7-5
1.1.1.4 root 2096:
1.1.1.2 root 2097: SetPSR(epsr);
1.1 root 2098:
1.1.1.2 root 2099: // LUNA88K の ROM1.2 は sxip, snip, sfip を制御してくる。
2100: // ROM1.2 の DAE ハンドラは、
2101: // sxip = INVALID
2102: // snip = 0 (INVALID)
2103: // sfip = original sxip
2104: // で rte してくる。
2105: // CPU は sxip は評価しない。snip は 0 なので、無効として nop 扱い。
2106: // (実際はクロックが消費されるかも?)
2107: // sfip が VALID なので、そこから実行を再開する。
1.1.1.9 root 2108: if ((snip & SIP_V)) {
1.1.1.4 root 2109: EnterBranch(snip & SIP_MASK);
2110: ExitBranch();
1.1.1.2 root 2111: fip = sfip & SIP_MASK;
2112: } else {
1.1.1.4 root 2113: EnterBranch(sfip & SIP_MASK);
2114: ExitBranch();
1.1.1.2 root 2115: }
1.1 root 2116:
2117: // ディレイスロットにいた命令かどうかをやんわり復元する。
2118: // 88110 ではこの情報が E?IP に保持されているが
2119: // 88100 にはない。
2120: if (nip + 4 != fip) {
1.1.1.4 root 2121: ExitDelayBranch();
1.1 root 2122: }
2123: }
2124:
2125: // 111101_zzzzzSSSSS_111110_00000SSSSS
2126: OP_DEF(tbnd_1)
2127: {
2128: if (rS1 > rS2) {
2129: Exception(M88K_EXCEP_BOUNDS);
2130: }
2131: }
2132:
2133: // 111110_zzzzzSSSSS_nnnnnn_nnnnnnnnnn
2134: OP_DEF(tbnd_2)
2135: {
2136: if (rS1 > IMM16) {
2137: Exception(M88K_EXCEP_BOUNDS);
2138: }
2139: }
2140:
1.1.1.9 root 2141: // 111111_DDDDDSSSSS_000001_nnnnnnnnnn
2142: OP_DEF(doscall)
1.1 root 2143: {
1.1.1.9 root 2144: // Human68k の DOS call エミュレーションのような何か。
2145: // 独自ニーモニックでは doscall rD, rS1, #nn と表記することにする。
2146: //
2147: // Human68k の DOS コール #nn 番を実行し、戻り値を rD に書き込む。
2148: // 戻り値のない DOS コールでは rD に 0 を指定すること。
2149: // 引数は rS1 以降に一つずつ置く。m68k でのワードやバイト値の場合は
2150: // 下位詰めするだけで上位ビットのクリア等は不要。
2151: // 処理するこちら側が必要なビット幅だけを取り出すこと。
2152: //
2153: // また、ここでのコンソールは VM 内のコンソールではなくホストの標準入出力。
2154: //
2155: // コールバックがセットされていて特権状態の時のみ発動する。
2156: // それ以外では現物同様不当命令扱い。
1.1 root 2157:
1.1.1.9 root 2158: if (fline_callback && IsSuper()) {
2159: if (fline_callback(this, fline_arg)) {
2160: return;
2161: }
2162: }
2163:
2164: OP_FUNC(illegal);
1.1 root 2165: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.