|
|
1.1 ! root 1: ; ! 2: ; nono ! 3: ; Copyright (C) 2025 nono project ! 4: ; ! 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. ! 25: ! 26: ; FMOVE.? FPn,<ea> で例外の起きる <ea> を確認する。 ! 27: ; あと不当命令のところで命令を処理してしまわないことを確認する。 ! 28: ! 29: ; How to compile ! 30: ; > has fmoveto.has ! 31: ; > hlk fmoveto.o ! 32: ! 33: .include doscall.mac ! 34: .include iocscall.mac ! 35: .list ! 36: .cpu 68030 ! 37: ! 38: PRINT .macro msg ! 39: pea.l msg ! 40: DOS _PRINT ! 41: addq.l #4,sp ! 42: .endm ! 43: ! 44: .text ! 45: .even ! 46: ! 47: <?php ! 48: // レジスタ割り当て ! 49: // d0-d3 work ! 50: // d4 d8(An,IX) の IX で使う。形式だけでいいので値は 0。 ! 51: // d7 1=検査対象命令でFライン例外がおきた ! 52: // 2=FPSR の condition byte が変化した ! 53: // a0-a1 work ! 54: // a2 結果(1テストにつき、期待値.b と結果.b)バッファ ! 55: // a3 検査対象命令の次の位置 (Fライン例外から戻るのに使用) ! 56: // a4 元のFライン例外ハンドラ置き場 ! 57: ?> ! 58: <?php ! 59: // サイズ名から dstfmt への変換。 ! 60: $sizelist = array( ! 61: "B" => 6, ! 62: "W" => 4, ! 63: "L" => 0, ! 64: "S" => 1, ! 65: "D" => 5, ! 66: "X" => 2, ! 67: "P" => 3, ! 68: ); ! 69: // EA 種別と、テストに使うモード(6ビット)、表示名。 ! 70: $ealist = array( ! 71: "d" => array("mode" => 006, "name" => "Dn"), // d6 を使う ! 72: "a" => array("mode" => 010, "name" => "An"), ! 73: "m" => array("mode" => 020, "name" => "(An)"), ! 74: "mi" => array("mode" => 030, "name" => "(An)+"), ! 75: "md" => array("mode" => 040, "name" => "-(An)"), ! 76: "r" => array("mode" => 050, "name" => "d16(An)"), ! 77: "x" => array("mode" => 060, "name" => "d8(An,IX)"), ! 78: // ちょっとテストが難しいので保留。 ! 79: //"w" => array("mode" => 071, "name" => "Abs", ! 80: "p" => array("mode" => 072, "name" => "(PC)"), ! 81: "i" => array("mode" => 074, "name" => "#imm"), ! 82: "o" => array("mode" => 075, "name" => "075"), ! 83: ); ! 84: ! 85: // "exp_int", "exp_mem" はそれぞれ .BWLS と .DXP の場合の期待値。 ! 86: // 下位 4 ビットが FPSR の Condition Byte で、 ! 87: // 4ビット目はトラップの有無、%0 なら通過、%1 ならトラップを表す。 ! 88: // Condition Byte には通常絶対成立しない $b を入れておいて ! 89: // これが変化するかしないかを調べる。 ! 90: $testlist = array(); ! 91: ! 92: // FMOVE.? FPn,<ea> ! 93: $table = array( ! 94: // +----- .B/W/L/S の期待値 (0が通過、1がトラップ) ! 95: // | +-- .D/X/P の期待値 (〃) ! 96: "d" => array(0, 1), ! 97: "a" => array(1, 1), ! 98: "m" => array(0, 0), ! 99: "mi" => array(0, 0), ! 100: "md" => array(0, 0), ! 101: "r" => array(0, 0), ! 102: "x" => array(0, 0), ! 103: "w" => array(0, 0), ! 104: "p" => array(1, 1), ! 105: "i" => array(1, 1), ! 106: "o" => array(1, 1), ! 107: ); ! 108: foreach ($table as $eatype => $exparray) { ! 109: list ($exp_int, $exp_mem) = $exparray; ! 110: if (!isset($ealist[$eatype])) continue; ! 111: $eamode = $ealist[$eatype]['mode']; ! 112: $ei = ($exp_int == 1 ? 0x1b : 0x0b); ! 113: $em = ($exp_mem == 1 ? 0x1b : 0x0b); ! 114: $test = array( ! 115: "opname" => "fmove", ! 116: "is_store" => true, ! 117: "eatype" => $eatype, ! 118: "eamode" => $eamode, ! 119: "inst" => 0xf2006000 | ($eamode << 16), ! 120: "has_dstfmt"=> true, ! 121: "expected" => array( ! 122: "B" => $ei, ! 123: "W" => $ei, ! 124: "L" => $ei, ! 125: "S" => $ei, ! 126: "D" => $em, ! 127: "X" => $em, ! 128: "P" => $em, ! 129: ), ! 130: ); ! 131: $testlist[] = $test; ! 132: } ! 133: ! 134: // Fgen.? <ea>,FPn (代表として FMOVE を使う) ! 135: $table = array( ! 136: // +----- .B/W/L/S の期待値 (0が通過、1がトラップ) ! 137: // | +-- .D/X/P の期待値 (〃) ! 138: "d" => array(0, 1), ! 139: "a" => array(1, 1), ! 140: "m" => array(0, 0), ! 141: "mi" => array(0, 0), ! 142: "md" => array(0, 0), ! 143: "r" => array(0, 0), ! 144: "x" => array(0, 0), ! 145: "w" => array(0, 0), ! 146: "p" => array(0, 0), ! 147: "i" => array(0, 0), ! 148: "o" => array(1, 1), ! 149: ); ! 150: foreach ($table as $eatype => $exparray) { ! 151: list ($exp_int, $exp_mem) = $exparray; ! 152: if (!isset($ealist[$eatype])) continue; ! 153: $eamode = $ealist[$eatype]['mode']; ! 154: $ei = ($exp_int == 1 ? 0x1b : 0x04); ! 155: $em = ($exp_mem == 1 ? 0x1b : 0x04); ! 156: $test = array( ! 157: "opname" => "fgen", ! 158: "is_store" => false, ! 159: "eatype" => $eatype, ! 160: "eamode" => $eamode, ! 161: "inst" => 0xf2004000 | ($eamode << 16), ! 162: "has_dstfmt"=> true, ! 163: "expected" => array( ! 164: "B" => $ei, ! 165: "W" => $ei, ! 166: "L" => $ei, ! 167: "S" => $ei, ! 168: "D" => $em, ! 169: "X" => $em, ! 170: "P" => $em, ! 171: ), ! 172: ); ! 173: $testlist[] = $test; ! 174: } ! 175: // FSCALE.? <ea>,FPn は NetBSD FPE が Fgen とは別パスで実装してあるので ! 176: // 同じ結果になることを確認する。 ! 177: foreach ($table as $eatype => $exparray) { ! 178: list ($exp_int, $exp_mem) = $exparray; ! 179: if (!isset($ealist[$eatype])) continue; ! 180: $eamode = $ealist[$eatype]['mode']; ! 181: $ei = ($exp_int == 1 ? 0x1b : 0x04); ! 182: $em = ($exp_mem == 1 ? 0x1b : 0x04); ! 183: $test = array( ! 184: "opname" => "fscale", ! 185: "is_store" => false, ! 186: "eatype" => $eatype, ! 187: "eamode" => $eamode, ! 188: "inst" => 0xf2004026 | ($eamode << 16), ! 189: "has_dstfmt"=> true, ! 190: "expected" => array( ! 191: "B" => $ei, ! 192: "W" => $ei, ! 193: "L" => $ei, ! 194: "S" => $ei, ! 195: "D" => $em, ! 196: "X" => $em, ! 197: "P" => $em, ! 198: ), ! 199: ); ! 200: $testlist[] = $test; ! 201: } ! 202: ! 203: // FScc.B <ea>。サイズは .B のみ。 ! 204: // An と (PC), #imm に相当するところには FDBcc、FTRAPcc がいるので ! 205: // 検査しない(出来ない)。 ! 206: $table = array( ! 207: // .B の期待値 (0が通過、1がトラップ) ! 208: "d" => 0, ! 209: "m" => 0, ! 210: "mi" => 0, ! 211: "md" => 0, ! 212: "r" => 0, ! 213: "x" => 0, ! 214: "w" => 0, ! 215: "o" => 1, ! 216: ); ! 217: foreach ($table as $eatype => $exp_int) { ! 218: if (!isset($ealist[$eatype])) continue; ! 219: $eamode = $ealist[$eatype]['mode']; ! 220: $ei = ($exp_int == 1 ? 0x1b : 0x0b); // フラグは変化しない ! 221: $test = array( ! 222: "opname" => "fscc", ! 223: "is_store" => true, ! 224: "eatype" => $eatype, ! 225: "eamode" => $eamode, ! 226: "inst" => 0xf2400000 | ($eamode << 16), // FSF ! 227: "expected" => array( ! 228: "B" => $ei, ! 229: ), ! 230: ); ! 231: $testlist[] = $test; ! 232: } ! 233: ! 234: // FMOVEM.X FPn,<ea>。 ! 235: // FMOVEM 自体のテストではないのでレジスタリストは FPn 1つのみ。 ! 236: $table = array( ! 237: // 期待値 (0が通過、1がトラップ) ! 238: "d" => 1, ! 239: "a" => 1, ! 240: "m" => 0, ! 241: "mi" => 1, ! 242: "md" => 0, ! 243: "r" => 0, ! 244: "x" => 0, ! 245: "w" => 0, ! 246: "p" => 1, ! 247: "i" => 1, ! 248: "o" => 1, ! 249: ); ! 250: foreach ($table as $eatype => $exp_int) { ! 251: if (!isset($ealist[$eatype])) continue; ! 252: $eamode = $ealist[$eatype]['mode']; ! 253: $ei = ($exp_int == 1 ? 0x1b : 0x0b); // フラグは変化しない ! 254: $cmode = ($eatype == "md") ? 0 : 0x1000; ! 255: $test = array( ! 256: "opname" => "fmovem_rm", ! 257: "is_store" => true, ! 258: "eatype" => $eatype, ! 259: "eamode" => $eamode, ! 260: "inst" => 0xf200e001 | ($eamode << 16) | $cmode, ! 261: "expected" => array( ! 262: "X" => $ei, ! 263: ), ! 264: ); ! 265: $testlist[] = $test; ! 266: } ! 267: ! 268: // FMOVEM.X <ea>,FPn。 ! 269: // FMOVEM 自体のテストではないのでレジスタリストは FPn 1つのみ。 ! 270: $table = array( ! 271: // 期待値 (0が通過、1がトラップ) ! 272: "d" => 1, ! 273: "a" => 1, ! 274: "m" => 0, ! 275: "mi" => 0, ! 276: "md" => 1, ! 277: "r" => 0, ! 278: "x" => 0, ! 279: "w" => 0, ! 280: "p" => 0, ! 281: "i" => 1, ! 282: "o" => 1, ! 283: ); ! 284: foreach ($table as $eatype => $exp_int) { ! 285: if (!isset($ealist[$eatype])) continue; ! 286: $eamode = $ealist[$eatype]['mode']; ! 287: $ei = ($exp_int == 1 ? 0x1b : 0x0b); // フラグは変化しない ! 288: $cmode = ($eatype == "md") ? 0 : 0x1000; ! 289: $test = array( ! 290: "opname" => "fmovem_mr", ! 291: "is_store" => false, ! 292: "eatype" => $eatype, ! 293: "eamode" => $eamode, ! 294: "inst" => 0xf200c001 | ($eamode << 16) | $cmode, ! 295: "expected" => array( ! 296: "X" => $ei, ! 297: ), ! 298: ); ! 299: $testlist[] = $test; ! 300: } ! 301: ! 302: $crlist = array( ! 303: "c" => array("mode" => (4 << 10), "name" => "FPCR"), ! 304: "s" => array("mode" => (2 << 10), "name" => "FPSR"), ! 305: "i" => array("mode" => (1 << 10), "name" => "FPIAR"), ! 306: "m" => array("mode" => (3 << 10), "name" => "FPSR/FPIAR"), ! 307: ); ! 308: ! 309: // FMOVEM.L FPcr,<ea>。 ! 310: // FPIAR かどうか、リストが複数かどうかで変わる。 ! 311: // 横はサイズではなくレジスタリストをとる。 ! 312: $table = array( ! 313: // FPCR FPSR FPIAR multi ! 314: "d" => array( 0, 0, 0, 1), // 単一レジスタのみ可能 ! 315: "a" => array( 1, 1, 0, 1), // FPIAR のみ可能 ! 316: "m" => array( 0, 0, 0, 0), ! 317: "mi" => array( 0, 0, 0, 0), ! 318: "md" => array( 0, 0, 0, 0), ! 319: "r" => array( 0, 0, 0, 0), ! 320: "x" => array( 0, 0, 0, 0), ! 321: "w" => array( 0, 0, 0, 0), ! 322: "p" => array( 1, 1, 1, 1), ! 323: "i" => array( 1, 1, 1, 1), ! 324: "o" => array( 1, 1, 1, 1), ! 325: ); ! 326: foreach ($table as $eatype => $exparray) { ! 327: list ($exp_cr, $exp_sr, $exp_ir, $exp_m) = $exparray; ! 328: if (!isset($ealist[$eatype])) continue; ! 329: $eamode = $ealist[$eatype]['mode']; ! 330: // フラグは変化しない ! 331: $ec = ($exp_cr == 1 ? 0x1b : 0x0b); ! 332: $es = ($exp_sr == 1 ? 0x1b : 0x0b); ! 333: $ei = ($exp_ir == 1 ? 0x1b : 0x0b); ! 334: $em = ($exp_m == 1 ? 0x1b : 0x0b); ! 335: $test = array( ! 336: "opname" => "fmovem_cm", ! 337: "is_store" => true, ! 338: "eatype" => $eatype, ! 339: "eamode" => $eamode, ! 340: "inst" => 0xf200a000 | ($eamode << 16), ! 341: "fmovemc" => true, ! 342: "expected" => array( ! 343: "c" => $ec, ! 344: "s" => $es, ! 345: "i" => $ei, ! 346: "m" => $em, ! 347: ), ! 348: ); ! 349: $testlist[] = $test; ! 350: } ! 351: ! 352: // FMOVEM.L <ea>,FPcr。 ! 353: // FPIAR かどうか、リストが複数かどうかで変わる。 ! 354: $table = array( ! 355: // FPCR FPSR FPIAR multi ! 356: "d" => array( 0, 0, 0, 1), // 単一レジスタのみ可能 ! 357: "a" => array( 1, 1, 0, 1), // FPIAR のみ可能 ! 358: "m" => array( 0, 0, 0, 0), ! 359: "mi" => array( 0, 0, 0, 0), ! 360: "md" => array( 0, 0, 0, 0), ! 361: "r" => array( 0, 0, 0, 0), ! 362: "x" => array( 0, 0, 0, 0), ! 363: "w" => array( 0, 0, 0, 0), ! 364: "p" => array( 0, 0, 0, 0), ! 365: "i" => array( 0, 0, 0, 0), ! 366: "o" => array( 1, 1, 1, 1), ! 367: ); ! 368: foreach ($table as $eatype => $exparray) { ! 369: list ($exp_cr, $exp_sr, $exp_ir, $exp_m) = $exparray; ! 370: if (!isset($ealist[$eatype])) continue; ! 371: $eamode = $ealist[$eatype]['mode']; ! 372: // フラグは FPSR への代入だけ変化することになる ! 373: $ec = ($exp_cr == 1 ? 0x1b : 0x0b); ! 374: $es = ($exp_sr == 1 ? 0x1b : 0x00); // FPSR ! 375: $ei = ($exp_ir == 1 ? 0x1b : 0x0b); ! 376: $em = ($exp_m == 1 ? 0x1b : 0x00); // FPSR/FPIAR ! 377: $test = array( ! 378: "opname" => "fmovem_mc", ! 379: "is_store" => false, ! 380: "eatype" => $eatype, ! 381: "eamode" => $eamode, ! 382: "inst" => 0xf2008000 | ($eamode << 16), ! 383: "fmovemc" => true, ! 384: "expected" => array( ! 385: "c" => $ec, ! 386: "s" => $es, ! 387: "i" => $ei, ! 388: "m" => $em, ! 389: ), ! 390: ); ! 391: $testlist[] = $test; ! 392: } ! 393: ! 394: ! 395: // コマンド名を抽出する。 ! 396: $cmdlist = array(); ! 397: foreach ($testlist as $test) { ! 398: $opname = $test['opname']; ! 399: if (!isset($cmdlist[$opname])) { ! 400: $cmdlist[$opname] = $opname; ! 401: } ! 402: } ! 403: ?> ! 404: ! 405: start: ! 406: bsr parse_arg ! 407: clr.l -(sp) ! 408: DOS _SUPER ! 409: ! 410: fmovem.x fp0-fp7,-(sp) ! 411: fmovem.l fpcr/fpsr/fpiar,-(sp) ! 412: ! 413: moveq.l #0,d0 ! 414: fmove.s d0,fp0 ; FP0 = +0.0 ! 415: fmove.l d0,fpcr ; Init round prec, round mode. ! 416: move.l d0,failed ; Init failed count. ! 417: ! 418: <?php ! 419: $opname = ""; ! 420: foreach ($testlist as $test) { ! 421: if ($opname != $test['opname']) { ! 422: $opname = $test['opname']; ! 423: out("@@:"); ! 424: out("tst.b is_{$opname}(pc)"); ! 425: out("beq @f"); ! 426: out("PRINT msg_head_{$opname}(pc)"); ! 427: $n = count($test['expected']); ! 428: if ($n == 4 || $n == 7) { ! 429: out("PRINT msg_head_guide{$n}(pc)"); ! 430: } ! 431: } ! 432: out(" bsr test_{$opname}_{$test['eatype']}"); ! 433: } ! 434: ?> ! 435: @@: ! 436: tst.l failed(pc) ! 437: beq @f ! 438: PRINT msg_failed(pc) ! 439: @@: ! 440: fmovem.l (sp)+,fpcr/fpsr/fpiar ! 441: fmovem.x (sp)+,fp0-fp7 ! 442: DOS _EXIT ! 443: ! 444: <?php ! 445: // ここからテスト本体を展開。 ! 446: // テスト中では Dn の場合の格納先は d6、アドレスは A0。 ! 447: foreach ($testlist as $test) { ! 448: $eatype = $test['eatype']; ! 449: $eaname = $ealist[$eatype]['name']; ! 450: $expected_array = $test['expected']; ! 451: out("test_{$test['opname']}_{$eatype}:"); ! 452: out(" lea.l result(pc),a2"); ! 453: foreach ($expected_array as $sizename => $expected) { ! 454: $inst = $test['inst']; ! 455: if (($test['has_dstfmt'] ?? false) != false) { ! 456: $dstfmt = $sizelist[$sizename]; ! 457: $inst |= ($dstfmt << 10); ! 458: } ! 459: if (($test['fmovemc'] ?? false) != false) { ! 460: // FMOVEM FPcr の時だけループ変数は $sizename ではなく $crtype。 ! 461: $crtype = $sizename; ! 462: $inst |= $crlist[$crtype]['mode']; ! 463: $crname = $crlist[$crtype]['name']; ! 464: } ! 465: switch ($test['opname']) { ! 466: case "fmove": ! 467: out(" ; FMOVE.{$sizename} FPn,{$eaname}"); ! 468: break; ! 469: case "fgen": ! 470: out(" ; Fgen.{$sizename} {$eaname},FPn"); ! 471: break; ! 472: case "fscale": ! 473: out(" ; FSCALE.{$sizename} {$eaname},FPn"); ! 474: break; ! 475: case "fscc": ! 476: out(" ; FScc.B {$eaname}"); ! 477: break; ! 478: case "fmovem_rm": ! 479: out(" ; FMOVEM.X FPn,{$eaname}"); ! 480: break; ! 481: case "fmovem_mr": ! 482: out(" ; FMOVEM.X {$eaname},FPn"); ! 483: break; ! 484: case "fmovem_cm": ! 485: out(" ; FMOVEM.L {$crname},{$eaname}"); ! 486: break; ! 487: case "fmovem_mc": ! 488: out(" ; FMOVEM.L {$eaname},{$crname}"); ! 489: break; ! 490: } ! 491: $expected = sprintf("$%02x", $expected); ! 492: out(" move.b #{$expected},(a2)+"); ! 493: // ConditionByte の N, Inf, NAN を立てる。Z は下げておく。 ! 494: out(" fmovem.l #$0b000000,fpsr"); ! 495: out(" bsr set_fline"); ! 496: out(" moveq.l #0,d7"); ! 497: // 命令を作成。 ! 498: $post = ""; ! 499: $dir = ($test['is_store'] ? "store" : "load"); ! 500: switch ("{$dir}_{$eatype}") { ! 501: // 書き込み先のポインタだけ設定。 ! 502: case "store_m": ! 503: case "store_mi": ! 504: out(" lea.l workarea(pc),a0"); ! 505: break; ! 506: case "store_md": ! 507: out(" lea.l workarea+12(pc),a0"); ! 508: break; ! 509: case "store_r": ! 510: out(" lea.l workarea(pc),a0"); ! 511: $post = ".dc.w $0000"; ! 512: break; ! 513: case "store_x": ! 514: out(" moveq.l #0,d4"); ! 515: out(" lea.l workarea(pc),a0"); ! 516: $post = ".dc.w $4000"; ! 517: break; ! 518: ! 519: // 読み込み元になるデータもゼロで用意する必要がある。 ! 520: case "load_d": ! 521: out(" moveq.l #0,d6"); ! 522: break; ! 523: case "load_m": ! 524: case "load_mi": ! 525: out(" lea.l workarea+12(pc),a0"); ! 526: out(" move.l d7,-(a0)"); ! 527: out(" move.l d7,-(a0)"); ! 528: out(" move.l d7,-(a0)"); ! 529: break; ! 530: case "load_md": ! 531: out(" lea.l workarea(pc),a0"); ! 532: out(" move.l d7,(a0)+"); ! 533: out(" move.l d7,(a0)+"); ! 534: out(" move.l d7,(a0)+"); ! 535: break; ! 536: case "load_r": ! 537: out(" lea.l workarea+12(pc),a0"); ! 538: out(" move.l d7,-(a0)"); ! 539: out(" move.l d7,-(a0)"); ! 540: out(" move.l d7,-(a0)"); ! 541: $post = ".dc.w $0000"; ! 542: break; ! 543: case "load_x": ! 544: out(" moveq.l #0,d4"); ! 545: out(" lea.l workarea+12(pc),a0"); ! 546: out(" move.l d7,-(a0)"); ! 547: out(" move.l d7,-(a0)"); ! 548: out(" move.l d7,-(a0)"); ! 549: $post = ".dc.w $4000"; ! 550: break; ! 551: case "load_p": ! 552: out(" bra @f"); ! 553: out(" .dc.l 0, 0, 0"); ! 554: out("@@:"); ! 555: // 命令本体(4) + 直前のLEA(6) + ここ(12) ! 556: $post = ".dc.w -4-6-12"; ! 557: break; ! 558: case "load_i": ! 559: switch ($sizename) { ! 560: case "B": ! 561: case "W": ! 562: $post = ".dc.w 0"; ! 563: break; ! 564: case "L": ! 565: case "S": ! 566: case "c": // FPCR ! 567: case "s": // FPSR ! 568: case "i": // FPIAR ! 569: $post = ".dc.l 0"; ! 570: break; ! 571: case "D": ! 572: case "m": // FPSR/FPIAR ! 573: $post = ".dc.l 0, 0"; ! 574: break; ! 575: case "X": ! 576: case "P": ! 577: $post = ".dc.l 0, 0, 0"; ! 578: break; ! 579: } ! 580: break; ! 581: ! 582: default: ! 583: break; ! 584: } ! 585: out(" lea.l @f,a3"); ! 586: out(" .dc.l $%08x", $inst); ! 587: if (strlen($post) > 0) { ! 588: out(" {$post}"); ! 589: } ! 590: out("@@:"); ! 591: out(" bsr restore_fline"); ! 592: out(" fmovem.l fpsr,d0"); ! 593: out(" rol.l #8,d0"); ! 594: out(" or.l d7,d0"); ! 595: out(" move.b d0,(a2)+"); ! 596: out(""); ! 597: } ! 598: out(" lea.l msg_test_{$test['eatype']},a0"); ! 599: out(" moveq.l #" . count($expected_array) . "-1,d0"); ! 600: out(" bsr print_result"); ! 601: out(" rts"); ! 602: out(""); ! 603: } ! 604: ?> ! 605: <?php ! 606: // 1行を出力する。引数は printf のように fmt... で指定可能。 ! 607: // 改行はこちらで付加する。 ! 608: function out() ! 609: { ! 610: $args = func_get_args(); ! 611: $fmt = array_shift($args); ! 612: print vsprintf($fmt, $args); ! 613: print "\n"; ! 614: } ! 615: ?> ! 616: ! 617: ; 引数を処理する。 ! 618: ; 引数がなければヘルプを表示。 ! 619: ; 引数... があれば列挙されたテストを実行。 ! 620: ; "all" ならすべて実行。 ! 621: parse_arg: ! 622: movem.l d0-d2/a0,-(sp) ! 623: tst.b (a2) ! 624: beq parse_done ! 625: parse_loop: ! 626: adda.l #1,a2 ! 627: move.b (a2),d0 ; '\0' なら終了 ! 628: beq parse_done ! 629: ! 630: cmpi.b #' ',d0 ! 631: beq parse_loop ! 632: cmpi.b #$09,d0 ! 633: beq parse_loop ! 634: ! 635: ; "help" ! 636: lea.l cmd_help(pc),a0 ! 637: bsr match ! 638: beq print_help ! 639: ! 640: ; "all" ! 641: lea.l cmd_all(pc),a0 ! 642: bsr match ! 643: bne @f ! 644: <?php ! 645: foreach ($cmdlist as $cmd) { ! 646: out(" st.b is_{$cmd}"); ! 647: } ! 648: ?> ! 649: ; 後は無視していいだろう。 ! 650: bra parse_done ! 651: @@: ! 652: <?php ! 653: // 個別コマンドのループ ! 654: foreach ($cmdlist as $cmd) { ! 655: out(" ; \"{$cmd}\""); ! 656: out(" lea.l cmd_{$cmd}(pc),a0"); ! 657: out(" bsr match"); ! 658: out(" bne @f"); ! 659: out(" st.b is_{$cmd}"); ! 660: out(" bra parse_loop"); ! 661: out("@@:"); ! 662: } ! 663: ?> ! 664: ! 665: parse_done: ! 666: ; どのコマンドも実行になってなければヘルプを表示。 ! 667: moveq.l #0,d0 ! 668: lea.l is_tests(pc),a0 ! 669: moveq.l #<?php print count($cmdlist); ?>-1,d1 ! 670: @@: ! 671: or.b (a0)+,d0 ! 672: dbra d1,@b ! 673: beq print_help ! 674: ! 675: movem.l (sp)+,d0-d2/a0 ! 676: rts ! 677: ! 678: ; ヘルプを表示して終了。 ! 679: print_help: ! 680: PRINT msg_help(pc) ! 681: DOS _EXIT ! 682: ! 683: ; (a2) からの単語が (a0) からのゼロ終端文字列と一致するか。 ! 684: ; 一致すれば d0 = 0 を返して (a2) は単語の最後の1文字を指すようにする。 ! 685: ; 一致しなければ d0 != 0 を返して (a2) は元の位置のまま。 ! 686: match: ! 687: movem.l a1,-(sp) ! 688: movea.l a2,a1 ; 戻り値用 ! 689: match_loop: ! 690: move.b (a2)+,d0 ! 691: cmpi.b #' ',d0 ; d0 が ' ' なら '\0' に ! 692: bne @f ! 693: moveq.l #0,d0 ! 694: bra match_main ! 695: @@: ! 696: cmpi.b #$09,d0 ; d0 が TAB なら '\0' に ! 697: bne match_main ! 698: moveq.l #0,d0 ! 699: match_main: ! 700: ; この状態で比較 ! 701: cmp.b (a0)+,d0 ! 702: bne not_match ! 703: ; '\0' 以外で一致したら次の文字へ。 ! 704: tst.b d0 ! 705: bne match_loop ! 706: ; '\0' で一致したので完了。 ! 707: suba.l #1,a2 ! 708: moveq.l #0,d0 ! 709: movem.l (sp)+,a1 ! 710: rts ! 711: ! 712: not_match: ! 713: ; 不一致なので a2 を元に戻す。 ! 714: movea.l a1,a2 ! 715: moveq.l #1,d0 ! 716: movem.l (sp)+,a1 ! 717: rts ! 718: ! 719: ; 結果を1行表示する。 ! 720: ; A0 にテスト名、D0 に(テスト数-1)を入れて呼ぶこと。 ! 721: ; ! 722: ; A2 からの result バッファは 2バイト1組で、 ! 723: ; +0 バイト目が期待値、bit4 がトラップの有無、bit3-0 が ConditionByte。 ! 724: ; +1 バイト目が結果値、構造は同じ。 ! 725: ; ! 726: ; 期待値 結果 ! 727: ; (0<<4)|(x) (0<<4)|(x) pass:OK ! 728: ; (0<<4)|(x) (0<<4)|(y) flag:FAIL ! 729: ; (0<<4)|(x) (1<<4)|(x) trap:FAIL ! 730: ; (0<<4)|(x) (1<<4)|(y) trap:FAIL ! 731: ; (1<<4)|(x) (0<<4)|(x) pass:FAIL ! 732: ; (1<<4)|(x) (0<<4)|(y) pass:FAIL ! 733: ; (1<<4)|(x) (1<<4)|(x) trap:OK ! 734: ; (1<<4)|(x) (1<<4)|(y) flag:FAIL ! 735: print_result: ! 736: movem.l d0-d4/a2,-(sp) ! 737: move.l d0,d4 ! 738: PRINT (a0) ! 739: lea.l result(pc),a2 ! 740: moveq.l #0,d0 ! 741: moveq.l #0,d1 ! 742: prloop: ! 743: move.b (a2)+,d0 ; 期待値 ! 744: move.b (a2)+,d1 ; 結果 ! 745: ; 先に failed のカウント ! 746: cmp.b d1,d0 ! 747: beq @f ! 748: addi.l #1,failed ! 749: @@: ! 750: bfextu d0{#27:#1},d2 ; 期待値のトラップビット ! 751: bfextu d1{#27:#1},d3 ; 結果のトラップビット ! 752: andi.b #$0f,d0 ! 753: andi.b #$0f,d1 ! 754: cmp.b d1,d0 ! 755: sne.b d0 ! 756: neg.b d0 ; d0 は一致なら $0、そうでなければ $1 ! 757: lsl.l #1,d3 ; d3 は結果がトラップなら $2、通過なら $0 ! 758: or.b d3,d0 ! 759: lsl.l #2,d2 ; d2 は期待値がトラップなら $4、通過なら $0 ! 760: or.b d2,d0 ! 761: add.b d0,d0 ; d0 *= 2 ! 762: PRINT msg_result(pc,d0.w*8) ! 763: dbra d4,prloop ! 764: PRINT msg_crlf(pc) ! 765: movem.l (sp)+,d0-d4/a2 ! 766: rts ! 767: ! 768: ; Fライン例外をテスト用のものに差し替える。 ! 769: ; 変更前のアドレスを a4 に格納する。 ! 770: set_fline: ! 771: movem.l d0-d1/a1,-(sp) ! 772: moveq.l #$b,d1 ! 773: lea.l fline_handler(pc),a1 ! 774: IOCS _B_INTVCS ! 775: movea.l d0,a4 ! 776: movem.l (sp)+,d0-d1/a1 ! 777: rts ! 778: ! 779: ; Fライン例外を元に戻す。 ! 780: restore_fline: ! 781: movem.l d0-d1/a1,-(sp) ! 782: moveq.l #$b,d1 ! 783: movea.l a4,a1 ! 784: IOCS _B_INTVCS ! 785: movem.l (sp)+,d0-d1/a1 ! 786: rts ! 787: ! 788: ; Fライン例外ハンドラ ! 789: ; a3 に戻りアドレスをセットしてあること ! 790: ; d7 を $10 にして帰る ! 791: fline_handler: ! 792: moveq.l #$10,d7 ! 793: move.l a3,2(sp) ! 794: rte ! 795: ! 796: <?php ! 797: foreach ($ealist as $eatype => $arr) { ! 798: $eaname = $arr['name']; ! 799: while (strlen($eaname) < 9) { ! 800: $eaname .= " "; ! 801: } ! 802: out("msg_test_{$eatype}: .dc.b \" {$eaname}\",0"); ! 803: } ! 804: ?> ! 805: ! 806: msg_head_fmove: ! 807: .dc.b "FMOVEtomem ",0 ! 808: msg_head_fgen: ! 809: .dc.b "Fgen ",0 ! 810: msg_head_fscale: ! 811: .dc.b "FSCALE ",0 ! 812: msg_head_fmovem_cm: ! 813: .dc.b "FMOVEM_cm ",0 ! 814: msg_head_fmovem_mc: ! 815: .dc.b "FMOVEM_mc ",0 ! 816: msg_head_fscc: ! 817: .dc.b "FScc .B",$d,$a,0 ! 818: msg_head_fmovem_rm: ! 819: .dc.b "FMOVEM_rm .X",$d,$a,0 ! 820: msg_head_fmovem_mr: ! 821: .dc.b "FMOVEM_mr .X",$d,$a,0 ! 822: ! 823: msg_head_guide4: ! 824: .dc.b "FPCR " ! 825: .dc.b "FPSR " ! 826: .dc.b "FPIAR " ! 827: .dc.b "FPSR/FPIAR",$d,$a,0 ! 828: ! 829: msg_head_guide7: ! 830: .dc.b ".B " ! 831: .dc.b ".W " ! 832: .dc.b ".L " ! 833: .dc.b ".S " ! 834: .dc.b ".D " ! 835: .dc.b ".X " ! 836: .dc.b ".P",$d,$a,0 ! 837: ! 838: msg_result: ! 839: .dc.b " pass:OK ",0,0,0,0,0,0 ! 840: .dc.b " flag:FAIL",0,0,0,0,0,0 ! 841: .dc.b " trap:FAIL",0,0,0,0,0,0 ! 842: .dc.b " trap:FAIL",0,0,0,0,0,0 ! 843: .dc.b " pass:FAIL",0,0,0,0,0,0 ! 844: .dc.b " pass:FAIL",0,0,0,0,0,0 ! 845: .dc.b " trap:OK ",0,0,0,0,0,0 ! 846: .dc.b " flag:FAIL",0 ! 847: ! 848: msg_failed: ! 849: .dc.b "FAILED" ; ,$d,$a,0 ! 850: msg_crlf: ! 851: .dc.b $d,$a,0 ! 852: ! 853: msg_help: ! 854: .dc.b "usage: { 'all' | 'help' | testnames... }",$d,$a ! 855: .dc.b " testnames:" ! 856: <?php ! 857: foreach ($cmdlist as $cmd) { ! 858: out(" .dc.b \" {$cmd}\""); ! 859: } ! 860: ?> ! 861: .dc.b $d,$a,0 ! 862: ! 863: cmd_help: ! 864: .dc.b "help",0 ! 865: cmd_all: ! 866: .dc.b "all",0 ! 867: <?php ! 868: foreach ($cmdlist as $cmd) { ! 869: out("cmd_{$cmd}:"); ! 870: out(" .dc.b \"{$cmd}\",0"); ! 871: } ! 872: ?> ! 873: ! 874: .bss ! 875: .even ! 876: result: ! 877: .ds.w <?php print count($sizelist)."\n"; ?> ! 878: .align 4 ! 879: workarea: ! 880: .ds.l 3 ! 881: failed: ! 882: .ds.l 1 ! 883: ! 884: ; テストを実行する場合は !0 ! 885: is_tests: ! 886: <?php ! 887: foreach ($cmdlist as $cmd) { ! 888: out("is_{$cmd}:"); ! 889: out(" .ds.b 1"); ! 890: } ! 891: ?> ! 892: ! 893: .end start
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.