|
|
1.1 root 1: ;
2: ; nono
1.1.1.2 root 3: ; Copyright (C) 2020 nono project
1.1 root 4: ;
1.1.1.2 root 5: ; Redistribution and use in source and binary forms, with or without
6: ; modification, are permitted provided that the following conditions
7: ; are met:
8: ; 1. Redistributions of source code must retain the above copyright
9: ; notice, this list of conditions and the following disclaimer.
10: ; 2. Redistributions in binary form must reproduce the above copyright
11: ; notice, this list of conditions and the following disclaimer in the
12: ; documentation and/or other materials provided with the distribution.
13: ;
14: ; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15: ; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16: ; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17: ; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18: ; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19: ; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20: ; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
21: ; AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22: ; OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23: ; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24: ; SUCH DAMAGE.
1.1 root 25:
26: ; How to compile:
1.1.1.3 root 27: ; > has fmovemn.has
28: ; > hlk fmovemn.o si_util.o
1.1 root 29:
30: .xref hexstr_long
31: .include doscall.mac
1.1.1.4 ! root 32: .include iocscall.mac
1.1 root 33: .list
34: .cpu 68030
35:
36: PRINT .macro msg
1.1.1.4 ! root 37: pea.l msg
1.1 root 38: DOS _PRINT
39: addq.l #4,sp
40: .endm
41:
42: .text
43: .even
1.1.1.3 root 44:
1.1 root 45: <?php
46: // レジスタ割り当て
47: // d0-d1 work
1.1.1.4 ! root 48: // d4 d8(An,IX) の IX で使う。形式だけでいいので値は 0。
! 49: // d5 0=easy, $ffffffff=hard
1.1 root 50: // d6 ダイナミックモードでのレジスタ
51: // d7 1=検査対象命令でFライン例外がおきた
52: // その後は ok を表示するかどうかのカウント
53: // a0-a2 work
54: // a3 検査対象命令の次の位置 (Fライン例外から戻るのに使用)
55: // a4 元のFライン例外ハンドラ置き場
56: ?>
57: <?php
1.1.1.4 ! root 58:
! 59: // 第2ワードの下位バイトが FP 指定、3通りある。
! 60: //
! 61: // b7 b6 b5 b4 b3 b2 b1 b0
! 62: // -------------------------------
! 63: // FP7 FP6 FP5 FP4 FP3 FP2 FP1 FP0 : static pred
! 64: // FP0 FP1 FP2 FP3 FP4 FP5 FP6 FP7 : static ctrl
! 65: // 0 r r r 0 0 0 0 : dynamic
! 66: //
! 67: // ここでは常に %0110'0000 ($60) を指定しておき、
! 68: // プリデクリメントなら FP6-FP5、
! 69: // それ以外なら FP1-FP2、
! 70: // 動的レジスタ指定なら d6 を指すようにしておく。
! 71: // d6 の中は $30 (FP5-FP4 か FP2-FP3 になる) にしておく。
! 72: $d6 = "$30";
! 73:
1.1.1.3 root 74: $srctable = array(
1.1.1.4 ! root 75: // dir ,mode1 easy hard
! 76: 0 /* toFP, pred */ => ".......... !!m+!rxwp!",
! 77: 2 /* toFP, ctrl */ => "..m+.rxwp. !!m+!rxwp!",
! 78: 4 /* fromFP, pred */ => "....-..... !!m!-rxw!!",
! 79: 6 /* fromFP, ctrl */ => "..m..rxw.. !!m!-rxw!!",
1.1 root 80: );
1.1.1.4 ! root 81: $testlist = array();
! 82: $testnum = 0;
1.1.1.3 root 83: foreach ($srctable as $mode21 => $eastr) {
1.1.1.4 ! root 84: list ($easy_str, $hard_str) = preg_split('/\s+/', $eastr);
1.1.1.3 root 85: $easy_ea = preg_split("//", $easy_str, -1, PREG_SPLIT_NO_EMPTY);
86: $hard_ea = preg_split("//", $hard_str, -1, PREG_SPLIT_NO_EMPTY);
1.1.1.4 ! root 87: // mode0 ビットは dynamic or static。
1.1.1.3 root 88: for ($mode0 = 0; $mode0 <= 1; $mode0++) {
1.1.1.4 ! root 89: $mode = $mode21 + $mode0;
! 90: for ($i = 0; $i < 10; $i++) {
! 91: $eatype = substr("dam+-rxwpi", $i, 1);
! 92: $ee = $easy_ea[$i];
! 93: $eh = $hard_ea[$i];
! 94:
! 95: // 難しいので保留。
! 96: if ($i >= 7) {
! 97: continue;
1.1 root 98: }
1.1.1.4 ! root 99:
! 100: // 命令語。
! 101: $inst = 0xf200c060;
! 102: $inst |= eatype2word($eatype) << 16;
! 103: $inst |= $mode << 11;
! 104:
! 105: $test = array(
! 106: "num" => $testnum++,
! 107: "mode" => $mode,
! 108: "mem_to_fp" => (($mode & 4) == 0),
! 109: "is_pred" => (($mode & 2) == 0),
! 110: "dynamic" => (($mode & 1) != 0),
! 111:
! 112: "eatype" => $eatype,
! 113: "is_easy" => ($ee != '.'),
! 114: "is_trap" => ($eh == '!'),
! 115: "inst" => $inst,
! 116: );
! 117: $testlist[] = $test;
1.1 root 118: }
119: }
120: }
121: ?>
1.1.1.4 ! root 122: start:
! 123: clr.l -(sp)
! 124: DOS _SUPER
! 125: movem.l d4-d7/a2-a4,-(sp)
! 126: moveq.l #<?php print $d6; ?>,d6 ; Init D6 for dynamic
! 127: moveq.l #0,d4 ; Init D4 for d8(An,IX)
! 128: fmove.l d4,fpcr ; Init FPCR, especially round mode and round prec.
1.1 root 129:
1.1.1.4 ! root 130: ; rough argument check
! 131: cmpi.b #4,(a2)+ ; strlen(arg)<4 ?
! 132: bcs easymode
! 133: cmpi.l #$68617264,(a2) ; "hard"
! 134: bne easymode
1.1 root 135:
1.1.1.4 ! root 136: hardmode:
! 137: moveq.l #-1,d5
! 138: PRINT msg_hard(pc)
! 139: <?php
! 140: foreach ($testlist as $test) {
! 141: out(" bsr test_{$test["num"]}");
1.1 root 142: }
1.1.1.4 ! root 143: ?>
! 144: bsr test_nofpn
! 145: bsr test_illdyn
! 146: bra done
1.1 root 147:
1.1.1.4 ! root 148: easymode:
! 149: moveq.l #0,d5
! 150: PRINT msg_easy(pc)
! 151: <?php
! 152: foreach ($testlist as $test) {
! 153: if ($test["is_easy"]) {
! 154: out(" bsr test_{$test["num"]}");
! 155: }
1.1 root 156: }
1.1.1.4 ! root 157: ?>
1.1.1.3 root 158:
1.1.1.4 ! root 159: done:
! 160: movem.l (sp)+,d4-d7/a2-a4
! 161: DOS _EXIT
1.1 root 162:
1.1.1.4 ! root 163: <?php
! 164: // テスト本体を出力。
! 165: foreach ($testlist as $test) {
! 166: $dir = $test["mem_to_fp"] ? "to" : "from";
! 167: $pred = $test["is_pred"] ? "pred" : "ctrl";
! 168: $dyn = $test["dynamic"] ? "dyn" : "sta";
! 169: $hard = $test["is_easy"] ? "" : " (hard)";
! 170: out("; {$dir},{$pred},{$dyn},EA={$test["eatype"]}{$hard}");
! 171: out("test_%d:", $test["num"]);
! 172: // msg_test_* は先頭にテスト番号 "nn:ctrl;" が8バイトある。
! 173: // hard モードでは表示したいが easy モードでは表示したくない。
! 174: out(" moveq.l #-8,d0");
! 175: out(" and.w d5,d0");
! 176: out(" PRINT msg_test_{$test["num"]}+8(pc,d0.w)");
1.1 root 177:
1.1.1.4 ! root 178: if ($test["is_trap"]) {
! 179: test_trap($test);
! 180: } else {
! 181: if ($test["mem_to_fp"]) {
! 182: test_to($test);
! 183: } else {
! 184: test_from($test);
! 185: }
! 186: }
! 187: }
! 188: ?>
! 189: <?php
! 190: function test_trap($test)
1.1 root 191: {
1.1.1.4 ! root 192: // 実行
! 193: out_run($test, "");
1.1 root 194:
195: // 例外が起きるはずなので D7 が非ゼロなら成功(次へ)
196: out(" tst.l d7");
197: out(" bne @f");
1.1.1.4 ! root 198: out(" PRINT msg_fail_notrap(pc)");
1.1 root 199: out(" rts");
200: out("@@:");
1.1.1.4 ! root 201: out(" PRINT msg_oktrap(pc)");
1.1 root 202: out(" rts");
203: out("");
204: }
205:
1.1.1.4 ! root 206: function test_to($test)
1.1 root 207: {
1.1.1.4 ! root 208: $eatype = $test["eatype"];
1.1 root 209:
1.1.1.4 ! root 210: // FPn を初期化。(こっちでは使わない書き込みバッファも初期化されるけど)
! 211: out(" bsr init_from");
1.1 root 212:
1.1.1.4 ! root 213: // 実行。
! 214: out_run($test, "srcdata");
1.1 root 215:
216: // 例外は起きないはずなので D7 がゼロなら成功(次へ)
217: out(" tst.l d7");
218: out(" beq @f");
1.1.1.4 ! root 219: out(" PRINT msg_fail_trap(pc)");
1.1 root 220: out(" rts");
221: out("@@:");
222:
1.1.1.4 ! root 223: // An を照合する。
! 224: // (An) なら変化なし。
! 225: // -(An) なら実行前に進めてあるので +0 に戻る。
! 226: // (An)+ なら進む。
! 227: out(" lea.l srcdata%s(pc),a1", ($eatype == "+" ? "+24" : ""));
1.1 root 228: out(" cmp.l a1,a0");
229: out(" beq @f");
230: out(" pea.l msg_fail_addr(pc)");
231: out(" move.l a1,-(sp)");
232: out(" move.l a0,-(sp)");
233: out(" bsr result");
234: out(" lea.l 12(sp),sp");
235: out("@@:");
236:
1.1.1.4 ! root 237: // FPn を比較。
! 238: // 8本のうち、どこかの2本が (昇順か降順かで) 書き換わってる。
! 239: // $s1 が srcdata+0 が転送されたレジスタ番号、
! 240: // $s2 が srcdata+12 が転送されたレジスタ番号。
! 241: list ($s1, $s2) = get_fplist($test);
! 242: // ただし src が -(An) なら(undocumented)、レジスタは書き換わらないようだ。
! 243: if ($eatype == "-") {
! 244: $s1 = -1;
! 245: $s2 = -1;
! 246: }
1.1 root 247:
248: out(" lea.l workarea(pc),a2");
249: for ($i = 0; $i < 8; $i++) {
250: out(" ; compare FP${i}");
251: out(" pea.l msg_fail_fp{$i}(pc)");
1.1.1.4 ! root 252: if ($i == $s1) {
! 253: out(" pea.l srcdata(pc)");
! 254: } else if ($i == $s2) {
1.1 root 255: out(" pea.l srcdata+12(pc)");
256: } else {
257: out(" pea.l (initdata+%d*12)(pc)", $i);
258: }
259: out(" fmove.x fp{$i},(a2)");
260: out(" pea.l (a2)");
261: out(" bsr check_ext");
262: out(" lea.l 12(sp),sp");
263: }
1.1.1.4 ! root 264:
! 265: out("");
1.1 root 266: out(" tst.l d7");
267: out(" bne @f");
1.1.1.4 ! root 268: out(" PRINT msg_ok(pc)");
1.1 root 269: out("@@:");
270: out(" rts");
271: out("");
272: }
273:
1.1.1.4 ! root 274: function test_from($test)
1.1 root 275: {
1.1.1.4 ! root 276: $eatype = $test["eatype"];
1.1 root 277:
1.1.1.4 ! root 278: // FPn と書き込みバッファを初期化。
! 279: out(" bsr init_from");
1.1 root 280:
1.1.1.4 ! root 281: // 実行
! 282: out_run($test, "workarea");
1.1 root 283:
284: // 例外は起きないはずなので D7 がゼロなら成功(次へ)
285: out(" tst.l d7");
286: out(" beq @f");
1.1.1.4 ! root 287: out(" PRINT msg_fail_trap(pc)");
1.1 root 288: out(" rts");
289: out("@@:");
290:
1.1.1.4 ! root 291: // An を照合する。
! 292: // (An) なら変化なし。
! 293: // -(An) なら実行前に進めてあるので +0 に戻る。
! 294: // (An)+ なら進む。
! 295: out(" lea.l workarea%s(pc),a1", ($eatype == "+" ? "+24" : ""));
1.1 root 296: out(" cmp.l a1,a0");
297: out(" beq @f");
298: out(" pea.l msg_fail_addr(pc)");
299: out(" move.l a1,-(sp)");
300: out(" move.l a0,-(sp)");
301: out(" bsr result");
302: out(" lea.l 12(sp),sp");
303: out("@@:");
304:
1.1.1.4 ! root 305: // workarea に書き出されたのを initdata と比較。
! 306: if ($eatype == "+") {
! 307: // dst が (An)+ なら(undocumented)、謎な書き込みが行われるようだ。
! 308: // 法則はありそうだが分からないのでテストしないことにする。
! 309: out(" PRINT msg_skip_dst(pc)");
! 310: } else {
! 311: // workarea の若いアドレスから順に比較するが、
! 312: // FMOVEM fpnlist,-(An) の時 (predec の時ではなく eatype='-' の時) は
! 313: // 転送順にメモリを下っていくので、比較も下りながら行わないといけない。
! 314: list ($s1, $s2) = get_fplist($test);
! 315: $work = 0;
! 316: if ($eatype == "-") {
! 317: $work = 1 - $work;
! 318: }
! 319: out(" ; compare first one");
! 320: out(" pea.l msg_fail_1st(pc)");
! 321: out(" pea.l (initdata+%d*12)(pc)", $s1);
! 322: out(" pea.l (%d*12)(a1)", $work);
! 323: out(" bsr check_ext");
! 324: out(" lea.l 12(sp),sp");
! 325: $work = 1 - $work;
! 326: out(" ; compare second one");
! 327: out(" pea.l msg_fail_2nd(pc)");
! 328: out(" pea.l (initdata+%d*12)(pc)", $s2);
! 329: out(" pea.l (%d*12)(a1)", $work);
! 330: out(" bsr check_ext");
! 331: out(" lea.l 12(sp),sp");
! 332: }
1.1 root 333: out("");
1.1.1.4 ! root 334:
1.1 root 335: out(" tst.l d7");
336: out(" bne @f");
1.1.1.4 ! root 337: out(" PRINT msg_ok(pc)");
1.1 root 338: out("@@:");
339: out(" rts");
340: out("");
341: }
1.1.1.4 ! root 342:
! 343: // 1行を出力する。引数は printf のように fmt... で指定可能。
! 344: // 改行はこちらで付加する。
! 345: function out()
! 346: {
! 347: $args = func_get_args();
! 348: $fmt = array_shift($args);
! 349: print vsprintf($fmt, $args);
! 350: print "\n";
! 351: }
! 352:
! 353: // ターゲット実行部分を出力する。
! 354: function out_run($test, $label)
! 355: {
! 356: // EA ごとに命令前後にいろいろ必要。
! 357: // to/from どちらも EA (の先頭) が $label を指すようにする。
! 358: $pre = "";
! 359: $post = "";
! 360: if ($test["is_trap"] == false) {
! 361: switch ($test["eatype"]) {
! 362: case 'm':
! 363: case '+':
! 364: $pre = "lea.l {$label}(pc),a0";
! 365: break;
! 366: case '-':
! 367: $pre = "lea.l ({$label}+24)(pc),a0";
! 368: break;
! 369: case 'r': // d18(An)
! 370: // 賢いアセンブラだと 0(An) は (An) にしてしまうが、ここは
! 371: // 生の命令列を書き込んでいるので 0(An) は d16(An) 扱いになる。
! 372: $pre = "lea.l {$label}(pc),a0";
! 373: $post = ".dc.w 0";
! 374: break;
! 375: case 'x': // d8(An,IX) = 0(An,d4<0>)
! 376: $pre = "lea.l {$label}(pc),a0";
! 377: $post = ".dc.w $4000";
! 378: break;
! 379: case 'w': // Abs、ここでは Abs.L のみ
! 380: $post = ".dc.l {$label}";
! 381: break;
! 382: case 'p': // d8(PC,IX)
! 383: // これは難しいので保留。
! 384: break;
! 385: default:
! 386: break;
! 387: }
! 388: }
! 389: if (strlen($pre) > 0) {
! 390: out(" {$pre}");
! 391: }
! 392: out(" bsr set_fline");
! 393: out(" moveq.l #0,d7");
! 394: out(" lea.l @f,a3");
! 395: out(" .dc.l $%08x", $test["inst"]);
! 396: if (strlen($post) > 0) {
! 397: out(" {$post}");
! 398: }
! 399: out("@@:");
! 400: out(" bsr restore_fline");
! 401: }
! 402:
! 403: // ターゲットレジスタを返す。
! 404: // 制御モードとプリデクリメントとでビットの割り当てが違う。
! 405: // スタティックと動的ではあえて違うビットを割り当てている。
! 406: function get_fplist($test)
! 407: {
! 408: $fplist = array(
! 409: 0 /*pred, static */ => array(6, 5),
! 410: 1 /*pred, dynamic */ => array(5, 4),
! 411: 2 /*ctrl, static */ => array(1, 2),
! 412: 3 /*ctrl, dynamic */ => array(2, 3),
! 413: );
! 414: $mode = $test["mode"];
! 415: return $fplist[$mode & 3];
! 416: }
! 417:
! 418: // EA 種別文字から命令ワードに。n はすべて0
! 419: function eatype2word($eatype)
! 420: {
! 421: switch ($eatype) {
! 422: case 'd': return 000; // D0
! 423: case 'a': return 010; // A0
! 424: case 'm': return 020; // (A0)
! 425: case '+': return 030; // (A0)+
! 426: case '-': return 040; // -(A0)
! 427: case 'r': return 050; // d16(An)
! 428: case 'x': return 060; // d8(An,IX)
! 429: case 'w': return 071; // Abs.L
! 430: case 'p': return 072; // (PC,IX)
! 431: case 'i': return 074; // #imm
! 432: }
! 433: err("unknown eatype '{$eatype}'");
! 434: }
! 435:
! 436: // EA 種別文字からニーモニックに。
! 437: function eatype2mnem($eatype, $n = 0)
! 438: {
! 439: switch ($eatype) {
! 440: case 'd': return "d{$n}";
! 441: case 'a': return "a{$n}";
! 442: case 'm': return "(a{$n})";
! 443: case '+': return "(a{$n})+";
! 444: case '-': return "-(a{$n})";
! 445: case 'r': return "d16(a{$n})";
! 446: case 'x': return "d8(a{$n},ix)";
! 447: case 'w': return "abs";
! 448: case 'p': return "(pc,ix)";
! 449: case 'i': return "#imm";
1.1 root 450: }
1.1.1.4 ! root 451: return "";
! 452: }
1.1 root 453: ?>
1.1.1.4 ! root 454:
! 455: ; 空リストは正しく0個転送という扱いになる。
! 456: ; たぶん dynamic でも同様だろうけどもうテストしない。
! 457: test_nofpn:
! 458: PRINT msg_test_nofpn(pc)
! 459: bsr init_from
! 460: ; 実行
! 461: lea.l srcdata(pc),a0
! 462: bsr set_fline
1.1 root 463: moveq.l #0,d7
464: lea.l @f,a3
1.1.1.4 ! root 465: .dc.l $f218d000 ; fmovem.x (a0)+,nofpn
1.1 root 466: @@:
1.1.1.4 ! root 467: bsr restore_fline
! 468: ; 例外は起きないはずなので D7 がゼロなら成功(次へ)
1.1 root 469: tst.l d7
470: beq @f
1.1.1.4 ! root 471: PRINT msg_fail_trap(pc)
1.1 root 472: rts
473: @@:
1.1.1.4 ! root 474: ; An を照合する。(An)+ だけど変わらないはず。
! 475: lea.l srcdata(pc),a1
! 476: cmp.l a1,a0
! 477: beq @f
! 478: pea.l msg_fail_addr(pc)
! 479: move.l a1,-(sp)
! 480: move.l a0,-(sp)
! 481: bsr result
1.1 root 482: lea.l 12(sp),sp
1.1.1.4 ! root 483: @@:
! 484: lea.l workarea(pc),a2
! 485: <?php
! 486: // FPn を比較。
! 487: for ($i = 0; $i < 8; $i++) {
! 488: out(" ; compare FP${i}");
! 489: out(" pea.l msg_fail_fp{$i}(pc)");
! 490: out(" pea.l (initdata+%d*12)(pc)", $i);
! 491: out(" fmove.x fp{$i},(a2)");
! 492: out(" pea.l (a2)");
! 493: out(" bsr check_ext");
! 494: out(" lea.l 12(sp),sp");
! 495: }
! 496: ?>
1.1 root 497:
498: tst.l d7
499: bne @f
1.1.1.4 ! root 500: PRINT msg_ok(pc)
1.1 root 501: @@:
502: rts
503:
1.1.1.4 ! root 504: ; dynamic レジスタ指定の 0rrr_0000 の %0 のところに何か書かれてても無視。
! 505: test_illdyn:
! 506: PRINT msg_test_illdyn(pc)
! 507: bsr init_from
! 508: ; 実行
1.1 root 509: lea.l srcdata(pc),a0
510: moveq.l #$80,d6
511: moveq.l #0,d7
512: lea.l @f,a3
1.1.1.4 ! root 513: .dc.l $f210d86f ; fmovem.x (a0),d6
1.1 root 514: @@:
1.1.1.4 ! root 515: bsr restore_fline
! 516: ; 例外は起きないはずなので D7 がゼロなら成功(次へ)
1.1 root 517: tst.l d7
518: beq @f
1.1.1.4 ! root 519: PRINT msg_fail_trap(pc)
1.1 root 520: rts
521: @@:
1.1.1.4 ! root 522: ; An を照合する。
! 523: lea.l srcdata(pc),a1
! 524: cmp.l a1,a0
! 525: beq @f
! 526: pea.l msg_fail_addr(pc)
! 527: move.l a1,-(sp)
! 528: move.l a0,-(sp)
! 529: bsr result
1.1 root 530: lea.l 12(sp),sp
531: @@:
1.1.1.4 ! root 532: lea.l workarea(pc),a2
1.1 root 533: <?php
1.1.1.4 ! root 534: // FPn を比較。
! 535: for ($i = 0; $i < 8; $i++) {
! 536: out(" ; compare FP${i}");
! 537: out(" pea.l msg_fail_fp{$i}(pc)");
! 538: if ($i == 0) {
! 539: out(" pea.l srcdata(pc)");
! 540: } else {
! 541: out(" pea.l (initdata+%d*12)(pc)", $i);
! 542: }
! 543: out(" fmove.x fp{$i},(a2)");
! 544: out(" pea.l (a2)");
! 545: out(" bsr check_ext");
! 546: out(" lea.l 12(sp),sp");
! 547: }
1.1 root 548: ?>
1.1.1.3 root 549:
1.1.1.4 ! root 550: tst.l d7
! 551: bne @f
! 552: PRINT msg_ok(pc)
1.1.1.3 root 553: @@:
1.1.1.4 ! root 554: rts
1.1.1.3 root 555:
1.1.1.4 ! root 556: ; test_from 用の初期化。
! 557: ; FP0..7 を初期値で埋めるのと、書き込み先バッファを用意。
! 558: ; a0/a1 は破壊する。
! 559: init_from:
! 560: lea.l initdata(pc),a0
1.1 root 561: <?php
1.1.1.4 ! root 562: for ($i = 0; $i < 8; $i++) {
! 563: out(" fmove.x (a0)+,fp{$i}");
1.1 root 564: }
565: ?>
1.1.1.3 root 566:
1.1.1.4 ! root 567: ; 書き込み先を分かりやすいデータで初期化。
! 568: lea.l initdata_from(pc),a0
! 569: lea.l workarea(pc),a1
! 570: move.l (a0)+,(a1)+
! 571: move.l (a0)+,(a1)+
! 572: move.l (a0),(a1)+
! 573: subq.l #8,a0
! 574: move.l (a0)+,(a1)+
! 575: move.l (a0)+,(a1)+
! 576: move.l (a0),(a1)+
! 577: rts
1.1 root 578:
579: ; 結果表示
580: ; スタックには、メッセージ、期待値、実際の値の順で積む。
581: result:
582: link a6,#0
583: movem.l d0/a0,-(sp)
584:
585: move.l 8+8(a6),-(sp)
586: DOS _PRINT
587: addq.l #4,sp
588:
589: move.l 8+4(a6),d0
590: lea.l buf(pc),a0
591: bsr hexstr_long
1.1.1.4 ! root 592: PRINT buf(pc)
! 593: PRINT msg_but(pc)
1.1 root 594:
595: move.l 8+0(a6),d0
596: lea.l buf(pc),a0
597: bsr hexstr_long
1.1.1.4 ! root 598: PRINT buf(pc)
! 599: PRINT msg_crlf(pc)
1.1 root 600:
601: addq.l #1,d7 ; errcnt
602: movem.l (sp)+,d0/a0
603: unlk a6
604: rts
605:
606: ; 拡張精度の比較と結果表示。
607: ; 一致したら何もせず帰る。一致しなければエラーメッセージを表示。
608: ; スタックには、(エラー時の)メッセージ、期待値、実際の値の順で積む
609: check_ext:
610: link a6,#0
611: movem.l d0/a0-a2,-(sp)
612:
613: move.l 8+4(a6),a1
614: move.l 8+0(a6),a2
615: cmpm.l (a1)+,(a2)+
616: bne @f
617: cmpm.l (a1)+,(a2)+
618: bne @f
619: cmpm.l (a1)+,(a2)+
620: bne @f
621: ; equal
622: bra check_ext_done
623:
624: @@: ; not equal
1.1.1.4 ! root 625: ; テスト名を表示した行に続けてこれを表示すると折り返してしまうので、
! 626: ; これが1件目のエラーなら先に一つ改行する。
! 627: tst.l d7
! 628: bne @f
! 629: PRINT msg_crlf(pc)
! 630: @@:
1.1 root 631: move.l 8+8(a6),-(sp)
632: DOS _PRINT
633: addq.l #4,sp
634:
635: lea.l buf(pc),a0
636: move.l 8+4(a6),a1
637: move.l (a1)+,d0
638: bsr hexstr_long
639: move.b #'_',(a0)+
640: move.l (a1)+,d0
641: bsr hexstr_long
642: move.b #'_',(a0)+
643: move.l (a1),d0
644: bsr hexstr_long
1.1.1.4 ! root 645: PRINT buf(pc)
! 646: PRINT msg_but(pc)
1.1 root 647:
648: lea.l buf(pc),a0
649: move.l 8+0(a6),a2
650: move.l (a2)+,d0
651: bsr hexstr_long
652: move.b #'_',(a0)+
653: move.l (a2)+,d0
654: bsr hexstr_long
655: move.b #'_',(a0)+
656: move.l (a2),d0
657: bsr hexstr_long
1.1.1.4 ! root 658: PRINT buf(pc)
! 659: PRINT msg_crlf(pc)
1.1 root 660:
661: addq.l #1,d7 ; errcnt
662: check_ext_done:
663: movem.l (sp)+,d0/a0-a2
664: unlk a6
665: rts
666:
1.1.1.4 ! root 667: ; Fライン例外をテスト用のものに差し替える。
! 668: ; 変更前のアドレスを a4 に格納する。
! 669: ; a1 は破壊する。
! 670: set_fline:
! 671: movem.l d0-d1,-(sp)
! 672: moveq.l #$b,d1
! 673: lea.l fline_handler(pc),a1
! 674: IOCS _B_INTVCS
! 675: movea.l d0,a4
! 676: movem.l (sp)+,d0-d1
! 677: rts
! 678:
! 679: ; Fライン例外を元に戻す。
! 680: ; a1 は破壊する。
! 681: restore_fline:
! 682: movem.l d0-d1,-(sp)
! 683: moveq.l #$b,d1
! 684: movea.l a4,a1
! 685: IOCS _B_INTVCS
! 686: movem.l (sp)+,d0-d1
! 687: rts
! 688:
1.1 root 689: ; Fライン例外ハンドラ
690: ; a3 に戻りアドレスをセットしてあること
691: ; d7 を 1 にして帰る
692: fline_handler:
693: moveq.l #1,d7
694: move.l a3,2(sp)
695: rte
696:
697: ; FPn を埋める初期値
698: initdata:
1.1.1.4 ! root 699: .dc.l $00010000, $80888888, $88888888
! 700: .dc.l $00010000, $80111111, $11111111
! 701: .dc.l $00010000, $80222222, $22222222
! 702: .dc.l $00010000, $80333333, $33333333
! 703: .dc.l $00010000, $80444444, $44444444
! 704: .dc.l $00010000, $80555555, $55555555
! 705: .dc.l $00010000, $80666666, $66666666
! 706: .dc.l $00010000, $80777777, $77777777
1.1 root 707:
708: ; ターゲットの FPn に転送するデータ
709: srcdata:
1.1.1.4 ! root 710: .dc.l $3fff0000, $80aaaaaa, $aaaaaaaa
! 711: .dc.l $3fff0000, $80bbbbbb, $bbbbbbbb
1.1 root 712:
1.1.1.4 ! root 713: ; 書き込み先の初期化用データ
! 714: initdata_from:
! 715: .dc.l $90919293, $94959697, $98999a9b
1.1 root 716:
1.1.1.3 root 717: msg_hard: .dc.b "hard mode",$d,$a,0
718: msg_easy: .dc.b "easy mode",$d,$a,0
1.1 root 719: msg_oktrap: .dc.b $9,"ok(trap)",$d,$a,0, 0,0
720: msg_fail_notrap: .dc.b $9,"FAIL: trap expected but not occured",$d,$a,0
721: msg_fail_trap: .dc.b $9,"FAIL: unexpected trap occured",$d,$a,0
1.1.1.4 ! root 722: msg_skip_dst: .dc.b $9,"SKIP(dstmem)",0
1.1 root 723:
724: msg_ok: .dc.b $9,"ok",$d,$a,0
725: msg_fail_fp0: .dc.b $9,"FAIL: fp0 expects ",0
726: msg_fail_fp1: .dc.b $9,"FAIL: fp1 expects ",0
727: msg_fail_fp2: .dc.b $9,"FAIL: fp2 expects ",0
728: msg_fail_fp3: .dc.b $9,"FAIL: fp3 expects ",0
729: msg_fail_fp4: .dc.b $9,"FAIL: fp4 expects ",0
730: msg_fail_fp5: .dc.b $9,"FAIL: fp5 expects ",0
731: msg_fail_fp6: .dc.b $9,"FAIL: fp6 expects ",0
732: msg_fail_fp7: .dc.b $9,"FAIL: fp7 expects ",0
733: msg_fail_1st: .dc.b $9,"FAIL: 1st expects ",0
734: msg_fail_2nd: .dc.b $9,"FAIL: 2nd expects ",0
735: msg_fail_addr: .dc.b $9,"FAIL: an expects ",0
736: msg_but: .dc.b " but ",0
737: msg_crlf: .dc.b $d,$a,0
738:
739: <?php
1.1.1.4 ! root 740: foreach ($testlist as $test) {
! 741: $name = sprintf("%02d:", $test["num"]);
! 742: if ($test["is_pred"]) {
! 743: $name .= "pred;";
! 744: } else {
! 745: $name .= "ctrl;";
! 746: }
! 747: $name .= "fmovem.x ";
! 748: $m = eatype2mnem($test["eatype"]);
! 749: $f = get_fplist($test);
! 750: sort($f);
! 751: if ($test["dynamic"]) {
! 752: $r = "d6<fp{$f[0]}-fp{$f[1]}>";
! 753: } else {
! 754: $r = "fp{$f[0]}-fp{$f[1]}";
! 755: }
! 756: if ($test["mem_to_fp"]) {
! 757: $name .= "{$m},{$r}";
! 758: } else {
! 759: $name .= "{$r},{$m}";
! 760: }
! 761: out("msg_test_{$test["num"]}: .dc.b \"{$name}\",0");
1.1 root 762: }
763: ?>
1.1.1.4 ! root 764: msg_test_nofpn: .dc.b "fmovem.x (a0)+,nofpn",0
! 765: msg_test_illdyn:.dc.b "fmovem.x (a0),d6<FP0>_bit",0
1.1 root 766:
767: .data
768: .even
769: workarea: .ds.b 24
1.1.1.3 root 770: buf: .ds.b 64
1.1 root 771:
772: .end start
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.