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

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

unix.superglobalmegacorp.com

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