Annotation of nono/exp/optestm88k/optestm88k_gen.cpp, revision 1.1.1.4

1.1       root        1: //
                      2: // nono
                      3: // Copyright (C) 2021 nono project
                      4: // Licensed under nono-license.txt
                      5: //
                      6: 
                      7: // instruction test for m88100
                      8: //
                      9: // optestm88k_gen.cpp (this file)
                     10: //  |
                     11: //  | compile and link on the host
                     12: //  v
                     13: // optestm88k_gen
                     14: //  |
                     15: //  | (executing it will create following files)
                     16: //  v
                     17: //  +--> optestm88k_add.s      ---+
                     18: //  +--> optestm88k_bitfield.s ---+
1.1.1.3   root       19: //  +--> optestm88k_fcmp.s     ---+
                     20: //  +--> optestm88k_flt.s      ---+
1.1       root       21: //  +--> optestm88k_lda.s      ---+
                     22: //  +--> optestm88k_logical.s  ---+
                     23: //  +--> optestm88k_muldiv.s   ---+
                     24: //  +--> optestm88k_sub.s      ---+
                     25: //  +--> optestm88k_table.c    ---+
                     26: //  +--> optestm88k_table.h    ---+
                     27: //                                |
                     28: //       optestm88k_main.[ch]  ---+
                     29: //       optestm88k_code.s     ---+
                     30: //                                | compile and link on m88k
                     31: //                                v
                     32: //                             optestm88k
                     33: 
                     34: // XXX mul/div/divu 命令の FPU disabled のケースは未検査
                     35: 
                     36: #include "header.h"
1.1.1.3   root       37: #include "mystring.h"
1.1.1.2   root       38: #include <assert.h>
1.1       root       39: #include <sys/stat.h>
                     40: #include <sys/wait.h>
                     41: #include <algorithm>
1.1.1.3   root       42: #include <cfenv>
                     43: #include <cmath>
1.1       root       44: #include <tuple>
                     45: #include <vector>
                     46: 
1.1.1.2   root       47: struct fpi
                     48: {
                     49:        union {
                     50:                double d {};
                     51:                uint64 q;
                     52:                // float は h の位置に置く
1.1.1.4 ! root       53: #if BYTE_ORDER == LITTLE_ENDIAN
1.1.1.2   root       54:                struct { uint32 l, h; };
                     55:                struct { float dummy_f, f; };
                     56:                struct { uint32 dummy_i, i; };
                     57: #else
                     58:                struct { uint32 h, l; };
                     59:                struct { float f, dummy_f; };
                     60:                struct { uint32 i, dummy_i; };
                     61: #endif
                     62:        };
                     63: 
                     64:        enum {
                     65:                NONE,
                     66:                FLOAT,
                     67:                DOUBLE,
1.1.1.3   root       68:                INT,
1.1.1.2   root       69:        } type {};
                     70:        bool IsFloat()  const { return (type == FLOAT); }
                     71:        bool IsDouble() const { return (type == DOUBLE); }
1.1.1.3   root       72:        bool IsInt()    const { return (type == INT); }
1.1.1.2   root       73: 
1.1.1.3   root       74:        // コンストラクタ
                     75:        fpi() {
                     76:        }
                     77:        fpi(float f_) {
                     78:                Set(f_);
                     79:        }
                     80:        fpi(double d_) {
                     81:                Set(d_);
                     82:        }
                     83:        fpi(uint32 i_) {
                     84:                SetInt(i_);
                     85:        }
                     86: 
                     87:        // どの値を保持しているか覚えておく
1.1.1.2   root       88:        void Set(float f_) {
                     89:                f = f_;
                     90:                type = FLOAT;
                     91:        }
                     92:        void Set(double d_) {
                     93:                d = d_;
                     94:                type = DOUBLE;
                     95:        }
                     96:        void Set(uint32 i_) {
                     97:                i = i_;
                     98:                type = FLOAT;
                     99:        }
                    100:        void Set(uint64 q_) {
                    101:                q = q_;
                    102:                type = DOUBLE;
                    103:        }
1.1.1.3   root      104:        void SetInt(uint32 i_) {
                    105:                i = i_;
                    106:                type = INT;
1.1.1.2   root      107:        }
1.1.1.3   root      108: 
                    109:        // どっちであっても double 値を返す (printf 用)
                    110:        double AsDouble() const {
                    111:                if (IsFloat()) {
                    112:                        return (double)f;
                    113:                } else {
                    114:                        return d;
                    115:                }
1.1.1.2   root      116:        }
1.1.1.3   root      117: 
                    118:        std::string ToString() const {
                    119:                switch (type) {
                    120:                 case FLOAT:
                    121:                        return string_format("%9.8g", f);
                    122:                 case DOUBLE:
                    123:                        return string_format("%19.18g", d);
                    124:                 case INT:
                    125:                        return string_format("$%08x", i);
                    126:                 default:
                    127:                        return "NONE";
                    128:                }
1.1.1.2   root      129:        }
                    130: };
                    131: 
1.1       root      132: // テスト情報 (グローバル)
                    133: static const char *testname;
                    134: static int testnum;
                    135: // 出力先 (グローバル)
                    136: static FILE *fp;
                    137: 
                    138: #define IMM    (0xff)
                    139: 
1.1.1.2   root      140: // 理解しやすさのため 1, 2, 3 で表現しているが実際は r8, r10, r12 を使う
                    141: static constexpr uint32 ntor(uint32 n) {
                    142:        assert(n < 4);
                    143:        if (n == 0) return 0;
                    144:        if (n == 1) return 8;
                    145:        if (n == 2) return 10;
                    146:        if (n == 3) return 12;
                    147: }
1.1       root      148: static constexpr uint32 R3(uint32 d, uint32 s1, uint32 s2) {
1.1.1.2   root      149:        d  = ntor(d);
                    150:        s1 = ntor(s1);
                    151:        s2 = ntor(s2);
1.1       root      152:        return (d << 16) | (s1 << 8) | s2;
                    153: }
                    154: // 3オペランドの場合のレジスタの組み合わせ
                    155: static std::vector<uint32> reglist3 = {
                    156:        R3(0, 0, 0),
                    157:        R3(0, 0, 1),
                    158:        R3(0, 1, 0),
                    159:        R3(0, 1, 1),
                    160:        R3(0, 1, 2),
                    161: 
                    162:        R3(1, 0, 0),
                    163:        R3(1, 0, 1),
                    164:        R3(1, 1, 0),
                    165:        R3(1, 1, 1),
                    166:        R3(1, 0, 2),
                    167:        R3(1, 2, 0),
                    168:        R3(1, 2, 2),
                    169:        R3(1, 1, 2),
                    170:        R3(1, 2, 1),
                    171:        R3(1, 2, 3),
                    172: };
                    173: 
                    174: // 2オペランド(+IMM)の場合のレジスタの組み合わせ
                    175: #define R2(d, s1)              R3(d, s1, 0)
                    176: static std::vector<uint32> reglist2 = {
                    177:        R2(0, 0),
                    178:        R2(0, 1),
                    179:        R2(1, 0),
                    180:        R2(1, 1),
                    181:        R2(1, 2),
                    182: };
                    183: 
                    184: // r0 用の値リスト
                    185: static std::vector<uint32> v0 = {
                    186:        0,
                    187: };
1.1.1.2   root      188: 
1.1       root      189: // 数値演算用の入力値リスト
                    190: static std::vector<uint32> vlist_arith = {
                    191:        0,
                    192:        1,
                    193:        2,
                    194:        0x7f,
                    195:        0x80,
                    196:        0xff,
                    197:        0x7fff,
                    198:        0x8000,
                    199:        0xffff,
                    200:        0x7fffffff,
                    201:        0x80000000,
                    202:        0xffffffff,
                    203: };
                    204: // ビットフィールド用の入力値リスト
                    205: // XXX どのパターンで試せばいいか
                    206: static std::vector<uint32> vlist_bf = {
                    207:        0x00000000,
                    208:        0x87654321,
                    209:        0xffffffff,
                    210: };
                    211: // ビットフィールド用の入力 W,O リスト
                    212: // XXX どのパターンで試せばいいか
                    213: #define WO(w, o)       (((w) << 5) | (o))
                    214: static std::vector<uint32> vlist_wo = {
                    215:        WO( 0,  0),
                    216:        WO( 0,  1),
                    217:        WO( 0,  2),
                    218:        WO( 0, 31),
                    219:        WO( 1,  0),
                    220:        WO( 1,  1),
                    221:        WO( 1, 31),
                    222:        WO(16,  0),
                    223:        WO(16, 15),
                    224:        WO(16, 16),
                    225:        WO(16, 17),
                    226:        WO(16, 31),
                    227:        WO(31,  0),
                    228:        WO(31,  1),
                    229:        WO(31, 31),
                    230: };
                    231: // ff0/ff1 用の入力値リスト
                    232: static std::vector<uint32> vlist_ff = {
                    233:        0x00000000,
                    234:        0x00000001,
                    235:        0x00000020,
                    236:        0x00000480,
                    237:        0x00009000,
                    238:        0x00010000,
                    239:        0x00200000,
                    240:        0x06000000,
                    241:        0xf0000000,
                    242: };
1.1.1.3   root      243: // r0 用
                    244: static std::vector<double> vf0 = {
                    245:        0.0,
                    246: };
                    247: // 浮動小数点数の入力値リスト
                    248: static std::vector<double> vlist_double = {
                    249:        0.0,
                    250:        1.0,
                    251:        2.0,
                    252:        16777215.0,             // float → int で正確に表現できる最大値?
                    253:        16777215.5,
                    254:        16777217.0,             // 16777216 は 1.0*2^24 で表現できるため省略
                    255:        1000000000.0,   // 2^29 以上 2^30 以下
                    256:        2147483646.0,   // INT32_MAX と区別可能な最大値
                    257:        2147483647.0,   // INT32_MAX
                    258:        2147483647.5,
                    259:        2147483649.0,
                    260:        4294967295.0,   // double → uint32 で正確に表現できる最大値?
                    261:        4294967295.5,
                    262:        4294967297.0,
                    263: 
                    264:        -0.0,
                    265:        -1.0,
                    266:        -2.0,
                    267:        -16777215.0,
                    268:        -16777215.5,
                    269:        -16777217.0,
                    270:        -1000000000.0,
                    271:        -2000000000.0,
                    272:        -2147483648.0,
                    273:        -2147483648.5,
                    274:        -2147483649.0,
                    275: 
                    276:         std::numeric_limits<double>::infinity(),
                    277:        -std::numeric_limits<double>::infinity(),
                    278:        std::nan(""),
                    279: };
                    280: 
                    281: #define RM_NEAR                (0)
                    282: #define RM_ZERO                (1)
                    283: #define RM_MINUS       (2)
                    284: #define RM_PLUS                (3)
                    285: 
                    286: static const char *rmstr[] = {
                    287:        "RN",
                    288:        "RZ",
                    289:        "RM",
                    290:        "RP",
                    291: };
1.1       root      292: 
                    293: template <class T>
1.1.1.2   root      294: using Tuple2_1 = std::tuple<uint32, uint32, T>;
1.1       root      295: template <class T>
1.1.1.2   root      296: using Tuple2_2 = std::tuple<uint32, uint32, T, T>;
1.1       root      297: template <class T>
1.1.1.2   root      298: using Tuple3_2 = std::tuple<uint32, uint32, uint32, T, T>;
1.1       root      299: 
1.1.1.3   root      300: static std::vector<Tuple3_2<uint32>> param_arith_reg;
                    301: static std::vector<Tuple2_2<uint32>> param_arith_imm;
                    302: static std::vector<Tuple3_2<uint32>> param_bitfield_reg;
                    303: static std::vector<Tuple2_2<uint32>> param_bitfield_imm;
                    304: static std::vector<Tuple2_1<uint32>> param_ff01;
                    305: static std::vector<Tuple2_1<uint32>> param_flt;
                    306: static std::vector<Tuple2_1<double>> param_trnc;
                    307: static std::vector<Tuple3_2<double>> param_fcmp;
1.1       root      308: 
                    309: // 2オペランドテストの要素を変数に取り出す部分 (副作用のあるマクロ)
                    310: #define VAR_DIADIC(t, rd, rs2, vs2)    \
                    311:        uint32 rd  = std::get<0>(t);    \
                    312:        uint32 rs2 = std::get<1>(t);    \
1.1.1.2   root      313:        auto   vs2 = std::get<2>(t)
1.1       root      314: 
                    315: // 3オペランドテストの要素を変数に取り出す部分 (副作用のあるマクロ)
                    316: #define VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2) \
                    317:        uint32 rd  = std::get<0>(t); \
                    318:        uint32 rs1 = std::get<1>(t); \
                    319:        uint32 rs2 = std::get<2>(t); \
1.1.1.2   root      320:        auto   vs1 = std::get<3>(t); \
                    321:        auto   vs2 = std::get<4>(t)
1.1       root      322: 
                    323: // 3オペランド(IMM)テストの要素を変数に取り出す部分 (副作用のあるマクロ)
                    324: #define VAR_TRI_IMM(t, rd, rs1, vs1, imm) \
                    325:        uint32 rd  = std::get<0>(t); \
                    326:        uint32 rs1 = std::get<1>(t); \
1.1.1.2   root      327:        auto   vs1 = std::get<2>(t); \
                    328:        auto   imm = std::get<3>(t)
1.1       root      329: 
                    330: 
1.1.1.3   root      331: // 自前の Round Mode 定数でシステムの丸めモードを設定する。
                    332: static void
                    333: setround(uint32 rm)
                    334: {
                    335:        int mode;
                    336:        switch (rm) {
                    337:         case RM_NEAR:
                    338:                mode = FE_TONEAREST;
                    339:                break;
                    340:         case RM_ZERO:
                    341:                mode = FE_TOWARDZERO;
                    342:                break;
                    343:         case RM_MINUS:
                    344:                mode = FE_DOWNWARD;
                    345:                break;
                    346:         case RM_PLUS:
                    347:                mode = FE_UPWARD;
                    348:                break;
                    349:         default:
                    350:                __unreachable();
                    351:        }
                    352:        std::fesetround(mode);
                    353: }
                    354: 
                    355: // d が float でも同じ値として表現可能なら true を返す
                    356: static bool
                    357: can_float(double d)
                    358: {
                    359:        float f = (float)d;
                    360: 
                    361:        // NAN 同士の == 比較は false になるため
                    362:        if (std::isnan(d) && std::isnan(f))
                    363:                return true;
                    364:        if (d == f)
                    365:                return true;
                    366:        return false;
                    367: }
                    368: 
1.1       root      369: // fp に出力
                    370: static void out(const char *fmt, ...)
                    371: {
                    372:        va_list ap;
                    373: 
                    374:        va_start(ap, fmt);
                    375:        vfprintf(fp, fmt, ap);
                    376:        va_end(ap);
                    377: }
                    378: 
                    379: // レジスタ regno に即値 imm をセットする
                    380: static void
                    381: MOV_imm(int regno, uint32 imm)
                    382: {
                    383:        if (regno == 0) {
                    384:                // nop
                    385:        } else if (imm == 0) {
                    386:                out("   xor     %%r%d, %%r%d, %%r%d\n", regno, regno, regno);
                    387:        } else if (imm < 0x10000) {
                    388:                out("   or      %%r%d, %%r0, 0x%04x\n", regno, imm);
                    389:        } else if (imm == 0xffffffff) {
                    390:                out("   or.c    %%r%d, %%r0, %%r0       | MOV %%r%d, 0xffffffff\n",
                    391:                        regno, regno);
                    392:        } else {
                    393:                out("   or.u    %%r%d, %%r0, 0x%04x     | MOV %%r%d, 0x%08x\n",
                    394:                        regno, (imm >> 16), regno, imm);
1.1.1.3   root      395:                if ((imm & 0xffff) != 0) {
                    396:                        out("   or      %%r%d, %%r%d, 0x%04x\n",
                    397:                                regno, regno, imm & 0xffff);
                    398:                }
1.1       root      399:        }
                    400: }
                    401: 
                    402: 
                    403: //
                    404: // ここからテストコード
                    405: //
                    406: 
                    407: // r2: 引数1: グローバル変数の先頭
                    408: //  r2[0] = &exception_occurred
                    409: //  r2[1] = &exception_expected
                    410: // r3: 引数2: 今回のテストのパラメータの先頭。内容は code ごとに異なる。
                    411: //
1.1.1.2   root      412: // r5: r1 のバックアップ
                    413: // r6(,r7):   期待 rD
                    414: // r8(,r9):   rD  (テストで使う)、結果の rD をここに入れて返す
                    415: // r10(,r11): rS1 (テストで使う)
                    416: // r12(,r13): rS2 (テストで使う)
                    417: //
                    418: // 規約では r10-13 がサブルーチンが破壊してよいレジスタで、
                    419: // r2-r9 は呼び出し側が引数を置くレジスタだがここもサブルーチンが破壊してよい
                    420: // ので使ってしまう。
                    421: 
                    422: #define Rexp (6)       // 期待値を格納するレジスタ
                    423: #define Rres (8)       // 結果を格納するレジスタ
1.1       root      424: 
                    425: // add でのオーバーフロー条件
                    426: static inline bool
                    427: isovf_add(uint32 s1, uint32 s2, uint32 res)
                    428: {
                    429:        return (int32)((s1 ^ res) & (s2 ^ res)) < 0;
                    430: }
                    431: 
                    432: // sub でのオーバーフロー条件
                    433: static inline bool
                    434: isovf_sub(uint32 s1, uint32 s2, uint32 res)
                    435: {
                    436:        return (int32)((s1 ^ s2) & (s1 ^ res)) < 0;
                    437: }
                    438: 
                    439: // 汎用演算命令共通のテストパターン出力部分
                    440: static void
1.1.1.3   root      441: outtest_generic(const char *mnemonic,
1.1       root      442:        uint32 rd, uint32 rs1, uint32 rs2, uint32 vs1, uint32 vs2, uint32 exp_rd)
                    443: {
                    444:        // rs2 が IMM なら #imm
                    445:        bool is_imm = (rs2 == IMM);
                    446:        uint32& imm = vs2;
                    447: 
                    448:        out("test_%s_%d:\n", testname, testnum);
                    449:        if (is_imm) {
                    450:                out("   /* %s r%d, r%d, #0x%04x (S1=$%08x) */\n",
                    451:                        mnemonic, rd, rs1, imm, vs1);
                    452:        } else {
                    453:                out("   /* %s r%d, r%d, r%d (S1=$%08x, S2=$%08x) */\n",
                    454:                        mnemonic, rd, rs1, rs2, vs1, vs2);
                    455:        }
                    456: 
                    457:        out("   .word   0x%08x  | exp_rd\n", exp_rd);
                    458:        // ここからコード
                    459:        MOV_imm(rs1, vs1);
                    460:        if (!is_imm && rs1 != rs2) {
                    461:                MOV_imm(rs2, vs2);
                    462:        }
                    463: 
                    464:        if (is_imm) {
                    465:                out("   %s      %%r%d, %%r%d, 0x%04x    | test\n", mnemonic, rd, rs1, imm);
                    466:        } else {
                    467:                out("   %s      %%r%d, %%r%d, %%r%d     | test\n", mnemonic, rd, rs1, rs2);
                    468:        }
                    469: 
1.1.1.2   root      470:        if (rd != Rres) {
                    471:                out("   or      %%r%d, %%r0, %%r%d\n", Rres, rd);
1.1       root      472:        }
                    473:        out("   jmp     %%r1\n");
                    474:        out("\n");
                    475: 
                    476:        testnum++;
                    477: }
                    478: 
                    479: // 2項ビットフィールド命令共通のテストパターン出力部分
1.1.1.3   root      480: // (outtest_generic と似てるけど微妙に違う)
1.1       root      481: static void
1.1.1.3   root      482: outtest_bitfield(const char *mnemonic,
1.1       root      483:        uint32 rd, uint32 rs1, uint32 vs1, uint32 wo, uint32 exp_rd)
                    484: {
                    485:        uint32 w = (wo >> 5) & 0x1f;    // XXX 表記上は 0 なのか 32 なのか
                    486:        uint32 o =  wo       & 0x1f;
                    487: 
                    488:        out("test_%s_%d:\n", testname, testnum);
                    489:        out("   /* %s r%d, r%d, %d<%d> (S1=$%08x) */\n",
                    490:                mnemonic, rd, rs1, w, o, vs1);
                    491: 
                    492:        out("   .word   0x%08x  | exp_rd\n", exp_rd);
                    493:        // ここからコード
                    494:        MOV_imm(rs1, vs1);
                    495: 
                    496:        out("   %s      %%r%d, %%r%d, %d<%d>    | test\n", mnemonic, rd, rs1, w, o);
                    497: 
1.1.1.2   root      498:        if (rd != Rres) {
                    499:                out("   or      %%r%d, %%r0, %%r%d\n", Rres, rd);
1.1       root      500:        }
                    501:        out("   jmp     %%r1\n");
                    502:        out("\n");
                    503: 
                    504:        testnum++;
                    505: }
                    506: 
                    507: // ff0/ff1 命令共通のテストパターン出力部分
1.1.1.3   root      508: // (outtest_generic と似てるけど微妙に違う)
1.1       root      509: static void
1.1.1.3   root      510: outtest_ff01(const char *mnemonic,
1.1       root      511:        uint32 rd, uint32 rs2, uint32 vs2, uint32 exp_rd)
                    512: {
                    513:        out("test_%s_%d:\n", testname, testnum);
                    514:        out("   /* %s r%d, r%d (S2=$%08x) */\n",
                    515:                mnemonic, rd, rs2, vs2);
                    516: 
                    517:        out("   .word   0x%08x  | exp_rd\n", exp_rd);
                    518:        // ここからコード
                    519:        MOV_imm(rs2, vs2);
                    520: 
                    521:        out("   %s      %%r%d, %%r%d    | test\n", mnemonic, rd, rs2);
                    522: 
1.1.1.2   root      523:        if (rd != Rres) {
                    524:                out("   or      %%r%d, %%r0, %%r%d\n", Rres, rd);
1.1       root      525:        }
                    526:        out("   jmp     %%r1\n");
                    527:        out("\n");
                    528: 
                    529:        testnum++;
                    530: }
                    531: 
                    532: // add/sub 命令共通のテストパターン出力部分
                    533: // rs2 == IMM なら即値指定。
                    534: // scale == true なら lda rD, rS1[rS2] 形式。
                    535: static void
1.1.1.3   root      536: outtest_addsub(const char *mnemonic,
1.1       root      537:        uint32 rd, uint32 rs1, uint32 rs2, uint32 vs1, uint32 vs2, int cin,
                    538:        uint32 exp_rd, uint32 exp_cy, bool exception = false, bool is_scale = false)
                    539: {
                    540:        // rs2 が IMM なら #imm
                    541:        bool is_imm = (rs2 == IMM);
                    542:        uint32& imm = vs2;
                    543: 
                    544:        out("test_%s_%d:\n", testname, testnum);
                    545:        if (is_imm) {
                    546:                out("   /* %s r%d, r%d, #0x%04x (S1=$%08x, Cin=%d) */\n",
                    547:                        mnemonic, rd, rs1, imm, vs1, cin);
                    548:        } else if (is_scale) {
                    549:                out("   /* %s r%d, r%d[r%d] (S1=$%08x, S2=$%08x) */\n",
                    550:                        mnemonic, rd, rs1, rs2, vs1, vs2);
                    551:        } else {
                    552:                out("   /* %s r%d, r%d, r%d (S1=$%08x, S2=$%08x, Cin=%d) */\n",
                    553:                        mnemonic, rd, rs1, rs2, vs1, vs2, cin);
                    554:        }
                    555: 
                    556:        out("   .word   0x%08x  | exp_rd\n", exp_rd);
                    557:        out("   .word   0x%08x  | Cin|ExpCy|Exception|0\n",
                    558:                (cin << 24) | (exp_cy << 16) | (exception << 8));
                    559:        // ここからテストコード
                    560:        // ソースレジスタをセット、実行、結果を保存
                    561:        MOV_imm(rs1, vs1);
                    562:        if (!is_imm && rs1 != rs2) {
                    563:                MOV_imm(rs2, vs2);
                    564:        }
                    565:        if (exception) {
                    566:                // 例外期待なら、rD (と Cy)の期待値は命令実行前の値 (p.6-19, 6.6)
1.1.1.2   root      567:                out("   or      %%r%d, %%r0, %%r%d\n", Rexp, rd);
1.1       root      568:        } else {
1.1.1.2   root      569:                MOV_imm(Rexp, exp_rd);
1.1       root      570:        }
                    571: 
                    572:        if (exception) {
                    573:                out("   | exception is expected\n");
                    574:        }
                    575:        if (is_imm) {
                    576:                out("   %s      %%r%d, %%r%d, 0x%04x    | test\n", mnemonic, rd, rs1, imm);
                    577:        } else if (is_scale) {
                    578:                out("   %s      %%r%d, %%r%d[%%r%d]     | test\n", mnemonic, rd, rs1, rs2);
                    579:        } else {
                    580:                out("   %s      %%r%d, %%r%d, %%r%d     | test\n", mnemonic, rd, rs1, rs2);
                    581:        }
                    582: 
1.1.1.2   root      583:        if (rd != Rres) {
                    584:                out("   or      %%r%d, %%r0, %%r%d\n", Rres, rd);
1.1       root      585:        }
                    586:        out("   jmp     %%r1\n");
                    587:        out("\n");
                    588: 
                    589:        testnum++;
                    590: }
                    591: 
                    592: // div 命令共通のテストパターン出力部分
                    593: static void
1.1.1.3   root      594: outtest_div(const char *mnemonic,
1.1       root      595:        uint32 rd, uint32 rs1, uint32 rs2, uint32 vs1, uint32 vs2,
                    596:        uint32 exp_rd, bool exception = false)
                    597: {
                    598:        // rs2 が IMM なら #imm
                    599:        bool is_imm = (rs2 == IMM);
                    600:        uint32& imm = vs2;
                    601: 
                    602:        out("test_%s_%d:\n", testname, testnum);
                    603:        if (is_imm) {
                    604:                out("   /* %s r%d, r%d, #0x%04x (S1=$%08x) */\n",
                    605:                        mnemonic, rd, rs1, imm, vs1);
                    606:        } else {
                    607:                out("   /* %s r%d, r%d, r%d (S1=$%08x, S2=$%08x) */\n",
                    608:                        mnemonic, rd, rs1, rs2, vs1, vs2);
                    609:        }
                    610: 
                    611:        out("   .word   0x%08x  | exp_ex\n", exception ? 2 : 0);
                    612:        // ここからテストコード
                    613:        // ソースレジスタをセット、実行、結果を保存
                    614:        MOV_imm(rs1, vs1);
                    615:        if (!is_imm && rs1 != rs2) {
                    616:                MOV_imm(rs2, vs2);
                    617:        }
                    618:        if (exception) {
                    619:                // 例外期待なら、rD の期待値は命令実行前の値 (p.6-40, 6.8.3)
1.1.1.2   root      620:                out("   or      %%r%d, %%r0, %%r%d\n", Rexp, rd);
1.1       root      621:        } else {
1.1.1.2   root      622:                MOV_imm(Rexp, exp_rd);
1.1       root      623:        }
                    624: 
                    625:        if (exception) {
                    626:                out("   | exception is expected\n");
                    627:        }
                    628:        if (is_imm) {
                    629:                out("   %s      %%r%d, %%r%d, 0x%04x    | test\n", mnemonic, rd, rs1, imm);
                    630:        } else {
                    631:                out("   %s      %%r%d, %%r%d, %%r%d     | test\n", mnemonic, rd, rs1, rs2);
                    632:        }
                    633: 
1.1.1.2   root      634:        if (rd != Rres) {
                    635:                out("   or      %%r%d, %%r0, %%r%d\n", Rres, rd);
                    636:        }
                    637:        out("   jmp     %%r1\n");
                    638:        out("\n");
                    639: 
                    640:        testnum++;
                    641: }
                    642: 
1.1.1.3   root      643: // FP 命令共通のテストパターン出力部分。
                    644: // ソースレジスタが1つの場合 (rs1 を使わない場合) は fsz1 = '\0'、rs1 = -1 に
                    645: // すること(vs1 は不定でよい)。
                    646: static void
                    647: outtest_fop(const char *mnemonic, char fsz0, char fsz1, char fsz2,
                    648:        uint32 rd, uint32 rs1, uint32 rs2, fpi vs1, fpi vs2,
                    649:        uint32 rm, fpi expected, uint32 exception)
1.1.1.2   root      650: {
1.1.1.3   root      651:        bool r4_backup = false;
                    652: 
1.1.1.2   root      653:        out("test_%s_%d:\n", testname, testnum);
1.1.1.3   root      654:        if (fsz1 == '\0') {
                    655:                out("   /* %s.%c%c r%d, r%d (S2=%s; %s) */\n",
                    656:                        mnemonic, fsz0, fsz2, rd, rs2,
                    657:                        vs2.ToString().c_str(), rmstr[rm]);
                    658:        } else {
                    659:                out("   /* %s.%c%c%c r%d, r%d, r%d (S1=%s, S2=%s; %s) */\n",
                    660:                        mnemonic, fsz0, fsz1, fsz2, rd, rs1, rs2,
                    661:                        vs1.ToString().c_str(), vs2.ToString().c_str(), rmstr[rm]);
                    662:        }
1.1.1.2   root      663: 
1.1.1.3   root      664:        out("   .word   0x%08x  | RndMode | exp_ex\n",
                    665:                exception | (rm << (16 + 14)));
1.1.1.2   root      666:        // ここからテストコード
1.1.1.3   root      667:        if (fsz1 != '\0') {
                    668:                MOV_imm(rs1, vs1.h);
                    669:                if (fsz1 == 'd') {
                    670:                        if (rs1 == 0) {
                    671:                                // ソースが r0,r1 になるので r1 を(さらに)退避
                    672:                                out("   or      %%r4, %%r0, %%r1\n");
                    673:                                r4_backup = true;
                    674:                        }
                    675:                        MOV_imm(rs1 + 1, vs1.l);
                    676:                }
                    677:        }
                    678:        MOV_imm(rs2, vs2.h);
                    679:        if (fsz2 == 'd') {
                    680:                if (r4_backup == false && rs2 == 0) {
                    681:                        // ソースが r0,r1 になるので r1 を(さらに)退避
                    682:                        out("   or      %%r4, %%r0, %%r1\n");
                    683:                        r4_backup = true;
                    684:                }
                    685:                MOV_imm(rs2 + 1, vs2.l);
                    686:        }
1.1.1.2   root      687: 
1.1.1.3   root      688:        if (exception != 0) {
1.1.1.2   root      689:                // 例外期待なら rD の期待値は命令実行前の値
                    690:                out("   or      %%r%d, %%r0, %%r%d\n", Rexp,     rd);
1.1.1.3   root      691:                if (fsz0 == 'd') {
                    692:                        out("   or      %%r%d, %%r0, %%r%d\n", Rexp + 1, rd + 1);
1.1.1.2   root      693:                }
1.1.1.3   root      694:        } else {
1.1.1.2   root      695:                // 例外が起きないことを期待する
1.1.1.3   root      696:                MOV_imm(Rexp, expected.h);
                    697:                if (fsz0 == 'd') {
                    698:                        MOV_imm(Rexp + 1, expected.l);
                    699:                }
1.1.1.2   root      700:        }
                    701: 
1.1.1.3   root      702:        if (fsz1 == '\0') {
                    703:                out("   %s.%c%c %%r%d, %%r%d    | test\n",
                    704:                        mnemonic, fsz0, fsz2, rd, rs2);
                    705:        } else {
                    706:                out("   %s.%c%c%c       %%r%d, %%r%d, %%r%d     | test\n",
                    707:                        mnemonic, fsz0, fsz1, fsz2, rd, rs1, rs2);
                    708:        }
1.1.1.2   root      709: 
1.1.1.3   root      710:        if (r4_backup) {
                    711:                out("   or      %%r1, %%r0, %%r4\n");
                    712:        }
1.1.1.2   root      713:        if (rd != Rres) {
1.1.1.3   root      714:                out("   or      %%r%d, %%r0, %%r%d\n", Rres, rd);
                    715:                if (fsz0 == 'd') {
                    716:                        out("   or      %%r%d, %%r0, %%r%d\n", Rres + 1, rd + 1);
                    717:                }
1.1       root      718:        }
                    719:        out("   jmp     %%r1\n");
                    720:        out("\n");
                    721: 
                    722:        testnum++;
                    723: }
                    724: 
1.1.1.3   root      725: // FP 命令共通 (ソースレジスタが1つの形式)
                    726: static void
                    727: outtest_fop(const char *mnemonic, char fsz0, char fsz2,
                    728:        uint32 rd, uint32 rs2, fpi vs2,
                    729:        uint32 rm, fpi expected, uint32 exception)
                    730: {
                    731:        fpi dummy_vs1;
                    732: 
                    733:        outtest_fop(mnemonic, fsz0, '\0', fsz2,
                    734:                rd, (uint32)-1, rs2, dummy_vs1, vs2,
                    735:                rm, expected, exception);
                    736: }
                    737: 
                    738: // int, nint, trnc 命令共通のテストパターン出力部分。
                    739: // rm はテスト環境内の FPCR に設定する丸めモード (入力パラメータ)。
                    740: static void
                    741: outtest_toint(const char *mnemonic, uint32 rd, uint32 rs2, fpi vs2,
                    742:        uint32 rm, uint64 exp)
                    743: {
                    744:        uint32 exception = exp >> 32;
                    745:        uint32 expected  = exp;
                    746: 
                    747:        outtest_fop(mnemonic, 's', (vs2.IsFloat() ? 's' : 'd'),
                    748:                rd, rs2, vs2, rm, expected, exception);
                    749: }
                    750: 
                    751: 
                    752: //
                    753: // ここからテストの出力
                    754: //
                    755: 
1.1       root      756: static void
                    757: gen_add()
                    758: {
1.1.1.3   root      759:        for (const auto& t : param_arith_reg) {
1.1       root      760:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                    761: 
                    762:                for (int cin = 0; cin <= 1; cin++) {
                    763:                        // 期待値
                    764:                        uint64 result = (uint64)vs1 + vs2;
                    765:                        uint32 exp_rd = (uint32)result;
                    766:                        uint32 exp_cy = cin;
                    767:                        if (rd == 0) {
                    768:                                exp_rd = 0;
                    769:                        }
                    770:                        bool exp_ex = isovf_add(vs1, vs2, result);
                    771:                        if (exp_ex) {
                    772:                                exp_cy = cin;
                    773:                        }
                    774: 
1.1.1.3   root      775:                        outtest_addsub("add",
1.1       root      776:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy, exp_ex);
                    777:                }
                    778:        }
                    779: }
                    780: 
                    781: static void
                    782: gen_add_ci()
                    783: {
1.1.1.3   root      784:        for (const auto& t : param_arith_reg) {
1.1       root      785:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                    786: 
                    787:                for (int cin = 0; cin <= 1; cin++) {
                    788:                        // 期待値
                    789:                        uint64 result = (uint64)vs1 + vs2 + cin;
                    790:                        uint32 exp_rd = (uint32)result;
                    791:                        uint32 exp_cy = cin;
                    792:                        if (rd == 0) {
                    793:                                exp_rd = 0;
                    794:                        }
                    795:                        bool exp_ex = isovf_add(vs1, vs2, result);
                    796:                        if (exp_ex) {
                    797:                                exp_cy = cin;
                    798:                        }
                    799: 
1.1.1.3   root      800:                        outtest_addsub("add.ci",
1.1       root      801:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy, exp_ex);
                    802:                }
                    803:        }
                    804: }
                    805: 
                    806: static void
                    807: gen_add_co()
                    808: {
1.1.1.3   root      809:        for (const auto& t : param_arith_reg) {
1.1       root      810:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                    811: 
                    812:                for (int cin = 0; cin <= 1; cin++) {
                    813:                        // 期待値
                    814:                        uint64 result = (uint64)vs1 + vs2;
                    815:                        uint32 exp_rd = (uint32)result;
                    816:                        uint32 exp_cy = result >> 32;
                    817:                        if (rd == 0) {
                    818:                                exp_rd = 0;
                    819:                        }
                    820:                        bool exp_ex = isovf_add(vs1, vs2, result);
                    821:                        if (exp_ex) {
                    822:                                exp_cy = cin;
                    823:                        }
                    824: 
1.1.1.3   root      825:                        outtest_addsub("add.co",
1.1       root      826:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy, exp_ex);
                    827:                }
                    828:        }
                    829: }
                    830: 
                    831: static void
                    832: gen_add_cio()
                    833: {
1.1.1.3   root      834:        for (const auto& t : param_arith_reg) {
1.1       root      835:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                    836: 
                    837:                for (int cin = 0; cin <= 1; cin++) {
                    838:                        // 期待値
                    839:                        uint64 result = (uint64)vs1 + vs2 + cin;
                    840:                        uint32 exp_rd = (uint32)result;
                    841:                        uint32 exp_cy = result >> 32;
                    842:                        if (rd == 0) {
                    843:                                exp_rd = 0;
                    844:                        }
                    845:                        bool exp_ex = isovf_add(vs1, vs2, result);
                    846:                        if (exp_ex) {
                    847:                                exp_cy = cin;
                    848:                        }
                    849: 
1.1.1.3   root      850:                        outtest_addsub("add.cio",
1.1       root      851:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy, exp_ex);
                    852:                }
                    853:        }
                    854: }
                    855: 
                    856: static void
                    857: gen_add_imm()
                    858: {
1.1.1.3   root      859:        for (const auto& t : param_arith_imm) {
1.1       root      860:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                    861: 
                    862:                for (int cin = 0; cin <= 1; cin++) {
                    863:                        // 期待値
                    864:                        uint64 result = (uint64)vs1 + imm;
                    865:                        uint32 exp_rd = (uint32)result;
                    866:                        uint32 exp_cy = cin;
                    867:                        if (rd == 0) {
                    868:                                exp_rd = 0;
                    869:                        }
                    870:                        bool exp_ex = isovf_add(vs1, imm, result);
                    871:                        if (exp_ex) {
                    872:                                exp_cy = cin;
                    873:                        }
                    874: 
1.1.1.3   root      875:                        outtest_addsub("add",
1.1       root      876:                                rd, rs1, IMM, vs1, imm, cin, exp_rd, exp_cy, exp_ex);
                    877:                }
                    878:        }
                    879: }
                    880: 
                    881: // addu rD, rS1, rS2 と lda rD, rS1, rS2 は名前が違うだけで同じ…
                    882: static void
                    883: gen_addu_lda(const char *mnemonic)
                    884: {
1.1.1.3   root      885:        for (const auto& t : param_arith_reg) {
1.1       root      886:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                    887: 
                    888:                for (int cin = 0; cin <= 1; cin++) {
                    889:                        // 期待値
                    890:                        uint64 result = (uint64)vs1 + vs2;
                    891:                        uint32 exp_rd = (uint32)result;
                    892:                        uint32 exp_cy = cin;
                    893:                        if (rd == 0) {
                    894:                                exp_rd = 0;
                    895:                        }
                    896: 
1.1.1.3   root      897:                        outtest_addsub(mnemonic,
1.1       root      898:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy);
                    899:                }
                    900:        }
                    901: }
                    902: 
                    903: static void
                    904: gen_addu()
                    905: {
                    906:        gen_addu_lda("addu");
                    907: }
                    908: 
                    909: static void
                    910: gen_addu_ci()
                    911: {
1.1.1.3   root      912:        for (const auto& t : param_arith_reg) {
1.1       root      913:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                    914: 
                    915:                for (int cin = 0; cin <= 1; cin++) {
                    916:                        // 期待値
                    917:                        uint64 result = (uint64)vs1 + vs2 + cin;
                    918:                        uint32 exp_rd = (uint32)result;
                    919:                        uint32 exp_cy = cin;
                    920:                        if (rd == 0) {
                    921:                                exp_rd = 0;
                    922:                        }
                    923: 
1.1.1.3   root      924:                        outtest_addsub("addu.ci",
1.1       root      925:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy);
                    926:                }
                    927:        }
                    928: }
                    929: 
                    930: static void
                    931: gen_addu_co()
                    932: {
1.1.1.3   root      933:        for (const auto& t : param_arith_reg) {
1.1       root      934:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                    935: 
                    936:                for (int cin = 0; cin <= 1; cin++) {
                    937:                        // 期待値
                    938:                        uint64 result = (uint64)vs1 + vs2;
                    939:                        uint32 exp_rd = (uint32)result;
                    940:                        uint32 exp_cy = result >> 32;
                    941:                        if (rd == 0) {
                    942:                                exp_rd = 0;
                    943:                        }
                    944: 
1.1.1.3   root      945:                        outtest_addsub("addu.co",
1.1       root      946:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy);
                    947:                }
                    948:        }
                    949: }
                    950: 
                    951: static void
                    952: gen_addu_cio()
                    953: {
1.1.1.3   root      954:        for (const auto& t : param_arith_reg) {
1.1       root      955:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                    956: 
                    957:                for (int cin = 0; cin <= 1; cin++) {
                    958:                        // 期待値
                    959:                        uint64 result = (uint64)vs1 + vs2 + cin;
                    960:                        uint32 exp_rd = (uint32)result;
                    961:                        uint32 exp_cy = result >> 32;
                    962:                        if (rd == 0) {
                    963:                                exp_rd = 0;
                    964:                        }
                    965: 
1.1.1.3   root      966:                        outtest_addsub("addu.cio",
1.1       root      967:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy);
                    968:                }
                    969:        }
                    970: }
                    971: 
                    972: // addu rD, rS1, #imm と lda rD, rS1, #imm は名前が違うだけで同じ…
                    973: static void
                    974: gen_addu_lda_imm(const char *mnemonic)
                    975: {
1.1.1.3   root      976:        for (const auto& t : param_arith_imm) {
1.1       root      977:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                    978: 
                    979:                for (int cin = 0; cin <= 1; cin++) {
                    980:                        // 期待値
                    981:                        uint64 result = (uint64)vs1 + imm;
                    982:                        uint32 exp_rd = (uint32)result;
                    983:                        uint32 exp_cy = cin;
                    984:                        if (rd == 0) {
                    985:                                exp_rd = 0;
                    986:                        }
                    987: 
1.1.1.3   root      988:                        outtest_addsub(mnemonic,
1.1       root      989:                                rd, rs1, IMM, vs1, imm, cin, exp_rd, exp_cy);
                    990:                }
                    991:        }
                    992: }
                    993: 
                    994: static void
                    995: gen_addu_imm()
                    996: {
                    997:        gen_addu_lda_imm("addu");
                    998: }
                    999: 
                   1000: static void
                   1001: gen_and()
                   1002: {
1.1.1.3   root     1003:        for (const auto& t : param_arith_reg) {
1.1       root     1004:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   1005:                uint32 exp_rd = vs1 & vs2;
                   1006:                if (rd == 0) {
                   1007:                        exp_rd = 0;
                   1008:                }
1.1.1.3   root     1009:                outtest_generic("and", rd, rs1, rs2, vs1, vs2, exp_rd);
1.1       root     1010:        }
                   1011: }
                   1012: 
                   1013: static void
                   1014: gen_and_c()
                   1015: {
1.1.1.3   root     1016:        for (const auto& t : param_arith_reg) {
1.1       root     1017:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   1018:                uint32 exp_rd = vs1 & ~vs2;
                   1019:                if (rd == 0) {
                   1020:                        exp_rd = 0;
                   1021:                }
1.1.1.3   root     1022:                outtest_generic("and.c", rd, rs1, rs2, vs1, vs2, exp_rd);
1.1       root     1023:        }
                   1024: }
                   1025: 
                   1026: static void
                   1027: gen_and_imm()
                   1028: {
1.1.1.3   root     1029:        for (const auto& t : param_arith_imm) {
1.1       root     1030:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                   1031:                uint32 exp_rd = vs1 & (imm | 0xffff0000);
                   1032:                if (rd == 0) {
                   1033:                        exp_rd = 0;
                   1034:                }
1.1.1.3   root     1035:                outtest_generic("and", rd, rs1, IMM, vs1, imm, exp_rd);
1.1       root     1036:        }
                   1037: }
                   1038: 
                   1039: static void
                   1040: gen_and_u()
                   1041: {
1.1.1.3   root     1042:        for (const auto& t : param_arith_imm) {
1.1       root     1043:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                   1044:                uint32 exp_rd = vs1 & ((imm << 16) | 0xffff);
                   1045:                if (rd == 0) {
                   1046:                        exp_rd = 0;
                   1047:                }
1.1.1.3   root     1048:                outtest_generic("and.u", rd, rs1, IMM, vs1, imm, exp_rd);
1.1       root     1049:        }
                   1050: }
                   1051: 
                   1052: static uint32
                   1053: calc_clr(uint32 src, uint32 wo)
                   1054: {
                   1055:        uint32 w = ((wo >> 5) & 0x1f) ?: 32;
                   1056:        uint32 o =   wo       & 0x1f;
                   1057:        uint32 mask = (uint32)(((1ULL << w) - 1) << o);
                   1058:        return src & ~mask;
                   1059: }
                   1060: 
                   1061: static void
                   1062: gen_clr_imm()
                   1063: {
1.1.1.3   root     1064:        for (const auto& t : param_bitfield_imm) {
1.1       root     1065:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                   1066:                uint32 exp_rd = calc_clr(vs1, imm);
                   1067:                if (rd == 0) {
                   1068:                        exp_rd = 0;
                   1069:                }
1.1.1.3   root     1070:                outtest_bitfield("clr", rd, rs1, vs1, imm, exp_rd);
1.1       root     1071:        }
                   1072: }
                   1073: 
                   1074: static void
                   1075: gen_clr_reg()
                   1076: {
1.1.1.3   root     1077:        for (const auto& t : param_bitfield_reg) {
1.1       root     1078:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   1079:                uint32 exp_rd = calc_clr(vs1, vs2);
                   1080:                if (rd == 0) {
                   1081:                        exp_rd = 0;
                   1082:                }
1.1.1.3   root     1083:                outtest_generic("clr", rd, rs1, rs2, vs1, vs2, exp_rd);
1.1       root     1084:        }
                   1085: }
                   1086: 
                   1087: static uint32
                   1088: calc_cmp(uint32 vs1, uint32 vs2)
                   1089: {
                   1090:        // 期待値
                   1091:        uint32 exp_rd = 0;
                   1092: 
                   1093:        exp_rd |= (vs1 >= vs2) ? 0x0800 : 0;
                   1094:        exp_rd |= (vs1 <  vs2) ? 0x0400 : 0;
                   1095:        exp_rd |= (vs1 <= vs2) ? 0x0200 : 0;
                   1096:        exp_rd |= (vs1 >  vs2) ? 0x0100 : 0;
                   1097:        exp_rd |= ((int32)vs1 >= (int32)vs2) ? 0x0080 : 0;
                   1098:        exp_rd |= ((int32)vs1 <  (int32)vs2) ? 0x0040 : 0;
                   1099:        exp_rd |= ((int32)vs1 <= (int32)vs2) ? 0x0020 : 0;
                   1100:        exp_rd |= ((int32)vs1 >  (int32)vs2) ? 0x0010 : 0;
                   1101:        exp_rd |= (vs1 != vs2) ? 0x0008 : 0;
                   1102:        exp_rd |= (vs1 == vs2) ? 0x0004 : 0;
                   1103: 
                   1104:        return exp_rd;
                   1105: }
                   1106: 
                   1107: static void
                   1108: gen_cmp()
                   1109: {
1.1.1.3   root     1110:        for (const auto& t : param_arith_reg) {
1.1       root     1111:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   1112:                uint32 exp_rd = calc_cmp(vs1, vs2);
                   1113:                if (rd == 0) {
                   1114:                        exp_rd = 0;
                   1115:                }
1.1.1.3   root     1116:                outtest_generic("cmp", rd, rs1, rs2, vs1, vs2, exp_rd);
1.1       root     1117:        }
                   1118: }
                   1119: 
                   1120: static void
                   1121: gen_cmp_imm()
                   1122: {
1.1.1.3   root     1123:        for (const auto& t : param_arith_imm) {
1.1       root     1124:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                   1125:                uint32 exp_rd = calc_cmp(vs1, imm);
                   1126:                if (rd == 0) {
                   1127:                        exp_rd = 0;
                   1128:                }
1.1.1.3   root     1129:                outtest_generic("cmp", rd, rs1, IMM, vs1, imm, exp_rd);
1.1       root     1130:        }
                   1131: }
                   1132: 
                   1133: // 符号付きで x / y の期待値を計算する。
                   1134: // 計算可能な場合は *exp_rd に結果を書き戻し *exp_ex に false を書き戻す。
                   1135: // 例外を期待する場合は *exp_ex に true を書き戻す。
                   1136: static void
                   1137: calc_div(uint32 *exp_rd, bool *exp_ex, int32 x, int32 y)
                   1138: {
                   1139:        // どちらかのオペランドが負でも例外らしい。符号付きとは一体…。
                   1140:        if (x < 0 || y <= 0) {
                   1141:                *exp_ex = true;
                   1142:                *exp_rd = 0;    // なくていいはずだけどコンパイラに怒られるので
                   1143:        } else {
                   1144:                *exp_ex = false;
                   1145:                *exp_rd = (uint32)(x / y);
                   1146:        }
                   1147: }
                   1148: 
                   1149: static void
                   1150: gen_div()
                   1151: {
1.1.1.3   root     1152:        for (const auto& t : param_arith_reg) {
1.1       root     1153:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   1154:                uint32 exp_rd;
                   1155:                bool exp_ex;
                   1156:                calc_div(&exp_rd, &exp_ex, vs1, vs2);
                   1157:                if (rd == 0) {
                   1158:                        exp_rd = 0;
                   1159:                }
1.1.1.3   root     1160:                outtest_div("div", rd, rs1, rs2, vs1, vs2, exp_rd, exp_ex);
1.1       root     1161:        }
                   1162: }
                   1163: 
                   1164: static void
                   1165: gen_div_imm()
                   1166: {
1.1.1.3   root     1167:        for (const auto& t : param_arith_imm) {
1.1       root     1168:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                   1169:                uint32 exp_rd;
                   1170:                bool exp_ex;
                   1171:                calc_div(&exp_rd, &exp_ex, vs1, imm);
                   1172:                if (rd == 0) {
                   1173:                        exp_rd = 0;
                   1174:                }
1.1.1.3   root     1175:                outtest_div("div", rd, rs1, IMM, vs1, imm, exp_rd, exp_ex);
1.1       root     1176:        }
                   1177: }
                   1178: 
                   1179: // 符号無しで x / y の期待値を計算する。
                   1180: // 計算可能な場合は *exp_rd に結果を書き戻し *exp_ex に false を書き戻す。
                   1181: // DivByZero を期待する場合は *exp_ex に true を書き戻す。
                   1182: static void
                   1183: calc_divu(uint32 *exp_rd, bool *exp_ex, uint32 x, uint32 y)
                   1184: {
                   1185:        if (y == 0) {
                   1186:                *exp_ex = true;
                   1187:                *exp_rd = 0;    // なくていいはずだけどコンパイラに怒られるので
                   1188:        } else {
                   1189:                *exp_ex = false;
                   1190:                *exp_rd = x / y;
                   1191:        }
                   1192: }
                   1193: 
                   1194: static void
                   1195: gen_divu()
                   1196: {
1.1.1.3   root     1197:        for (const auto& t : param_arith_reg) {
1.1       root     1198:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   1199:                uint32 exp_rd;
                   1200:                bool exp_ex;
                   1201:                calc_divu(&exp_rd, &exp_ex, vs1, vs2);
                   1202:                if (rd == 0) {
                   1203:                        exp_rd = 0;
                   1204:                }
1.1.1.3   root     1205:                outtest_div("divu", rd, rs1, rs2, vs1, vs2, exp_rd, exp_ex);
1.1       root     1206:        }
                   1207: }
                   1208: 
                   1209: static void
                   1210: gen_divu_imm()
                   1211: {
1.1.1.3   root     1212:        for (const auto& t : param_arith_imm) {
1.1       root     1213:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                   1214:                uint32 exp_rd;
                   1215:                bool exp_ex;
                   1216:                calc_divu(&exp_rd, &exp_ex, vs1, imm);
                   1217:                if (rd == 0) {
                   1218:                        exp_rd = 0;
                   1219:                }
1.1.1.3   root     1220:                outtest_div("divu", rd, rs1, IMM, vs1, imm, exp_rd, exp_ex);
1.1       root     1221:        }
                   1222: }
                   1223: 
                   1224: static uint32
                   1225: calc_ext(uint32 src, uint32 wo)
                   1226: {
                   1227:        uint32 w = ((wo >> 5) & 0x1f) ?: 32;
                   1228:        uint32 o =   wo       & 0x1f;
                   1229:        uint32 mask = (uint32)(((1ULL << w) - 1) << o);
                   1230: 
                   1231:        src &= mask;
                   1232: 
                   1233:        int shift = 0;
                   1234:        if (o + w < 32) {
                   1235:                shift = 32 - (o + w);
                   1236:                src <<= shift;
                   1237:        }
                   1238:        src = (int32)src >> (o + shift);
                   1239:        return src;
                   1240: }
                   1241: 
                   1242: static void
                   1243: gen_ext_imm()
                   1244: {
1.1.1.3   root     1245:        for (const auto& t : param_bitfield_imm) {
1.1       root     1246:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                   1247:                uint32 exp_rd = calc_ext(vs1, imm);
                   1248:                if (rd == 0) {
                   1249:                        exp_rd = 0;
                   1250:                }
1.1.1.3   root     1251:                outtest_bitfield("ext", rd, rs1, vs1, imm, exp_rd);
1.1       root     1252:        }
                   1253: }
                   1254: 
                   1255: static void
                   1256: gen_ext_reg()
                   1257: {
1.1.1.3   root     1258:        for (const auto& t : param_bitfield_reg) {
1.1       root     1259:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   1260:                uint32 exp_rd = calc_ext(vs1, vs2);
                   1261:                if (rd == 0) {
                   1262:                        exp_rd = 0;
                   1263:                }
1.1.1.3   root     1264:                outtest_generic("ext", rd, rs1, rs2, vs1, vs2, exp_rd);
1.1       root     1265:        }
                   1266: }
                   1267: 
                   1268: static uint32
                   1269: calc_extu(uint32 src, uint32 wo)
                   1270: {
                   1271:        uint32 w = ((wo >> 5) & 0x1f) ?: 32;
                   1272:        uint32 o =   wo       & 0x1f;
                   1273:        uint32 mask = (uint32)(((1ULL << w) - 1) << o);
                   1274: 
                   1275:        return (src & mask) >> o;
                   1276: }
                   1277: 
                   1278: static void
                   1279: gen_extu_imm()
                   1280: {
1.1.1.3   root     1281:        for (const auto& t : param_bitfield_imm) {
1.1       root     1282:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                   1283:                uint32 exp_rd = calc_extu(vs1, imm);
                   1284:                if (rd == 0) {
                   1285:                        exp_rd = 0;
                   1286:                }
1.1.1.3   root     1287:                outtest_bitfield("extu", rd, rs1, vs1, imm, exp_rd);
1.1       root     1288:        }
                   1289: }
                   1290: 
                   1291: static void
                   1292: gen_extu_reg()
                   1293: {
1.1.1.3   root     1294:        for (const auto& t : param_bitfield_reg) {
1.1       root     1295:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   1296:                uint32 exp_rd = calc_extu(vs1, vs2);
                   1297:                if (rd == 0) {
                   1298:                        exp_rd = 0;
                   1299:                }
1.1.1.3   root     1300:                outtest_generic("extu", rd, rs1, rs2, vs1, vs2, exp_rd);
                   1301:        }
                   1302: }
                   1303: 
                   1304: // fcmp.sXX の計算部分のみ
                   1305: static uint32
                   1306: calc_fcmp(double vs1, double vs2)
                   1307: {
                   1308:        uint32 res = 0;
                   1309: 
                   1310:        if (vs2 >= 0) {
                   1311:                res |= (vs1 <= 0 || vs1 >= vs2) ? 0x0800 : 0;   // ob
                   1312:                res |= (0 <  vs1 && vs1 <  vs2) ? 0x0400 : 0;   // in
                   1313:                res |= (0 <= vs1 && vs1 <= vs2) ? 0x0200 : 0;   // ib
                   1314:                res |= (vs1 <  0 || vs1 >  vs2) ? 0x0100 : 0;   // ou
                   1315:        }
                   1316:        res |= (vs1 >= vs2) ? 0x0080 : 0;       // ge
                   1317:        res |= (vs1 <  vs2) ? 0x0040 : 0;       // lt
                   1318:        res |= (vs1 <= vs2) ? 0x0020 : 0;       // le
                   1319:        res |= (vs1 >  vs2) ? 0x0010 : 0;       // gt
                   1320:        res |= (vs1 != vs2) ? 0x0008 : 0;       // ne
                   1321:        res |= (vs1 == vs2) ? 0x0004 : 0;       // eq
                   1322:        // cp; if and only if the two operands are comparable
                   1323:        if (!std::isnan(vs1) && !std::isnan(vs2)) {
                   1324:                res |= 0x0002;
1.1       root     1325:        }
1.1.1.3   root     1326:        // nc; if, and only if, the two operands are not comparable
                   1327:        if (std::isnan(vs1) || std::isnan(vs2)) {
                   1328:                res |= 0x0001;
                   1329:        }
                   1330: 
                   1331:        return res;
1.1       root     1332: }
                   1333: 
1.1.1.3   root     1334: // fcmp.sXX の共通部分
                   1335: static void
                   1336: gen_fcmp(char fsz1, const char fsz2)
                   1337: {
                   1338:        for (uint32 rm = 0; rm < 4; rm++) {
                   1339:                for (const auto& t : param_fcmp) {
                   1340:                        VAR_TRI_REG(t, rd, rs1, rs2, v1, v2);
                   1341:                        uint32 exception = 0;
                   1342:                        uint32 exp_rd = 0;
                   1343:                        fpi fpi1;
                   1344:                        fpi fpi2;
                   1345: 
                   1346:                        // rS1, rS2 が同じで幅が違うのは(ゼロ以外は)意味がないので飛ばす
                   1347:                        if (rs1 == rs2 && fsz1 != fsz2 && (v1 != 0 && v2 != 0)) {
                   1348:                                continue;
                   1349:                        }
                   1350:                        // double で r0 を指すのは実質意味がないので飛ばす
                   1351:                        // (ゼロの場合は飛ばさなくてもいいけど面倒なので飛ばす)
                   1352:                        if (fsz1 == 'd' && rs1 == 0)
                   1353:                                continue;
                   1354:                        if (fsz2 == 'd' && rs2 == 0)
                   1355:                                continue;
                   1356: 
                   1357:                        // ソースサイズが s なら float で表現できない値は飛ばす
                   1358:                        if (fsz1 == 's' && can_float(v1) == false)
                   1359:                                continue;
                   1360:                        if (fsz2 == 's' && can_float(v2) == false)
                   1361:                                continue;
                   1362: 
                   1363:                        // r0 なら値も 0 としておかないといけない
                   1364:                        if (rs1 == 0) {
                   1365:                                v1 = 0;
                   1366:                        }
                   1367:                        if (rs2 == 0) {
                   1368:                                v2 = 0;
                   1369:                        }
                   1370: 
                   1371:                        // rd ==0 の場合もソースに出力するコメントのために必要
                   1372:                        if (fsz1 == 's') {
                   1373:                                fpi1.Set((float)v1);
                   1374:                        } else {
                   1375:                                fpi1.Set(v1);
                   1376:                        }
                   1377:                        if (fsz2 == 's') {
                   1378:                                fpi2.Set((float)v2);
                   1379:                        } else {
                   1380:                                fpi2.Set(v2);
                   1381:                        }
                   1382: 
                   1383:                        if (rd == 0) {
                   1384:                                exception = 0x1000;
                   1385:                        } else {
                   1386:                                exp_rd = calc_fcmp(fpi1.AsDouble(), fpi2.AsDouble());
                   1387:                        }
                   1388: 
                   1389:                        outtest_fop("fcmp", 's', fsz1, fsz2,
                   1390:                                rd, rs1, rs2, fpi1, fpi2, rm, exp_rd, exception);
                   1391:                }
                   1392:        }
                   1393: }
                   1394: static void gen_fcmp_sss() { gen_fcmp('s', 's'); }
                   1395: static void gen_fcmp_ssd() { gen_fcmp('s', 'd'); }
                   1396: static void gen_fcmp_sds() { gen_fcmp('d', 's'); }
                   1397: static void gen_fcmp_sdd() { gen_fcmp('d', 'd'); }
                   1398: 
1.1       root     1399: static void
                   1400: gen_ff0()
                   1401: {
1.1.1.3   root     1402:        for (const auto& t : param_ff01) {
1.1       root     1403:                VAR_DIADIC(t, rd, rs2, vs2);
                   1404:                // 最も MSB 側にある %0 のビット位置(LSBを0とする)を返す
                   1405:                // %0 がなければ 32 を返す
                   1406:                uint32 exp_rd = 32;
                   1407:                if (vs2 != 0xffffffff) {
                   1408:                        exp_rd = 31 - __builtin_clz(~vs2);
                   1409:                }
                   1410:                if (rd == 0) {
                   1411:                        exp_rd = 0;
                   1412:                }
1.1.1.3   root     1413:                outtest_ff01("ff0", rd, rs2, vs2, exp_rd);
1.1       root     1414:        }
                   1415: }
                   1416: 
                   1417: static void
                   1418: gen_ff1()
                   1419: {
1.1.1.3   root     1420:        for (const auto& t : param_ff01) {
1.1       root     1421:                VAR_DIADIC(t, rd, rs2, vs2);
                   1422:                // 最も MSB 側にある %1 のビット位置(LSBを0とする)を返す
                   1423:                // %0 がなければ 32 を返す
                   1424:                uint32 exp_rd = 32;
                   1425:                if (vs2 != 0x00000000) {
                   1426:                        exp_rd = 31 - __builtin_clz(vs2);
                   1427:                }
                   1428:                if (rd == 0) {
                   1429:                        exp_rd = 0;
                   1430:                }
1.1.1.3   root     1431:                outtest_ff01("ff1", rd, rs2, vs2, exp_rd);
1.1       root     1432:        }
                   1433: }
                   1434: 
1.1.1.2   root     1435: static void
1.1.1.3   root     1436: gen_flt_ss()
1.1.1.2   root     1437: {
1.1.1.3   root     1438:        for (uint32 rm = 0; rm < 4; rm++) {
                   1439:                setround(rm);
                   1440:                for (const auto& t : param_flt) {
                   1441:                        VAR_DIADIC(t, rd, rs2, vs2);
                   1442:                        fpi fpi((float)(int32)vs2);
1.1.1.2   root     1443: 
1.1.1.3   root     1444:                        outtest_fop("flt", 's', 's',
                   1445:                                rd, rs2, vs2, rm, fpi, (rd == 0 ? 0x1000 : 0));
                   1446:                }
1.1.1.2   root     1447:        }
                   1448: }
                   1449: 
                   1450: static void
                   1451: gen_flt_ds()
                   1452: {
1.1.1.3   root     1453:        for (uint32 rm = 0; rm < 4; rm++) {
                   1454:                setround(rm);
                   1455:                for (const auto& t : param_flt) {
                   1456:                        VAR_DIADIC(t, rd, rs2, vs2);
                   1457:                        fpi fpi((double)(int32)vs2);
                   1458: 
                   1459:                        outtest_fop("flt", 'd', 's',
                   1460:                                rd, rs2, vs2, rm, fpi, (rd == 0 ? 0x1000 : 0));
                   1461:                }
                   1462:        }
                   1463: }
                   1464: 
                   1465: // int, nint, trnc 命令共通の期待値計算。
                   1466: // 期待値を計算するための丸めモードはあらかじめ setround() で設定しておくこと。
                   1467: // 戻り値は上位 32bit が例外、下位 32bit が期待値。
                   1468: // 例外が出ることを期待する時は、上位が例外コード(非0)、下位は無視。
                   1469: // 例外が出ないことを期待する場合は、上位が 0、下位が期待値。
                   1470: static uint64
                   1471: calc_toint(uint32 rd, fpi vs2)
                   1472: {
                   1473:        uint32 expected = 0;
                   1474:        uint32 exception = 0;
                   1475: 
                   1476:        if (rd == 0) {
                   1477:                exception = 0x1000;
                   1478:        } else {
                   1479:                double src = vs2.AsDouble();
                   1480:                double result = std::nearbyint(src);
                   1481: 
                   1482:                int exponent = 0;
                   1483:                std::frexp(result, &exponent);
                   1484: 
                   1485:                // 実際には trnc 命令は 30ビット以上で例外を出すが、
                   1486:                // そこから先は (OpenBSD の) ソフトウェアハンドラが処理して
                   1487:                // 実際に収まらなかった時は最大値を返す。
                   1488:                if (std::isinf(result) || std::isnan(result) || exponent >= 32) {
                   1489:                        if (std::signbit(result)) {
                   1490:                                expected = 0x80000000;
                   1491:                        } else {
                   1492:                                expected = 0x7fffffff;
                   1493:                        }
                   1494:                } else {
                   1495:                        expected = (int32)result;
                   1496:                }
                   1497:        }
                   1498: 
                   1499:        return ((uint64)exception << 32) | expected;
                   1500: }
                   1501: 
                   1502: static void
                   1503: gen_int_ss()
                   1504: {
                   1505:        for (uint32 rm = 0; rm < 4; rm++) {
                   1506:                setround(rm);
                   1507:                for (const auto& t : param_trnc) {
                   1508:                        VAR_DIADIC(t, rd, rs2, vs2);
                   1509:                        // float で表現できない値は飛ばす
                   1510:                        if (can_float(vs2))
                   1511:                                continue;
                   1512:                        fpi fpi((float)vs2);
                   1513:                        uint64 exp = calc_toint(rd, fpi);
                   1514:                        outtest_toint("int", rd, rs2, fpi, rm, exp);
                   1515:                }
                   1516:        }
1.1.1.2   root     1517: }
                   1518: 
                   1519: static void
1.1.1.3   root     1520: gen_int_sd()
1.1.1.2   root     1521: {
1.1.1.3   root     1522:        for (uint32 rm = 0; rm < 4; rm++) {
                   1523:                setround(rm);
                   1524:                for (const auto& t : param_trnc) {
                   1525:                        VAR_DIADIC(t, rd, rs2, vs2);
                   1526:                        fpi fpi(vs2);
                   1527:                        uint64 exp = calc_toint(rd, fpi);
                   1528:                        outtest_toint("int", rd, rs2, fpi, rm, exp);
                   1529:                }
                   1530:        }
1.1.1.2   root     1531: }
                   1532: 
1.1       root     1533: // lda.* rD, rS1, #imm は addu rD, rS1, #imm と同じ
                   1534: static void
                   1535: gen_lda_imm()
                   1536: {
                   1537:        gen_addu_lda_imm("lda");
                   1538: }
                   1539: static void
                   1540: gen_lda_b_imm()
                   1541: {
                   1542:        gen_addu_lda_imm("lda.b");
                   1543: }
                   1544: static void
                   1545: gen_lda_h_imm()
                   1546: {
                   1547:        gen_addu_lda_imm("lda.h");
                   1548: }
                   1549: static void
                   1550: gen_lda_d_imm()
                   1551: {
                   1552:        gen_addu_lda_imm("lda.d");
                   1553: }
                   1554: 
                   1555: // lda.* rD, rS1, rS2 は addu rD, rS1, rS2 と同じ
                   1556: static void
                   1557: gen_lda_reg()
                   1558: {
                   1559:        gen_addu_lda("lda");
                   1560: }
                   1561: static void
                   1562: gen_lda_b_reg()
                   1563: {
                   1564:        gen_addu_lda("lda.b");
                   1565: }
                   1566: static void
                   1567: gen_lda_h_reg()
                   1568: {
                   1569:        gen_addu_lda("lda.h");
                   1570: }
                   1571: static void
                   1572: gen_lda_d_reg()
                   1573: {
                   1574:        gen_addu_lda("lda.d");
                   1575: }
                   1576: 
                   1577: static void
                   1578: gen_lda_scale(const char *mnemonic, uint32 scale)
                   1579: {
1.1.1.3   root     1580:        for (const auto& t : param_arith_reg) {
1.1       root     1581:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   1582: 
                   1583:                for (int cin = 0; cin <= 1; cin++) {
                   1584:                        // 期待値
                   1585:                        uint64 result = (uint64)vs1 + vs2 * scale;
                   1586:                        uint32 exp_rd = (uint32)result;
                   1587:                        uint32 exp_cy = cin;
                   1588:                        if (rd == 0) {
                   1589:                                exp_rd = 0;
                   1590:                        }
                   1591: 
                   1592:                        bool exception = false;
                   1593:                        bool is_scale = true;
1.1.1.3   root     1594:                        outtest_addsub(mnemonic,
1.1       root     1595:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy,
                   1596:                                exception, is_scale);
                   1597:                }
                   1598:        }
                   1599: }
                   1600: static void
                   1601: gen_lda_scale()
                   1602: {
                   1603:        gen_lda_scale("lda", 4);
                   1604: }
                   1605: static void
                   1606: gen_lda_b_scale()
                   1607: {
                   1608:        gen_addu_lda("lda.b");
                   1609: }
                   1610: static void
                   1611: gen_lda_h_scale()
                   1612: {
                   1613:        gen_lda_scale("lda.h", 2);
                   1614: }
                   1615: static void
                   1616: gen_lda_d_scale()
                   1617: {
                   1618:        gen_lda_scale("lda.d", 8);
                   1619: }
                   1620: 
                   1621: static uint32
                   1622: calc_mak(uint32 src, uint32 wo)
                   1623: {
                   1624:        uint32 w = ((wo >> 5) & 0x1f) ?: 32;
                   1625:        uint32 o =   wo       & 0x1f;
                   1626:        uint32 mask = (uint32)((1ULL << w) - 1);
                   1627: 
                   1628:        return (src & mask) << o;
                   1629: }
                   1630: 
                   1631: static void
                   1632: gen_mak_imm()
                   1633: {
1.1.1.3   root     1634:        for (const auto& t : param_bitfield_imm) {
1.1       root     1635:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                   1636:                uint32 exp_rd = calc_mak(vs1, imm);
                   1637:                if (rd == 0) {
                   1638:                        exp_rd = 0;
                   1639:                }
1.1.1.3   root     1640:                outtest_bitfield("mak", rd, rs1, vs1, imm, exp_rd);
1.1       root     1641:        }
                   1642: }
                   1643: 
                   1644: static void
                   1645: gen_mak_reg()
                   1646: {
1.1.1.3   root     1647:        for (const auto& t : param_bitfield_reg) {
1.1       root     1648:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   1649:                uint32 exp_rd = calc_mak(vs1, vs2);
                   1650:                if (rd == 0) {
                   1651:                        exp_rd = 0;
                   1652:                }
1.1.1.3   root     1653:                outtest_generic("mak", rd, rs1, rs2, vs1, vs2, exp_rd);
1.1       root     1654:        }
                   1655: }
                   1656: 
                   1657: static void
                   1658: gen_mask_imm()
                   1659: {
1.1.1.3   root     1660:        for (const auto& t : param_arith_imm) {
1.1       root     1661:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                   1662:                uint32 exp_rd = vs1 & imm;
                   1663:                if (rd == 0) {
                   1664:                        exp_rd = 0;
                   1665:                }
1.1.1.3   root     1666:                outtest_generic("mask", rd, rs1, IMM, vs1, imm, exp_rd);
1.1       root     1667:        }
                   1668: }
                   1669: 
                   1670: static void
                   1671: gen_mask_u()
                   1672: {
1.1.1.3   root     1673:        for (const auto& t : param_arith_imm) {
1.1       root     1674:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                   1675:                uint32 exp_rd = vs1 & (imm << 16);
                   1676:                if (rd == 0) {
                   1677:                        exp_rd = 0;
                   1678:                }
1.1.1.3   root     1679:                outtest_generic("mask.u", rd, rs1, IMM, vs1, imm, exp_rd);
1.1       root     1680:        }
                   1681: }
                   1682: 
                   1683: static void
                   1684: gen_mul()
                   1685: {
1.1.1.3   root     1686:        for (const auto& t : param_arith_reg) {
1.1       root     1687:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   1688:                uint32 exp_rd = (uint32)((uint64)vs1 * vs2);
                   1689:                if (rd == 0) {
                   1690:                        exp_rd = 0;
                   1691:                }
1.1.1.3   root     1692:                outtest_generic("mul", rd, rs1, rs2, vs1, vs2, exp_rd);
1.1       root     1693:        }
                   1694: }
                   1695: 
                   1696: static void
                   1697: gen_mul_imm()
                   1698: {
1.1.1.3   root     1699:        for (const auto& t : param_arith_imm) {
1.1       root     1700:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                   1701:                uint32 exp_rd = (uint32)((uint64)vs1 * imm);
                   1702:                if (rd == 0) {
                   1703:                        exp_rd = 0;
                   1704:                }
1.1.1.3   root     1705:                outtest_generic("mul", rd, rs1, IMM, vs1, imm, exp_rd);
                   1706:        }
                   1707: }
                   1708: 
                   1709: static void
                   1710: gen_nint_ss()
                   1711: {
                   1712:        // 期待値は NEAR で計算
                   1713:        setround(RM_NEAR);
                   1714: 
                   1715:        for (uint32 rm = 0; rm < 4; rm++) {
                   1716:                for (const auto& t : param_trnc) {
                   1717:                        VAR_DIADIC(t, rd, rs2, vs2);
                   1718:                        // float で表現できない値は飛ばす
                   1719:                        if (can_float(vs2))
                   1720:                                continue;
                   1721:                        fpi fpi((float)vs2);
                   1722:                        uint64 exp = calc_toint(rd, fpi);
                   1723:                        outtest_toint("nint", rd, rs2, fpi, rm, exp);
                   1724:                }
                   1725:        }
                   1726: }
                   1727: 
                   1728: static void
                   1729: gen_nint_sd()
                   1730: {
                   1731:        // 期待値は NEAR で計算
                   1732:        setround(RM_NEAR);
                   1733: 
                   1734:        for (uint32 rm = 0; rm < 4; rm++) {
                   1735:                for (const auto& t : param_trnc) {
                   1736:                        VAR_DIADIC(t, rd, rs2, vs2);
                   1737:                        fpi fpi(vs2);
                   1738:                        uint64 exp = calc_toint(rd, fpi);
                   1739:                        outtest_toint("nint", rd, rs2, fpi, rm, exp);
                   1740:                }
1.1       root     1741:        }
                   1742: }
                   1743: 
                   1744: static void
                   1745: gen_or()
                   1746: {
1.1.1.3   root     1747:        for (const auto& t : param_arith_reg) {
1.1       root     1748:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   1749:                uint32 exp_rd = vs1 | vs2;
                   1750:                if (rd == 0) {
                   1751:                        exp_rd = 0;
                   1752:                }
1.1.1.3   root     1753:                outtest_generic("or", rd, rs1, rs2, vs1, vs2, exp_rd);
1.1       root     1754:        }
                   1755: }
                   1756: 
                   1757: static void
                   1758: gen_or_c()
                   1759: {
1.1.1.3   root     1760:        for (const auto& t : param_arith_reg) {
1.1       root     1761:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   1762:                uint32 exp_rd = vs1 | ~vs2;
                   1763:                if (rd == 0) {
                   1764:                        exp_rd = 0;
                   1765:                }
1.1.1.3   root     1766:                outtest_generic("or.c", rd, rs1, rs2, vs1, vs2, exp_rd);
1.1       root     1767:        }
                   1768: }
                   1769: 
                   1770: static void
                   1771: gen_or_imm()
                   1772: {
1.1.1.3   root     1773:        for (const auto& t : param_arith_imm) {
1.1       root     1774:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                   1775:                uint32 exp_rd = vs1 | imm;
                   1776:                if (rd == 0) {
                   1777:                        exp_rd = 0;
                   1778:                }
1.1.1.3   root     1779:                outtest_generic("or", rd, rs1, IMM, vs1, imm, exp_rd);
1.1       root     1780:        }
                   1781: }
                   1782: 
                   1783: static void
                   1784: gen_or_u()
                   1785: {
1.1.1.3   root     1786:        for (const auto& t : param_arith_imm) {
1.1       root     1787:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                   1788:                uint32 exp_rd = vs1 | (imm << 16);
                   1789:                if (rd == 0) {
                   1790:                        exp_rd = 0;
                   1791:                }
1.1.1.3   root     1792:                outtest_generic("or.u", rd, rs1, IMM, vs1, imm, exp_rd);
1.1       root     1793:        }
                   1794: }
                   1795: 
                   1796: static uint32
                   1797: calc_rot(uint32 src, uint32 wo)
                   1798: {
                   1799:        uint32 o = wo & 0x1f;
                   1800:        return (src >> o) | (src << (32 - o));
                   1801: }
                   1802: 
                   1803: static void
                   1804: gen_rot_imm()
                   1805: {
                   1806:        // 手抜きで W は無視するのでパターンが重複する
1.1.1.3   root     1807:        for (const auto& t : param_bitfield_imm) {
1.1       root     1808:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                   1809:                uint32 exp_rd = calc_rot(vs1, imm);
                   1810:                if (rd == 0) {
                   1811:                        exp_rd = 0;
                   1812:                }
1.1.1.3   root     1813:                outtest_bitfield("rot", rd, rs1, vs1, imm, exp_rd);
1.1       root     1814:        }
                   1815: }
                   1816: 
                   1817: static void
                   1818: gen_rot_reg()
                   1819: {
                   1820:        // 手抜きで W は無視するのでパターンが重複する
1.1.1.3   root     1821:        for (const auto& t : param_bitfield_reg) {
1.1       root     1822:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   1823:                uint32 exp_rd = calc_rot(vs1, vs2);
                   1824:                if (rd == 0) {
                   1825:                        exp_rd = 0;
                   1826:                }
1.1.1.3   root     1827:                outtest_generic("rot", rd, rs1, rs2, vs1, vs2, exp_rd);
1.1       root     1828:        }
                   1829: }
                   1830: 
                   1831: static uint32
                   1832: calc_set(uint32 src, uint32 wo)
                   1833: {
                   1834:        uint32 w = ((wo >> 5) & 0x1f) ?: 32;
                   1835:        uint32 o =   wo       & 0x1f;
                   1836:        uint32 mask = (uint32)(((1ULL << w) - 1) << o);
                   1837:        return src | mask;
                   1838: }
                   1839: 
                   1840: static void
                   1841: gen_set_imm()
                   1842: {
1.1.1.3   root     1843:        for (const auto& t : param_bitfield_imm) {
1.1       root     1844:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                   1845:                uint32 exp_rd = calc_set(vs1, imm);
                   1846:                if (rd == 0) {
                   1847:                        exp_rd = 0;
                   1848:                }
1.1.1.3   root     1849:                outtest_bitfield("set", rd, rs1, vs1, imm, exp_rd);
1.1       root     1850:        }
                   1851: }
                   1852: 
                   1853: static void
                   1854: gen_set_reg()
                   1855: {
1.1.1.3   root     1856:        for (const auto& t : param_bitfield_reg) {
1.1       root     1857:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   1858:                uint32 exp_rd = calc_set(vs1, vs2);
                   1859:                if (rd == 0) {
                   1860:                        exp_rd = 0;
                   1861:                }
1.1.1.3   root     1862:                outtest_generic("set", rd, rs1, rs2, vs1, vs2, exp_rd);
1.1       root     1863:        }
                   1864: }
                   1865: 
                   1866: static void
                   1867: gen_sub()
                   1868: {
1.1.1.3   root     1869:        for (const auto& t : param_arith_reg) {
1.1       root     1870:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   1871: 
                   1872:                for (int cin = 0; cin <= 1; cin++) {
                   1873:                        // 期待値
                   1874:                        uint64 result = (uint64)vs1 + (~vs2) + 1;
                   1875:                        uint32 exp_rd = (uint32)result;
                   1876:                        uint32 exp_cy = cin;
                   1877:                        if (rd == 0) {
                   1878:                                exp_rd = 0;
                   1879:                        }
                   1880:                        bool exp_ex = isovf_sub(vs1, vs2, result);
                   1881:                        if (exp_ex) {
                   1882:                                exp_cy = cin;
                   1883:                        }
                   1884: 
1.1.1.3   root     1885:                        outtest_addsub("sub",
1.1       root     1886:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy, exp_ex);
                   1887:                }
                   1888:        }
                   1889: }
                   1890: 
                   1891: static void
                   1892: gen_sub_ci()
                   1893: {
1.1.1.3   root     1894:        for (const auto& t : param_arith_reg) {
1.1       root     1895:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   1896: 
                   1897:                for (int cin = 0; cin <= 1; cin++) {
                   1898:                        // 期待値
                   1899:                        uint64 result = (uint64)vs1 + (~vs2) + cin;
                   1900:                        uint32 exp_rd = (uint32)result;
                   1901:                        uint32 exp_cy = cin;
                   1902:                        if (rd == 0) {
                   1903:                                exp_rd = 0;
                   1904:                        }
                   1905:                        bool exp_ex = isovf_sub(vs1, vs2, result);
                   1906:                        if (exp_ex) {
                   1907:                                exp_cy = cin;
                   1908:                        }
                   1909: 
1.1.1.3   root     1910:                        outtest_addsub("sub.ci",
1.1       root     1911:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy, exp_ex);
                   1912:                }
                   1913:        }
                   1914: }
                   1915: 
                   1916: static void
                   1917: gen_sub_co()
                   1918: {
1.1.1.3   root     1919:        for (const auto& t : param_arith_reg) {
1.1       root     1920:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   1921: 
                   1922:                for (int cin = 0; cin <= 1; cin++) {
                   1923:                        // 期待値
                   1924:                        uint64 result = (uint64)vs1 + (~vs2) + 1;
                   1925:                        uint32 exp_rd = (uint32)result;
                   1926:                        uint32 exp_cy = result >> 32;
                   1927:                        if (rd == 0) {
                   1928:                                exp_rd = 0;
                   1929:                        }
                   1930:                        bool exp_ex = isovf_sub(vs1, vs2, result);
                   1931:                        if (exp_ex) {
                   1932:                                exp_cy = cin;
                   1933:                        }
                   1934: 
1.1.1.3   root     1935:                        outtest_addsub("sub.co",
1.1       root     1936:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy, exp_ex);
                   1937:                }
                   1938:        }
                   1939: }
                   1940: 
                   1941: static void
                   1942: gen_sub_cio()
                   1943: {
1.1.1.3   root     1944:        for (const auto& t : param_arith_reg) {
1.1       root     1945:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   1946: 
                   1947:                for (int cin = 0; cin <= 1; cin++) {
                   1948:                        // 期待値
                   1949:                        uint64 result = (uint64)vs1 + (~vs2) + cin;
                   1950:                        uint32 exp_rd = (uint32)result;
                   1951:                        uint32 exp_cy = result >> 32;
                   1952:                        if (rd == 0) {
                   1953:                                exp_rd = 0;
                   1954:                        }
                   1955:                        bool exp_ex = isovf_sub(vs1, vs2, result);
                   1956:                        if (exp_ex) {
                   1957:                                exp_cy = cin;
                   1958:                        }
                   1959: 
1.1.1.3   root     1960:                        outtest_addsub("sub.cio",
1.1       root     1961:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy, exp_ex);
                   1962:                }
                   1963:        }
                   1964: }
                   1965: 
                   1966: static void
                   1967: gen_sub_imm()
                   1968: {
1.1.1.3   root     1969:        for (const auto& t : param_arith_imm) {
1.1       root     1970:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                   1971: 
                   1972:                for (int cin = 0; cin <= 1; cin++) {
                   1973:                        // 期待値
                   1974:                        uint64 result = (uint64)vs1 + (~imm) + 1;
                   1975:                        uint32 exp_rd = (uint32)result;
                   1976:                        uint32 exp_cy = cin;
                   1977:                        if (rd == 0) {
                   1978:                                exp_rd = 0;
                   1979:                        }
                   1980:                        bool exp_ex = isovf_sub(vs1, imm, result);
                   1981:                        if (exp_ex) {
                   1982:                                exp_cy = cin;
                   1983:                        }
                   1984: 
1.1.1.3   root     1985:                        outtest_addsub("sub",
1.1       root     1986:                                rd, rs1, IMM, vs1, imm, cin, exp_rd, exp_cy, exp_ex);
                   1987:                }
                   1988:        }
                   1989: }
                   1990: 
                   1991: static void
                   1992: gen_subu()
                   1993: {
1.1.1.3   root     1994:        for (const auto& t : param_arith_reg) {
1.1       root     1995:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   1996: 
                   1997:                for (int cin = 0; cin <= 1; cin++) {
                   1998:                        // 期待値
                   1999:                        uint64 result = (uint64)vs1 + (~vs2) + 1;
                   2000:                        uint32 exp_rd = (uint32)result;
                   2001:                        uint32 exp_cy = cin;
                   2002:                        if (rd == 0) {
                   2003:                                exp_rd = 0;
                   2004:                        }
                   2005: 
1.1.1.3   root     2006:                        outtest_addsub("subu",
1.1       root     2007:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy);
                   2008:                }
                   2009:        }
                   2010: }
                   2011: 
                   2012: static void
                   2013: gen_subu_ci()
                   2014: {
1.1.1.3   root     2015:        for (const auto& t : param_arith_reg) {
1.1       root     2016:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   2017: 
                   2018:                for (int cin = 0; cin <= 1; cin++) {
                   2019:                        // 期待値
                   2020:                        uint64 result = (uint64)vs1 + (~vs2) + cin;
                   2021:                        uint32 exp_rd = (uint32)result;
                   2022:                        uint32 exp_cy = cin;
                   2023:                        if (rd == 0) {
                   2024:                                exp_rd = 0;
                   2025:                        }
                   2026: 
1.1.1.3   root     2027:                        outtest_addsub("subu.ci",
1.1       root     2028:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy);
                   2029:                }
                   2030:        }
                   2031: }
                   2032: 
                   2033: static void
                   2034: gen_subu_co()
                   2035: {
1.1.1.3   root     2036:        for (const auto& t : param_arith_reg) {
1.1       root     2037:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   2038: 
                   2039:                for (int cin = 0; cin <= 1; cin++) {
                   2040:                        // 期待値
                   2041:                        uint64 result = (uint64)vs1 + (~vs2) + 1;
                   2042:                        uint32 exp_rd = (uint32)result;
                   2043:                        uint32 exp_cy = result >> 32;
                   2044:                        if (rd == 0) {
                   2045:                                exp_rd = 0;
                   2046:                        }
                   2047: 
1.1.1.3   root     2048:                        outtest_addsub("subu.co",
1.1       root     2049:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy);
                   2050:                }
                   2051:        }
                   2052: }
                   2053: 
                   2054: static void
                   2055: gen_subu_cio()
                   2056: {
1.1.1.3   root     2057:        for (const auto& t : param_arith_reg) {
1.1       root     2058:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   2059: 
                   2060:                for (int cin = 0; cin <= 1; cin++) {
                   2061:                        // 期待値
                   2062:                        uint64 result = (uint64)vs1 + (~vs2) + cin;
                   2063:                        uint32 exp_rd = (uint32)result;
                   2064:                        uint32 exp_cy = result >> 32;
                   2065:                        if (rd == 0) {
                   2066:                                exp_rd = 0;
                   2067:                        }
                   2068: 
1.1.1.3   root     2069:                        outtest_addsub("subu.cio",
1.1       root     2070:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy);
                   2071:                }
                   2072:        }
                   2073: }
                   2074: 
                   2075: static void
                   2076: gen_subu_imm()
                   2077: {
1.1.1.3   root     2078:        for (const auto& t : param_arith_imm) {
1.1       root     2079:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                   2080: 
                   2081:                for (int cin = 0; cin <= 1; cin++) {
                   2082:                        // 期待値
                   2083:                        uint64 result = (uint64)vs1 + (~imm) + 1;
                   2084:                        uint32 exp_rd = (uint32)result;
                   2085:                        uint32 exp_cy = cin;
                   2086:                        if (rd == 0) {
                   2087:                                exp_rd = 0;
                   2088:                        }
                   2089: 
1.1.1.3   root     2090:                        outtest_addsub("subu",
1.1       root     2091:                                rd, rs1, IMM, vs1, imm, cin, exp_rd, exp_cy);
                   2092:                }
                   2093:        }
                   2094: }
                   2095: 
                   2096: static void
1.1.1.3   root     2097: gen_trnc_ss()
                   2098: {
                   2099:        // 期待値は ZERO で計算
                   2100:        setround(RM_ZERO);
                   2101: 
                   2102:        for (uint32 rm = 0; rm < 4; rm++) {
                   2103:                for (const auto& t : param_trnc) {
                   2104:                        VAR_DIADIC(t, rd, rs2, vs2);
                   2105:                        // float で表現できない値は飛ばす
                   2106:                        if (can_float(vs2))
                   2107:                                continue;
                   2108:                        fpi fpi((float)vs2);
                   2109:                        uint64 exp = calc_toint(rd, fpi);
                   2110:                        outtest_toint("trnc", rd, rs2, fpi, rm, exp);
                   2111:                }
                   2112:        }
                   2113: }
                   2114: 
                   2115: static void
                   2116: gen_trnc_sd()
                   2117: {
                   2118:        // 期待値は ZERO で計算
                   2119:        setround(RM_ZERO);
                   2120: 
                   2121:        for (uint32 rm = 0; rm < 4; rm++) {
                   2122:                for (const auto& t : param_trnc) {
                   2123:                        VAR_DIADIC(t, rd, rs2, vs2);
                   2124:                        fpi fpi(vs2);
                   2125:                        uint64 exp = calc_toint(rd, fpi);
                   2126:                        outtest_toint("trnc", rd, rs2, fpi, rm, exp);
                   2127:                }
                   2128:        }
                   2129: }
                   2130: 
                   2131: static void
1.1       root     2132: gen_xor()
                   2133: {
1.1.1.3   root     2134:        for (const auto& t : param_arith_reg) {
1.1       root     2135:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   2136:                uint32 exp_rd = vs1 ^ vs2;
                   2137:                if (rd == 0) {
                   2138:                        exp_rd = 0;
                   2139:                }
1.1.1.3   root     2140:                outtest_generic("xor", rd, rs1, rs2, vs1, vs2, exp_rd);
1.1       root     2141:        }
                   2142: }
                   2143: 
                   2144: static void
                   2145: gen_xor_c()
                   2146: {
1.1.1.3   root     2147:        for (const auto& t : param_arith_reg) {
1.1       root     2148:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
                   2149:                uint32 exp_rd = vs1 ^ ~vs2;
                   2150:                if (rd == 0) {
                   2151:                        exp_rd = 0;
                   2152:                }
1.1.1.3   root     2153:                outtest_generic("xor.c", rd, rs1, rs2, vs1, vs2, exp_rd);
1.1       root     2154:        }
                   2155: }
                   2156: 
                   2157: static void
                   2158: gen_xor_imm()
                   2159: {
1.1.1.3   root     2160:        for (const auto& t : param_arith_imm) {
1.1       root     2161:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                   2162:                uint32 exp_rd = vs1 ^ imm;
                   2163:                if (rd == 0) {
                   2164:                        exp_rd = 0;
                   2165:                }
1.1.1.3   root     2166:                outtest_generic("xor", rd, rs1, IMM, vs1, imm, exp_rd);
1.1       root     2167:        }
                   2168: }
                   2169: 
                   2170: static void
                   2171: gen_xor_u()
                   2172: {
1.1.1.3   root     2173:        for (const auto& t : param_arith_imm) {
1.1       root     2174:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
                   2175:                uint32 exp_rd = vs1 ^ (imm << 16);
                   2176:                if (rd == 0) {
                   2177:                        exp_rd = 0;
                   2178:                }
1.1.1.3   root     2179:                outtest_generic("xor.u", rd, rs1, IMM, vs1, imm, exp_rd);
1.1       root     2180:        }
                   2181: }
                   2182: 
                   2183: 
                   2184: 
                   2185: //
                   2186: // ここから出力用の処理
                   2187: //
                   2188: 
                   2189: enum {
                   2190:        G_ADD = 1,
                   2191:        G_SUB,
                   2192:        G_LOGICAL,
                   2193:        G_BITFIELD,
                   2194:        G_LDA,
                   2195:        G_MULDIV,
1.1.1.2   root     2196:        G_FLT,
1.1.1.3   root     2197:        G_FCMP,
1.1       root     2198: };
                   2199: 
                   2200: // テスト一覧 (編集しやすいように実体は一番下に置いてある)
                   2201: struct testentry {
                   2202:        int group;
                   2203:        const char *code;
                   2204:        void (*genfunc)();
1.1.1.3   root     2205:        int quad;                       // 結果が 64bit なら 1
1.1       root     2206:        const char *name;
                   2207: };
                   2208: extern std::vector<testentry> test_table;
                   2209: 
                   2210: // list の中に val がなければ追加する
                   2211: template <class T>
                   2212: static void append(std::vector<T>& list, const T& val)
                   2213: {
                   2214:        if (std::find(list.begin(), list.end(), val) == list.end()) {
                   2215:                list.emplace_back(val);
                   2216:        }
                   2217: }
                   2218: 
                   2219: // ファイルオープンとクローズ (副作用のあるマクロ)
                   2220: #define FOPEN(filename_)       do { \
                   2221:        filename = filename_;   \
                   2222:        tmpname = filename + ".tmp";    \
                   2223:        fp = fopen(tmpname.c_str(), "w");       \
                   2224:        if (fp == NULL) {       \
                   2225:                err(1, "%s", tmpname.c_str());  \
                   2226:        }       \
                   2227:        out("/* This file was created by %s */\n", getprogname());      \
                   2228:        out("\n");      \
                   2229: } while (0)
                   2230: #define FCLOSE()       do {    \
                   2231:        fclose(fp);     \
                   2232:        compare_and_move(tmpname, filename);    \
                   2233: } while (0)
                   2234: 
1.1.1.3   root     2235: // src, dst のファイルが異なっていれば src を dst に rename する
                   2236: static void
                   2237: compare_and_move(const std::string& src, const std::string& dst)
                   2238: {
                   2239:        struct stat st;
                   2240:        int r;
                   2241:        bool update;
                   2242: 
                   2243:        update = false;
                   2244:        r = stat(dst.c_str(), &st);
                   2245:        if (r < 0) {
                   2246:                // dst not found
                   2247:                update = true;
                   2248:        } else {
                   2249:                // dst exists
                   2250: 
                   2251:                std::string cmd = "cmp -s " + src + " " + dst;
                   2252:                r = system(cmd.c_str());
                   2253:                if (r < 0) {
                   2254:                        err(1, "system");
                   2255:                }
                   2256:                r = WEXITSTATUS(r);
                   2257:                if (r > 1) {
                   2258:                        errx(1, "cmp failed?");
                   2259:                }
                   2260: 
                   2261:                if (r == 0) {
                   2262:                        // src and dst are the same
                   2263:                } else {
                   2264:                        update = true;
                   2265:                }
                   2266:        }
                   2267: 
                   2268:        if (update) {
                   2269:                // 違っていれば、src を dst に移動
                   2270:                r = rename(src.c_str(), dst.c_str());
                   2271:                if (r < 0) {
                   2272:                        err(1, "rename: %s %s", src.c_str(), dst.c_str());
                   2273:                }
                   2274:                printf("Updated: %s\n", dst.c_str());
                   2275:        } else {
                   2276:                // 同じなら、今作った src のほうを消す
                   2277:                r = remove(src.c_str());
                   2278:                if (r < 0) {
                   2279:                        err(1, "remove: %s", src.c_str());
                   2280:                }
                   2281:        }
                   2282: }
1.1       root     2283: // テストアセンブリソースの出力共通部分
                   2284: static void
                   2285: print_test(const testentry& t)
                   2286: {
                   2287:        // グローバル変数にセット
                   2288:        testname = t.name;
                   2289:        testnum = 0;
                   2290: 
                   2291:        // テストの実体を出力
                   2292:        t.genfunc();
                   2293: 
                   2294:        // テーブル
                   2295:        out(".globl list_%s\n", testname);
                   2296:        out("list_%s:\n", testname);
                   2297:        for (int i = 0; i < testnum; i++) {
                   2298:                out("\t.word    test_%s_%d\n", testname, i);
                   2299:        }
                   2300:        out("\t.word    0\n");
                   2301:        out("\n");
                   2302: }
                   2303: 
1.1.1.3   root     2304: // ソースファイルを作成
                   2305: static void
                   2306: create_file(const std::string& filename_, int group)
                   2307: {
                   2308:        std::string filename;
                   2309:        std::string tmpname;
                   2310: 
                   2311:        FOPEN(filename_);
                   2312:        for (const auto& t : test_table) {
                   2313:                if (t.group == group) {
                   2314:                        print_test(t);
                   2315:                }
                   2316:        }
                   2317:        FCLOSE();
                   2318: }
                   2319: 
1.1       root     2320: static void compare_and_move(const std::string&, const std::string&);
                   2321: 
                   2322: int
                   2323: main(int ac, char *av[])
                   2324: {
                   2325:        std::string filename;
                   2326:        std::string tmpname;
                   2327: 
                   2328:        // テストパターンを用意
                   2329:        for (const auto& rlist : reglist3) {
                   2330:                auto rd  = (rlist >> 16) & 0xff;
                   2331:                auto rs1 = (rlist >>  8) & 0xff;
                   2332:                auto rs2 =  rlist        & 0xff;
                   2333: 
                   2334:                std::vector<uint32> *v_arith_s1 = (rs1 == 0) ? &v0 : &vlist_arith;
                   2335:                std::vector<uint32> *v_arith_s2 = (rs2 == 0) ? &v0 : &vlist_arith;
                   2336: 
                   2337:                if (rs1 == rs2) {
                   2338:                        for (const auto& vs1 : *v_arith_s1) {
1.1.1.2   root     2339:                                Tuple3_2<uint32> val(rd, rs1, rs2, vs1, vs1);
1.1.1.3   root     2340:                                append(param_arith_reg, val);
1.1       root     2341:                        }
                   2342:                } else {
                   2343:                        for (const auto& vs1 : *v_arith_s1) {
                   2344:                                for (const auto& vs2 : *v_arith_s2) {
1.1.1.2   root     2345:                                        Tuple3_2<uint32> val(rd, rs1, rs2, vs1, vs2);
1.1.1.3   root     2346:                                        append(param_arith_reg, val);
1.1       root     2347:                                }
                   2348:                        }
                   2349:                }
                   2350:        }
                   2351:        for (const auto& rlist : reglist2) {
                   2352:                auto rd  = (rlist >> 16) & 0xff;
                   2353:                auto rs1 = (rlist >>  8) & 0xff;
                   2354: 
                   2355:                std::vector<uint32> *v_arith_s1 = (rs1 == 0) ? &v0 : &vlist_arith;
                   2356: 
                   2357:                for (const auto& vs1 : *v_arith_s1) {
                   2358:                        for (const auto& imm : vlist_arith) {
                   2359:                                if (imm <= 0xffff) {
1.1.1.2   root     2360:                                        Tuple2_2<uint32> val(rd, rs1, vs1, imm);
1.1.1.3   root     2361:                                        append(param_arith_imm, val);
1.1       root     2362:                                }
                   2363:                        }
                   2364:                }
                   2365:        }
                   2366:        for (const auto& rlist : reglist3) {
                   2367:                auto rd  = (rlist >> 16) & 0xff;
                   2368:                auto rs1 = (rlist >>  8) & 0xff;
                   2369:                auto rs2 =  rlist        & 0xff;
                   2370: 
                   2371:                std::vector<uint32> *v_bf = (rs1 == 0) ? &v0 : &vlist_bf;
                   2372:                std::vector<uint32> *v_wo = (rs2 == 0) ? &v0 : &vlist_wo;
                   2373: 
                   2374:                if (rs1 == rs2) {
                   2375:                        for (const auto& vs1 : *v_bf) {
1.1.1.2   root     2376:                                Tuple3_2<uint32> val(rd, rs1, rs2, vs1, vs1);
1.1.1.3   root     2377:                                append(param_bitfield_reg, val);
1.1       root     2378:                        }
                   2379:                        for (const auto& vs2 : *v_wo) {
1.1.1.2   root     2380:                                Tuple3_2<uint32> val(rd, rs1, rs2, vs2, vs2);
1.1.1.3   root     2381:                                append(param_bitfield_reg, val);
1.1       root     2382:                        }
                   2383:                } else {
                   2384:                        for (const auto& vs1 : *v_bf) {
                   2385:                                for (const auto& vs2 : *v_wo) {
1.1.1.2   root     2386:                                        Tuple3_2<uint32> val(rd, rs1, rs2, vs1, vs2);
1.1.1.3   root     2387:                                        append(param_bitfield_reg, val);
1.1       root     2388:                                }
                   2389:                        }
                   2390:                }
                   2391:        }
                   2392:        for (const auto& rlist : reglist2) {
                   2393:                auto rd  = (rlist >> 16) & 0xff;
                   2394:                auto rs1 = (rlist >>  8) & 0xff;
                   2395: 
                   2396:                std::vector<uint32> *v_bf = (rs1 == 0) ? &v0 : &vlist_bf;
                   2397: 
                   2398:                for (const auto& vs1 : *v_bf) {
                   2399:                        for (const auto& wo : vlist_wo) {
1.1.1.2   root     2400:                                Tuple2_2<uint32> val(rd, rs1, vs1, wo);
1.1.1.3   root     2401:                                append(param_bitfield_imm, val);
1.1       root     2402:                        }
                   2403:                }
                   2404:        }
                   2405:        for (const auto& rlist : reglist2) {
                   2406:                auto rd  = (rlist >> 16) & 0xff;
                   2407:                auto rs2 = (rlist >>  8) & 0xff;
                   2408: 
                   2409:                std::vector<uint32> v_ff;
                   2410:                if (rs2 == 0) {
                   2411:                        v_ff = v0;
                   2412:                } else {
                   2413:                        // vlist_arith とそれをビット反転したもの
                   2414:                        for (const auto v : vlist_arith) {
                   2415:                                v_ff.emplace_back(v);
                   2416:                                v_ff.emplace_back(~v);
                   2417:                        }
                   2418:                }
                   2419: 
                   2420:                for (const auto& vs2 : v_ff) {
1.1.1.2   root     2421:                        Tuple2_1<uint32> val(rd, rs2, vs2);
1.1.1.3   root     2422:                        append(param_ff01, val);
1.1       root     2423:                }
                   2424:        }
1.1.1.2   root     2425:        for (const auto& rlist : reglist2) {
                   2426:                auto rd  = (rlist >> 16) & 0xff;
                   2427:                auto rs2 = (rlist >>  8) & 0xff;
                   2428: 
                   2429:                std::vector<uint32> *v_arith_s2 = (rs2 == 0) ? &v0 : &vlist_arith;
                   2430: 
                   2431:                for (const auto& vs2 : *v_arith_s2) {
                   2432:                        Tuple2_1<uint32> val(rd, rs2, vs2);
1.1.1.3   root     2433:                        append(param_flt, val);
1.1       root     2434:                }
                   2435:        }
1.1.1.3   root     2436:        for (const auto& rlist : reglist2) {
                   2437:                auto rd  = (rlist >> 16) & 0xff;
                   2438:                auto rs2 = (rlist >>  8) & 0xff;
1.1       root     2439: 
1.1.1.3   root     2440:                if (rs2 == 0) {
                   2441:                        Tuple2_1<double> val(rd, rs2, 0.0);
                   2442:                        append(param_trnc, val);
                   2443:                } else {
                   2444:                        for (const auto& vs2 : vlist_double) {
                   2445:                                Tuple2_1<double> val(rd, rs2, vs2);
                   2446:                                append(param_trnc, val);
                   2447:                        }
1.1       root     2448:                }
                   2449:        }
                   2450: 
1.1.1.3   root     2451:        for (const auto& rlist : reglist3) {
                   2452:                auto rd  = (rlist >> 16) & 0xff;
                   2453:                auto rs1 = (rlist >>  8) & 0xff;
                   2454:                auto rs2 =  rlist        & 0xff;
1.1       root     2455: 
1.1.1.3   root     2456:                std::vector<double> *vlist1 = (rs1 == 0) ? &vf0 : &vlist_double;
                   2457:                std::vector<double> *vlist2 = (rs2 == 0) ? &vf0 : &vlist_double;
1.1       root     2458: 
1.1.1.3   root     2459:                if (rs1 == rs2) {
                   2460:                        for (const auto& vs1 : *vlist1) {
                   2461:                                Tuple3_2<double> val(rd, rs1, rs2, vs1, vs1);
                   2462:                                append(param_fcmp, val);
                   2463:                        }
                   2464:                } else {
                   2465:                        for (const auto& vs1 : *vlist1) {
                   2466:                                for (const auto& vs2 : *vlist2) {
                   2467:                                        Tuple3_2<double> val(rd, rs1, rs2, vs1, vs2);
                   2468:                                        append(param_fcmp, val);
                   2469:                                }
                   2470:                        }
1.1       root     2471:                }
                   2472:        }
                   2473: 
1.1.1.3   root     2474:        // ソースファイルを出力
                   2475:        create_file("optestm88k_add.s",         G_ADD);
                   2476:        create_file("optestm88k_sub.s",         G_SUB);
                   2477:        create_file("optestm88k_logical.s",     G_LOGICAL);
                   2478:        create_file("optestm88k_bitfield.s",G_BITFIELD);
                   2479:        create_file("optestm88k_lda.s",         G_LDA);
                   2480:        create_file("optestm88k_muldiv.s",      G_MULDIV);
                   2481:        create_file("optestm88k_flt.s",         G_FLT);
                   2482:        create_file("optestm88k_fcmp.s",        G_FCMP);
1.1.1.2   root     2483: 
                   2484:        //
1.1       root     2485:        // table.h を出力
                   2486:        //
                   2487:        FOPEN("optestm88k_table.h");
                   2488:        out("#ifndef optestm88k_table_h\n");
                   2489:        out("#define optestm88k_table_h\n");
                   2490:        out("\n");
                   2491:        // testcode は table_*.name を uniq したもの
                   2492:        std::vector<std::string> test_code_list;
                   2493:        for (const auto& t : test_table) {
                   2494:                append(test_code_list, std::string(t.code));
                   2495:        }
                   2496:        for (const auto& name : test_code_list) {
                   2497:                out("extern int test_%s(int *, int *);\n", name.c_str());
                   2498:        }
                   2499:        out("\n");
                   2500: 
                   2501:        for (const auto& t : test_table) {
                   2502:                out("extern int *list_%s[];\n", t.name);
                   2503:        }
                   2504:        out("\n");
                   2505:        out("#endif /* !optestm88k_table_h */\n");
                   2506:        FCLOSE();
                   2507: 
                   2508:        //
                   2509:        // table.c を出力
                   2510:        //
                   2511:        FOPEN("optestm88k_table.c");
                   2512:        out("#include \"optestm88k_main.h\"\n");
                   2513:        out("#include \"optestm88k_table.h\"\n");
                   2514:        out("\n");
                   2515:        out("struct testentry test_table[] = {\n");
                   2516:        for (const auto& t : test_table) {
1.1.1.3   root     2517:                out("   { test_%s,\tlist_%s,\t%d, \"%s\" },\n",
                   2518:                        t.code, t.name, t.quad, t.name);
1.1       root     2519:        }
1.1.1.3   root     2520:        out("   { NULL },\n");
1.1       root     2521:        out("};\n");
                   2522:        FCLOSE();
                   2523: 
                   2524:        return 0;
                   2525: }
                   2526: 
                   2527: //
                   2528: // テスト一覧
                   2529: //
1.1.1.3   root     2530: #define T(group, code, quad, name)     { group, code, gen_##name, quad, #name }
1.1       root     2531: std::vector<testentry> test_table = {
1.1.1.3   root     2532:        T(G_ADD,                "addsub",       0,      add),
                   2533:        T(G_ADD,                "addsub",       0,      add_ci),
                   2534:        T(G_ADD,                "addsub",       0,      add_co),
                   2535:        T(G_ADD,                "addsub",       0,      add_cio),
                   2536:        T(G_ADD,                "addsub",       0,      add_imm),
                   2537:        T(G_ADD,                "addsub",       0,      addu),
                   2538:        T(G_ADD,                "addsub",       0,      addu_ci),
                   2539:        T(G_ADD,                "addsub",       0,      addu_co),
                   2540:        T(G_ADD,                "addsub",       0,      addu_cio),
                   2541:        T(G_ADD,                "addsub",       0,      addu_imm),
                   2542: 
                   2543:        T(G_SUB,                "addsub",       0,      sub),
                   2544:        T(G_SUB,                "addsub",       0,      sub_ci),
                   2545:        T(G_SUB,                "addsub",       0,      sub_co),
                   2546:        T(G_SUB,                "addsub",       0,      sub_cio),
                   2547:        T(G_SUB,                "addsub",       0,      sub_imm),
                   2548:        T(G_SUB,                "addsub",       0,      subu),
                   2549:        T(G_SUB,                "addsub",       0,      subu_ci),
                   2550:        T(G_SUB,                "addsub",       0,      subu_co),
                   2551:        T(G_SUB,                "addsub",       0,      subu_cio),
                   2552:        T(G_SUB,                "addsub",       0,      subu_imm),
                   2553:        T(G_SUB,                "generic",      0,      cmp),
                   2554:        T(G_SUB,                "generic",      0,      cmp_imm),
                   2555: 
                   2556:        T(G_LOGICAL,    "generic",      0,      and),
                   2557:        T(G_LOGICAL,    "generic",      0,      and_c),
                   2558:        T(G_LOGICAL,    "generic",      0,      and_imm),
                   2559:        T(G_LOGICAL,    "generic",      0,      and_u),
                   2560:        T(G_LOGICAL,    "generic",      0,      mask_imm),
                   2561:        T(G_LOGICAL,    "generic",      0,      mask_u),
                   2562:        T(G_LOGICAL,    "generic",      0,      or),
                   2563:        T(G_LOGICAL,    "generic",      0,      or_c),
                   2564:        T(G_LOGICAL,    "generic",      0,      or_imm),
                   2565:        T(G_LOGICAL,    "generic",      0,      or_u),
                   2566:        T(G_LOGICAL,    "generic",      0,      xor),
                   2567:        T(G_LOGICAL,    "generic",      0,      xor_c),
                   2568:        T(G_LOGICAL,    "generic",      0,      xor_imm),
                   2569:        T(G_LOGICAL,    "generic",      0,      xor_u),
                   2570: 
                   2571:        T(G_BITFIELD,   "generic",      0,      clr_imm),
                   2572:        T(G_BITFIELD,   "generic",      0,      clr_reg),
                   2573:        T(G_BITFIELD,   "generic",      0,      ext_imm),
                   2574:        T(G_BITFIELD,   "generic",      0,      ext_reg),
                   2575:        T(G_BITFIELD,   "generic",      0,      extu_imm),
                   2576:        T(G_BITFIELD,   "generic",      0,      extu_reg),
                   2577:        T(G_BITFIELD,   "generic",      0,      ff0),
                   2578:        T(G_BITFIELD,   "generic",      0,      ff1),
                   2579:        T(G_BITFIELD,   "generic",      0,      mak_imm),
                   2580:        T(G_BITFIELD,   "generic",      0,      mak_reg),
                   2581:        T(G_BITFIELD,   "generic",      0,      rot_imm),
                   2582:        T(G_BITFIELD,   "generic",      0,      rot_reg),
                   2583:        T(G_BITFIELD,   "generic",      0,      set_imm),
                   2584:        T(G_BITFIELD,   "generic",      0,      set_reg),
                   2585: 
                   2586:        T(G_LDA,                "addsub",       0,      lda_imm),
                   2587:        T(G_LDA,                "addsub",       0,      lda_b_imm),
                   2588:        T(G_LDA,                "addsub",       0,      lda_h_imm),
                   2589:        T(G_LDA,                "addsub",       0,      lda_d_imm),
                   2590:        T(G_LDA,                "addsub",       0,      lda_reg),
                   2591:        T(G_LDA,                "addsub",       0,      lda_b_reg),
                   2592:        T(G_LDA,                "addsub",       0,      lda_h_reg),
                   2593:        T(G_LDA,                "addsub",       0,      lda_d_reg),
                   2594:        T(G_LDA,                "addsub",       0,      lda_scale),
                   2595:        T(G_LDA,                "addsub",       0,      lda_b_scale),
                   2596:        T(G_LDA,                "addsub",       0,      lda_h_scale),
                   2597:        T(G_LDA,                "addsub",       0,      lda_d_scale),
                   2598: 
                   2599:        T(G_MULDIV,             "generic",      0,      mul),
                   2600:        T(G_MULDIV,             "generic",      0,      mul_imm),
                   2601:        T(G_MULDIV,             "div",          0,      div),
                   2602:        T(G_MULDIV,             "div",          0,      div_imm),
                   2603:        T(G_MULDIV,             "div",          0,      divu),
                   2604:        T(G_MULDIV,             "div",          0,      divu_imm),
                   2605: 
                   2606:        T(G_FLT,                "fop_s",        0,      flt_ss),
                   2607:        T(G_FLT,                "fop_d",        1,      flt_ds),
                   2608:        T(G_FLT,                "fop_s",        0,      trnc_ss),
                   2609:        T(G_FLT,                "fop_s",        0,      trnc_sd),
                   2610:        T(G_FLT,                "fop_s",        0,      nint_ss),
                   2611:        T(G_FLT,                "fop_s",        0,      nint_sd),
                   2612:        T(G_FLT,                "fop_s",        0,      int_ss),
                   2613:        T(G_FLT,                "fop_s",        0,      int_sd),
                   2614: 
                   2615:        T(G_FCMP,               "fop_s",        0,      fcmp_sss),
                   2616:        T(G_FCMP,               "fop_s",        0,      fcmp_ssd),
                   2617:        T(G_FCMP,               "fop_s",        0,      fcmp_sds),
                   2618:        T(G_FCMP,               "fop_s",        0,      fcmp_sdd),
1.1       root     2619: };

unix.superglobalmegacorp.com

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