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

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

unix.superglobalmegacorp.com

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