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