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

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

unix.superglobalmegacorp.com

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