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

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

unix.superglobalmegacorp.com

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