--- nono/exp/optestm88k/optestm88k_code.s 2026/04/29 17:04:57 1.1 +++ nono/exp/optestm88k/optestm88k_code.s 2026/04/29 17:05:04 1.1.1.3 @@ -6,6 +6,25 @@ | アセンブラのテストコードのうち固定部分 +| main.c と揃えること + .equiv exception_occurred, (0 * 4) + .equiv exception_expected, (1 * 4) + .equiv expected_val, (2 * 4) + .equiv expected_val2, (3 * 4) + .equiv actual_val, (4 * 4) + .equiv actual_val2, (5 * 4) + +| RoundMode を設定 +| 入力: %r12 に設定したい Round Mode (bit15, 14 の位置) +| 破壊: %r6 +set_rnd_mode: + fldcr %r6, %fcr63 + and %r6, %r6, 0x3fff + or %r6, %r6, %r12 + fstcr %r6, %fcr63 + jmp %r1 + + | 汎用演算命令のテストベース | | r3 の指す先は @@ -14,24 +33,28 @@ .globl test_generic test_generic: | 例外は起きない - st %r0, %r2, 4 + st %r0, %r2, exception_expected | r1 を退避してテストコードへジャンプ - or %r9, %r0, %r1 + or %r5, %r0, %r1 addu %r12, %r3, 4 jsr %r12 | test - or %r1, %r0, %r9 + or %r1, %r0, %r5 - | r2[0] の指す先(exception_occurred) は例外が起きたら 1、起きなければ 0。 + | 結果表示用 + st %r6, %r2, expected_val + st %r8, %r2, actual_val + + | r2[exception_occurred] は例外が起きたら 1、起きなければ 0。 | これを最後に r2 はつぶして、戻り値として使う。 - ld %r2, %r2, 0 + ld %r2, %r2, exception_occurred | rD をチェック。 - | 実行結果は r11 に、期待値は r3[0] に入っている。 + | 実行結果は r8 に、期待値は r3[0] に入っている。 | cmp 結果の bit0 は %0 なので直前の例外結果と OR できる。 - ld %r10, %r3, 0 - cmp %r10, %r10, %r11 - or %r2, %r2, %r10 + ld %r6, %r3, 0 + cmp %r6, %r6, %r8 + or %r2, %r2, %r6 | ここで r2 は | 例外の期待と結果が異なれば bit0(0x01) がセットされている、 @@ -52,7 +75,7 @@ test_generic: test_addsub: | 例外期待の有無を _main.c の exception_expected に書き戻す ld.bu %r12, %r3, 6 - st %r12, %r2, 4 + st %r12, %r2, exception_expected | Cy の初期値をセット | cin == 1 ならセット、cin == 0 ならクリア @@ -61,24 +84,28 @@ test_addsub: addu.co %r0, %r12, %r13 | r1 を退避してテストコードへジャンプ - or %r9, %r0, %r1 + or %r5, %r0, %r1 addu %r12, %r3, 8 jsr %r12 | test - or %r1, %r0, %r9 + or %r1, %r0, %r5 + + | 結果表示用 + st %r6, %r2, expected_val + st %r8, %r2, actual_val - | r2[0] の指す先(exception_occurred) は例外が起きたら 1、起きなければ 0。 + | r2[exception_occurred] は例外が起きたら 1、起きなければ 0。 | r3.b[6] は例外期待なら 1、例外が起きないことを期待なら 0。 | よって r2[0] と r3[2] を XOR して 0 になれば成功。 | これを最後に r2 はつぶして、戻り値として使う。 - ld %r2, %r2, 0 + ld %r2, %r2, exception_occurred ld.bu %r13, %r3, 6 xor %r2, %r2, %r13 | rD をチェック。 - | 実行結果は r11 に、期待値は r10 に入っている。 + | 実行結果は r8 に、期待値は r6 に入っている。 | cmp 結果の bit0 は %0 なので直前の例外結果と OR できる。 - cmp %r11, %r11, %r10 - or %r2, %r2, %r11 + cmp %r8, %r8, %r6 + or %r2, %r2, %r8 | Cy をチェック。 | 実行結果は Cy に、期待値は r3.b[5] にある。 @@ -97,34 +124,37 @@ test_addsub: | div 命令のテストベース | | r3 の指す先は -| +0 [0] = exp_rd (rD の期待値) -| +4 [1] = exp_ex (Integer Divide 例外を期待するなら 2) -| +8 [3] ここからテストコード (可変長) +| +0 [0] = exp_ex (Integer Divide 例外を期待するなら 2) +| +4 ここからテストコード (可変長) .globl test_div test_div: | 例外期待の有無を _main.c の exception_expected に書き戻す - ld %r12, %r3, 4 - st %r12, %r2, 4 + ld %r12, %r3, 0 + st %r12, %r2, exception_expected | r1 を退避してテストコードへジャンプ - or %r9, %r0, %r1 - addu %r12, %r3, 8 + or %r5, %r0, %r1 + addu %r12, %r3, 4 jsr %r12 | test - or %r1, %r0, %r9 + or %r1, %r0, %r5 - | r2[0] の指す先(exception_occurred) は IntDiv 例外が起きたら 2。 - | r3[1] は IntDiv 例外期待なら 2、起きないことを期待なら 0。 - | よって r2[0] と r3[1] を XOR して 0 になれば成功。 + | 結果表示用 + st %r6, %r2, expected_val + st %r8, %r2, actual_val + + | r2[exception_occurred] は IntDiv 例外が起きたら 2。 + | r3[0] は IntDiv 例外期待なら 2、起きないことを期待なら 0。 + | よって r2[exception_occurred] と r3[0] を XOR して 0 になれば成功。 | これを最後に r2 はつぶして戻り値として使う。 - ld %r2, %r2, 0 - ld %r13, %r3, 4 + ld %r2, %r2, exception_occurred + ld %r13, %r3, 0 xor %r2, %r2, %r13 | rD をチェック。 - | 実行結果は r11 に、期待値は r10 に入っている。 + | 実行結果は r8 に、期待値は r6 に入っている。 | cmp 結果の bit0-1 は %0 なので直前の例外結果と OR できる。 - cmp %r11, %r11, %r10 - or %r2, %r2, %r11 + cmp %r8, %r8, %r6 + or %r2, %r2, %r8 | ここで r2 は | 例外の期待と結果が異なれば bit0-1(0x03) がセットされている、 @@ -132,3 +162,97 @@ test_div: | 0x0b で AND すると、全部成功すれば 0、そうでなければ非 0 になる。 and %r2, %r2, 0xb jmp %r1 + +| FP 命令(結果が 32bit の場合)のテストベース +| +| r3 の指す先は +| +0.w [0] = RoundMode +| +2.w [1] = exp_ex (例外を期待するなら 0x1000) +| +4 ここからテストコード +.globl test_fop_s +test_fop_s: + | 例外期待の有無を _main.c の exception_expected に書き戻す + ld.h %r12, %r3, 2 + st %r12, %r2, exception_expected + + | r1 を退避して.. + or %r5, %r0, %r1 + | RoundMode を設定してテストコードへジャンプ + ld.h %r12, %r3, 0 + bsr set_rnd_mode + addu %r12, %r3, 4 + jsr %r12 | test + or %r1, %r0, %r5 + + | 結果表示用 + st %r6, %r2, expected_val + st %r8, %r2, actual_val + + | r2[exception_occurred] は FltInv 例外が起きたら 0x1000。 + | r3[1] は FltInv 例外期待なら 0x1000、起きないことを期待なら 0。 + | よって r2[exception_occurred] と r3[1] を XOR して 0 になれば成功。 + | これを最後に r2 はつぶして戻り値として使う。 + ld %r2, %r2, exception_occurred + ld.h %r13, %r3, 2 + xor %r2, %r2, %r13 + + | rD をチェック。 + | 実行結果は r8 に、期待値は r6 に入っている。 + cmp %r6, %r6, %r8 + or %r2, %r2, %r6 + + | ここで r2 は + | 例外の期待と結果が異なれば bit12(0x1000) がセットされている、 + | 演算の期待と結果が異なれば bit3(0x08) がセットされているので + | 0x1008 で AND すると、全部成功すれば 0、そうでなければ非 0 になる。 + and %r2, %r2, 0x1008 + jmp %r1 + +| FP 命令(結果が 64bit の場合)のテストベース +| +| r3 の指す先は +| +0.w [0] = RoundMode +| +2.w [1] = exp_ex (例外を期待するなら 0x1000) +| +4 ここからテストコード +.globl test_fop_d +test_fop_d: + | 例外期待の有無を _main.c の exception_expected に書き戻す + ld.h %r12, %r3, 2 + st %r12, %r2, exception_expected + + | r1 を退避して.. + or %r5, %r0, %r1 + | RoundMode を設定してテストコードへジャンプ + ld.h %r12, %r3, 0 + bsr set_rnd_mode + addu %r12, %r3, 4 + jsr %r12 | test + or %r1, %r0, %r5 + + | 結果表示用 + st %r6, %r2, expected_val + st %r7, %r2, expected_val2 + st %r8, %r2, actual_val + st %r9, %r2, actual_val2 + + | r2[exception_occurred] は FltInv 例外が起きたら 0x1000。 + | r3[1] は FltInv 例外期待なら 0x1000、起きないことを期待なら 0。 + | よって r2[exception_occurred] と r3[1] を XOR して 0 になれば成功。 + | これを最後に r2 はつぶして戻り値として使う。 + ld %r2, %r2, exception_occurred + ld.h %r13, %r3, 2 + xor %r2, %r2, %r13 + + | rD, rD+1 をチェック。 + | 実行結果は r8(,r9) に、期待値は r6(,r7) に入っている。 + cmp %r6, %r6, %r8 + cmp %r7, %r7, %r9 + or %r2, %r2, %r6 + or %r2, %r2, %r7 + + | ここで r2 は + | 例外の期待と結果が異なれば bit12(0x1000) がセットされている、 + | 演算の期待と結果が異なれば bit3(0x08) がセットされているので + | 0x1008 で AND すると、全部成功すれば 0、そうでなければ非 0 になる。 + and %r2, %r2, 0x1008 + jmp %r1