Annotation of nono/exp/fmoveto.php, revision 1.1

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

unix.superglobalmegacorp.com

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