|
|
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.12! root 8: #include "bitops.h"
1.1.1.5 root 9: #include <cfenv>
10: #include <cmath>
1.1.1.2 root 11:
1.1 root 12: // 命令のフィールド取り出し
1.1.1.2 root 13: #define FLD_D m88100opf_D(opX)
14: #define FLD_S1 m88100opf_S1(opX)
15: #define FLD_S2 m88100opf_S2(opX)
16: #define FLD_CR m88100opf_CR(opX)
17: #define B5 m88100opf_B5(opX)
18: #define M5 m88100opf_M5(opX)
19: #define W5 m88100opf_W5(opX)
20: #define O5 m88100opf_O5(opX)
21: #define IMM16 m88100opf_IMM16(opX)
22: #define VEC9 m88100opf_VEC9(opX)
1.1 root 23:
24: // 符号拡張・シフト済みのディスプレースメント
25: // XXX: (負数の右シフト)GCC only
26: #define D16 (((int32)(int16)opX) << 2)
27: #define D26 (((int32)(opX << 6) >> 4))
28: #define IsCO ((opX >> 8) & 1)
29: #define IsCI ((opX >> 9) & 1)
30:
31: // レジスタアクセス
32: #define rD (r[FLD_D])
33: #define rS1 (r[FLD_S1])
34: #define rS2 (r[FLD_S2])
1.1.1.4 root 35: // ダブルワードの2ワード目
1.1.1.5 root 36: #define FLD_D2 ((FLD_D + 1) & 0x1f)
37: #define rD2 (r[FLD_D2])
1.1 root 38:
1.1.1.5 root 39: // FP フィールド
40: #define FP_T1 m88100opf_FP_T1(opX)
41: #define FP_T2 m88100opf_FP_T2(opX)
42: #define FP_TD m88100opf_FP_TD(opX)
43:
1.1.1.11 root 44: // XXX t(サイズ)が原因で Reserved Operand になった時の S1, S2 はどうなる?
1.1.1.5 root 45: #define FP_GET(v, t, n) \
46: do { \
47: if (t == 0) { \
48: v = u2f(r[n]); \
49: } else if (t == 1) { \
1.1.1.11 root 50: v = u2d(((uint64)r[n] << 32) | r[(n + 1) & 31]); \
1.1.1.5 root 51: } else { \
1.1.1.11 root 52: FPPreciseException(FPECR_FROP); \
1.1.1.5 root 53: return; \
54: } \
55: } while (0)
56:
57: #define FP_SET(t, n, v) \
58: do { \
59: if (t == 0) { \
60: r[n] = f2u(v); \
61: } else if (t == 1) { \
62: uint64 tmp = d2u(v); \
63: r[n] = tmp >> 32; \
1.1.1.11 root 64: if (__predict_true(n != 31)) \
65: r[n + 1] = (uint32)tmp; \
1.1.1.5 root 66: } else { \
1.1.1.11 root 67: FPPreciseException(FPECR_FROP); \
1.1.1.5 root 68: return; \
69: } \
70: } while (0)
1.1 root 71:
72: // ブランチ命令入り口
73: inline void
1.1.1.4 root 74: m88kcpu::EnterBranch(uint32 toaddr)
1.1.1.2 root 75: {
1.1.1.9 root 76: // ジャンプ先アドレスの下位2bitはマスクされる
77: toaddr &= ~3;
1.1.1.2 root 78: // ブランチヒストリに登録しつつ、
79: // ブランチヒストリからブランチ状況を取得
1.1.1.5 root 80: auto e = brhist.AddEntry(xip | (IsSuper() ? 1 : 0), toaddr, opX);
1.1.1.2 root 81: fip = toaddr;
82:
83: // STOP 検出。
84: // m88k には STOP 状態 (何もせず割り込みだけ待つ状態。m68k の STOP 命令
85: // による STOP 状態に相当するもの) は存在せず、割り込みが起きるまで NOP
86: // 相当の命令を無限ループで実行し続ける方法が一般的にとられる。
87: // 実機であれば (電力が無駄なこと以外は) これで特段困らないかも知れないが
88: // エミュレータ (特に高速モード) ではこのような無限ループはホストの CPU
89: // がぶん回る状況になるため避けたい。そのためこの無限ループを検出したい。
90: // ただし特定の(または定番の)命令列があるわけではなく、任意の無限ループが
91: // 用いられているため、汎用的に自動検出する必要がある。
92:
93: // ループの 1 回目のブランチで初期化して、
94: // 2 回目のブランチで STOP だったかどうかをチェックする。
95: // 3 回目以降の場合は STOP でなかったので、もうチェックする必要はない。
96:
97: // m68k の STOP 命令が特権命令なので、それに倣ってここでも特権状態のみを
98: // 対象とする。
99:
100: // 通常のブランチで来る回数がはるかに多いと考えられるので、
101: // 先にカウント数をチェック対象かどうか調べる。
102: if (e.count < 3 && IsSuper()) {
103: if (e.count == 1) {
104: // 新規ブランチ
105: // 初期化
106: nop_counter = 0;
1.1.1.8 root 107: } else if (pseudo_stop_enable) {
108: // 疑似 STOP 状態有効のときに、
1.1.1.2 root 109: // e.count == 2 のときだけ STOP の検証をすれば良い。
110:
111: // d はブランチ間の命令数
112: uint32 d = (xip - toaddr) / sizeof(uint32);
113: // 遅延ブランチなら 1 命令余分に実行するはずなので 1 足す
1.1.1.9 root 114: if ((opX & (1 << 26)) != 0) {
1.1.1.2 root 115: d++;
116: }
117: // ブランチ間の命令がすべて NOP なら STOP ということにする。
118: if (nop_counter == d) {
1.1.1.12! root 119: ChangeState(CPU_STATE_STOP);
1.1.1.2 root 120: }
1.1.1.8 root 121:
122: // OpenBSD 6.6 では
123: // L1: tb1 #1 r0, #0xff
124: // ld r13, r21, #0x168
125: // bcnd.n eq0, r13, L1
126: // or r2, r25, #0x5ea0
127: // の命令列が使用されている。
128: // これについては tb1 で実装してある。
1.1.1.2 root 129: }
130: // STOP ではなかったら、あとは放置していい
131: }
132: }
133:
1.1 root 134: // 通常(即時)ブランチ出口
135: inline void
136: m88kcpu::ExitBranch()
137: {
138: // re-fetch branched instruction
139: fetch();
140: }
141:
142: // 遅延ブランチ出口
1.1.1.4 root 143: // 速度を稼ぐため、ビット反転だけでこれを区別しているので、
144: // 同じ op 中で複数回呼び出さないこと。
1.1 root 145: inline void
146: m88kcpu::ExitDelayBranch()
147: {
1.1.1.4 root 148: opF ^= DELAYSLOT;
1.1 root 149: }
150:
151: // ロードストアユニットの usr の処理。
152: // 正常なら true を返す (ので呼び出し側は実行継続)、
153: // 例外が起きたら処理して false を返すので呼び出し側は即リターンすること。
154: inline bool
1.1.1.2 root 155: m88kcpu::ldst_usr(uint32& usr)
1.1 root 156: {
157: usr = (opX & (1 << 8)) ? DM_USR : 0;
158: if (IsUser() && usr) {
159: Exception(M88K_EXCEP_PRIV);
160: return false;
161: }
162: return true;
163: }
164:
1.1.1.2 root 165: // MEMO: ロードストアでの usr の処理で、CMMU に対して
166: // usr を引数ではなくSetSuper() の呼び出しで渡すようにしている。
167: // データのロードストアだけがあるのなら usr を引数で渡すほうが
168: // 効率的だが、CMMU は 命令/データで同じものを使うため、
169: // 命令 CMMU では 100% 無駄な引数の引き渡しが必要になってしまう。
170: // そして命令アクセスのほうが何倍も比率が多い。
171: // .usr 指定は比率としてはレアなので、状態変更メソッドによる
172: // 方法にしてみた。
173:
1.1 root 174: // ロードストアユニットの scale の処理。addr を返す。
175: inline uint32
176: m88kcpu::ldst_scale(uint32 size)
177: {
1.1.1.9 root 178: if ((opX & (1 << 9)) != 0) {
1.1 root 179: return rS1 + rS2 * size;
180: } else {
181: return rS1 + rS2;
182: }
183: }
184:
185: // ロードストアユニットの align の処理。
186: // 正常なら true を返す (ので呼び出し側は実行継続)、
187: // 例外が起きたら処理して false を返すので呼び出し側は即リターンすること。
188: inline bool
189: m88kcpu::ldst_align(uint32 size, uint32& addr)
190: {
1.1.1.9 root 191: if ((addr & (size - 1)) != 0) {
1.1 root 192: if (IsMXM()) {
193: addr &= ~(size - 1);
194: } else {
195: Exception(M88K_EXCEP_MISALIGNED);
196: return false;
197: }
198: }
199: return true;
200: }
201:
202: // ロードストアユニットの usr と scale の処理 (呼び出し用マクロ)
203: #define LDST_USR_SCALE(size) do { \
1.1.1.2 root 204: if (ldst_usr(usr) == false) \
1.1 root 205: return; \
206: addr = ldst_scale(size); \
207: } while (0)
208:
209: // ロードストアユニットの align の処理 (呼び出し用マクロ)
210: #define LDST_ALIGN(size) do { \
211: if (ldst_align(size, addr) == false) \
212: return; \
213: } while (0)
214:
215: // ロードストアユニットのまとめたもの
216: #define LDST_USR_SCALE_ALIGN(size) do { \
217: LDST_USR_SCALE(size); \
218: LDST_ALIGN(size); \
219: } while (0)
220:
221: // 幅規制付き算術左シフト
222: static inline uint32
223: ASL(uint32 a, int n)
224: {
225: if (n <= 0)
226: return a;
227: if (n >= 32)
228: return 0;
229: return a << n;
230: }
231:
232: // 幅規制付き算術右シフト
233: static inline uint32
234: ASR(uint32 a, int n)
235: {
236: if (n <= 0)
237: return a;
238: if (n >= 32)
239: return (int32)a < 0 ? -1 : 0;
240: // XXX: 負数の右シフト
241: return (int32)a >> n;
242: }
243:
244: // 幅規制付き論理右シフト
245: static inline uint32
246: LSR(uint32 a, int n)
247: {
248: if (n <= 0)
249: return a;
250: if (n >= 32)
251: return 0;
252: return a >> n;
253: }
254:
255: // add でのオーバーフロー条件
256: static inline bool
257: isovf_add(uint32 s1, uint32 s2, uint32 res)
258: {
259: return (int32)((s1 ^ res) & (s2 ^ res)) < 0;
260: }
261: // sub でのオーバーフロー条件
262: static inline bool
263: isovf_sub(uint32 s1, uint32 s2, uint32 res)
264: {
265: return (int32)((s1 ^ s2) & (s1 ^ res)) < 0;
266: }
267:
268: // bcnd のやつ
269: static inline int
270: acc_cnd(uint32 r)
271: {
272: int rv;
1.1.1.9 root 273: if ((r & 0x80000000) != 0) {
1.1 root 274: if (r == 0x80000000) {
275: rv = 0x8;
276: } else {
277: rv = 0x4;
278: }
279: } else {
280: if (r == 0) {
281: rv = 0x2;
282: } else {
283: rv = 0x1;
284: }
285: }
286: return rv;
287: }
288:
289: // bitfield
290: static inline uint32
291: acc_bf(int w, int ofs)
292: {
293: uint32 m;
294: if (w == 0) {
295: m = 0xFFFFFFFFU;
296: } else {
297: m = ~(0xFFFFFFFFU << w);
298: }
299: return m << ofs;
300: }
301:
1.1.1.11 root 302: // m88100 FPCR の RndMode (0..3) から <cfenv> の丸めモード値への変換。
303: // 大抵ここに渡す前に 3 で AND しているはずなので範囲外は考慮しない。
304: static int rm_to_round[4] = {
305: FE_TONEAREST,
306: FE_TOWARDZERO,
307: FE_DOWNWARD,
308: FE_UPWARD,
309: };
310:
311:
1.1 root 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)) {
1.1.1.11 root 788: // 制御レジスタ番号が範囲外の時は
789: // 88100 では undocumented、
790: // 88110 では Unimplemented Opcode 例外。
1.1 root 791: Exception(M88K_EXCEP_UNIMPL_OP);
792: return;
793: }
794: if (FLD_D == 0)
795: return;
796: rD = cr[FLD_CR];
797: }
798:
799: // 100000_DDDDDzzzzz_01001n_nnnnnzzzzz
800: OP_DEF(fldcr)
801: {
802: int n = FLD_CR;
803:
1.1.1.11 root 804: // 88100 88110(Only for reference)
805: // Super User Super User
806: // ----- ----- ----- -----
807: // FCR0 read FPRV read FPRV
808: // FCR1..8 read FPRV FUNIMP FPRV
809: // FCR9..61 read0 FPRV FUNIMP FPRV
810: // FCR62,63 read read read read
1.1 root 811:
812: if (n >= 62) {
813: n = n - 62 + 9;
1.1.1.11 root 814: } else {
815: if (IsUser()) {
816: FPPreciseException(FPECR_FPRV);
817: return;
818: }
819: if (n > 8) {
820: rD = 0;
821: return;
822: }
1.1 root 823: }
824: if (FLD_D == 0)
825: return;
1.1.1.11 root 826:
827: // XXX 内部がバグってなければ読み出す時にマスクする必要はないが、一応
828: rD = fcr[n] & fcr_mask[n];
1.1 root 829: }
830:
831: // 100000_zzzzzSSSSS_10000n_nnnnnsssss
832: OP_DEF(stcr)
833: {
834: if (IsUser()) {
835: Exception(M88K_EXCEP_PRIV);
836: return;
837: }
838: if (FLD_CR > countof(cr)) {
1.1.1.11 root 839: // 制御レジスタ番号が範囲外の時は
840: // 88100 では undocumented、
841: // 88110 では Unimplemented Opcode 例外。
1.1 root 842: Exception(M88K_EXCEP_UNIMPL_OP);
843: return;
844: }
845: cr[FLD_CR] = rS1;
1.1.1.2 root 846: if (FLD_CR == 1) {
1.1.1.4 root 847: SetPSR();
1.1.1.2 root 848: }
1.1 root 849: }
850:
851: // 100000_zzzzzSSSSS_10001n_nnnnnsssss
852: OP_DEF(fstcr)
853: {
854: int n = FLD_CR;
855:
1.1.1.11 root 856: // 88100 88110(Only for reference)
857: // Super User Super User
858: // ----- ----- ----- -----
859: // FCR0 write FPRV write FPRV
860: // FCR1..8 noop FPRV FUNIMP FPRV
861: // FCR9..61 noop FPRV FUNIMP FPRV
862: // FCR62,63 write write write write
863:
864: if (n >= 62) {
865: n = n - 62 + 9;
866: } else {
867: if (IsUser()) {
868: FPPreciseException(FPECR_FPRV);
869: return;
870: }
871: // FCR1..8(読み込み専用レジスタ)、9..61(未実装レジスタ) ともに noop
872: if (n > 0) {
1.1 root 873: return;
874: }
875: }
876:
1.1.1.11 root 877: fcr[n] = rS1 & fcr_mask[n];
1.1 root 878:
1.1.1.11 root 879: // FPCR が変更されたら、ホストの丸めモードも更新
880: if (n == 10) {
881: uint32 rm = (fpcr >> 14) & 3;
882: std::fesetround(rm_to_round[rm]);
1.1 root 883: }
884: }
885:
886: // 100000_DDDDDSSSSS_11000n_nnnnnsssss
887: OP_DEF(xcr)
888: {
889: uint32 tmp;
890:
891: if (IsUser()) {
892: Exception(M88K_EXCEP_PRIV);
893: return;
894: }
895: if (FLD_CR > countof(cr)) {
1.1.1.11 root 896: // 制御レジスタ番号が範囲外の時は
897: // 88100 では undocumented、
898: // 88110 では Unimplemented Opcode 例外。
1.1 root 899: Exception(M88K_EXCEP_UNIMPL_OP);
900: return;
901: }
902: tmp = rS1;
903: rD = cr[FLD_CR];
904: cr[FLD_CR] = tmp;
1.1.1.2 root 905: if (FLD_CR == 1) {
1.1.1.4 root 906: SetPSR();
1.1.1.2 root 907: }
1.1 root 908: r[0] = 0;
909: }
910:
911: // 100000_DDDDDSSSSS_11001n_nnnnnsssss
912: OP_DEF(fxcr)
913: {
1.1.1.11 root 914: uint n = FLD_CR;
1.1 root 915:
1.1.1.11 root 916: // 88100 88110(Only for reference)
917: // Super User Super User
918: // ----- ----- ----- -----
919: // FCR0 xchg FPRV xchg FPRV
920: // FCR1..8 read FPRV FUNIMP FPRV
921: // FCR9..61 read0 FPRV FUNIMP FPRV
922: // FCR62,63 xchg xchg xchg xchg
1.1 root 923:
1.1.1.11 root 924: if (IsUser() && n < 62) {
925: FPPreciseException(FPECR_FPRV);
1.1 root 926: return;
927: }
928:
1.1.1.11 root 929: if (n == 0) {
930: goto exchange;
931: } else if (__predict_false(n < 9)) {
932: // FCR1..8 は読み込み専用レジスタなので、読み出す側のみ
933: rD = fcr[n] & fcr_mask[n];
934: r[0] = 0;
935: return;
936: } else if (__predict_false(n < 62)) {
937: // FCR9..61 は未実装レジスタなので、0 が読み出せるのみ
938: rD = 0;
939: return;
940: } else {
1.1 root 941: n = n - 62 + 9;
942: }
1.1.1.11 root 943:
944: exchange:
945: uint32 tmp = rS1;
946: rD = fcr[n] & fcr_mask[n];
947: fcr[n] = tmp & fcr_mask[n];
948:
1.1 root 949: r[0] = 0;
950: }
951:
952: // 100001_DDDDDSSSSS_00000n_nnnnnsssss
953: OP_DEF(fmul)
954: {
1.1.1.5 root 955: // 暫定
956: double s1;
957: double s2;
958:
959: if (FLD_D == 0) {
1.1.1.11 root 960: FPPreciseException(FPECR_FUNIMP);
1.1.1.5 root 961: return;
962: }
963:
964: FP_GET(s1, FP_T1, FLD_S1);
965: FP_GET(s2, FP_T2, FLD_S2);
966: FP_SET(FP_TD, FLD_D, s1 * s2);
1.1 root 967: }
968:
969: // 100001_DDDDD00000_001000_000nnsssss
970: OP_DEF(flt)
971: {
1.1.1.5 root 972: // 暫定
973: if (FLD_D == 0) {
1.1.1.11 root 974: FPPreciseException(FPECR_FUNIMP);
1.1.1.5 root 975: return;
976: }
977:
1.1.1.10 root 978: FP_SET(FP_TD, FLD_D, (double)(int32)rS2);
1.1 root 979: }
980:
1.1.1.5 root 981:
1.1 root 982: // 100001_DDDDDSSSSS_00101n_nnnnnsssss
983: OP_DEF(fadd)
984: {
1.1.1.5 root 985: // 暫定
986: double s1;
987: double s2;
988:
989: if (FLD_D == 0) {
1.1.1.11 root 990: FPPreciseException(FPECR_FUNIMP);
1.1.1.5 root 991: return;
992: }
993:
994: FP_GET(s1, FP_T1, FLD_S1);
995: FP_GET(s2, FP_T2, FLD_S2);
996: FP_SET(FP_TD, FLD_D, s1 + s2);
1.1 root 997: }
998:
999: // 100001_DDDDDSSSSS_00110n_nnnnnsssss
1000: OP_DEF(fsub)
1001: {
1.1.1.5 root 1002: // 暫定
1003: double s1;
1004: double s2;
1005:
1006: if (FLD_D == 0) {
1.1.1.11 root 1007: FPPreciseException(FPECR_FUNIMP);
1.1.1.5 root 1008: return;
1009: }
1010:
1011: FP_GET(s1, FP_T1, FLD_S1);
1012: FP_GET(s2, FP_T2, FLD_S2);
1013: FP_SET(FP_TD, FLD_D, s1 - s2);
1.1 root 1014: }
1015:
1016: // 100001_DDDDDSSSSS_00111n_nnnnnsssss
1017: OP_DEF(fcmp)
1018: {
1.1.1.5 root 1019: double s1;
1020: double s2;
1021:
1022: if (FLD_D == 0) {
1.1.1.11 root 1023: FPPreciseException(FPECR_FUNIMP);
1.1.1.5 root 1024: return;
1025: }
1026:
1027: FP_GET(s1, FP_T1, FLD_S1);
1028: FP_GET(s2, FP_T2, FLD_S2);
1.1.1.11 root 1029:
1030: // XXX テストが出来てないので Inf と非正規化数は未対応
1031: // 非正規化数もここのはず
1032: if (std::isnan(s1) || std::isnan(s2) ||
1033: std::isinf(s1) || std::isinf(s2) )
1034: {
1035: FPPreciseException(FPECR_FROP, s1, s2);
1036: return;
1037: }
1038:
1039: //
1040: // 31 .. 12 11 10 9 8 7 6 5 4 3 2 1 0
1041: // +---- ---+----+----+----+----+----+----+----+----+----+----+----+----+
1042: // | 0 | ob | in | ib | ou | ge | lt | le | gt | ne | eq | cp | nc |
1043: // +---- ---+----+----+----+----+----+----+----+----+----+----+----+----+
1044:
1045: uint32 res = 0;
1046: if (s2 >= 0) {
1047: if (s1 <= 0 || s2 <= s1) res |= 0x0800; // ob
1048: if (0 < s1 && s1 < s2) res |= 0x0400; // in
1049: if (0 <= s1 && s1 <= s2) res |= 0x0200; // ib
1050: if (s1 < 0 || s2 < s1) res |= 0x0100; // ou
1051: }
1052: if (s1 >= s2) res |= 0x0080; // ge
1053: if (s1 < s2) res |= 0x0040; // lt
1054: if (s1 <= s2) res |= 0x0020; // le
1055: if (s1 > s2) res |= 0x0010; // gt
1056: if (s1 != s2) res |= 0x0008; // ne
1057: if (s1 == s2) res |= 0x0004; // eq
1058: // cp; if and only if the two operands are comparable
1059: if (!std::isnan(s1) && !std::isnan(s2)) {
1060: res |= 0x0002;
1061: }
1062: // nc; if, and only if, the two operands are not comparable
1063: if (std::isnan(s1) || std::isnan(s2)) {
1064: res |= 0x0001;
1065: }
1066:
1067: rD = res;
1.1 root 1068: }
1069:
1.1.1.11 root 1070: // int, nint, trnc 命令の共通部
1071: void
1072: m88kcpu::ops_int(int rndmode)
1073: {
1074: double src;
1075: double res;
1076: int exponent;
1.1.1.5 root 1077:
1078: if (FLD_D == 0) {
1.1.1.11 root 1079: FPPreciseException(FPECR_FUNIMP);
1.1.1.5 root 1080: return;
1081: }
1082:
1.1.1.11 root 1083: if (FP_T2 == 0) {
1084: float f;
1085: FP_GET(f, FP_T2, FLD_S2);
1086: src = f;
1087: } else {
1088: FP_GET(src, FP_T2, FLD_S2);
1089: }
1090:
1091: int saved_rndmode = std::fegetround();
1.1.1.5 root 1092:
1.1.1.11 root 1093: std::fesetround(rndmode);
1094: res = std::nearbyint(src);
1095: std::fesetround(saved_rndmode);
1096:
1097: exponent = 0;
1098: std::frexp(res, &exponent);
1099: if (std::isinf(res) || std::isnan(res) || exponent >= 30) {
1100: // 整数で表現出来ない(かも知れない)ので例外
1101: FPPreciseException(FPECR_FIOV, src);
1102: return;
1.1.1.5 root 1103: }
1.1.1.11 root 1104: rD = (uint32)(int32)res;
1105: }
1106:
1107: // 100001_DDDDD00000_010010_0nn00sssss
1108: OP_DEF(int)
1109: {
1110: // 現在のモードのまま (ちょっと無駄だけど…)
1111: ops_int(std::fegetround());
1.1 root 1112: }
1113:
1114: // 100001_DDDDD00000_010100_0nn00sssss
1115: OP_DEF(nint)
1116: {
1.1.1.11 root 1117: ops_int(FE_TONEAREST);
1.1 root 1118: }
1119:
1120: // 100001_DDDDD00000_010110_0nn00sssss
1121: OP_DEF(trnc)
1122: {
1.1.1.11 root 1123: ops_int(FE_TOWARDZERO);
1.1 root 1124: }
1125:
1126: // 100001_DDDDDSSSSS_01110n_nnnnnsssss
1127: OP_DEF(fdiv)
1128: {
1.1.1.5 root 1129: // 暫定
1130: double s1;
1131: double s2;
1132:
1133: if (FLD_D == 0) {
1.1.1.11 root 1134: FPPreciseException(FPECR_FUNIMP);
1.1.1.5 root 1135: return;
1136: }
1137:
1138: FP_GET(s1, FP_T1, FLD_S1);
1139: FP_GET(s2, FP_T2, FLD_S2);
1140: FP_SET(FP_TD, FLD_D, s1 / s2);
1.1 root 1141: }
1142:
1143: // 110000_nnnnnnnnnn_nnnnnn_nnnnnnnnnn
1144: OP_DEF(br)
1145: {
1.1.1.5 root 1146: AddCycle(1); // Table.7-5
1.1.1.4 root 1147: EnterBranch(xip + D26);
1.1 root 1148: ExitBranch();
1149: }
1150:
1151: // 110001_nnnnnnnnnn_nnnnnn_nnnnnnnnnn
1152: OP_DEF(br_n)
1153: {
1.1.1.5 root 1154: AddCycle(0); // Table.7-5
1.1.1.4 root 1155: EnterBranch(xip + D26);
1.1 root 1156: ExitDelayBranch();
1157: }
1158:
1159: // 110010_nnnnnnnnnn_nnnnnn_nnnnnnnnnn
1160: OP_DEF(bsr)
1161: {
1.1.1.5 root 1162: AddCycle(1); // Table.7-5
1.1.1.4 root 1163: EnterBranch(xip + D26);
1.1 root 1164: r[1] = nip;
1165: ExitBranch();
1166: }
1167:
1168: // 110011_nnnnnnnnnn_nnnnnn_nnnnnnnnnn
1169: OP_DEF(bsr_n)
1170: {
1.1.1.5 root 1171: AddCycle(0); // Table.7-5
1.1.1.4 root 1172: EnterBranch(xip + D26);
1.1 root 1173: r[1] = nip + 4;
1174: ExitDelayBranch();
1175: }
1176:
1177: // 110100_nnnnnSSSSS_nnnnnn_nnnnnnnnnn
1178: OP_DEF(bb0)
1179: {
1180: if ((rS1 & (1 << B5)) == 0) {
1.1.1.5 root 1181: AddCycle(1); // Table.7-5
1.1.1.4 root 1182: EnterBranch(xip + D16);
1.1 root 1183: ExitBranch();
1184: }
1185: }
1186:
1187: // 110101_nnnnnSSSSS_nnnnnn_nnnnnnnnnn
1188: OP_DEF(bb0_n)
1189: {
1190: if ((rS1 & (1 << B5)) == 0) {
1.1.1.4 root 1191: EnterBranch(xip + D16);
1.1 root 1192: ExitDelayBranch();
1193: }
1194: }
1195:
1196: // 110110_nnnnnSSSSS_nnnnnn_nnnnnnnnnn
1197: OP_DEF(bb1)
1198: {
1199: if ((rS1 & (1 << B5)) != 0) {
1.1.1.5 root 1200: AddCycle(1); // Table.7-5
1.1.1.4 root 1201: EnterBranch(xip + D16);
1.1 root 1202: ExitBranch();
1203: }
1204: }
1205:
1206: // 110111_nnnnnSSSSS_nnnnnn_nnnnnnnnnn
1207: OP_DEF(bb1_n)
1208: {
1209: if ((rS1 & (1 << B5)) != 0) {
1.1.1.4 root 1210: EnterBranch(xip + D16);
1.1 root 1211: ExitDelayBranch();
1212: }
1213: }
1214:
1215: // 111010_MMMMMSSSSS_nnnnnn_nnnnnnnnnn
1216: OP_DEF(bcnd)
1217: {
1.1.1.9 root 1218: if ((acc_cnd(rS1) & M5) != 0) {
1.1.1.5 root 1219: AddCycle(1); // Table.7-5
1.1.1.4 root 1220: EnterBranch(xip + D16);
1.1 root 1221: ExitBranch();
1222: }
1223: }
1224:
1225: // 111011_MMMMMSSSSS_nnnnnn_nnnnnnnnnn
1226: OP_DEF(bcnd_n)
1227: {
1.1.1.9 root 1228: if ((acc_cnd(rS1) & M5) != 0) {
1.1.1.4 root 1229: EnterBranch(xip + D16);
1.1 root 1230: ExitDelayBranch();
1231: }
1232: }
1233:
1234: // 111100_DDDDDSSSSS_100000_wwwwwooooo
1235: OP_DEF(clr_1)
1236: {
1237: if (FLD_D == 0)
1238: return;
1239: rD = rS1 & ~acc_bf(W5, O5);
1240: }
1241:
1242: // 111100_DDDDDSSSSS_100010_wwwwwooooo
1243: OP_DEF(set_1)
1244: {
1245: if (FLD_D == 0)
1246: return;
1247: rD = rS1 | acc_bf(W5, O5);
1248: }
1249:
1250: // 111100_DDDDDSSSSS_100100_wwwwwooooo
1251: OP_DEF(ext_1)
1252: {
1253: int w, o, left;
1254: uint32 tmp;
1255:
1256: if (FLD_D == 0)
1257: return;
1258: w = W5;
1259: if (w == 0)
1260: w = 32;
1261: o = O5;
1262: left = 32 - w - o;
1263: tmp = ASL(rS1, left);
1264: tmp = ASR(tmp, left);
1265: rD = ASR(tmp, o);
1266: }
1267:
1268: // 111100_DDDDDSSSSS_100110_wwwwwooooo
1269: OP_DEF(extu_1)
1270: {
1271: int w, o, left;
1272: uint32 tmp;
1273:
1274: if (FLD_D == 0)
1275: return;
1276: w = W5;
1277: if (w == 0)
1278: w = 32;
1279: o = O5;
1280: left = 32 - w - o;
1281: tmp = ASL(rS1, left);
1282: tmp = LSR(tmp, left);
1283: rD = tmp >> o;
1284: }
1285:
1286: // 111100_DDDDDSSSSS_101000_wwwwwooooo
1287: OP_DEF(mak_1)
1288: {
1289: if (FLD_D == 0)
1290: return;
1291: rD = (rS1 << O5) & acc_bf(W5, O5);
1292: }
1293:
1294: // 111100_DDDDDSSSSS_101010_zzzzzooooo
1295: OP_DEF(rot_1)
1296: {
1297: if (FLD_D == 0)
1298: return;
1.1.1.12! root 1299: rD = ROR32(rS1, O5);
1.1 root 1300: }
1301:
1302: // 111100_bbbbbSSSSS_110100_0vvvvvvvvv
1303: OP_DEF(tb0)
1304: {
1305: if (IsUser() && VEC9 < 128) {
1306: Exception(M88K_EXCEP_PRIV);
1307: return;
1308: }
1309: if ((rS1 & (1 << B5)) == 0) {
1310: ExceptionCore(VEC9, ExceptionKind::TRAP);
1311: }
1312: }
1313:
1314: // 111100_bbbbbSSSSS_110110_0vvvvvvvvv
1315: OP_DEF(tb1)
1316: {
1317: if (IsUser() && VEC9 < 128) {
1318: Exception(M88K_EXCEP_PRIV);
1319: return;
1320: }
1321: if ((rS1 & (1 << B5)) != 0) {
1322: ExceptionCore(VEC9, ExceptionKind::TRAP);
1.1.1.8 root 1323: } else if (pseudo_stop_enable) {
1324:
1325: // OpenBSD の STOP エミュレーション。
1326: // OpenBSD 6.6 では
1327: // L1: tb1 #1 r0, #0xff
1328: // ld r13, r21, #0x168
1329: // bcnd.n eq0, r13, L1
1330: // or r2, r25, #0x5ea0
1331: // の命令列が使用されている。
1332: // tb1 は volatile 変数をアクセスするための同期命令として
1333: // gcc により出力されている。スーパバイザが volatile を
1334: // 観測するために同じアドレスの tb1 に直接ブランチで 3 回飛び込んで
1335: // きたら、それは割り込みか別プロセッサか I/O による変更を待っている
1336: // はずなので STOP と判断してみる。
1337: // o. 3回、という数字に確たる理由はない。
1338: // o. 念の為、16バイト(4命令)後方以内からのブランチに限定しておく。
1339:
1340: if (IsSuper() && VEC9 == 0xff) {
1341: const auto& e = brhist.entry[brhist.top];
1342: if (e.count == 3
1343: && e.to == xip
1344: && e.from - e.to < 16) {
1.1.1.12! root 1345: ChangeState(CPU_STATE_STOP);
1.1.1.8 root 1346: }
1347: }
1.1 root 1348: }
1349: }
1350:
1351: // 111100_MMMMMSSSSS_111010_0vvvvvvvvv
1352: OP_DEF(tcnd)
1353: {
1354: if (IsUser() && VEC9 < 128) {
1355: Exception(M88K_EXCEP_PRIV);
1356: return;
1357: }
1.1.1.9 root 1358: if ((acc_cnd(rS1) & M5) != 0) {
1.1 root 1359: ExceptionCore(VEC9, ExceptionKind::TRAP);
1360: }
1361: }
1362:
1363: // 111101_DDDDDSSSSS_000000_xU000sssss
1364: OP_DEF(xmem_bu)
1365: {
1366: uint64 tmp;
1367: uint32 addr;
1368: uint32 usr;
1369:
1370: LDST_USR_SCALE_ALIGN(1);
1371:
1.1.1.5 root 1372: AddCycle(4); // Table.7-3
1.1.1.4 root 1373:
1.1 root 1374: lastaddr = addr;
1.1.1.2 root 1375:
1376: // 例外安全のために都度 S/U ビットを制御
1377: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.6 root 1378: tmp = cmmu[1].xmem_8(addr, rD & 0xff);
1.1.1.2 root 1379: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1.1 root 1380: if ((int64)tmp < 0) {
1.1.1.5 root 1381: XmemDataException(addr, DM_BU | DM_LOCK | usr);
1.1 root 1382: return;
1383: }
1384: if (FLD_D == 0)
1385: return;
1386: rD = tmp;
1387: }
1388:
1389: // 111101_DDDDDSSSSS_000001_xU000sssss
1390: OP_DEF(xmem_w)
1391: {
1392: uint64 tmp;
1393: uint32 addr;
1394: uint32 usr;
1395:
1396: LDST_USR_SCALE_ALIGN(4);
1397:
1.1.1.5 root 1398: AddCycle(4); // Table.7-3
1.1.1.4 root 1399:
1.1 root 1400: lastaddr = addr;
1.1.1.2 root 1401:
1402: // 例外安全のために都度 S/U ビットを制御
1403: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1404: tmp = cmmu[1].xmem_32(addr, rD);
1405: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1.1 root 1406: if ((int64)tmp < 0) {
1.1.1.5 root 1407: XmemDataException(addr, DM_W | DM_LOCK | usr);
1.1 root 1408: return;
1409: }
1.1.1.2 root 1410:
1.1 root 1411: if (FLD_D == 0)
1412: return;
1413: rD = tmp;
1414: }
1415:
1416: // 111101_DDDDDSSSSS_000010_xU000sssss
1417: OP_DEF(ld_hu)
1418: {
1.1.1.4 root 1419: uint64 data;
1.1 root 1420: uint32 addr;
1421: uint32 usr;
1422:
1423: LDST_USR_SCALE_ALIGN(2);
1424:
1.1.1.5 root 1425: AddCycle(3); // Table.7-3
1.1.1.4 root 1426:
1.1 root 1427: lastaddr = addr;
1.1.1.2 root 1428:
1429: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1430: data = cmmu[1].load_16(addr);
1.1.1.2 root 1431: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1432:
1.1.1.4 root 1433: if ((int64)data < 0) {
1.1.1.5 root 1434: ReadDataException32(addr, DM_HU | usr);
1.1 root 1435: return;
1436: }
1437: if (FLD_D == 0)
1438: return;
1.1.1.4 root 1439: rD = data;
1.1 root 1440: }
1441:
1442: // 111101_DDDDDSSSSS_000011_xU000sssss
1443: OP_DEF(ld_bu)
1444: {
1.1.1.4 root 1445: uint64 data;
1.1 root 1446: uint32 addr;
1447: uint32 usr;
1448:
1449: LDST_USR_SCALE_ALIGN(1);
1450:
1.1.1.5 root 1451: AddCycle(3); // Table.7-3
1.1.1.4 root 1452:
1.1 root 1453: lastaddr = addr;
1.1.1.2 root 1454:
1455: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1456: data = cmmu[1].load_8(addr);
1.1.1.2 root 1457: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1458:
1.1.1.4 root 1459: if ((int64)data < 0) {
1.1.1.5 root 1460: ReadDataException32(addr, DM_BU | usr);
1.1 root 1461: return;
1462: }
1463: if (FLD_D == 0)
1464: return;
1.1.1.4 root 1465: rD = data;
1.1 root 1466: }
1467:
1468: // 111101_DDDDDSSSSS_000100_xU000sssss
1469: OP_DEF(ld_d)
1470: {
1.1.1.4 root 1471: uint64 data1, data2;
1.1 root 1472: uint32 addr;
1473: uint32 usr;
1474:
1475: LDST_USR_SCALE_ALIGN(8);
1476:
1.1.1.5 root 1477: AddCycle(4); // Table.7-3
1.1.1.4 root 1478:
1.1 root 1479: lastaddr = addr;
1.1.1.2 root 1480:
1481: // 例外安全のために都度 S/U ビットを制御
1482: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1483: data1 = cmmu[1].load_32(addr);
1.1.1.2 root 1484: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1485:
1.1.1.4 root 1486: if ((int64)data1 < 0) {
1.1.1.5 root 1487: ReadDataException64(addr, DM_D1 | usr);
1.1 root 1488: return;
1489: }
1490: addr += 4;
1.1.1.2 root 1491:
1492: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1493: data2 = cmmu[1].load_32(addr);
1.1.1.2 root 1494: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1495:
1.1.1.4 root 1496: if ((int64)data2 < 0) {
1.1.1.5 root 1497: ReadDataException64(addr, DM_D2 | usr);
1.1 root 1498: return;
1499: }
1.1.1.4 root 1500: rD = data1;
1501: rD2 = data2;
1.1 root 1502: r[0] = 0;
1503: }
1504:
1505: // 111101_DDDDDSSSSS_000101_xU000sssss
1506: OP_DEF(ld_w)
1507: {
1.1.1.4 root 1508: uint64 data;
1.1 root 1509: uint32 addr;
1510: uint32 usr;
1511:
1512: LDST_USR_SCALE_ALIGN(4);
1513:
1.1.1.5 root 1514: AddCycle(3); // Table.7-3
1.1.1.4 root 1515:
1.1 root 1516: lastaddr = addr;
1.1.1.2 root 1517:
1518: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1519: data = cmmu[1].load_32(addr);
1.1.1.2 root 1520: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1521:
1.1.1.4 root 1522: if ((int64)data < 0) {
1.1.1.5 root 1523: ReadDataException32(addr, DM_W | usr);
1.1 root 1524: return;
1525: }
1526: if (FLD_D == 0)
1527: return;
1.1.1.4 root 1528: rD = data;
1.1 root 1529: }
1530:
1531: // 111101_DDDDDSSSSS_000110_xU000sssss
1532: OP_DEF(ld_h)
1533: {
1.1.1.4 root 1534: uint64 data;
1.1 root 1535: uint32 addr;
1536: uint32 usr;
1537:
1538: LDST_USR_SCALE_ALIGN(2);
1539:
1.1.1.5 root 1540: AddCycle(3); // Table.7-3
1.1.1.4 root 1541:
1.1 root 1542: lastaddr = addr;
1.1.1.2 root 1543:
1544: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1545: data = cmmu[1].load_16(addr);
1.1.1.2 root 1546: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1547:
1.1.1.4 root 1548: if ((int64)data < 0) {
1.1.1.5 root 1549: ReadDataException32(addr, DM_H | usr);
1.1 root 1550: return;
1551: }
1552: if (FLD_D == 0)
1553: return;
1.1.1.4 root 1554: rD = (uint32)(int32)(int16)data;
1.1 root 1555: }
1556:
1557: // 111101_DDDDDSSSSS_000111_xU000sssss
1558: OP_DEF(ld_b)
1559: {
1.1.1.4 root 1560: uint64 data;
1.1 root 1561: uint32 addr;
1562: uint32 usr;
1563:
1564: LDST_USR_SCALE_ALIGN(1);
1565:
1.1.1.5 root 1566: AddCycle(3); // Table.7-3
1.1.1.4 root 1567:
1.1 root 1568: lastaddr = addr;
1.1.1.2 root 1569:
1570: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1571: data = cmmu[1].load_8(addr);
1.1.1.2 root 1572: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1573:
1.1.1.4 root 1574: if ((int64)data < 0) {
1.1.1.5 root 1575: ReadDataException32(addr, DM_B | usr);
1.1 root 1576: return;
1577: }
1578: if (FLD_D == 0)
1579: return;
1.1.1.4 root 1580: rD = (uint32)(int32)(int8)data;
1.1 root 1581: }
1582:
1583: // 111101_DDDDDSSSSS_001000_xU000sssss
1584: OP_DEF(st_d)
1585: {
1.1.1.4 root 1586: uint64 rv;
1.1 root 1587: uint32 addr;
1588: uint32 usr;
1589:
1590: LDST_USR_SCALE_ALIGN(8);
1591:
1.1.1.5 root 1592: AddCycle(1 + 4); // Table.7-3
1.1.1.4 root 1593:
1.1 root 1594: lastaddr = addr;
1.1.1.2 root 1595:
1596: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1597: rv = cmmu[1].store_32(addr, rD);
1.1.1.2 root 1598: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1599:
1.1.1.4 root 1600: if ((int64)rv < 0) {
1.1.1.5 root 1601: WriteDataException64(addr, DM_D1 | usr);
1.1 root 1602: return;
1603: }
1.1.1.2 root 1604:
1.1 root 1605: addr += 4;
1.1.1.2 root 1606:
1607: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1608: rv = cmmu[1].store_32(addr, rD2);
1.1.1.2 root 1609: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1610:
1.1.1.4 root 1611: if ((int64)rv < 0) {
1.1.1.5 root 1612: WriteDataException64(addr, DM_D2 | usr);
1.1 root 1613: return;
1614: }
1615: }
1616:
1617: // 111101_DDDDDSSSSS_001001_xU000sssss
1618: OP_DEF(st_w)
1619: {
1.1.1.4 root 1620: uint64 rv;
1.1 root 1621: uint32 addr;
1622: uint32 usr;
1623:
1624: LDST_USR_SCALE_ALIGN(4);
1625:
1.1.1.5 root 1626: AddCycle(3); // Table.7-3
1.1.1.4 root 1627:
1.1 root 1628: lastaddr = addr;
1.1.1.2 root 1629:
1630: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.4 root 1631: rv = cmmu[1].store_32(addr, rD);
1.1.1.2 root 1632: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1633:
1.1.1.4 root 1634: if ((int64)rv < 0) {
1.1.1.5 root 1635: WriteDataException32(addr, DM_W | usr);
1.1 root 1636: return;
1637: }
1638: }
1639:
1640: // 111101_DDDDDSSSSS_001010_xU000sssss
1641: OP_DEF(st_h)
1642: {
1.1.1.4 root 1643: uint64 rv;
1.1 root 1644: uint32 addr;
1645: uint32 usr;
1646:
1647: LDST_USR_SCALE_ALIGN(2);
1648:
1.1.1.5 root 1649: AddCycle(3); // Table.7-3
1.1.1.4 root 1650:
1.1 root 1651: lastaddr = addr;
1.1.1.2 root 1652:
1653: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.5 root 1654: rv = cmmu[1].store_16(addr, rD & 0xffff);
1.1.1.2 root 1655: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1656:
1.1.1.4 root 1657: if ((int64)rv < 0) {
1.1.1.5 root 1658: WriteDataException32(addr, DM_H | usr);
1.1 root 1659: return;
1660: }
1661: }
1662:
1663: // 111101_DDDDDSSSSS_001011_xU000sssss
1664: OP_DEF(st_b)
1665: {
1.1.1.4 root 1666: uint64 rv;
1.1 root 1667: uint32 addr;
1668: uint32 usr;
1669:
1670: LDST_USR_SCALE_ALIGN(1);
1671:
1.1.1.5 root 1672: AddCycle(3); // Table.7-3
1.1.1.4 root 1673:
1.1 root 1674: lastaddr = addr;
1.1.1.2 root 1675:
1676: if (__predict_false(usr)) cmmu[1].SetSuper(false);
1.1.1.5 root 1677: rv = cmmu[1].store_8(addr, rD & 0xff);
1.1.1.2 root 1678: if (__predict_false(usr)) cmmu[1].SetSuper(true);
1679:
1.1.1.4 root 1680: if ((int64)rv < 0) {
1.1.1.5 root 1681: WriteDataException32(addr, DM_B | usr);
1.1 root 1682: return;
1683: }
1684: }
1685:
1686: // 111101_DDDDDSSSSS_001100_xU000sssss
1687: OP_DEF(lda_d)
1688: {
1689: uint32 addr;
1690: uint32 usr;
1691:
1692: LDST_USR_SCALE(8);
1693:
1694: if (FLD_D == 0)
1695: return;
1696: rD = addr;
1697: }
1698:
1699: // 111101_DDDDDSSSSS_001101_xU000sssss
1700: OP_DEF(lda_w)
1701: {
1702: uint32 addr;
1703: uint32 usr;
1704:
1705: LDST_USR_SCALE(4);
1706:
1707: if (FLD_D == 0)
1708: return;
1709: rD = addr;
1710: }
1711:
1712: // 111101_DDDDDSSSSS_001110_xU000sssss
1713: OP_DEF(lda_h)
1714: {
1715: uint32 addr;
1716: uint32 usr;
1717:
1718: LDST_USR_SCALE(2);
1719:
1720: if (FLD_D == 0)
1721: return;
1722: rD = addr;
1723: }
1724:
1725: // 111101_DDDDDSSSSS_001111_xU000sssss
1726: OP_DEF(lda_b)
1727: {
1728: uint32 addr;
1729: uint32 usr;
1730:
1731: LDST_USR_SCALE(1);
1732:
1733: if (FLD_D == 0)
1734: return;
1735: rD = addr;
1736: }
1737:
1738: // 111101_DDDDDSSSSS_010000_00000sssss
1739: OP_DEF(and)
1740: {
1741: if (FLD_D == 0)
1742: return;
1743: rD = rS1 & rS2;
1744: }
1745:
1746: // 111101_DDDDDSSSSS_010001_00000sssss
1747: OP_DEF(and_c)
1748: {
1749: if (FLD_D == 0)
1750: return;
1751: rD = rS1 & ~rS2;
1752: }
1753:
1754: // 111101_DDDDDSSSSS_010100_00000sssss
1755: OP_DEF(xor)
1756: {
1757: if (FLD_D == 0)
1758: return;
1759: rD = rS1 ^ rS2;
1760: }
1761:
1762: // 111101_DDDDDSSSSS_010101_00000sssss
1763: OP_DEF(xor_c)
1764: {
1765: if (FLD_D == 0)
1766: return;
1767: rD = rS1 ^ ~rS2;
1768: }
1769:
1770: // 111101_DDDDDSSSSS_010110_00000sssss
1771: OP_DEF(or)
1772: {
1.1.1.2 root 1773: if (FLD_D == 0) {
1774: nop_counter++;
1.1 root 1775: return;
1.1.1.2 root 1776: }
1.1 root 1777: rD = rS1 | rS2;
1778: }
1779:
1780: // 111101_DDDDDSSSSS_010111_00000sssss
1781: OP_DEF(or_c)
1782: {
1783: if (FLD_D == 0)
1784: return;
1785: rD = rS1 | ~rS2;
1786: }
1787:
1788: // 111101_DDDDDSSSSS_011000_nn000sssss
1789: OP_DEF(addu)
1790: {
1.1.1.2 root 1791: uint64 res = (uint64)rS1 + rS2;
1.1 root 1792: if (IsCI) {
1793: res += GetCY();
1794: }
1795: if (IsCO) {
1.1.1.4 root 1796: SetCY(res >> 32);
1.1 root 1797: }
1798: if (FLD_D == 0)
1799: return;
1800: rD = res;
1801: }
1802:
1803: // 111101_DDDDDSSSSS_011001_nn000sssss
1804: OP_DEF(subu)
1805: {
1.1.1.9 root 1806: // sub* 命令の CY ビットはボローが発生*していない*時セット。
1.1.1.2 root 1807:
1808: // 1 の補数をとって足す。
1809: uint64 res = (uint64)rS1 + (~rS2);
1.1 root 1810: if (IsCI) {
1.1.1.2 root 1811: res += GetCY();
1812: } else {
1813: res += 1;
1.1 root 1814: }
1815: if (IsCO) {
1.1.1.4 root 1816: SetCY(res >> 32);
1.1 root 1817: }
1818: if (FLD_D == 0)
1819: return;
1820: rD = res;
1821: }
1822:
1823: // 111101_DDDDDSSSSS_011010_zz000sssss
1824: OP_DEF(divu)
1825: {
1826: if (!IsFPUEnable()) {
1827: fpu_unimpl();
1828: return;
1829: }
1.1.1.4 root 1830:
1.1.1.5 root 1831: AddCycle(38); // Table.7-6 (ただしざっくり)
1.1.1.4 root 1832:
1.1 root 1833: if (rS2 == 0) {
1834: Exception(M88K_EXCEP_INT_DIV);
1835: return;
1836: }
1837: if (FLD_D == 0)
1838: return;
1839: rD = rS1 / rS2;
1840: }
1841:
1842: // 111101_DDDDDSSSSS_011011_zz000sssss
1843: OP_DEF(mul)
1844: {
1845: if (!IsFPUEnable()) {
1846: fpu_unimpl();
1847: return;
1848: }
1.1.1.4 root 1849:
1.1.1.5 root 1850: AddCycle(4); // Table.7-6 (ただしざっくり)
1.1.1.4 root 1851:
1.1 root 1852: if (FLD_D == 0)
1853: return;
1854: rD = rS1 * rS2;
1855: }
1856:
1857: // 111101_DDDDDSSSSS_011100_nn000sssss
1858: OP_DEF(add)
1859: {
1.1.1.2 root 1860: uint64 res = (uint64)rS1 + rS2;
1.1 root 1861: if (IsCI) {
1862: res += GetCY();
1863: }
1864: if (isovf_add(rS1, rS2, res)) {
1865: Exception(M88K_EXCEP_INT_OVF);
1866: return;
1867: }
1.1.1.9 root 1868:
1869: // rD, Cy の更新は例外が起きなかった時だけ (p.6-19)
1870: if (IsCO) {
1871: SetCY(res >> 32);
1872: }
1.1 root 1873: if (FLD_D == 0)
1874: return;
1875: rD = res;
1876: }
1877:
1878: // 111101_DDDDDSSSSS_011101_nn000sssss
1879: OP_DEF(sub)
1880: {
1.1.1.9 root 1881: // sub* 命令の CY ビットはボローが発生*していない*時セット。
1.1.1.2 root 1882:
1883: // 1 の補数をとって足す。
1884: uint64 res = (uint64)rS1 + (~rS2);
1.1 root 1885: if (IsCI) {
1.1.1.2 root 1886: res += GetCY();
1887: } else {
1888: res += 1;
1.1 root 1889: }
1890: if (isovf_sub(rS1, rS2, res)) {
1891: Exception(M88K_EXCEP_INT_OVF);
1892: return;
1893: }
1.1.1.9 root 1894:
1895: // rD, Cy の更新は例外が起きなかった時だけ (p.6-19)
1896: if (IsCO) {
1897: SetCY(res >> 32);
1898: }
1.1 root 1899: if (FLD_D == 0)
1900: return;
1901: rD = res;
1902: }
1903:
1904: // 111101_DDDDDSSSSS_011110_zz000sssss
1905: OP_DEF(div)
1906: {
1907: if (!IsFPUEnable()) {
1908: fpu_unimpl();
1909: return;
1910: }
1.1.1.4 root 1911:
1.1.1.5 root 1912: AddCycle(38); // Table.7-6 (ただしざっくり)
1.1.1.4 root 1913:
1.1.1.2 root 1914: if ((int32)rS1 < 0 || (int32)rS2 <= 0) {
1.1 root 1915: Exception(M88K_EXCEP_INT_DIV);
1916: return;
1917: }
1918: if (FLD_D == 0)
1919: return;
1920: rD = rS1 / rS2;
1921: }
1922:
1923: // 111101_DDDDDSSSSS_011111_zz000sssss
1924: OP_DEF(cmp)
1925: {
1926: if (FLD_D == 0)
1927: return;
1928: rD = acc_cmp(rS1, rS2);
1929: }
1930:
1931: // 111101_DDDDDSSSSS_100000_00000sssss
1932: OP_DEF(clr_2)
1933: {
1934: if (FLD_D == 0)
1935: return;
1936: rD = rS1 & ~acc_bf((rS2 >> 5) & 0x1f, rS2 & 0x1f);
1937: }
1938:
1939: // 111101_DDDDDSSSSS_100010_00000sssss
1940: OP_DEF(set_2)
1941: {
1942: if (FLD_D == 0)
1943: return;
1944: rD = rS1 | acc_bf((rS2 >> 5) & 0x1f, rS2 & 0x1f);
1945: }
1946:
1947: // 111101_DDDDDSSSSS_100100_00000sssss
1948: OP_DEF(ext_2)
1949: {
1950: int w, o, left;
1951: uint32 tmp;
1952:
1953: if (FLD_D == 0)
1954: return;
1955: w = (rS2 >> 5) & 0x1f;
1956: if (w == 0)
1957: w = 32;
1958: o = (rS2 ) & 0x1f;
1959: left = 32 - w - o;
1960: tmp = ASL(rS1, left);
1961: tmp = ASR(tmp, left);
1962: rD = ASR(tmp, o);
1963: }
1964:
1965: // 111101_DDDDDSSSSS_100110_00000sssss
1966: OP_DEF(extu_2)
1967: {
1968: int w, o, left;
1969: uint32 tmp;
1970:
1971: if (FLD_D == 0)
1972: return;
1973: w = (rS2 >> 5) & 0x1f;
1974: if (w == 0)
1975: w = 32;
1976: o = (rS2 ) & 0x1f;
1977: left = 32 - w - o;
1978: tmp = ASL(rS1, left);
1979: tmp = LSR(tmp, left);
1980: rD = tmp >> o;
1981: }
1982:
1983: // 111101_DDDDDSSSSS_101000_00000sssss
1984: OP_DEF(mak_2)
1985: {
1986: if (FLD_D == 0)
1987: return;
1988: int w = (rS2 >> 5) & 0x1f;
1989: int o = (rS2 ) & 0x1f;
1990: rD = (rS1 << o) & acc_bf(w, o);
1991: }
1992:
1993: // 111101_DDDDDSSSSS_101010_00000sssss
1994: OP_DEF(rot_2)
1995: {
1996: if (FLD_D == 0)
1997: return;
1998: int o = (rS2 ) & 0x1f;
1.1.1.12! root 1999: rD = ROR32(rS1, o);
1.1 root 2000: }
2001:
2002: // 111101_zzzzzzzzzz_110000_00000sssss
2003: OP_DEF(jmp)
2004: {
1.1.1.5 root 2005: AddCycle(1); // Table.7-5
1.1.1.4 root 2006: EnterBranch(rS2);
1.1 root 2007: ExitBranch();
2008: }
2009:
2010: // 111101_zzzzzzzzzz_110001_00000sssss
2011: OP_DEF(jmp_n)
2012: {
1.1.1.5 root 2013: AddCycle(0); // Table.7-5
1.1.1.4 root 2014: EnterBranch(rS2);
1.1 root 2015: ExitDelayBranch();
2016: }
2017:
2018: // 111101_zzzzzzzzzz_110010_00000sssss
2019: OP_DEF(jsr)
2020: {
1.1.1.5 root 2021: AddCycle(1); // Table.7-5
1.1.1.4 root 2022: EnterBranch(rS2);
1.1 root 2023: r[1] = nip;
2024: ExitBranch();
2025: }
2026:
2027: // 111101_zzzzzzzzzz_110011_00000sssss
2028: OP_DEF(jsr_n)
2029: {
1.1.1.5 root 2030: AddCycle(0); // Table.7-5
1.1.1.4 root 2031: EnterBranch(rS2);
1.1 root 2032: r[1] = nip + 4;
2033: ExitDelayBranch();
2034: }
2035:
1.1.1.2 root 2036: // 111101_DDDDDzzzzz_111010_00000sssss
2037: OP_DEF(ff1)
2038: {
2039: int i;
2040: uint32 m = 0x80000000U;
2041:
2042: if (FLD_D == 0)
2043: return;
2044:
2045: if (rS2 == 0) {
2046: rD = 32;
2047: } else {
2048: for (i = 31; i >= 0; i--, m >>= 1) {
2049: if ((rS2 & m) != 0) {
2050: break;
2051: }
2052: }
2053: rD = i;
2054: }
2055:
2056: }
2057:
2058: // 111101_DDDDDzzzzz_111011_00000sssss
2059: OP_DEF(ff0)
2060: {
2061: int i;
2062: uint32 m = 0x80000000U;
2063:
2064: if (FLD_D == 0)
2065: return;
2066:
2067: if (rS2 == 0xffffffffU) {
2068: rD = 32;
2069: } else {
2070: for (i = 31; i >= 0; i--, m >>= 1) {
2071: if ((rS2 & m) == 0) {
2072: break;
2073: }
2074: }
2075: rD = i;
2076: }
2077: }
2078:
1.1 root 2079: // 111101_zzzzzzzzzz_111111_0000000000
2080: OP_DEF(rte)
2081: {
1.1.1.5 root 2082: AddCycle(2); // Table.7-5
1.1.1.4 root 2083:
1.1.1.2 root 2084: SetPSR(epsr);
1.1 root 2085:
1.1.1.2 root 2086: // LUNA88K の ROM1.2 は sxip, snip, sfip を制御してくる。
2087: // ROM1.2 の DAE ハンドラは、
2088: // sxip = INVALID
2089: // snip = 0 (INVALID)
2090: // sfip = original sxip
2091: // で rte してくる。
2092: // CPU は sxip は評価しない。snip は 0 なので、無効として nop 扱い。
2093: // (実際はクロックが消費されるかも?)
2094: // sfip が VALID なので、そこから実行を再開する。
1.1.1.9 root 2095: if ((snip & SIP_V)) {
1.1.1.4 root 2096: EnterBranch(snip & SIP_MASK);
2097: ExitBranch();
1.1.1.2 root 2098: fip = sfip & SIP_MASK;
2099: } else {
1.1.1.4 root 2100: EnterBranch(sfip & SIP_MASK);
2101: ExitBranch();
1.1.1.2 root 2102: }
1.1 root 2103:
2104: // ディレイスロットにいた命令かどうかをやんわり復元する。
2105: // 88110 ではこの情報が E?IP に保持されているが
2106: // 88100 にはない。
2107: if (nip + 4 != fip) {
1.1.1.4 root 2108: ExitDelayBranch();
1.1 root 2109: }
2110: }
2111:
2112: // 111101_zzzzzSSSSS_111110_00000SSSSS
2113: OP_DEF(tbnd_1)
2114: {
2115: if (rS1 > rS2) {
2116: Exception(M88K_EXCEP_BOUNDS);
2117: }
2118: }
2119:
2120: // 111110_zzzzzSSSSS_nnnnnn_nnnnnnnnnn
2121: OP_DEF(tbnd_2)
2122: {
2123: if (rS1 > IMM16) {
2124: Exception(M88K_EXCEP_BOUNDS);
2125: }
2126: }
2127:
1.1.1.9 root 2128: // 111111_DDDDDSSSSS_000001_nnnnnnnnnn
2129: OP_DEF(doscall)
1.1 root 2130: {
1.1.1.9 root 2131: // Human68k の DOS call エミュレーションのような何か。
2132: // 独自ニーモニックでは doscall rD, rS1, #nn と表記することにする。
2133: //
2134: // Human68k の DOS コール #nn 番を実行し、戻り値を rD に書き込む。
2135: // 戻り値のない DOS コールでは rD に 0 を指定すること。
2136: // 引数は rS1 以降に一つずつ置く。m68k でのワードやバイト値の場合は
2137: // 下位詰めするだけで上位ビットのクリア等は不要。
2138: // 処理するこちら側が必要なビット幅だけを取り出すこと。
2139: //
2140: // また、ここでのコンソールは VM 内のコンソールではなくホストの標準入出力。
2141: //
2142: // コールバックがセットされていて特権状態の時のみ発動する。
2143: // それ以外では現物同様不当命令扱い。
1.1 root 2144:
1.1.1.9 root 2145: if (fline_callback && IsSuper()) {
2146: if (fline_callback(this, fline_arg)) {
2147: return;
2148: }
2149: }
2150:
2151: OP_FUNC(illegal);
1.1 root 2152: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.