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

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

unix.superglobalmegacorp.com

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