Annotation of nono/m88xx0/m88100ops.cpp, revision 1.1.1.11

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.