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

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

unix.superglobalmegacorp.com

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