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

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 ---+
        !            19: //  +--> optestm88k_lda.s      ---+
        !            20: //  +--> optestm88k_logical.s  ---+
        !            21: //  +--> optestm88k_muldiv.s   ---+
        !            22: //  +--> optestm88k_sub.s      ---+
        !            23: //  +--> optestm88k_table.c    ---+
        !            24: //  +--> optestm88k_table.h    ---+
        !            25: //                                |
        !            26: //       optestm88k_main.[ch]  ---+
        !            27: //       optestm88k_code.s     ---+
        !            28: //                                | compile and link on m88k
        !            29: //                                v
        !            30: //                             optestm88k
        !            31: 
        !            32: // XXX mul/div/divu 命令の FPU disabled のケースは未検査
        !            33: 
        !            34: #include "header.h"
        !            35: #include <sys/stat.h>
        !            36: #include <sys/wait.h>
        !            37: #include <algorithm>
        !            38: #include <map>
        !            39: #include <tuple>
        !            40: #include <vector>
        !            41: 
        !            42: // テスト情報 (グローバル)
        !            43: static const char *testname;
        !            44: static int testnum;
        !            45: // 出力先 (グローバル)
        !            46: static FILE *fp;
        !            47: 
        !            48: #define IMM    (0xff)
        !            49: 
        !            50: // 理解しやすさのため 1, 2, 3 で表現しているが実際は r11, r12, r13 を使う
        !            51: static constexpr uint32 R3(uint32 d, uint32 s1, uint32 s2) {
        !            52:        d  = (d  > 0) ? (d  + 10) : 0;
        !            53:        s1 = (s1 > 0) ? (s1 + 10) : 0;
        !            54:        s2 = (s2 > 0) ? (s2 + 10) : 0;
        !            55:        return (d << 16) | (s1 << 8) | s2;
        !            56: }
        !            57: // 3オペランドの場合のレジスタの組み合わせ
        !            58: static std::vector<uint32> reglist3 = {
        !            59:        R3(0, 0, 0),
        !            60:        R3(0, 0, 1),
        !            61:        R3(0, 1, 0),
        !            62:        R3(0, 1, 1),
        !            63:        R3(0, 1, 2),
        !            64: 
        !            65:        R3(1, 0, 0),
        !            66:        R3(1, 0, 1),
        !            67:        R3(1, 1, 0),
        !            68:        R3(1, 1, 1),
        !            69:        R3(1, 0, 2),
        !            70:        R3(1, 2, 0),
        !            71:        R3(1, 2, 2),
        !            72:        R3(1, 1, 2),
        !            73:        R3(1, 2, 1),
        !            74:        R3(1, 2, 3),
        !            75: };
        !            76: 
        !            77: // 2オペランド(+IMM)の場合のレジスタの組み合わせ
        !            78: #define R2(d, s1)              R3(d, s1, 0)
        !            79: static std::vector<uint32> reglist2 = {
        !            80:        R2(0, 0),
        !            81:        R2(0, 1),
        !            82:        R2(1, 0),
        !            83:        R2(1, 1),
        !            84:        R2(1, 2),
        !            85: };
        !            86: 
        !            87: // r0 用の値リスト
        !            88: static std::vector<uint32> v0 = {
        !            89:        0,
        !            90: };
        !            91: // 数値演算用の入力値リスト
        !            92: static std::vector<uint32> vlist_arith = {
        !            93:        0,
        !            94:        1,
        !            95:        2,
        !            96:        0x7f,
        !            97:        0x80,
        !            98:        0xff,
        !            99:        0x7fff,
        !           100:        0x8000,
        !           101:        0xffff,
        !           102:        0x7fffffff,
        !           103:        0x80000000,
        !           104:        0xffffffff,
        !           105: };
        !           106: // ビットフィールド用の入力値リスト
        !           107: // XXX どのパターンで試せばいいか
        !           108: static std::vector<uint32> vlist_bf = {
        !           109:        0x00000000,
        !           110:        0x87654321,
        !           111:        0xffffffff,
        !           112: };
        !           113: // ビットフィールド用の入力 W,O リスト
        !           114: // XXX どのパターンで試せばいいか
        !           115: #define WO(w, o)       (((w) << 5) | (o))
        !           116: static std::vector<uint32> vlist_wo = {
        !           117:        WO( 0,  0),
        !           118:        WO( 0,  1),
        !           119:        WO( 0,  2),
        !           120:        WO( 0, 31),
        !           121:        WO( 1,  0),
        !           122:        WO( 1,  1),
        !           123:        WO( 1, 31),
        !           124:        WO(16,  0),
        !           125:        WO(16, 15),
        !           126:        WO(16, 16),
        !           127:        WO(16, 17),
        !           128:        WO(16, 31),
        !           129:        WO(31,  0),
        !           130:        WO(31,  1),
        !           131:        WO(31, 31),
        !           132: };
        !           133: // ff0/ff1 用の入力値リスト
        !           134: static std::vector<uint32> vlist_ff = {
        !           135:        0x00000000,
        !           136:        0x00000001,
        !           137:        0x00000020,
        !           138:        0x00000480,
        !           139:        0x00009000,
        !           140:        0x00010000,
        !           141:        0x00200000,
        !           142:        0x06000000,
        !           143:        0xf0000000,
        !           144: };
        !           145: 
        !           146: template <class T>
        !           147: using Tuple3 = std::tuple<T, T, T>;
        !           148: template <class T>
        !           149: using Tuple4 = std::tuple<T, T, T, T>;
        !           150: template <class T>
        !           151: using Tuple5 = std::tuple<T, T, T, T, T>;
        !           152: 
        !           153: static std::vector<Tuple5<uint32>> test_arith_reg;
        !           154: static std::vector<Tuple4<uint32>> test_arith_imm;
        !           155: static std::vector<Tuple5<uint32>> test_bitfield_reg;
        !           156: static std::vector<Tuple4<uint32>> test_bitfield_imm;
        !           157: static std::vector<Tuple3<uint32>> test_ff01;
        !           158: 
        !           159: // 2オペランドテストの要素を変数に取り出す部分 (副作用のあるマクロ)
        !           160: #define VAR_DIADIC(t, rd, rs2, vs2)    \
        !           161:        uint32 rd  = std::get<0>(t);    \
        !           162:        uint32 rs2 = std::get<1>(t);    \
        !           163:        uint32 vs2 = std::get<2>(t)
        !           164: 
        !           165: // 3オペランドテストの要素を変数に取り出す部分 (副作用のあるマクロ)
        !           166: #define VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2) \
        !           167:        uint32 rd  = std::get<0>(t); \
        !           168:        uint32 rs1 = std::get<1>(t); \
        !           169:        uint32 rs2 = std::get<2>(t); \
        !           170:        uint32 vs1 = std::get<3>(t); \
        !           171:        uint32 vs2 = std::get<4>(t)
        !           172: 
        !           173: // 3オペランド(IMM)テストの要素を変数に取り出す部分 (副作用のあるマクロ)
        !           174: #define VAR_TRI_IMM(t, rd, rs1, vs1, imm) \
        !           175:        uint32 rd  = std::get<0>(t); \
        !           176:        uint32 rs1 = std::get<1>(t); \
        !           177:        uint32 vs1 = std::get<2>(t); \
        !           178:        uint32 imm = std::get<3>(t)
        !           179: 
        !           180: 
        !           181: // fp に出力
        !           182: static void out(const char *fmt, ...)
        !           183: {
        !           184:        va_list ap;
        !           185: 
        !           186:        va_start(ap, fmt);
        !           187:        vfprintf(fp, fmt, ap);
        !           188:        va_end(ap);
        !           189: }
        !           190: 
        !           191: // レジスタ regno に即値 imm をセットする
        !           192: static void
        !           193: MOV_imm(int regno, uint32 imm)
        !           194: {
        !           195:        if (regno == 0) {
        !           196:                // nop
        !           197:        } else if (imm == 0) {
        !           198:                out("   xor     %%r%d, %%r%d, %%r%d\n", regno, regno, regno);
        !           199:        } else if (imm < 0x10000) {
        !           200:                out("   or      %%r%d, %%r0, 0x%04x\n", regno, imm);
        !           201:        } else if (imm == 0xffffffff) {
        !           202:                out("   or.c    %%r%d, %%r0, %%r0       | MOV %%r%d, 0xffffffff\n",
        !           203:                        regno, regno);
        !           204:        } else {
        !           205:                out("   or.u    %%r%d, %%r0, 0x%04x     | MOV %%r%d, 0x%08x\n",
        !           206:                        regno, (imm >> 16), regno, imm);
        !           207:                out("   or      %%r%d, %%r%d, 0x%04x\n", regno, regno, imm & 0xffff);
        !           208:        }
        !           209: }
        !           210: 
        !           211: 
        !           212: //
        !           213: // ここからテストコード
        !           214: //
        !           215: 
        !           216: // r2: 引数1: グローバル変数の先頭
        !           217: //  r2[0] = &exception_occurred
        !           218: //  r2[1] = &exception_expected
        !           219: // r3: 引数2: 今回のテストのパラメータの先頭。内容は code ごとに異なる。
        !           220: //
        !           221: // r9: r1 のバックアップ
        !           222: // r10: 期待 rD
        !           223: // r11: rD  (テストで使う)、結果の rD をここに入れて返す
        !           224: // r12: rS1 (テストで使う)
        !           225: // r13: rS2 (テストで使う)
        !           226: 
        !           227: // add でのオーバーフロー条件
        !           228: static inline bool
        !           229: isovf_add(uint32 s1, uint32 s2, uint32 res)
        !           230: {
        !           231:        return (int32)((s1 ^ res) & (s2 ^ res)) < 0;
        !           232: }
        !           233: 
        !           234: // sub でのオーバーフロー条件
        !           235: static inline bool
        !           236: isovf_sub(uint32 s1, uint32 s2, uint32 res)
        !           237: {
        !           238:        return (int32)((s1 ^ s2) & (s1 ^ res)) < 0;
        !           239: }
        !           240: 
        !           241: // 汎用演算命令共通のテストパターン出力部分
        !           242: static void
        !           243: gen_generic_test(const char *mnemonic,
        !           244:        uint32 rd, uint32 rs1, uint32 rs2, uint32 vs1, uint32 vs2, uint32 exp_rd)
        !           245: {
        !           246:        // rs2 が IMM なら #imm
        !           247:        bool is_imm = (rs2 == IMM);
        !           248:        uint32& imm = vs2;
        !           249: 
        !           250:        out("test_%s_%d:\n", testname, testnum);
        !           251:        if (is_imm) {
        !           252:                out("   /* %s r%d, r%d, #0x%04x (S1=$%08x) */\n",
        !           253:                        mnemonic, rd, rs1, imm, vs1);
        !           254:        } else {
        !           255:                out("   /* %s r%d, r%d, r%d (S1=$%08x, S2=$%08x) */\n",
        !           256:                        mnemonic, rd, rs1, rs2, vs1, vs2);
        !           257:        }
        !           258: 
        !           259:        out("   .word   0x%08x  | exp_rd\n", exp_rd);
        !           260:        // ここからコード
        !           261:        MOV_imm(rs1, vs1);
        !           262:        if (!is_imm && rs1 != rs2) {
        !           263:                MOV_imm(rs2, vs2);
        !           264:        }
        !           265: 
        !           266:        if (is_imm) {
        !           267:                out("   %s      %%r%d, %%r%d, 0x%04x    | test\n", mnemonic, rd, rs1, imm);
        !           268:        } else {
        !           269:                out("   %s      %%r%d, %%r%d, %%r%d     | test\n", mnemonic, rd, rs1, rs2);
        !           270:        }
        !           271: 
        !           272:        if (rd != 11) {
        !           273:                out("   or      %%r11, %%r0, %%r%d\n", rd);
        !           274:        }
        !           275:        out("   jmp     %%r1\n");
        !           276:        out("\n");
        !           277: 
        !           278:        testnum++;
        !           279: }
        !           280: 
        !           281: // 2項ビットフィールド命令共通のテストパターン出力部分
        !           282: // (gen_generic_test と似てるけど微妙に違う)
        !           283: static void
        !           284: gen_bitfield_test(const char *mnemonic,
        !           285:        uint32 rd, uint32 rs1, uint32 vs1, uint32 wo, uint32 exp_rd)
        !           286: {
        !           287:        uint32 w = (wo >> 5) & 0x1f;    // XXX 表記上は 0 なのか 32 なのか
        !           288:        uint32 o =  wo       & 0x1f;
        !           289: 
        !           290:        out("test_%s_%d:\n", testname, testnum);
        !           291:        out("   /* %s r%d, r%d, %d<%d> (S1=$%08x) */\n",
        !           292:                mnemonic, rd, rs1, w, o, vs1);
        !           293: 
        !           294:        out("   .word   0x%08x  | exp_rd\n", exp_rd);
        !           295:        // ここからコード
        !           296:        MOV_imm(rs1, vs1);
        !           297: 
        !           298:        out("   %s      %%r%d, %%r%d, %d<%d>    | test\n", mnemonic, rd, rs1, w, o);
        !           299: 
        !           300:        if (rd != 11) {
        !           301:                out("   or      %%r11, %%r0, %%r%d\n", rd);
        !           302:        }
        !           303:        out("   jmp     %%r1\n");
        !           304:        out("\n");
        !           305: 
        !           306:        testnum++;
        !           307: }
        !           308: 
        !           309: // ff0/ff1 命令共通のテストパターン出力部分
        !           310: // (gen_generic_test と似てるけど微妙に違う)
        !           311: static void
        !           312: gen_ff01_test(const char *mnemonic,
        !           313:        uint32 rd, uint32 rs2, uint32 vs2, uint32 exp_rd)
        !           314: {
        !           315:        out("test_%s_%d:\n", testname, testnum);
        !           316:        out("   /* %s r%d, r%d (S2=$%08x) */\n",
        !           317:                mnemonic, rd, rs2, vs2);
        !           318: 
        !           319:        out("   .word   0x%08x  | exp_rd\n", exp_rd);
        !           320:        // ここからコード
        !           321:        MOV_imm(rs2, vs2);
        !           322: 
        !           323:        out("   %s      %%r%d, %%r%d    | test\n", mnemonic, rd, rs2);
        !           324: 
        !           325:        if (rd != 11) {
        !           326:                out("   or      %%r11, %%r0, %%r%d\n", rd);
        !           327:        }
        !           328:        out("   jmp     %%r1\n");
        !           329:        out("\n");
        !           330: 
        !           331:        testnum++;
        !           332: }
        !           333: 
        !           334: // add/sub 命令共通のテストパターン出力部分
        !           335: // rs2 == IMM なら即値指定。
        !           336: // scale == true なら lda rD, rS1[rS2] 形式。
        !           337: static void
        !           338: gen_addsub_test(const char *mnemonic,
        !           339:        uint32 rd, uint32 rs1, uint32 rs2, uint32 vs1, uint32 vs2, int cin,
        !           340:        uint32 exp_rd, uint32 exp_cy, bool exception = false, bool is_scale = false)
        !           341: {
        !           342:        // rs2 が IMM なら #imm
        !           343:        bool is_imm = (rs2 == IMM);
        !           344:        uint32& imm = vs2;
        !           345: 
        !           346:        out("test_%s_%d:\n", testname, testnum);
        !           347:        if (is_imm) {
        !           348:                out("   /* %s r%d, r%d, #0x%04x (S1=$%08x, Cin=%d) */\n",
        !           349:                        mnemonic, rd, rs1, imm, vs1, cin);
        !           350:        } else if (is_scale) {
        !           351:                out("   /* %s r%d, r%d[r%d] (S1=$%08x, S2=$%08x) */\n",
        !           352:                        mnemonic, rd, rs1, rs2, vs1, vs2);
        !           353:        } else {
        !           354:                out("   /* %s r%d, r%d, r%d (S1=$%08x, S2=$%08x, Cin=%d) */\n",
        !           355:                        mnemonic, rd, rs1, rs2, vs1, vs2, cin);
        !           356:        }
        !           357: 
        !           358:        out("   .word   0x%08x  | exp_rd\n", exp_rd);
        !           359:        out("   .word   0x%08x  | Cin|ExpCy|Exception|0\n",
        !           360:                (cin << 24) | (exp_cy << 16) | (exception << 8));
        !           361:        // ここからテストコード
        !           362:        // ソースレジスタをセット、実行、結果を保存
        !           363:        MOV_imm(rs1, vs1);
        !           364:        if (!is_imm && rs1 != rs2) {
        !           365:                MOV_imm(rs2, vs2);
        !           366:        }
        !           367:        if (exception) {
        !           368:                // 例外期待なら、rD (と Cy)の期待値は命令実行前の値 (p.6-19, 6.6)
        !           369:                out("   or      %%r10, %%r0, %%r%d\n", rd);
        !           370:        } else {
        !           371:                MOV_imm(10, exp_rd);
        !           372:        }
        !           373: 
        !           374:        if (exception) {
        !           375:                out("   | exception is expected\n");
        !           376:        }
        !           377:        if (is_imm) {
        !           378:                out("   %s      %%r%d, %%r%d, 0x%04x    | test\n", mnemonic, rd, rs1, imm);
        !           379:        } else if (is_scale) {
        !           380:                out("   %s      %%r%d, %%r%d[%%r%d]     | test\n", mnemonic, rd, rs1, rs2);
        !           381:        } else {
        !           382:                out("   %s      %%r%d, %%r%d, %%r%d     | test\n", mnemonic, rd, rs1, rs2);
        !           383:        }
        !           384: 
        !           385:        if (rd != 11) {
        !           386:                out("   or      %%r11, %%r0, %%r%d\n", rd);
        !           387:        }
        !           388:        out("   jmp     %%r1\n");
        !           389:        out("\n");
        !           390: 
        !           391:        testnum++;
        !           392: }
        !           393: 
        !           394: // div 命令共通のテストパターン出力部分
        !           395: static void
        !           396: gen_div_test(const char *mnemonic,
        !           397:        uint32 rd, uint32 rs1, uint32 rs2, uint32 vs1, uint32 vs2,
        !           398:        uint32 exp_rd, bool exception = false)
        !           399: {
        !           400:        // rs2 が IMM なら #imm
        !           401:        bool is_imm = (rs2 == IMM);
        !           402:        uint32& imm = vs2;
        !           403: 
        !           404:        out("test_%s_%d:\n", testname, testnum);
        !           405:        if (is_imm) {
        !           406:                out("   /* %s r%d, r%d, #0x%04x (S1=$%08x) */\n",
        !           407:                        mnemonic, rd, rs1, imm, vs1);
        !           408:        } else {
        !           409:                out("   /* %s r%d, r%d, r%d (S1=$%08x, S2=$%08x) */\n",
        !           410:                        mnemonic, rd, rs1, rs2, vs1, vs2);
        !           411:        }
        !           412: 
        !           413:        out("   .word   0x%08x  | exp_rd\n", exp_rd);
        !           414:        out("   .word   0x%08x  | exp_ex\n", exception ? 2 : 0);
        !           415:        // ここからテストコード
        !           416:        // ソースレジスタをセット、実行、結果を保存
        !           417:        MOV_imm(rs1, vs1);
        !           418:        if (!is_imm && rs1 != rs2) {
        !           419:                MOV_imm(rs2, vs2);
        !           420:        }
        !           421:        if (exception) {
        !           422:                // 例外期待なら、rD の期待値は命令実行前の値 (p.6-40, 6.8.3)
        !           423:                out("   or      %%r10, %%r0, %%r%d\n", rd);
        !           424:        } else {
        !           425:                MOV_imm(10, exp_rd);
        !           426:        }
        !           427: 
        !           428:        if (exception) {
        !           429:                out("   | exception is expected\n");
        !           430:        }
        !           431:        if (is_imm) {
        !           432:                out("   %s      %%r%d, %%r%d, 0x%04x    | test\n", mnemonic, rd, rs1, imm);
        !           433:        } else {
        !           434:                out("   %s      %%r%d, %%r%d, %%r%d     | test\n", mnemonic, rd, rs1, rs2);
        !           435:        }
        !           436: 
        !           437:        if (rd != 11) {
        !           438:                out("   or      %%r11, %%r0, %%r%d\n", rd);
        !           439:        }
        !           440:        out("   jmp     %%r1\n");
        !           441:        out("\n");
        !           442: 
        !           443:        testnum++;
        !           444: }
        !           445: 
        !           446: static void
        !           447: gen_add()
        !           448: {
        !           449:        for (const auto& t : test_arith_reg) {
        !           450:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !           451: 
        !           452:                for (int cin = 0; cin <= 1; cin++) {
        !           453:                        // 期待値
        !           454:                        uint64 result = (uint64)vs1 + vs2;
        !           455:                        uint32 exp_rd = (uint32)result;
        !           456:                        uint32 exp_cy = cin;
        !           457:                        if (rd == 0) {
        !           458:                                exp_rd = 0;
        !           459:                        }
        !           460:                        bool exp_ex = isovf_add(vs1, vs2, result);
        !           461:                        if (exp_ex) {
        !           462:                                exp_cy = cin;
        !           463:                        }
        !           464: 
        !           465:                        gen_addsub_test("add",
        !           466:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy, exp_ex);
        !           467:                }
        !           468:        }
        !           469: }
        !           470: 
        !           471: static void
        !           472: gen_add_ci()
        !           473: {
        !           474:        for (const auto& t : test_arith_reg) {
        !           475:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !           476: 
        !           477:                for (int cin = 0; cin <= 1; cin++) {
        !           478:                        // 期待値
        !           479:                        uint64 result = (uint64)vs1 + vs2 + cin;
        !           480:                        uint32 exp_rd = (uint32)result;
        !           481:                        uint32 exp_cy = cin;
        !           482:                        if (rd == 0) {
        !           483:                                exp_rd = 0;
        !           484:                        }
        !           485:                        bool exp_ex = isovf_add(vs1, vs2, result);
        !           486:                        if (exp_ex) {
        !           487:                                exp_cy = cin;
        !           488:                        }
        !           489: 
        !           490:                        gen_addsub_test("add.ci",
        !           491:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy, exp_ex);
        !           492:                }
        !           493:        }
        !           494: }
        !           495: 
        !           496: static void
        !           497: gen_add_co()
        !           498: {
        !           499:        for (const auto& t : test_arith_reg) {
        !           500:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !           501: 
        !           502:                for (int cin = 0; cin <= 1; cin++) {
        !           503:                        // 期待値
        !           504:                        uint64 result = (uint64)vs1 + vs2;
        !           505:                        uint32 exp_rd = (uint32)result;
        !           506:                        uint32 exp_cy = result >> 32;
        !           507:                        if (rd == 0) {
        !           508:                                exp_rd = 0;
        !           509:                        }
        !           510:                        bool exp_ex = isovf_add(vs1, vs2, result);
        !           511:                        if (exp_ex) {
        !           512:                                exp_cy = cin;
        !           513:                        }
        !           514: 
        !           515:                        gen_addsub_test("add.co",
        !           516:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy, exp_ex);
        !           517:                }
        !           518:        }
        !           519: }
        !           520: 
        !           521: static void
        !           522: gen_add_cio()
        !           523: {
        !           524:        for (const auto& t : test_arith_reg) {
        !           525:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !           526: 
        !           527:                for (int cin = 0; cin <= 1; cin++) {
        !           528:                        // 期待値
        !           529:                        uint64 result = (uint64)vs1 + vs2 + cin;
        !           530:                        uint32 exp_rd = (uint32)result;
        !           531:                        uint32 exp_cy = result >> 32;
        !           532:                        if (rd == 0) {
        !           533:                                exp_rd = 0;
        !           534:                        }
        !           535:                        bool exp_ex = isovf_add(vs1, vs2, result);
        !           536:                        if (exp_ex) {
        !           537:                                exp_cy = cin;
        !           538:                        }
        !           539: 
        !           540:                        gen_addsub_test("add.cio",
        !           541:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy, exp_ex);
        !           542:                }
        !           543:        }
        !           544: }
        !           545: 
        !           546: static void
        !           547: gen_add_imm()
        !           548: {
        !           549:        for (const auto& t : test_arith_imm) {
        !           550:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !           551: 
        !           552:                for (int cin = 0; cin <= 1; cin++) {
        !           553:                        // 期待値
        !           554:                        uint64 result = (uint64)vs1 + imm;
        !           555:                        uint32 exp_rd = (uint32)result;
        !           556:                        uint32 exp_cy = cin;
        !           557:                        if (rd == 0) {
        !           558:                                exp_rd = 0;
        !           559:                        }
        !           560:                        bool exp_ex = isovf_add(vs1, imm, result);
        !           561:                        if (exp_ex) {
        !           562:                                exp_cy = cin;
        !           563:                        }
        !           564: 
        !           565:                        gen_addsub_test("add",
        !           566:                                rd, rs1, IMM, vs1, imm, cin, exp_rd, exp_cy, exp_ex);
        !           567:                }
        !           568:        }
        !           569: }
        !           570: 
        !           571: // addu rD, rS1, rS2 と lda rD, rS1, rS2 は名前が違うだけで同じ…
        !           572: static void
        !           573: gen_addu_lda(const char *mnemonic)
        !           574: {
        !           575:        for (const auto& t : test_arith_reg) {
        !           576:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !           577: 
        !           578:                for (int cin = 0; cin <= 1; cin++) {
        !           579:                        // 期待値
        !           580:                        uint64 result = (uint64)vs1 + vs2;
        !           581:                        uint32 exp_rd = (uint32)result;
        !           582:                        uint32 exp_cy = cin;
        !           583:                        if (rd == 0) {
        !           584:                                exp_rd = 0;
        !           585:                        }
        !           586: 
        !           587:                        gen_addsub_test(mnemonic,
        !           588:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy);
        !           589:                }
        !           590:        }
        !           591: }
        !           592: 
        !           593: static void
        !           594: gen_addu()
        !           595: {
        !           596:        gen_addu_lda("addu");
        !           597: }
        !           598: 
        !           599: static void
        !           600: gen_addu_ci()
        !           601: {
        !           602:        for (const auto& t : test_arith_reg) {
        !           603:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !           604: 
        !           605:                for (int cin = 0; cin <= 1; cin++) {
        !           606:                        // 期待値
        !           607:                        uint64 result = (uint64)vs1 + vs2 + cin;
        !           608:                        uint32 exp_rd = (uint32)result;
        !           609:                        uint32 exp_cy = cin;
        !           610:                        if (rd == 0) {
        !           611:                                exp_rd = 0;
        !           612:                        }
        !           613: 
        !           614:                        gen_addsub_test("addu.ci",
        !           615:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy);
        !           616:                }
        !           617:        }
        !           618: }
        !           619: 
        !           620: static void
        !           621: gen_addu_co()
        !           622: {
        !           623:        for (const auto& t : test_arith_reg) {
        !           624:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !           625: 
        !           626:                for (int cin = 0; cin <= 1; cin++) {
        !           627:                        // 期待値
        !           628:                        uint64 result = (uint64)vs1 + vs2;
        !           629:                        uint32 exp_rd = (uint32)result;
        !           630:                        uint32 exp_cy = result >> 32;
        !           631:                        if (rd == 0) {
        !           632:                                exp_rd = 0;
        !           633:                        }
        !           634: 
        !           635:                        gen_addsub_test("addu.co",
        !           636:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy);
        !           637:                }
        !           638:        }
        !           639: }
        !           640: 
        !           641: static void
        !           642: gen_addu_cio()
        !           643: {
        !           644:        for (const auto& t : test_arith_reg) {
        !           645:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !           646: 
        !           647:                for (int cin = 0; cin <= 1; cin++) {
        !           648:                        // 期待値
        !           649:                        uint64 result = (uint64)vs1 + vs2 + cin;
        !           650:                        uint32 exp_rd = (uint32)result;
        !           651:                        uint32 exp_cy = result >> 32;
        !           652:                        if (rd == 0) {
        !           653:                                exp_rd = 0;
        !           654:                        }
        !           655: 
        !           656:                        gen_addsub_test("addu.cio",
        !           657:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy);
        !           658:                }
        !           659:        }
        !           660: }
        !           661: 
        !           662: // addu rD, rS1, #imm と lda rD, rS1, #imm は名前が違うだけで同じ…
        !           663: static void
        !           664: gen_addu_lda_imm(const char *mnemonic)
        !           665: {
        !           666:        for (const auto& t : test_arith_imm) {
        !           667:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !           668: 
        !           669:                for (int cin = 0; cin <= 1; cin++) {
        !           670:                        // 期待値
        !           671:                        uint64 result = (uint64)vs1 + imm;
        !           672:                        uint32 exp_rd = (uint32)result;
        !           673:                        uint32 exp_cy = cin;
        !           674:                        if (rd == 0) {
        !           675:                                exp_rd = 0;
        !           676:                        }
        !           677: 
        !           678:                        gen_addsub_test(mnemonic,
        !           679:                                rd, rs1, IMM, vs1, imm, cin, exp_rd, exp_cy);
        !           680:                }
        !           681:        }
        !           682: }
        !           683: 
        !           684: static void
        !           685: gen_addu_imm()
        !           686: {
        !           687:        gen_addu_lda_imm("addu");
        !           688: }
        !           689: 
        !           690: static void
        !           691: gen_and()
        !           692: {
        !           693:        for (const auto& t : test_arith_reg) {
        !           694:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !           695:                uint32 exp_rd = vs1 & vs2;
        !           696:                if (rd == 0) {
        !           697:                        exp_rd = 0;
        !           698:                }
        !           699:                gen_generic_test("and", rd, rs1, rs2, vs1, vs2, exp_rd);
        !           700:        }
        !           701: }
        !           702: 
        !           703: static void
        !           704: gen_and_c()
        !           705: {
        !           706:        for (const auto& t : test_arith_reg) {
        !           707:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !           708:                uint32 exp_rd = vs1 & ~vs2;
        !           709:                if (rd == 0) {
        !           710:                        exp_rd = 0;
        !           711:                }
        !           712:                gen_generic_test("and.c", rd, rs1, rs2, vs1, vs2, exp_rd);
        !           713:        }
        !           714: }
        !           715: 
        !           716: static void
        !           717: gen_and_imm()
        !           718: {
        !           719:        for (const auto& t : test_arith_imm) {
        !           720:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !           721:                uint32 exp_rd = vs1 & (imm | 0xffff0000);
        !           722:                if (rd == 0) {
        !           723:                        exp_rd = 0;
        !           724:                }
        !           725:                gen_generic_test("and", rd, rs1, IMM, vs1, imm, exp_rd);
        !           726:        }
        !           727: }
        !           728: 
        !           729: static void
        !           730: gen_and_u()
        !           731: {
        !           732:        for (const auto& t : test_arith_imm) {
        !           733:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !           734:                uint32 exp_rd = vs1 & ((imm << 16) | 0xffff);
        !           735:                if (rd == 0) {
        !           736:                        exp_rd = 0;
        !           737:                }
        !           738:                gen_generic_test("and.u", rd, rs1, IMM, vs1, imm, exp_rd);
        !           739:        }
        !           740: }
        !           741: 
        !           742: static uint32
        !           743: calc_clr(uint32 src, uint32 wo)
        !           744: {
        !           745:        uint32 w = ((wo >> 5) & 0x1f) ?: 32;
        !           746:        uint32 o =   wo       & 0x1f;
        !           747:        uint32 mask = (uint32)(((1ULL << w) - 1) << o);
        !           748:        return src & ~mask;
        !           749: }
        !           750: 
        !           751: static void
        !           752: gen_clr_imm()
        !           753: {
        !           754:        for (const auto& t : test_bitfield_imm) {
        !           755:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !           756:                uint32 exp_rd = calc_clr(vs1, imm);
        !           757:                if (rd == 0) {
        !           758:                        exp_rd = 0;
        !           759:                }
        !           760:                gen_bitfield_test("clr", rd, rs1, vs1, imm, exp_rd);
        !           761:        }
        !           762: }
        !           763: 
        !           764: static void
        !           765: gen_clr_reg()
        !           766: {
        !           767:        for (const auto& t : test_bitfield_reg) {
        !           768:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !           769:                uint32 exp_rd = calc_clr(vs1, vs2);
        !           770:                if (rd == 0) {
        !           771:                        exp_rd = 0;
        !           772:                }
        !           773:                gen_generic_test("clr", rd, rs1, rs2, vs1, vs2, exp_rd);
        !           774:        }
        !           775: }
        !           776: 
        !           777: static uint32
        !           778: calc_cmp(uint32 vs1, uint32 vs2)
        !           779: {
        !           780:        // 期待値
        !           781:        uint32 exp_rd = 0;
        !           782: 
        !           783:        exp_rd |= (vs1 >= vs2) ? 0x0800 : 0;
        !           784:        exp_rd |= (vs1 <  vs2) ? 0x0400 : 0;
        !           785:        exp_rd |= (vs1 <= vs2) ? 0x0200 : 0;
        !           786:        exp_rd |= (vs1 >  vs2) ? 0x0100 : 0;
        !           787:        exp_rd |= ((int32)vs1 >= (int32)vs2) ? 0x0080 : 0;
        !           788:        exp_rd |= ((int32)vs1 <  (int32)vs2) ? 0x0040 : 0;
        !           789:        exp_rd |= ((int32)vs1 <= (int32)vs2) ? 0x0020 : 0;
        !           790:        exp_rd |= ((int32)vs1 >  (int32)vs2) ? 0x0010 : 0;
        !           791:        exp_rd |= (vs1 != vs2) ? 0x0008 : 0;
        !           792:        exp_rd |= (vs1 == vs2) ? 0x0004 : 0;
        !           793: 
        !           794:        return exp_rd;
        !           795: }
        !           796: 
        !           797: static void
        !           798: gen_cmp()
        !           799: {
        !           800:        for (const auto& t : test_arith_reg) {
        !           801:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !           802:                uint32 exp_rd = calc_cmp(vs1, vs2);
        !           803:                if (rd == 0) {
        !           804:                        exp_rd = 0;
        !           805:                }
        !           806:                gen_generic_test("cmp", rd, rs1, rs2, vs1, vs2, exp_rd);
        !           807:        }
        !           808: }
        !           809: 
        !           810: static void
        !           811: gen_cmp_imm()
        !           812: {
        !           813:        for (const auto& t : test_arith_imm) {
        !           814:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !           815:                uint32 exp_rd = calc_cmp(vs1, imm);
        !           816:                if (rd == 0) {
        !           817:                        exp_rd = 0;
        !           818:                }
        !           819:                gen_generic_test("cmp", rd, rs1, IMM, vs1, imm, exp_rd);
        !           820:        }
        !           821: }
        !           822: 
        !           823: // 符号付きで x / y の期待値を計算する。
        !           824: // 計算可能な場合は *exp_rd に結果を書き戻し *exp_ex に false を書き戻す。
        !           825: // 例外を期待する場合は *exp_ex に true を書き戻す。
        !           826: static void
        !           827: calc_div(uint32 *exp_rd, bool *exp_ex, int32 x, int32 y)
        !           828: {
        !           829:        // どちらかのオペランドが負でも例外らしい。符号付きとは一体…。
        !           830:        if (x < 0 || y <= 0) {
        !           831:                *exp_ex = true;
        !           832:                *exp_rd = 0;    // なくていいはずだけどコンパイラに怒られるので
        !           833:        } else {
        !           834:                *exp_ex = false;
        !           835:                *exp_rd = (uint32)(x / y);
        !           836:        }
        !           837: }
        !           838: 
        !           839: static void
        !           840: gen_div()
        !           841: {
        !           842:        for (const auto& t : test_arith_reg) {
        !           843:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !           844:                uint32 exp_rd;
        !           845:                bool exp_ex;
        !           846:                calc_div(&exp_rd, &exp_ex, vs1, vs2);
        !           847:                if (rd == 0) {
        !           848:                        exp_rd = 0;
        !           849:                }
        !           850:                gen_div_test("div", rd, rs1, rs2, vs1, vs2, exp_rd, exp_ex);
        !           851:        }
        !           852: }
        !           853: 
        !           854: static void
        !           855: gen_div_imm()
        !           856: {
        !           857:        for (const auto& t : test_arith_imm) {
        !           858:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !           859:                uint32 exp_rd;
        !           860:                bool exp_ex;
        !           861:                calc_div(&exp_rd, &exp_ex, vs1, imm);
        !           862:                if (rd == 0) {
        !           863:                        exp_rd = 0;
        !           864:                }
        !           865:                gen_div_test("div", rd, rs1, IMM, vs1, imm, exp_rd, exp_ex);
        !           866:        }
        !           867: }
        !           868: 
        !           869: // 符号無しで x / y の期待値を計算する。
        !           870: // 計算可能な場合は *exp_rd に結果を書き戻し *exp_ex に false を書き戻す。
        !           871: // DivByZero を期待する場合は *exp_ex に true を書き戻す。
        !           872: static void
        !           873: calc_divu(uint32 *exp_rd, bool *exp_ex, uint32 x, uint32 y)
        !           874: {
        !           875:        if (y == 0) {
        !           876:                *exp_ex = true;
        !           877:                *exp_rd = 0;    // なくていいはずだけどコンパイラに怒られるので
        !           878:        } else {
        !           879:                *exp_ex = false;
        !           880:                *exp_rd = x / y;
        !           881:        }
        !           882: }
        !           883: 
        !           884: static void
        !           885: gen_divu()
        !           886: {
        !           887:        for (const auto& t : test_arith_reg) {
        !           888:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !           889:                uint32 exp_rd;
        !           890:                bool exp_ex;
        !           891:                calc_divu(&exp_rd, &exp_ex, vs1, vs2);
        !           892:                if (rd == 0) {
        !           893:                        exp_rd = 0;
        !           894:                }
        !           895:                gen_div_test("divu", rd, rs1, rs2, vs1, vs2, exp_rd, exp_ex);
        !           896:        }
        !           897: }
        !           898: 
        !           899: static void
        !           900: gen_divu_imm()
        !           901: {
        !           902:        for (const auto& t : test_arith_imm) {
        !           903:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !           904:                uint32 exp_rd;
        !           905:                bool exp_ex;
        !           906:                calc_divu(&exp_rd, &exp_ex, vs1, imm);
        !           907:                if (rd == 0) {
        !           908:                        exp_rd = 0;
        !           909:                }
        !           910:                gen_div_test("divu", rd, rs1, IMM, vs1, imm, exp_rd, exp_ex);
        !           911:        }
        !           912: }
        !           913: 
        !           914: static uint32
        !           915: calc_ext(uint32 src, uint32 wo)
        !           916: {
        !           917:        uint32 w = ((wo >> 5) & 0x1f) ?: 32;
        !           918:        uint32 o =   wo       & 0x1f;
        !           919:        uint32 mask = (uint32)(((1ULL << w) - 1) << o);
        !           920: 
        !           921:        src &= mask;
        !           922: 
        !           923:        int shift = 0;
        !           924:        if (o + w < 32) {
        !           925:                shift = 32 - (o + w);
        !           926:                src <<= shift;
        !           927:        }
        !           928:        src = (int32)src >> (o + shift);
        !           929:        return src;
        !           930: }
        !           931: 
        !           932: static void
        !           933: gen_ext_imm()
        !           934: {
        !           935:        for (const auto& t : test_bitfield_imm) {
        !           936:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !           937:                uint32 exp_rd = calc_ext(vs1, imm);
        !           938:                if (rd == 0) {
        !           939:                        exp_rd = 0;
        !           940:                }
        !           941:                gen_bitfield_test("ext", rd, rs1, vs1, imm, exp_rd);
        !           942:        }
        !           943: }
        !           944: 
        !           945: static void
        !           946: gen_ext_reg()
        !           947: {
        !           948:        for (const auto& t : test_bitfield_reg) {
        !           949:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !           950:                uint32 exp_rd = calc_ext(vs1, vs2);
        !           951:                if (rd == 0) {
        !           952:                        exp_rd = 0;
        !           953:                }
        !           954:                gen_generic_test("ext", rd, rs1, rs2, vs1, vs2, exp_rd);
        !           955:        }
        !           956: }
        !           957: 
        !           958: static uint32
        !           959: calc_extu(uint32 src, uint32 wo)
        !           960: {
        !           961:        uint32 w = ((wo >> 5) & 0x1f) ?: 32;
        !           962:        uint32 o =   wo       & 0x1f;
        !           963:        uint32 mask = (uint32)(((1ULL << w) - 1) << o);
        !           964: 
        !           965:        return (src & mask) >> o;
        !           966: }
        !           967: 
        !           968: static void
        !           969: gen_extu_imm()
        !           970: {
        !           971:        for (const auto& t : test_bitfield_imm) {
        !           972:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !           973:                uint32 exp_rd = calc_extu(vs1, imm);
        !           974:                if (rd == 0) {
        !           975:                        exp_rd = 0;
        !           976:                }
        !           977:                gen_bitfield_test("extu", rd, rs1, vs1, imm, exp_rd);
        !           978:        }
        !           979: }
        !           980: 
        !           981: static void
        !           982: gen_extu_reg()
        !           983: {
        !           984:        for (const auto& t : test_bitfield_reg) {
        !           985:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !           986:                uint32 exp_rd = calc_extu(vs1, vs2);
        !           987:                if (rd == 0) {
        !           988:                        exp_rd = 0;
        !           989:                }
        !           990:                gen_generic_test("extu", rd, rs1, rs2, vs1, vs2, exp_rd);
        !           991:        }
        !           992: }
        !           993: 
        !           994: static void
        !           995: gen_ff0()
        !           996: {
        !           997:        for (const auto& t : test_ff01) {
        !           998:                VAR_DIADIC(t, rd, rs2, vs2);
        !           999:                // 最も MSB 側にある %0 のビット位置(LSBを0とする)を返す
        !          1000:                // %0 がなければ 32 を返す
        !          1001:                uint32 exp_rd = 32;
        !          1002:                if (vs2 != 0xffffffff) {
        !          1003:                        exp_rd = 31 - __builtin_clz(~vs2);
        !          1004:                }
        !          1005:                if (rd == 0) {
        !          1006:                        exp_rd = 0;
        !          1007:                }
        !          1008:                gen_ff01_test("ff0", rd, rs2, vs2, exp_rd);
        !          1009:        }
        !          1010: }
        !          1011: 
        !          1012: static void
        !          1013: gen_ff1()
        !          1014: {
        !          1015:        for (const auto& t : test_ff01) {
        !          1016:                VAR_DIADIC(t, rd, rs2, vs2);
        !          1017:                // 最も MSB 側にある %1 のビット位置(LSBを0とする)を返す
        !          1018:                // %0 がなければ 32 を返す
        !          1019:                uint32 exp_rd = 32;
        !          1020:                if (vs2 != 0x00000000) {
        !          1021:                        exp_rd = 31 - __builtin_clz(vs2);
        !          1022:                }
        !          1023:                if (rd == 0) {
        !          1024:                        exp_rd = 0;
        !          1025:                }
        !          1026:                gen_ff01_test("ff1", rd, rs2, vs2, exp_rd);
        !          1027:        }
        !          1028: }
        !          1029: 
        !          1030: // lda.* rD, rS1, #imm は addu rD, rS1, #imm と同じ
        !          1031: static void
        !          1032: gen_lda_imm()
        !          1033: {
        !          1034:        gen_addu_lda_imm("lda");
        !          1035: }
        !          1036: static void
        !          1037: gen_lda_b_imm()
        !          1038: {
        !          1039:        gen_addu_lda_imm("lda.b");
        !          1040: }
        !          1041: static void
        !          1042: gen_lda_h_imm()
        !          1043: {
        !          1044:        gen_addu_lda_imm("lda.h");
        !          1045: }
        !          1046: static void
        !          1047: gen_lda_d_imm()
        !          1048: {
        !          1049:        gen_addu_lda_imm("lda.d");
        !          1050: }
        !          1051: 
        !          1052: // lda.* rD, rS1, rS2 は addu rD, rS1, rS2 と同じ
        !          1053: static void
        !          1054: gen_lda_reg()
        !          1055: {
        !          1056:        gen_addu_lda("lda");
        !          1057: }
        !          1058: static void
        !          1059: gen_lda_b_reg()
        !          1060: {
        !          1061:        gen_addu_lda("lda.b");
        !          1062: }
        !          1063: static void
        !          1064: gen_lda_h_reg()
        !          1065: {
        !          1066:        gen_addu_lda("lda.h");
        !          1067: }
        !          1068: static void
        !          1069: gen_lda_d_reg()
        !          1070: {
        !          1071:        gen_addu_lda("lda.d");
        !          1072: }
        !          1073: 
        !          1074: static void
        !          1075: gen_lda_scale(const char *mnemonic, uint32 scale)
        !          1076: {
        !          1077:        for (const auto& t : test_arith_reg) {
        !          1078:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !          1079: 
        !          1080:                for (int cin = 0; cin <= 1; cin++) {
        !          1081:                        // 期待値
        !          1082:                        uint64 result = (uint64)vs1 + vs2 * scale;
        !          1083:                        uint32 exp_rd = (uint32)result;
        !          1084:                        uint32 exp_cy = cin;
        !          1085:                        if (rd == 0) {
        !          1086:                                exp_rd = 0;
        !          1087:                        }
        !          1088: 
        !          1089:                        bool exception = false;
        !          1090:                        bool is_scale = true;
        !          1091:                        gen_addsub_test(mnemonic,
        !          1092:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy,
        !          1093:                                exception, is_scale);
        !          1094:                }
        !          1095:        }
        !          1096: }
        !          1097: static void
        !          1098: gen_lda_scale()
        !          1099: {
        !          1100:        gen_lda_scale("lda", 4);
        !          1101: }
        !          1102: static void
        !          1103: gen_lda_b_scale()
        !          1104: {
        !          1105:        gen_addu_lda("lda.b");
        !          1106: }
        !          1107: static void
        !          1108: gen_lda_h_scale()
        !          1109: {
        !          1110:        gen_lda_scale("lda.h", 2);
        !          1111: }
        !          1112: static void
        !          1113: gen_lda_d_scale()
        !          1114: {
        !          1115:        gen_lda_scale("lda.d", 8);
        !          1116: }
        !          1117: 
        !          1118: static uint32
        !          1119: calc_mak(uint32 src, uint32 wo)
        !          1120: {
        !          1121:        uint32 w = ((wo >> 5) & 0x1f) ?: 32;
        !          1122:        uint32 o =   wo       & 0x1f;
        !          1123:        uint32 mask = (uint32)((1ULL << w) - 1);
        !          1124: 
        !          1125:        return (src & mask) << o;
        !          1126: }
        !          1127: 
        !          1128: static void
        !          1129: gen_mak_imm()
        !          1130: {
        !          1131:        for (const auto& t : test_bitfield_imm) {
        !          1132:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !          1133:                uint32 exp_rd = calc_mak(vs1, imm);
        !          1134:                if (rd == 0) {
        !          1135:                        exp_rd = 0;
        !          1136:                }
        !          1137:                gen_bitfield_test("mak", rd, rs1, vs1, imm, exp_rd);
        !          1138:        }
        !          1139: }
        !          1140: 
        !          1141: static void
        !          1142: gen_mak_reg()
        !          1143: {
        !          1144:        for (const auto& t : test_bitfield_reg) {
        !          1145:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !          1146:                uint32 exp_rd = calc_mak(vs1, vs2);
        !          1147:                if (rd == 0) {
        !          1148:                        exp_rd = 0;
        !          1149:                }
        !          1150:                gen_generic_test("mak", rd, rs1, rs2, vs1, vs2, exp_rd);
        !          1151:        }
        !          1152: }
        !          1153: 
        !          1154: static void
        !          1155: gen_mask_imm()
        !          1156: {
        !          1157:        for (const auto& t : test_arith_imm) {
        !          1158:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !          1159:                uint32 exp_rd = vs1 & imm;
        !          1160:                if (rd == 0) {
        !          1161:                        exp_rd = 0;
        !          1162:                }
        !          1163:                gen_generic_test("mask", rd, rs1, IMM, vs1, imm, exp_rd);
        !          1164:        }
        !          1165: }
        !          1166: 
        !          1167: static void
        !          1168: gen_mask_u()
        !          1169: {
        !          1170:        for (const auto& t : test_arith_imm) {
        !          1171:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !          1172:                uint32 exp_rd = vs1 & (imm << 16);
        !          1173:                if (rd == 0) {
        !          1174:                        exp_rd = 0;
        !          1175:                }
        !          1176:                gen_generic_test("mask.u", rd, rs1, IMM, vs1, imm, exp_rd);
        !          1177:        }
        !          1178: }
        !          1179: 
        !          1180: static void
        !          1181: gen_mul()
        !          1182: {
        !          1183:        for (const auto& t : test_arith_reg) {
        !          1184:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !          1185:                uint32 exp_rd = (uint32)((uint64)vs1 * vs2);
        !          1186:                if (rd == 0) {
        !          1187:                        exp_rd = 0;
        !          1188:                }
        !          1189:                gen_generic_test("mul", rd, rs1, rs2, vs1, vs2, exp_rd);
        !          1190:        }
        !          1191: }
        !          1192: 
        !          1193: static void
        !          1194: gen_mul_imm()
        !          1195: {
        !          1196:        for (const auto& t : test_arith_imm) {
        !          1197:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !          1198:                uint32 exp_rd = (uint32)((uint64)vs1 * imm);
        !          1199:                if (rd == 0) {
        !          1200:                        exp_rd = 0;
        !          1201:                }
        !          1202:                gen_generic_test("mul", rd, rs1, IMM, vs1, imm, exp_rd);
        !          1203:        }
        !          1204: }
        !          1205: 
        !          1206: static void
        !          1207: gen_or()
        !          1208: {
        !          1209:        for (const auto& t : test_arith_reg) {
        !          1210:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !          1211:                uint32 exp_rd = vs1 | vs2;
        !          1212:                if (rd == 0) {
        !          1213:                        exp_rd = 0;
        !          1214:                }
        !          1215:                gen_generic_test("or", rd, rs1, rs2, vs1, vs2, exp_rd);
        !          1216:        }
        !          1217: }
        !          1218: 
        !          1219: static void
        !          1220: gen_or_c()
        !          1221: {
        !          1222:        for (const auto& t : test_arith_reg) {
        !          1223:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !          1224:                uint32 exp_rd = vs1 | ~vs2;
        !          1225:                if (rd == 0) {
        !          1226:                        exp_rd = 0;
        !          1227:                }
        !          1228:                gen_generic_test("or.c", rd, rs1, rs2, vs1, vs2, exp_rd);
        !          1229:        }
        !          1230: }
        !          1231: 
        !          1232: static void
        !          1233: gen_or_imm()
        !          1234: {
        !          1235:        for (const auto& t : test_arith_imm) {
        !          1236:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !          1237:                uint32 exp_rd = vs1 | imm;
        !          1238:                if (rd == 0) {
        !          1239:                        exp_rd = 0;
        !          1240:                }
        !          1241:                gen_generic_test("or", rd, rs1, IMM, vs1, imm, exp_rd);
        !          1242:        }
        !          1243: }
        !          1244: 
        !          1245: static void
        !          1246: gen_or_u()
        !          1247: {
        !          1248:        for (const auto& t : test_arith_imm) {
        !          1249:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !          1250:                uint32 exp_rd = vs1 | (imm << 16);
        !          1251:                if (rd == 0) {
        !          1252:                        exp_rd = 0;
        !          1253:                }
        !          1254:                gen_generic_test("or.u", rd, rs1, IMM, vs1, imm, exp_rd);
        !          1255:        }
        !          1256: }
        !          1257: 
        !          1258: static uint32
        !          1259: calc_rot(uint32 src, uint32 wo)
        !          1260: {
        !          1261:        uint32 o = wo & 0x1f;
        !          1262:        return (src >> o) | (src << (32 - o));
        !          1263: }
        !          1264: 
        !          1265: static void
        !          1266: gen_rot_imm()
        !          1267: {
        !          1268:        // 手抜きで W は無視するのでパターンが重複する
        !          1269:        for (const auto& t : test_bitfield_imm) {
        !          1270:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !          1271:                uint32 exp_rd = calc_rot(vs1, imm);
        !          1272:                if (rd == 0) {
        !          1273:                        exp_rd = 0;
        !          1274:                }
        !          1275:                gen_bitfield_test("rot", rd, rs1, vs1, imm, exp_rd);
        !          1276:        }
        !          1277: }
        !          1278: 
        !          1279: static void
        !          1280: gen_rot_reg()
        !          1281: {
        !          1282:        // 手抜きで W は無視するのでパターンが重複する
        !          1283:        for (const auto& t : test_bitfield_reg) {
        !          1284:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !          1285:                uint32 exp_rd = calc_rot(vs1, vs2);
        !          1286:                if (rd == 0) {
        !          1287:                        exp_rd = 0;
        !          1288:                }
        !          1289:                gen_generic_test("rot", rd, rs1, rs2, vs1, vs2, exp_rd);
        !          1290:        }
        !          1291: }
        !          1292: 
        !          1293: static uint32
        !          1294: calc_set(uint32 src, uint32 wo)
        !          1295: {
        !          1296:        uint32 w = ((wo >> 5) & 0x1f) ?: 32;
        !          1297:        uint32 o =   wo       & 0x1f;
        !          1298:        uint32 mask = (uint32)(((1ULL << w) - 1) << o);
        !          1299:        return src | mask;
        !          1300: }
        !          1301: 
        !          1302: static void
        !          1303: gen_set_imm()
        !          1304: {
        !          1305:        for (const auto& t : test_bitfield_imm) {
        !          1306:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !          1307:                uint32 exp_rd = calc_set(vs1, imm);
        !          1308:                if (rd == 0) {
        !          1309:                        exp_rd = 0;
        !          1310:                }
        !          1311:                gen_bitfield_test("set", rd, rs1, vs1, imm, exp_rd);
        !          1312:        }
        !          1313: }
        !          1314: 
        !          1315: static void
        !          1316: gen_set_reg()
        !          1317: {
        !          1318:        for (const auto& t : test_bitfield_reg) {
        !          1319:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !          1320:                uint32 exp_rd = calc_set(vs1, vs2);
        !          1321:                if (rd == 0) {
        !          1322:                        exp_rd = 0;
        !          1323:                }
        !          1324:                gen_generic_test("set", rd, rs1, rs2, vs1, vs2, exp_rd);
        !          1325:        }
        !          1326: }
        !          1327: 
        !          1328: static void
        !          1329: gen_sub()
        !          1330: {
        !          1331:        for (const auto& t : test_arith_reg) {
        !          1332:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !          1333: 
        !          1334:                for (int cin = 0; cin <= 1; cin++) {
        !          1335:                        // 期待値
        !          1336:                        uint64 result = (uint64)vs1 + (~vs2) + 1;
        !          1337:                        uint32 exp_rd = (uint32)result;
        !          1338:                        uint32 exp_cy = cin;
        !          1339:                        if (rd == 0) {
        !          1340:                                exp_rd = 0;
        !          1341:                        }
        !          1342:                        bool exp_ex = isovf_sub(vs1, vs2, result);
        !          1343:                        if (exp_ex) {
        !          1344:                                exp_cy = cin;
        !          1345:                        }
        !          1346: 
        !          1347:                        gen_addsub_test("sub",
        !          1348:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy, exp_ex);
        !          1349:                }
        !          1350:        }
        !          1351: }
        !          1352: 
        !          1353: static void
        !          1354: gen_sub_ci()
        !          1355: {
        !          1356:        for (const auto& t : test_arith_reg) {
        !          1357:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !          1358: 
        !          1359:                for (int cin = 0; cin <= 1; cin++) {
        !          1360:                        // 期待値
        !          1361:                        uint64 result = (uint64)vs1 + (~vs2) + cin;
        !          1362:                        uint32 exp_rd = (uint32)result;
        !          1363:                        uint32 exp_cy = cin;
        !          1364:                        if (rd == 0) {
        !          1365:                                exp_rd = 0;
        !          1366:                        }
        !          1367:                        bool exp_ex = isovf_sub(vs1, vs2, result);
        !          1368:                        if (exp_ex) {
        !          1369:                                exp_cy = cin;
        !          1370:                        }
        !          1371: 
        !          1372:                        gen_addsub_test("sub.ci",
        !          1373:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy, exp_ex);
        !          1374:                }
        !          1375:        }
        !          1376: }
        !          1377: 
        !          1378: static void
        !          1379: gen_sub_co()
        !          1380: {
        !          1381:        for (const auto& t : test_arith_reg) {
        !          1382:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !          1383: 
        !          1384:                for (int cin = 0; cin <= 1; cin++) {
        !          1385:                        // 期待値
        !          1386:                        uint64 result = (uint64)vs1 + (~vs2) + 1;
        !          1387:                        uint32 exp_rd = (uint32)result;
        !          1388:                        uint32 exp_cy = result >> 32;
        !          1389:                        if (rd == 0) {
        !          1390:                                exp_rd = 0;
        !          1391:                        }
        !          1392:                        bool exp_ex = isovf_sub(vs1, vs2, result);
        !          1393:                        if (exp_ex) {
        !          1394:                                exp_cy = cin;
        !          1395:                        }
        !          1396: 
        !          1397:                        gen_addsub_test("sub.co",
        !          1398:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy, exp_ex);
        !          1399:                }
        !          1400:        }
        !          1401: }
        !          1402: 
        !          1403: static void
        !          1404: gen_sub_cio()
        !          1405: {
        !          1406:        for (const auto& t : test_arith_reg) {
        !          1407:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !          1408: 
        !          1409:                for (int cin = 0; cin <= 1; cin++) {
        !          1410:                        // 期待値
        !          1411:                        uint64 result = (uint64)vs1 + (~vs2) + cin;
        !          1412:                        uint32 exp_rd = (uint32)result;
        !          1413:                        uint32 exp_cy = result >> 32;
        !          1414:                        if (rd == 0) {
        !          1415:                                exp_rd = 0;
        !          1416:                        }
        !          1417:                        bool exp_ex = isovf_sub(vs1, vs2, result);
        !          1418:                        if (exp_ex) {
        !          1419:                                exp_cy = cin;
        !          1420:                        }
        !          1421: 
        !          1422:                        gen_addsub_test("sub.cio",
        !          1423:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy, exp_ex);
        !          1424:                }
        !          1425:        }
        !          1426: }
        !          1427: 
        !          1428: static void
        !          1429: gen_sub_imm()
        !          1430: {
        !          1431:        for (const auto& t : test_arith_imm) {
        !          1432:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !          1433: 
        !          1434:                for (int cin = 0; cin <= 1; cin++) {
        !          1435:                        // 期待値
        !          1436:                        uint64 result = (uint64)vs1 + (~imm) + 1;
        !          1437:                        uint32 exp_rd = (uint32)result;
        !          1438:                        uint32 exp_cy = cin;
        !          1439:                        if (rd == 0) {
        !          1440:                                exp_rd = 0;
        !          1441:                        }
        !          1442:                        bool exp_ex = isovf_sub(vs1, imm, result);
        !          1443:                        if (exp_ex) {
        !          1444:                                exp_cy = cin;
        !          1445:                        }
        !          1446: 
        !          1447:                        gen_addsub_test("sub",
        !          1448:                                rd, rs1, IMM, vs1, imm, cin, exp_rd, exp_cy, exp_ex);
        !          1449:                }
        !          1450:        }
        !          1451: }
        !          1452: 
        !          1453: static void
        !          1454: gen_subu()
        !          1455: {
        !          1456:        for (const auto& t : test_arith_reg) {
        !          1457:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !          1458: 
        !          1459:                for (int cin = 0; cin <= 1; cin++) {
        !          1460:                        // 期待値
        !          1461:                        uint64 result = (uint64)vs1 + (~vs2) + 1;
        !          1462:                        uint32 exp_rd = (uint32)result;
        !          1463:                        uint32 exp_cy = cin;
        !          1464:                        if (rd == 0) {
        !          1465:                                exp_rd = 0;
        !          1466:                        }
        !          1467: 
        !          1468:                        gen_addsub_test("subu",
        !          1469:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy);
        !          1470:                }
        !          1471:        }
        !          1472: }
        !          1473: 
        !          1474: static void
        !          1475: gen_subu_ci()
        !          1476: {
        !          1477:        for (const auto& t : test_arith_reg) {
        !          1478:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !          1479: 
        !          1480:                for (int cin = 0; cin <= 1; cin++) {
        !          1481:                        // 期待値
        !          1482:                        uint64 result = (uint64)vs1 + (~vs2) + cin;
        !          1483:                        uint32 exp_rd = (uint32)result;
        !          1484:                        uint32 exp_cy = cin;
        !          1485:                        if (rd == 0) {
        !          1486:                                exp_rd = 0;
        !          1487:                        }
        !          1488: 
        !          1489:                        gen_addsub_test("subu.ci",
        !          1490:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy);
        !          1491:                }
        !          1492:        }
        !          1493: }
        !          1494: 
        !          1495: static void
        !          1496: gen_subu_co()
        !          1497: {
        !          1498:        for (const auto& t : test_arith_reg) {
        !          1499:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !          1500: 
        !          1501:                for (int cin = 0; cin <= 1; cin++) {
        !          1502:                        // 期待値
        !          1503:                        uint64 result = (uint64)vs1 + (~vs2) + 1;
        !          1504:                        uint32 exp_rd = (uint32)result;
        !          1505:                        uint32 exp_cy = result >> 32;
        !          1506:                        if (rd == 0) {
        !          1507:                                exp_rd = 0;
        !          1508:                        }
        !          1509: 
        !          1510:                        gen_addsub_test("subu.co",
        !          1511:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy);
        !          1512:                }
        !          1513:        }
        !          1514: }
        !          1515: 
        !          1516: static void
        !          1517: gen_subu_cio()
        !          1518: {
        !          1519:        for (const auto& t : test_arith_reg) {
        !          1520:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !          1521: 
        !          1522:                for (int cin = 0; cin <= 1; cin++) {
        !          1523:                        // 期待値
        !          1524:                        uint64 result = (uint64)vs1 + (~vs2) + cin;
        !          1525:                        uint32 exp_rd = (uint32)result;
        !          1526:                        uint32 exp_cy = result >> 32;
        !          1527:                        if (rd == 0) {
        !          1528:                                exp_rd = 0;
        !          1529:                        }
        !          1530: 
        !          1531:                        gen_addsub_test("subu.cio",
        !          1532:                                rd, rs1, rs2, vs1, vs2, cin, exp_rd, exp_cy);
        !          1533:                }
        !          1534:        }
        !          1535: }
        !          1536: 
        !          1537: static void
        !          1538: gen_subu_imm()
        !          1539: {
        !          1540:        for (const auto& t : test_arith_imm) {
        !          1541:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !          1542: 
        !          1543:                for (int cin = 0; cin <= 1; cin++) {
        !          1544:                        // 期待値
        !          1545:                        uint64 result = (uint64)vs1 + (~imm) + 1;
        !          1546:                        uint32 exp_rd = (uint32)result;
        !          1547:                        uint32 exp_cy = cin;
        !          1548:                        if (rd == 0) {
        !          1549:                                exp_rd = 0;
        !          1550:                        }
        !          1551: 
        !          1552:                        gen_addsub_test("subu",
        !          1553:                                rd, rs1, IMM, vs1, imm, cin, exp_rd, exp_cy);
        !          1554:                }
        !          1555:        }
        !          1556: }
        !          1557: 
        !          1558: static void
        !          1559: gen_xor()
        !          1560: {
        !          1561:        for (const auto& t : test_arith_reg) {
        !          1562:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !          1563:                uint32 exp_rd = vs1 ^ vs2;
        !          1564:                if (rd == 0) {
        !          1565:                        exp_rd = 0;
        !          1566:                }
        !          1567:                gen_generic_test("xor", rd, rs1, rs2, vs1, vs2, exp_rd);
        !          1568:        }
        !          1569: }
        !          1570: 
        !          1571: static void
        !          1572: gen_xor_c()
        !          1573: {
        !          1574:        for (const auto& t : test_arith_reg) {
        !          1575:                VAR_TRI_REG(t, rd, rs1, rs2, vs1, vs2);
        !          1576:                uint32 exp_rd = vs1 ^ ~vs2;
        !          1577:                if (rd == 0) {
        !          1578:                        exp_rd = 0;
        !          1579:                }
        !          1580:                gen_generic_test("xor.c", rd, rs1, rs2, vs1, vs2, exp_rd);
        !          1581:        }
        !          1582: }
        !          1583: 
        !          1584: static void
        !          1585: gen_xor_imm()
        !          1586: {
        !          1587:        for (const auto& t : test_arith_imm) {
        !          1588:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !          1589:                uint32 exp_rd = vs1 ^ imm;
        !          1590:                if (rd == 0) {
        !          1591:                        exp_rd = 0;
        !          1592:                }
        !          1593:                gen_generic_test("xor", rd, rs1, IMM, vs1, imm, exp_rd);
        !          1594:        }
        !          1595: }
        !          1596: 
        !          1597: static void
        !          1598: gen_xor_u()
        !          1599: {
        !          1600:        for (const auto& t : test_arith_imm) {
        !          1601:                VAR_TRI_IMM(t, rd, rs1, vs1, imm);
        !          1602:                uint32 exp_rd = vs1 ^ (imm << 16);
        !          1603:                if (rd == 0) {
        !          1604:                        exp_rd = 0;
        !          1605:                }
        !          1606:                gen_generic_test("xor.u", rd, rs1, IMM, vs1, imm, exp_rd);
        !          1607:        }
        !          1608: }
        !          1609: 
        !          1610: 
        !          1611: 
        !          1612: //
        !          1613: // ここから出力用の処理
        !          1614: //
        !          1615: 
        !          1616: enum {
        !          1617:        G_ADD = 1,
        !          1618:        G_SUB,
        !          1619:        G_LOGICAL,
        !          1620:        G_BITFIELD,
        !          1621:        G_LDA,
        !          1622:        G_MULDIV,
        !          1623: };
        !          1624: 
        !          1625: // テスト一覧 (編集しやすいように実体は一番下に置いてある)
        !          1626: struct testentry {
        !          1627:        int group;
        !          1628:        const char *code;
        !          1629:        void (*genfunc)();
        !          1630:        const char *name;
        !          1631: };
        !          1632: extern std::vector<testentry> test_table;
        !          1633: 
        !          1634: // list の中に val がなければ追加する
        !          1635: template <class T>
        !          1636: static void append(std::vector<T>& list, const T& val)
        !          1637: {
        !          1638:        if (std::find(list.begin(), list.end(), val) == list.end()) {
        !          1639:                list.emplace_back(val);
        !          1640:        }
        !          1641: }
        !          1642: 
        !          1643: // ファイルオープンとクローズ (副作用のあるマクロ)
        !          1644: #define FOPEN(filename_)       do { \
        !          1645:        filename = filename_;   \
        !          1646:        tmpname = filename + ".tmp";    \
        !          1647:        fp = fopen(tmpname.c_str(), "w");       \
        !          1648:        if (fp == NULL) {       \
        !          1649:                err(1, "%s", tmpname.c_str());  \
        !          1650:        }       \
        !          1651:        out("/* This file was created by %s */\n", getprogname());      \
        !          1652:        out("\n");      \
        !          1653: } while (0)
        !          1654: #define FCLOSE()       do {    \
        !          1655:        fclose(fp);     \
        !          1656:        compare_and_move(tmpname, filename);    \
        !          1657: } while (0)
        !          1658: 
        !          1659: // テストアセンブリソースの出力共通部分
        !          1660: static void
        !          1661: print_test(const testentry& t)
        !          1662: {
        !          1663:        // グローバル変数にセット
        !          1664:        testname = t.name;
        !          1665:        testnum = 0;
        !          1666: 
        !          1667:        // テストの実体を出力
        !          1668:        t.genfunc();
        !          1669: 
        !          1670:        // テーブル
        !          1671:        out(".globl list_%s\n", testname);
        !          1672:        out("list_%s:\n", testname);
        !          1673:        for (int i = 0; i < testnum; i++) {
        !          1674:                out("\t.word    test_%s_%d\n", testname, i);
        !          1675:        }
        !          1676:        out("\t.word    0\n");
        !          1677:        out("\n");
        !          1678: }
        !          1679: 
        !          1680: static void compare_and_move(const std::string&, const std::string&);
        !          1681: 
        !          1682: int
        !          1683: main(int ac, char *av[])
        !          1684: {
        !          1685:        std::string filename;
        !          1686:        std::string tmpname;
        !          1687: 
        !          1688:        // テストパターンを用意
        !          1689:        for (const auto& rlist : reglist3) {
        !          1690:                auto rd  = (rlist >> 16) & 0xff;
        !          1691:                auto rs1 = (rlist >>  8) & 0xff;
        !          1692:                auto rs2 =  rlist        & 0xff;
        !          1693: 
        !          1694:                std::vector<uint32> *v_arith_s1 = (rs1 == 0) ? &v0 : &vlist_arith;
        !          1695:                std::vector<uint32> *v_arith_s2 = (rs2 == 0) ? &v0 : &vlist_arith;
        !          1696: 
        !          1697:                if (rs1 == rs2) {
        !          1698:                        for (const auto& vs1 : *v_arith_s1) {
        !          1699:                                Tuple5<uint32> val(rd, rs1, rs2, vs1, vs1);
        !          1700:                                append(test_arith_reg, val);
        !          1701:                        }
        !          1702:                } else {
        !          1703:                        for (const auto& vs1 : *v_arith_s1) {
        !          1704:                                for (const auto& vs2 : *v_arith_s2) {
        !          1705:                                        Tuple5<uint32> val(rd, rs1, rs2, vs1, vs2);
        !          1706:                                        append(test_arith_reg, val);
        !          1707:                                }
        !          1708:                        }
        !          1709:                }
        !          1710:        }
        !          1711:        for (const auto& rlist : reglist2) {
        !          1712:                auto rd  = (rlist >> 16) & 0xff;
        !          1713:                auto rs1 = (rlist >>  8) & 0xff;
        !          1714: 
        !          1715:                std::vector<uint32> *v_arith_s1 = (rs1 == 0) ? &v0 : &vlist_arith;
        !          1716: 
        !          1717:                for (const auto& vs1 : *v_arith_s1) {
        !          1718:                        for (const auto& imm : vlist_arith) {
        !          1719:                                if (imm <= 0xffff) {
        !          1720:                                        Tuple4<uint32> val(rd, rs1, vs1, imm);
        !          1721:                                        append(test_arith_imm, val);
        !          1722:                                }
        !          1723:                        }
        !          1724:                }
        !          1725:        }
        !          1726:        for (const auto& rlist : reglist3) {
        !          1727:                auto rd  = (rlist >> 16) & 0xff;
        !          1728:                auto rs1 = (rlist >>  8) & 0xff;
        !          1729:                auto rs2 =  rlist        & 0xff;
        !          1730: 
        !          1731:                std::vector<uint32> *v_bf = (rs1 == 0) ? &v0 : &vlist_bf;
        !          1732:                std::vector<uint32> *v_wo = (rs2 == 0) ? &v0 : &vlist_wo;
        !          1733: 
        !          1734:                if (rs1 == rs2) {
        !          1735:                        for (const auto& vs1 : *v_bf) {
        !          1736:                                Tuple5<uint32> val(rd, rs1, rs2, vs1, vs1);
        !          1737:                                append(test_bitfield_reg, val);
        !          1738:                        }
        !          1739:                        for (const auto& vs2 : *v_wo) {
        !          1740:                                Tuple5<uint32> val(rd, rs1, rs2, vs2, vs2);
        !          1741:                                append(test_bitfield_reg, val);
        !          1742:                        }
        !          1743:                } else {
        !          1744:                        for (const auto& vs1 : *v_bf) {
        !          1745:                                for (const auto& vs2 : *v_wo) {
        !          1746:                                        Tuple5<uint32> val(rd, rs1, rs2, vs1, vs2);
        !          1747:                                        append(test_bitfield_reg, val);
        !          1748:                                }
        !          1749:                        }
        !          1750:                }
        !          1751:        }
        !          1752:        for (const auto& rlist : reglist2) {
        !          1753:                auto rd  = (rlist >> 16) & 0xff;
        !          1754:                auto rs1 = (rlist >>  8) & 0xff;
        !          1755: 
        !          1756:                std::vector<uint32> *v_bf = (rs1 == 0) ? &v0 : &vlist_bf;
        !          1757: 
        !          1758:                for (const auto& vs1 : *v_bf) {
        !          1759:                        for (const auto& wo : vlist_wo) {
        !          1760:                                Tuple4<uint32> val(rd, rs1, vs1, wo);
        !          1761:                                append(test_bitfield_imm, val);
        !          1762:                        }
        !          1763:                }
        !          1764:        }
        !          1765:        for (const auto& rlist : reglist2) {
        !          1766:                auto rd  = (rlist >> 16) & 0xff;
        !          1767:                auto rs2 = (rlist >>  8) & 0xff;
        !          1768: 
        !          1769:                std::vector<uint32> v_ff;
        !          1770:                if (rs2 == 0) {
        !          1771:                        v_ff = v0;
        !          1772:                } else {
        !          1773:                        // vlist_arith とそれをビット反転したもの
        !          1774:                        for (const auto v : vlist_arith) {
        !          1775:                                v_ff.emplace_back(v);
        !          1776:                                v_ff.emplace_back(~v);
        !          1777:                        }
        !          1778:                }
        !          1779: 
        !          1780:                for (const auto& vs2 : v_ff) {
        !          1781:                        Tuple3<uint32> val(rd, rs2, vs2);
        !          1782:                        append(test_ff01, val);
        !          1783:                }
        !          1784:        }
        !          1785: 
        !          1786:        //
        !          1787:        // add.s を出力
        !          1788:        //
        !          1789:        FOPEN("optestm88k_add.s");
        !          1790:        for (const auto& t : test_table) {
        !          1791:                if (t.group == G_ADD) {
        !          1792:                        print_test(t);
        !          1793:                }
        !          1794:        }
        !          1795:        FCLOSE();
        !          1796: 
        !          1797:        //
        !          1798:        // sub.s を出力
        !          1799:        //
        !          1800:        FOPEN("optestm88k_sub.s");
        !          1801:        for (const auto& t : test_table) {
        !          1802:                if (t.group == G_SUB) {
        !          1803:                        print_test(t);
        !          1804:                }
        !          1805:        }
        !          1806:        FCLOSE();
        !          1807: 
        !          1808:        //
        !          1809:        // logical.s を出力
        !          1810:        //
        !          1811:        FOPEN("optestm88k_logical.s");
        !          1812:        for (const auto& t : test_table) {
        !          1813:                if (t.group == G_LOGICAL) {
        !          1814:                        print_test(t);
        !          1815:                }
        !          1816:        }
        !          1817:        FCLOSE();
        !          1818: 
        !          1819:        //
        !          1820:        // bitfield.s を出力
        !          1821:        //
        !          1822:        FOPEN("optestm88k_bitfield.s");
        !          1823:        for (const auto& t : test_table) {
        !          1824:                if (t.group == G_BITFIELD) {
        !          1825:                        print_test(t);
        !          1826:                }
        !          1827:        }
        !          1828:        FCLOSE();
        !          1829: 
        !          1830:        //
        !          1831:        // lda.s を出力
        !          1832:        //
        !          1833:        FOPEN("optestm88k_lda.s");
        !          1834:        for (const auto& t : test_table) {
        !          1835:                if (t.group == G_LDA) {
        !          1836:                        print_test(t);
        !          1837:                }
        !          1838:        }
        !          1839:        FCLOSE();
        !          1840: 
        !          1841:        //
        !          1842:        // muldiv.s を出力
        !          1843:        //
        !          1844:        FOPEN("optestm88k_muldiv.s");
        !          1845:        for (const auto& t : test_table) {
        !          1846:                if (t.group == G_MULDIV) {
        !          1847:                        print_test(t);
        !          1848:                }
        !          1849:        }
        !          1850:        FCLOSE();
        !          1851: 
        !          1852:        //
        !          1853:        // table.h を出力
        !          1854:        //
        !          1855:        FOPEN("optestm88k_table.h");
        !          1856:        out("#ifndef optestm88k_table_h\n");
        !          1857:        out("#define optestm88k_table_h\n");
        !          1858:        out("\n");
        !          1859:        // testcode は table_*.name を uniq したもの
        !          1860:        std::vector<std::string> test_code_list;
        !          1861:        for (const auto& t : test_table) {
        !          1862:                append(test_code_list, std::string(t.code));
        !          1863:        }
        !          1864:        for (const auto& name : test_code_list) {
        !          1865:                out("extern int test_%s(int *, int *);\n", name.c_str());
        !          1866:        }
        !          1867:        out("\n");
        !          1868: 
        !          1869:        for (const auto& t : test_table) {
        !          1870:                out("extern int *list_%s[];\n", t.name);
        !          1871:        }
        !          1872:        out("\n");
        !          1873:        out("#endif /* !optestm88k_table_h */\n");
        !          1874:        FCLOSE();
        !          1875: 
        !          1876:        //
        !          1877:        // table.c を出力
        !          1878:        //
        !          1879:        FOPEN("optestm88k_table.c");
        !          1880:        out("#include \"optestm88k_main.h\"\n");
        !          1881:        out("#include \"optestm88k_table.h\"\n");
        !          1882:        out("\n");
        !          1883:        out("struct testentry test_table[] = {\n");
        !          1884:        for (const auto& t : test_table) {
        !          1885:                out("   { test_%s,\tlist_%s,\t\"%s\" },\n", t.code, t.name, t.name);
        !          1886:        }
        !          1887:        out("   { NULL, NULL, NULL },\n");
        !          1888:        out("};\n");
        !          1889:        FCLOSE();
        !          1890: 
        !          1891:        return 0;
        !          1892: }
        !          1893: 
        !          1894: // src, dst のファイルが異なっていれば src を dst に rename する
        !          1895: static void
        !          1896: compare_and_move(const std::string& src, const std::string& dst)
        !          1897: {
        !          1898:        struct stat st;
        !          1899:        int r;
        !          1900:        bool update;
        !          1901: 
        !          1902:        update = false;
        !          1903:        r = stat(dst.c_str(), &st);
        !          1904:        if (r < 0) {
        !          1905:                // dst not found
        !          1906:                update = true;
        !          1907:        } else {
        !          1908:                // dst exists
        !          1909: 
        !          1910:                std::string cmd = "cmp -s " + src + " " + dst;
        !          1911:                r = system(cmd.c_str());
        !          1912:                if (r < 0) {
        !          1913:                        err(1, "system");
        !          1914:                }
        !          1915:                r = WEXITSTATUS(r);
        !          1916:                if (r > 1) {
        !          1917:                        errx(1, "cmp failed?");
        !          1918:                }
        !          1919: 
        !          1920:                if (r == 0) {
        !          1921:                        // src and dst are the same
        !          1922:                } else {
        !          1923:                        update = true;
        !          1924:                }
        !          1925:        }
        !          1926: 
        !          1927:        if (update) {
        !          1928:                // 違っていれば、src を dst に移動
        !          1929:                r = rename(src.c_str(), dst.c_str());
        !          1930:                if (r < 0) {
        !          1931:                        err(1, "rename: %s %s", src.c_str(), dst.c_str());
        !          1932:                }
        !          1933:                printf("Updated: %s\n", dst.c_str());
        !          1934:        } else {
        !          1935:                // 同じなら、今作った src のほうを消す
        !          1936:                r = remove(src.c_str());
        !          1937:                if (r < 0) {
        !          1938:                        err(1, "remove: %s", src.c_str());
        !          1939:                }
        !          1940:        }
        !          1941: }
        !          1942: 
        !          1943: //
        !          1944: // テスト一覧
        !          1945: //
        !          1946: #define T(group, code, name)   { group, code, gen_##name, #name }
        !          1947: std::vector<testentry> test_table = {
        !          1948:        T(G_ADD,                "addsub",       add),
        !          1949:        T(G_ADD,                "addsub",       add_ci),
        !          1950:        T(G_ADD,                "addsub",       add_co),
        !          1951:        T(G_ADD,                "addsub",       add_cio),
        !          1952:        T(G_ADD,                "addsub",       add_imm),
        !          1953:        T(G_ADD,                "addsub",       addu),
        !          1954:        T(G_ADD,                "addsub",       addu_ci),
        !          1955:        T(G_ADD,                "addsub",       addu_co),
        !          1956:        T(G_ADD,                "addsub",       addu_cio),
        !          1957:        T(G_ADD,                "addsub",       addu_imm),
        !          1958: 
        !          1959:        T(G_SUB,                "addsub",       sub),
        !          1960:        T(G_SUB,                "addsub",       sub_ci),
        !          1961:        T(G_SUB,                "addsub",       sub_co),
        !          1962:        T(G_SUB,                "addsub",       sub_cio),
        !          1963:        T(G_SUB,                "addsub",       sub_imm),
        !          1964:        T(G_SUB,                "addsub",       subu),
        !          1965:        T(G_SUB,                "addsub",       subu_ci),
        !          1966:        T(G_SUB,                "addsub",       subu_co),
        !          1967:        T(G_SUB,                "addsub",       subu_cio),
        !          1968:        T(G_SUB,                "addsub",       subu_imm),
        !          1969:        T(G_SUB,                "generic",      cmp),
        !          1970:        T(G_SUB,                "generic",      cmp_imm),
        !          1971: 
        !          1972:        T(G_LOGICAL,    "generic",      and),
        !          1973:        T(G_LOGICAL,    "generic",      and_c),
        !          1974:        T(G_LOGICAL,    "generic",      and_imm),
        !          1975:        T(G_LOGICAL,    "generic",      and_u),
        !          1976:        T(G_LOGICAL,    "generic",      mask_imm),
        !          1977:        T(G_LOGICAL,    "generic",      mask_u),
        !          1978:        T(G_LOGICAL,    "generic",      or),
        !          1979:        T(G_LOGICAL,    "generic",      or_c),
        !          1980:        T(G_LOGICAL,    "generic",      or_imm),
        !          1981:        T(G_LOGICAL,    "generic",      or_u),
        !          1982:        T(G_LOGICAL,    "generic",      xor),
        !          1983:        T(G_LOGICAL,    "generic",      xor_c),
        !          1984:        T(G_LOGICAL,    "generic",      xor_imm),
        !          1985:        T(G_LOGICAL,    "generic",      xor_u),
        !          1986: 
        !          1987:        T(G_BITFIELD,   "generic",      clr_imm),
        !          1988:        T(G_BITFIELD,   "generic",      clr_reg),
        !          1989:        T(G_BITFIELD,   "generic",      ext_imm),
        !          1990:        T(G_BITFIELD,   "generic",      ext_reg),
        !          1991:        T(G_BITFIELD,   "generic",      extu_imm),
        !          1992:        T(G_BITFIELD,   "generic",      extu_reg),
        !          1993:        T(G_BITFIELD,   "generic",      ff0),
        !          1994:        T(G_BITFIELD,   "generic",      ff1),
        !          1995:        T(G_BITFIELD,   "generic",      mak_imm),
        !          1996:        T(G_BITFIELD,   "generic",      mak_reg),
        !          1997:        T(G_BITFIELD,   "generic",      rot_imm),
        !          1998:        T(G_BITFIELD,   "generic",      rot_reg),
        !          1999:        T(G_BITFIELD,   "generic",      set_imm),
        !          2000:        T(G_BITFIELD,   "generic",      set_reg),
        !          2001: 
        !          2002:        T(G_LDA,                "addsub",       lda_imm),
        !          2003:        T(G_LDA,                "addsub",       lda_b_imm),
        !          2004:        T(G_LDA,                "addsub",       lda_h_imm),
        !          2005:        T(G_LDA,                "addsub",       lda_d_imm),
        !          2006:        T(G_LDA,                "addsub",       lda_reg),
        !          2007:        T(G_LDA,                "addsub",       lda_b_reg),
        !          2008:        T(G_LDA,                "addsub",       lda_h_reg),
        !          2009:        T(G_LDA,                "addsub",       lda_d_reg),
        !          2010:        T(G_LDA,                "addsub",       lda_scale),
        !          2011:        T(G_LDA,                "addsub",       lda_b_scale),
        !          2012:        T(G_LDA,                "addsub",       lda_h_scale),
        !          2013:        T(G_LDA,                "addsub",       lda_d_scale),
        !          2014: 
        !          2015:        T(G_MULDIV,             "generic",      mul),
        !          2016:        T(G_MULDIV,             "generic",      mul_imm),
        !          2017:        T(G_MULDIV,             "div",          div),
        !          2018:        T(G_MULDIV,             "div",          div_imm),
        !          2019:        T(G_MULDIV,             "div",          divu),
        !          2020:        T(G_MULDIV,             "div",          divu_imm),
        !          2021: };

unix.superglobalmegacorp.com

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