Annotation of nono/exp/fmovemn.php, revision 1.1.1.4

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.