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

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

unix.superglobalmegacorp.com

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