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