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