|
|
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: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.