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