|
|
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.2 root 326: tmp = cmmu[1].xmem_8(addr, rD);
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: printf("trunc(%f) => %f\n", s2, std::trunc(s2));
! 1073: rD = (uint32)(int32)std::trunc(s2);
1.1 root 1074: }
1075:
1076: // 100001_DDDDDSSSSS_01110n_nnnnnsssss
1077: OP_DEF(fdiv)
1078: {
1.1.1.5 ! root 1079: // 暫定
! 1080: double s1;
! 1081: double s2;
! 1082:
! 1083: if (FLD_D == 0) {
! 1084: FPException(M88K_FPEXCEP_FUNIMP);
! 1085: return;
! 1086: }
! 1087:
! 1088: FP_GET(s1, FP_T1, FLD_S1);
! 1089: FP_GET(s2, FP_T2, FLD_S2);
! 1090: FP_SET(FP_TD, FLD_D, s1 / s2);
1.1 root 1091: }
1092:
1093: // 110000_nnnnnnnnnn_nnnnnn_nnnnnnnnnn
1094: OP_DEF(br)
1095: {
1.1.1.5 ! root 1096: AddCycle(1); // Table.7-5
1.1.1.4 root 1097: EnterBranch(xip + D26);
1.1 root 1098: ExitBranch();
1099: }
1100:
1101: // 110001_nnnnnnnnnn_nnnnnn_nnnnnnnnnn
1102: OP_DEF(br_n)
1103: {
1.1.1.5 ! root 1104: AddCycle(0); // Table.7-5
1.1.1.4 root 1105: EnterBranch(xip + D26);
1.1 root 1106: ExitDelayBranch();
1107: }
1108:
1109: // 110010_nnnnnnnnnn_nnnnnn_nnnnnnnnnn
1110: OP_DEF(bsr)
1111: {
1.1.1.5 ! root 1112: AddCycle(1); // Table.7-5
1.1.1.4 root 1113: EnterBranch(xip + D26);
1.1 root 1114: r[1] = nip;
1115: ExitBranch();
1116: }
1117:
1118: // 110011_nnnnnnnnnn_nnnnnn_nnnnnnnnnn
1119: OP_DEF(bsr_n)
1120: {
1.1.1.5 ! root 1121: AddCycle(0); // Table.7-5
1.1.1.4 root 1122: EnterBranch(xip + D26);
1.1 root 1123: r[1] = nip + 4;
1124: ExitDelayBranch();
1125: }
1126:
1127: // 110100_nnnnnSSSSS_nnnnnn_nnnnnnnnnn
1128: OP_DEF(bb0)
1129: {
1130: if ((rS1 & (1 << B5)) == 0) {
1.1.1.5 ! root 1131: AddCycle(1); // Table.7-5
1.1.1.4 root 1132: EnterBranch(xip + D16);
1.1 root 1133: ExitBranch();
1134: }
1135: }
1136:
1137: // 110101_nnnnnSSSSS_nnnnnn_nnnnnnnnnn
1138: OP_DEF(bb0_n)
1139: {
1140: if ((rS1 & (1 << B5)) == 0) {
1.1.1.4 root 1141: EnterBranch(xip + D16);
1.1 root 1142: ExitDelayBranch();
1143: }
1144: }
1145:
1146: // 110110_nnnnnSSSSS_nnnnnn_nnnnnnnnnn
1147: OP_DEF(bb1)
1148: {
1149: if ((rS1 & (1 << B5)) != 0) {
1.1.1.5 ! root 1150: AddCycle(1); // Table.7-5
1.1.1.4 root 1151: EnterBranch(xip + D16);
1.1 root 1152: ExitBranch();
1153: }
1154: }
1155:
1156: // 110111_nnnnnSSSSS_nnnnnn_nnnnnnnnnn
1157: OP_DEF(bb1_n)
1158: {
1159: if ((rS1 & (1 << B5)) != 0) {
1.1.1.4 root 1160: EnterBranch(xip + D16);
1.1 root 1161: ExitDelayBranch();
1162: }
1163: }
1164:
1165: // 111010_MMMMMSSSSS_nnnnnn_nnnnnnnnnn
1166: OP_DEF(bcnd)
1167: {
1168: if (acc_cnd(rS1) & M5) {
1.1.1.5 ! root 1169: AddCycle(1); // Table.7-5
1.1.1.4 root 1170: EnterBranch(xip + D16);
1.1 root 1171: ExitBranch();
1172: }
1173: }
1174:
1175: // 111011_MMMMMSSSSS_nnnnnn_nnnnnnnnnn
1176: OP_DEF(bcnd_n)
1177: {
1178: if (acc_cnd(rS1) & M5) {
1.1.1.4 root 1179: EnterBranch(xip + D16);
1.1 root 1180: ExitDelayBranch();
1181: }
1182: }
1183:
1184: // 111100_DDDDDSSSSS_100000_wwwwwooooo
1185: OP_DEF(clr_1)
1186: {
1187: if (FLD_D == 0)
1188: return;
1189: rD = rS1 & ~acc_bf(W5, O5);
1190: }
1191:
1192: // 111100_DDDDDSSSSS_100010_wwwwwooooo
1193: OP_DEF(set_1)
1194: {
1195: if (FLD_D == 0)
1196: return;
1197: rD = rS1 | acc_bf(W5, O5);
1198: }
1199:
1200: // 111100_DDDDDSSSSS_100100_wwwwwooooo
1201: OP_DEF(ext_1)
1202: {
1203: int w, o, left;
1204: uint32 tmp;
1205:
1206: if (FLD_D == 0)
1207: return;
1208: w = W5;
1209: if (w == 0)
1210: w = 32;
1211: o = O5;
1212: left = 32 - w - o;
1213: tmp = ASL(rS1, left);
1214: tmp = ASR(tmp, left);
1215: rD = ASR(tmp, o);
1216: }
1217:
1218: // 111100_DDDDDSSSSS_100110_wwwwwooooo
1219: OP_DEF(extu_1)
1220: {
1221: int w, o, left;
1222: uint32 tmp;
1223:
1224: if (FLD_D == 0)
1225: return;
1226: w = W5;
1227: if (w == 0)
1228: w = 32;
1229: o = O5;
1230: left = 32 - w - o;
1231: tmp = ASL(rS1, left);
1232: tmp = LSR(tmp, left);
1233: rD = tmp >> o;
1234: }
1235:
1236: // 111100_DDDDDSSSSS_101000_wwwwwooooo
1237: OP_DEF(mak_1)
1238: {
1239: if (FLD_D == 0)
1240: return;
1241: rD = (rS1 << O5) & acc_bf(W5, O5);
1242: }
1243:
1244: // 111100_DDDDDSSSSS_101010_zzzzzooooo
1245: OP_DEF(rot_1)
1246: {
1247: if (FLD_D == 0)
1248: return;
1249: rD = ROR(rS1, O5);
1250: }
1251:
1252: // 111100_bbbbbSSSSS_110100_0vvvvvvvvv
1253: OP_DEF(tb0)
1254: {
1255: if (IsUser() && VEC9 < 128) {
1256: Exception(M88K_EXCEP_PRIV);
1257: return;
1258: }
1259: if ((rS1 & (1 << B5)) == 0) {
1260: ExceptionCore(VEC9, ExceptionKind::TRAP);
1261: }
1262: }
1263:
1264: // 111100_bbbbbSSSSS_110110_0vvvvvvvvv
1265: OP_DEF(tb1)
1266: {
1267: if (IsUser() && VEC9 < 128) {
1268: Exception(M88K_EXCEP_PRIV);
1269: return;
1270: }
1271: if ((rS1 & (1 << B5)) != 0) {
1272: ExceptionCore(VEC9, ExceptionKind::TRAP);
1273: }
1274: }
1275:
1276: // 111100_MMMMMSSSSS_111010_0vvvvvvvvv
1277: OP_DEF(tcnd)
1278: {
1279: if (IsUser() && VEC9 < 128) {
1280: Exception(M88K_EXCEP_PRIV);
1281: return;
1282: }
1283: if (acc_cnd(rS1) & M5) {
1284: ExceptionCore(VEC9, ExceptionKind::TRAP);
1285: }
1286: }
1287:
1288: // 111101_DDDDDSSSSS_000000_xU000sssss
1289: OP_DEF(xmem_bu)
1290: {
1291: uint64 tmp;
1292: uint32 addr;
1293: uint32 usr;
1294:
1295: LDST_USR_SCALE_ALIGN(1);
1296:
1.1.1.5 ! root 1297: AddCycle(4); // Table.7-3
1.1.1.4 root 1298:
1.1 root 1299: lastaddr = addr;
1.1.1.2 root 1300:
1301: // 例外安全のために都度 S/U ビットを制御
1302: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1303: tmp = cmmu[1].xmem_8(addr, rD);
1304: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1.1 root 1305: if ((int64)tmp < 0) {
1.1.1.5 ! root 1306: XmemDataException(addr, DM_BU | DM_LOCK | usr);
1.1 root 1307: return;
1308: }
1309: if (FLD_D == 0)
1310: return;
1311: rD = tmp;
1312: }
1313:
1314: // 111101_DDDDDSSSSS_000001_xU000sssss
1315: OP_DEF(xmem_w)
1316: {
1317: uint64 tmp;
1318: uint32 addr;
1319: uint32 usr;
1320:
1321: LDST_USR_SCALE_ALIGN(4);
1322:
1.1.1.5 ! root 1323: AddCycle(4); // Table.7-3
1.1.1.4 root 1324:
1.1 root 1325: lastaddr = addr;
1.1.1.2 root 1326:
1327: // 例外安全のために都度 S/U ビットを制御
1328: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1329: tmp = cmmu[1].xmem_32(addr, rD);
1330: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1.1 root 1331: if ((int64)tmp < 0) {
1.1.1.5 ! root 1332: XmemDataException(addr, DM_W | DM_LOCK | usr);
1.1 root 1333: return;
1334: }
1.1.1.2 root 1335:
1.1 root 1336: if (FLD_D == 0)
1337: return;
1338: rD = tmp;
1339: }
1340:
1341: // 111101_DDDDDSSSSS_000010_xU000sssss
1342: OP_DEF(ld_hu)
1343: {
1.1.1.4 root 1344: uint64 data;
1.1 root 1345: uint32 addr;
1346: uint32 usr;
1347:
1348: LDST_USR_SCALE_ALIGN(2);
1349:
1.1.1.5 ! root 1350: AddCycle(3); // Table.7-3
1.1.1.4 root 1351:
1.1 root 1352: lastaddr = addr;
1.1.1.2 root 1353:
1354: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1355: data = cmmu[1].load_16(addr);
1.1.1.2 root 1356: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1357:
1.1.1.4 root 1358: if ((int64)data < 0) {
1.1.1.5 ! root 1359: ReadDataException32(addr, DM_HU | usr);
1.1 root 1360: return;
1361: }
1362: if (FLD_D == 0)
1363: return;
1.1.1.4 root 1364: rD = data;
1.1 root 1365: }
1366:
1367: // 111101_DDDDDSSSSS_000011_xU000sssss
1368: OP_DEF(ld_bu)
1369: {
1.1.1.4 root 1370: uint64 data;
1.1 root 1371: uint32 addr;
1372: uint32 usr;
1373:
1374: LDST_USR_SCALE_ALIGN(1);
1375:
1.1.1.5 ! root 1376: AddCycle(3); // Table.7-3
1.1.1.4 root 1377:
1.1 root 1378: lastaddr = addr;
1.1.1.2 root 1379:
1380: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1381: data = cmmu[1].load_8(addr);
1.1.1.2 root 1382: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1383:
1.1.1.4 root 1384: if ((int64)data < 0) {
1.1.1.5 ! root 1385: ReadDataException32(addr, DM_BU | usr);
1.1 root 1386: return;
1387: }
1388: if (FLD_D == 0)
1389: return;
1.1.1.4 root 1390: rD = data;
1.1 root 1391: }
1392:
1393: // 111101_DDDDDSSSSS_000100_xU000sssss
1394: OP_DEF(ld_d)
1395: {
1.1.1.4 root 1396: uint64 data1, data2;
1.1 root 1397: uint32 addr;
1398: uint32 usr;
1399:
1400: LDST_USR_SCALE_ALIGN(8);
1401:
1.1.1.5 ! root 1402: AddCycle(4); // Table.7-3
1.1.1.4 root 1403:
1.1 root 1404: lastaddr = addr;
1.1.1.2 root 1405:
1406: // 例外安全のために都度 S/U ビットを制御
1407: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1408: data1 = cmmu[1].load_32(addr);
1.1.1.2 root 1409: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1410:
1.1.1.4 root 1411: if ((int64)data1 < 0) {
1.1.1.5 ! root 1412: ReadDataException64(addr, DM_D1 | usr);
1.1 root 1413: return;
1414: }
1415: addr += 4;
1.1.1.2 root 1416:
1417: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1418: data2 = cmmu[1].load_32(addr);
1.1.1.2 root 1419: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1420:
1.1.1.4 root 1421: if ((int64)data2 < 0) {
1.1.1.5 ! root 1422: ReadDataException64(addr, DM_D2 | usr);
1.1 root 1423: return;
1424: }
1.1.1.4 root 1425: rD = data1;
1426: rD2 = data2;
1.1 root 1427: r[0] = 0;
1428: }
1429:
1430: // 111101_DDDDDSSSSS_000101_xU000sssss
1431: OP_DEF(ld_w)
1432: {
1.1.1.4 root 1433: uint64 data;
1.1 root 1434: uint32 addr;
1435: uint32 usr;
1436:
1437: LDST_USR_SCALE_ALIGN(4);
1438:
1.1.1.5 ! root 1439: AddCycle(3); // Table.7-3
1.1.1.4 root 1440:
1.1 root 1441: lastaddr = addr;
1.1.1.2 root 1442:
1443: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1444: data = cmmu[1].load_32(addr);
1.1.1.2 root 1445: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1446:
1.1.1.4 root 1447: if ((int64)data < 0) {
1.1.1.5 ! root 1448: ReadDataException32(addr, DM_W | usr);
1.1 root 1449: return;
1450: }
1451: if (FLD_D == 0)
1452: return;
1.1.1.4 root 1453: rD = data;
1.1 root 1454: }
1455:
1456: // 111101_DDDDDSSSSS_000110_xU000sssss
1457: OP_DEF(ld_h)
1458: {
1.1.1.4 root 1459: uint64 data;
1.1 root 1460: uint32 addr;
1461: uint32 usr;
1462:
1463: LDST_USR_SCALE_ALIGN(2);
1464:
1.1.1.5 ! root 1465: AddCycle(3); // Table.7-3
1.1.1.4 root 1466:
1.1 root 1467: lastaddr = addr;
1.1.1.2 root 1468:
1469: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1470: data = cmmu[1].load_16(addr);
1.1.1.2 root 1471: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1472:
1.1.1.4 root 1473: if ((int64)data < 0) {
1.1.1.5 ! root 1474: ReadDataException32(addr, DM_H | usr);
1.1 root 1475: return;
1476: }
1477: if (FLD_D == 0)
1478: return;
1.1.1.4 root 1479: rD = (uint32)(int32)(int16)data;
1.1 root 1480: }
1481:
1482: // 111101_DDDDDSSSSS_000111_xU000sssss
1483: OP_DEF(ld_b)
1484: {
1.1.1.4 root 1485: uint64 data;
1.1 root 1486: uint32 addr;
1487: uint32 usr;
1488:
1489: LDST_USR_SCALE_ALIGN(1);
1490:
1.1.1.5 ! root 1491: AddCycle(3); // Table.7-3
1.1.1.4 root 1492:
1.1 root 1493: lastaddr = addr;
1.1.1.2 root 1494:
1495: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1496: data = cmmu[1].load_8(addr);
1.1.1.2 root 1497: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1498:
1.1.1.4 root 1499: if ((int64)data < 0) {
1.1.1.5 ! root 1500: ReadDataException32(addr, DM_B | usr);
1.1 root 1501: return;
1502: }
1503: if (FLD_D == 0)
1504: return;
1.1.1.4 root 1505: rD = (uint32)(int32)(int8)data;
1.1 root 1506: }
1507:
1508: // 111101_DDDDDSSSSS_001000_xU000sssss
1509: OP_DEF(st_d)
1510: {
1.1.1.4 root 1511: uint64 rv;
1.1 root 1512: uint32 addr;
1513: uint32 usr;
1514:
1515: LDST_USR_SCALE_ALIGN(8);
1516:
1.1.1.5 ! root 1517: AddCycle(1 + 4); // Table.7-3
1.1.1.4 root 1518:
1.1 root 1519: lastaddr = addr;
1.1.1.2 root 1520:
1521: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1522: rv = cmmu[1].store_32(addr, rD);
1.1.1.2 root 1523: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1524:
1.1.1.4 root 1525: if ((int64)rv < 0) {
1.1.1.5 ! root 1526: WriteDataException64(addr, DM_D1 | usr);
1.1 root 1527: return;
1528: }
1.1.1.2 root 1529:
1.1 root 1530: addr += 4;
1.1.1.2 root 1531:
1532: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1533: rv = cmmu[1].store_32(addr, rD2);
1.1.1.2 root 1534: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1535:
1.1.1.4 root 1536: if ((int64)rv < 0) {
1.1.1.5 ! root 1537: WriteDataException64(addr, DM_D2 | usr);
1.1 root 1538: return;
1539: }
1540: }
1541:
1542: // 111101_DDDDDSSSSS_001001_xU000sssss
1543: OP_DEF(st_w)
1544: {
1.1.1.4 root 1545: uint64 rv;
1.1 root 1546: uint32 addr;
1547: uint32 usr;
1548:
1549: LDST_USR_SCALE_ALIGN(4);
1550:
1.1.1.5 ! root 1551: AddCycle(3); // Table.7-3
1.1.1.4 root 1552:
1.1 root 1553: lastaddr = addr;
1.1.1.2 root 1554:
1555: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1556: rv = cmmu[1].store_32(addr, rD);
1.1.1.2 root 1557: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1558:
1.1.1.4 root 1559: if ((int64)rv < 0) {
1.1.1.5 ! root 1560: WriteDataException32(addr, DM_W | usr);
1.1 root 1561: return;
1562: }
1563: }
1564:
1565: // 111101_DDDDDSSSSS_001010_xU000sssss
1566: OP_DEF(st_h)
1567: {
1.1.1.4 root 1568: uint64 rv;
1.1 root 1569: uint32 addr;
1570: uint32 usr;
1571:
1572: LDST_USR_SCALE_ALIGN(2);
1573:
1.1.1.5 ! root 1574: AddCycle(3); // Table.7-3
1.1.1.4 root 1575:
1.1 root 1576: lastaddr = addr;
1.1.1.2 root 1577:
1578: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.5 ! root 1579: rv = cmmu[1].store_16(addr, rD & 0xffff);
1.1.1.2 root 1580: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1581:
1.1.1.4 root 1582: if ((int64)rv < 0) {
1.1.1.5 ! root 1583: WriteDataException32(addr, DM_H | usr);
1.1 root 1584: return;
1585: }
1586: }
1587:
1588: // 111101_DDDDDSSSSS_001011_xU000sssss
1589: OP_DEF(st_b)
1590: {
1.1.1.4 root 1591: uint64 rv;
1.1 root 1592: uint32 addr;
1593: uint32 usr;
1594:
1595: LDST_USR_SCALE_ALIGN(1);
1596:
1.1.1.5 ! root 1597: AddCycle(3); // Table.7-3
1.1.1.4 root 1598:
1.1 root 1599: lastaddr = addr;
1.1.1.2 root 1600:
1601: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.5 ! root 1602: rv = cmmu[1].store_8(addr, rD & 0xff);
1.1.1.2 root 1603: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1604:
1.1.1.4 root 1605: if ((int64)rv < 0) {
1.1.1.5 ! root 1606: WriteDataException32(addr, DM_B | usr);
1.1 root 1607: return;
1608: }
1609: }
1610:
1611: // 111101_DDDDDSSSSS_001100_xU000sssss
1612: OP_DEF(lda_d)
1613: {
1614: uint32 addr;
1615: uint32 usr;
1616:
1617: LDST_USR_SCALE(8);
1618:
1619: if (FLD_D == 0)
1620: return;
1621: rD = addr;
1622: }
1623:
1624: // 111101_DDDDDSSSSS_001101_xU000sssss
1625: OP_DEF(lda_w)
1626: {
1627: uint32 addr;
1628: uint32 usr;
1629:
1630: LDST_USR_SCALE(4);
1631:
1632: if (FLD_D == 0)
1633: return;
1634: rD = addr;
1635: }
1636:
1637: // 111101_DDDDDSSSSS_001110_xU000sssss
1638: OP_DEF(lda_h)
1639: {
1640: uint32 addr;
1641: uint32 usr;
1642:
1643: LDST_USR_SCALE(2);
1644:
1645: if (FLD_D == 0)
1646: return;
1647: rD = addr;
1648: }
1649:
1650: // 111101_DDDDDSSSSS_001111_xU000sssss
1651: OP_DEF(lda_b)
1652: {
1653: uint32 addr;
1654: uint32 usr;
1655:
1656: LDST_USR_SCALE(1);
1657:
1658: if (FLD_D == 0)
1659: return;
1660: rD = addr;
1661: }
1662:
1663: // 111101_DDDDDSSSSS_010000_00000sssss
1664: OP_DEF(and)
1665: {
1666: if (FLD_D == 0)
1667: return;
1668: rD = rS1 & rS2;
1669: }
1670:
1671: // 111101_DDDDDSSSSS_010001_00000sssss
1672: OP_DEF(and_c)
1673: {
1674: if (FLD_D == 0)
1675: return;
1676: rD = rS1 & ~rS2;
1677: }
1678:
1679: // 111101_DDDDDSSSSS_010100_00000sssss
1680: OP_DEF(xor)
1681: {
1682: if (FLD_D == 0)
1683: return;
1684: rD = rS1 ^ rS2;
1685: }
1686:
1687: // 111101_DDDDDSSSSS_010101_00000sssss
1688: OP_DEF(xor_c)
1689: {
1690: if (FLD_D == 0)
1691: return;
1692: rD = rS1 ^ ~rS2;
1693: }
1694:
1695: // 111101_DDDDDSSSSS_010110_00000sssss
1696: OP_DEF(or)
1697: {
1.1.1.2 root 1698: if (FLD_D == 0) {
1699: nop_counter++;
1.1 root 1700: return;
1.1.1.2 root 1701: }
1.1 root 1702: rD = rS1 | rS2;
1703: }
1704:
1705: // 111101_DDDDDSSSSS_010111_00000sssss
1706: OP_DEF(or_c)
1707: {
1708: if (FLD_D == 0)
1709: return;
1710: rD = rS1 | ~rS2;
1711: }
1712:
1713: // 111101_DDDDDSSSSS_011000_nn000sssss
1714: OP_DEF(addu)
1715: {
1.1.1.2 root 1716: uint64 res = (uint64)rS1 + rS2;
1.1 root 1717: if (IsCI) {
1718: res += GetCY();
1719: }
1720: if (IsCO) {
1.1.1.4 root 1721: SetCY(res >> 32);
1.1 root 1722: }
1723: if (FLD_D == 0)
1724: return;
1725: rD = res;
1726: }
1727:
1728: // 111101_DDDDDSSSSS_011001_nn000sssss
1729: OP_DEF(subu)
1730: {
1.1.1.2 root 1731: // sub 命令では CY ビットは Z80 とかと逆で、0 ならボロー発生。
1732: // 88100 のマニュアルには書いてない。88110 のマニュアルにある。
1733:
1734: // 1 の補数をとって足す。
1735: uint64 res = (uint64)rS1 + (~rS2);
1.1 root 1736: if (IsCI) {
1.1.1.2 root 1737: res += GetCY();
1738: } else {
1739: res += 1;
1.1 root 1740: }
1741: if (IsCO) {
1.1.1.4 root 1742: SetCY(res >> 32);
1.1 root 1743: }
1744: if (FLD_D == 0)
1745: return;
1746: rD = res;
1747: }
1748:
1749: // 111101_DDDDDSSSSS_011010_zz000sssss
1750: OP_DEF(divu)
1751: {
1752: if (!IsFPUEnable()) {
1753: fpu_unimpl();
1754: return;
1755: }
1.1.1.4 root 1756:
1.1.1.5 ! root 1757: AddCycle(38); // Table.7-6 (ただしざっくり)
1.1.1.4 root 1758:
1.1 root 1759: if (rS2 == 0) {
1760: Exception(M88K_EXCEP_INT_DIV);
1761: return;
1762: }
1763: if (FLD_D == 0)
1764: return;
1765: rD = rS1 / rS2;
1766: }
1767:
1768: // 111101_DDDDDSSSSS_011011_zz000sssss
1769: OP_DEF(mul)
1770: {
1771: if (!IsFPUEnable()) {
1772: fpu_unimpl();
1773: return;
1774: }
1.1.1.4 root 1775:
1.1.1.5 ! root 1776: AddCycle(4); // Table.7-6 (ただしざっくり)
1.1.1.4 root 1777:
1.1 root 1778: if (FLD_D == 0)
1779: return;
1780: rD = rS1 * rS2;
1781: }
1782:
1783: // 111101_DDDDDSSSSS_011100_nn000sssss
1784: OP_DEF(add)
1785: {
1.1.1.2 root 1786: uint64 res = (uint64)rS1 + rS2;
1.1 root 1787: if (IsCI) {
1788: res += GetCY();
1789: }
1790: // XXX: オーバーフローが起きたときにキャリーが更新されるかどうか
1791: // ドキュメントされてない気がする
1792: if (IsCO) {
1.1.1.4 root 1793: SetCY(res >> 32);
1.1 root 1794: }
1795: if (isovf_add(rS1, rS2, res)) {
1796: Exception(M88K_EXCEP_INT_OVF);
1797: return;
1798: }
1799: if (FLD_D == 0)
1800: return;
1801: rD = res;
1802: }
1803:
1804: // 111101_DDDDDSSSSS_011101_nn000sssss
1805: OP_DEF(sub)
1806: {
1.1.1.2 root 1807: // sub 命令では CY ビットは Z80 とかと逆で、0 ならボロー発生。
1808: // 88100 のマニュアルには書いてない。88110 のマニュアルにある。
1809:
1810: // 1 の補数をとって足す。
1811: uint64 res = (uint64)rS1 + (~rS2);
1.1 root 1812: if (IsCI) {
1.1.1.2 root 1813: res += GetCY();
1814: } else {
1815: res += 1;
1.1 root 1816: }
1817: // XXX: オーバーフローが起きたときにキャリーが更新されるかどうか
1818: // ドキュメントされてない気がする
1819: if (IsCO) {
1.1.1.4 root 1820: SetCY(res >> 32);
1.1 root 1821: }
1822: if (isovf_sub(rS1, rS2, res)) {
1823: Exception(M88K_EXCEP_INT_OVF);
1824: return;
1825: }
1826: if (FLD_D == 0)
1827: return;
1828: rD = res;
1829: }
1830:
1831: // 111101_DDDDDSSSSS_011110_zz000sssss
1832: OP_DEF(div)
1833: {
1834: if (!IsFPUEnable()) {
1835: fpu_unimpl();
1836: return;
1837: }
1.1.1.4 root 1838:
1.1.1.5 ! root 1839: AddCycle(38); // Table.7-6 (ただしざっくり)
1.1.1.4 root 1840:
1.1.1.2 root 1841: if ((int32)rS1 < 0 || (int32)rS2 <= 0) {
1.1 root 1842: Exception(M88K_EXCEP_INT_DIV);
1843: return;
1844: }
1845: if (FLD_D == 0)
1846: return;
1847: rD = rS1 / rS2;
1848: }
1849:
1850: // 111101_DDDDDSSSSS_011111_zz000sssss
1851: OP_DEF(cmp)
1852: {
1853: if (FLD_D == 0)
1854: return;
1855: rD = acc_cmp(rS1, rS2);
1856: }
1857:
1858: // 111101_DDDDDSSSSS_100000_00000sssss
1859: OP_DEF(clr_2)
1860: {
1861: if (FLD_D == 0)
1862: return;
1863: rD = rS1 & ~acc_bf((rS2 >> 5) & 0x1f, rS2 & 0x1f);
1864: }
1865:
1866: // 111101_DDDDDSSSSS_100010_00000sssss
1867: OP_DEF(set_2)
1868: {
1869: if (FLD_D == 0)
1870: return;
1871: rD = rS1 | acc_bf((rS2 >> 5) & 0x1f, rS2 & 0x1f);
1872: }
1873:
1874: // 111101_DDDDDSSSSS_100100_00000sssss
1875: OP_DEF(ext_2)
1876: {
1877: int w, o, left;
1878: uint32 tmp;
1879:
1880: if (FLD_D == 0)
1881: return;
1882: w = (rS2 >> 5) & 0x1f;
1883: if (w == 0)
1884: w = 32;
1885: o = (rS2 ) & 0x1f;
1886: left = 32 - w - o;
1887: tmp = ASL(rS1, left);
1888: tmp = ASR(tmp, left);
1889: rD = ASR(tmp, o);
1890: }
1891:
1892: // 111101_DDDDDSSSSS_100110_00000sssss
1893: OP_DEF(extu_2)
1894: {
1895: int w, o, left;
1896: uint32 tmp;
1897:
1898: if (FLD_D == 0)
1899: return;
1900: w = (rS2 >> 5) & 0x1f;
1901: if (w == 0)
1902: w = 32;
1903: o = (rS2 ) & 0x1f;
1904: left = 32 - w - o;
1905: tmp = ASL(rS1, left);
1906: tmp = LSR(tmp, left);
1907: rD = tmp >> o;
1908: }
1909:
1910: // 111101_DDDDDSSSSS_101000_00000sssss
1911: OP_DEF(mak_2)
1912: {
1913: if (FLD_D == 0)
1914: return;
1915: int w = (rS2 >> 5) & 0x1f;
1916: int o = (rS2 ) & 0x1f;
1917: rD = (rS1 << o) & acc_bf(w, o);
1918: }
1919:
1920: // 111101_DDDDDSSSSS_101010_00000sssss
1921: OP_DEF(rot_2)
1922: {
1923: if (FLD_D == 0)
1924: return;
1925: int o = (rS2 ) & 0x1f;
1926: rD = ROR(rS1, o);
1927: }
1928:
1929: // 111101_zzzzzzzzzz_110000_00000sssss
1930: OP_DEF(jmp)
1931: {
1.1.1.5 ! root 1932: AddCycle(1); // Table.7-5
1.1.1.4 root 1933: EnterBranch(rS2);
1.1 root 1934: ExitBranch();
1935: }
1936:
1937: // 111101_zzzzzzzzzz_110001_00000sssss
1938: OP_DEF(jmp_n)
1939: {
1.1.1.5 ! root 1940: AddCycle(0); // Table.7-5
1.1.1.4 root 1941: EnterBranch(rS2);
1.1 root 1942: ExitDelayBranch();
1943: }
1944:
1945: // 111101_zzzzzzzzzz_110010_00000sssss
1946: OP_DEF(jsr)
1947: {
1.1.1.5 ! root 1948: AddCycle(1); // Table.7-5
1.1.1.4 root 1949: EnterBranch(rS2);
1.1 root 1950: r[1] = nip;
1951: ExitBranch();
1952: }
1953:
1954: // 111101_zzzzzzzzzz_110011_00000sssss
1955: OP_DEF(jsr_n)
1956: {
1.1.1.5 ! root 1957: AddCycle(0); // Table.7-5
1.1.1.4 root 1958: EnterBranch(rS2);
1.1 root 1959: r[1] = nip + 4;
1960: ExitDelayBranch();
1961: }
1962:
1.1.1.2 root 1963: // 111101_DDDDDzzzzz_111010_00000sssss
1964: OP_DEF(ff1)
1965: {
1966: int i;
1967: uint32 m = 0x80000000U;
1968:
1969: if (FLD_D == 0)
1970: return;
1971:
1972: if (rS2 == 0) {
1973: rD = 32;
1974: } else {
1975: for (i = 31; i >= 0; i--, m >>= 1) {
1976: if ((rS2 & m) != 0) {
1977: break;
1978: }
1979: }
1980: rD = i;
1981: }
1982:
1983: }
1984:
1985: // 111101_DDDDDzzzzz_111011_00000sssss
1986: OP_DEF(ff0)
1987: {
1988: int i;
1989: uint32 m = 0x80000000U;
1990:
1991: if (FLD_D == 0)
1992: return;
1993:
1994: if (rS2 == 0xffffffffU) {
1995: rD = 32;
1996: } else {
1997: for (i = 31; i >= 0; i--, m >>= 1) {
1998: if ((rS2 & m) == 0) {
1999: break;
2000: }
2001: }
2002: rD = i;
2003: }
2004: }
2005:
1.1 root 2006: // 111101_zzzzzzzzzz_111111_0000000000
2007: OP_DEF(rte)
2008: {
1.1.1.5 ! root 2009: AddCycle(2); // Table.7-5
1.1.1.4 root 2010:
1.1.1.2 root 2011: SetPSR(epsr);
1.1 root 2012:
1.1.1.2 root 2013: // LUNA88K の ROM1.2 は sxip, snip, sfip を制御してくる。
2014: // ROM1.2 の DAE ハンドラは、
2015: // sxip = INVALID
2016: // snip = 0 (INVALID)
2017: // sfip = original sxip
2018: // で rte してくる。
2019: // CPU は sxip は評価しない。snip は 0 なので、無効として nop 扱い。
2020: // (実際はクロックが消費されるかも?)
2021: // sfip が VALID なので、そこから実行を再開する。
2022: if (snip & SIP_V) {
1.1.1.4 root 2023: EnterBranch(snip & SIP_MASK);
2024: ExitBranch();
1.1.1.2 root 2025: fip = sfip & SIP_MASK;
2026: } else {
1.1.1.4 root 2027: EnterBranch(sfip & SIP_MASK);
2028: ExitBranch();
1.1.1.2 root 2029: }
1.1 root 2030:
2031: // ディレイスロットにいた命令かどうかをやんわり復元する。
2032: // 88110 ではこの情報が E?IP に保持されているが
2033: // 88100 にはない。
2034: if (nip + 4 != fip) {
1.1.1.4 root 2035: ExitDelayBranch();
1.1 root 2036: }
2037: }
2038:
2039: // 111101_zzzzzSSSSS_111110_00000SSSSS
2040: OP_DEF(tbnd_1)
2041: {
2042: if (rS1 > rS2) {
2043: Exception(M88K_EXCEP_BOUNDS);
2044: }
2045: }
2046:
2047: // 111110_zzzzzSSSSS_nnnnnn_nnnnnnnnnn
2048: OP_DEF(tbnd_2)
2049: {
2050: if (rS1 > IMM16) {
2051: Exception(M88K_EXCEP_BOUNDS);
2052: }
2053: }
2054:
2055: // 111111_zzzzzzzzzz_000011_zzzzzzzzzz
2056: OP_DEF(getc)
2057: {
2058: printf("getc inst\n");
2059: int c = getchar();
2060: r[2] = c;
2061: }
2062:
2063: // 111111_zzzzzzzzzz_000100_zzzzzzzzzz
2064: OP_DEF(putc)
2065: {
2066: // r3 を表示
2067: putchar(r[3]);
2068: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.