|
|
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.