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