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

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

unix.superglobalmegacorp.com

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