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