Annotation of nono/exp/fmovemc.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 fmovemc.has
                     28: ;  > hlk fmovemc.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
                     37:        pea.l   msg(pc)
                     38:        DOS     _PRINT
                     39:        addq.l  #4,sp
                     40:        .endm
                     41: 
                     42:        .text
                     43:        .even
1.1.1.3   root       44: start:
                     45:        bra     start2
                     46: 
1.1       root       47: <?php
                     48:        // レジスタ割り当て
                     49:        // d0/d1        work
                     50:        // d7   1=検査対象命令でFライン例外がおきた
                     51:        //      その後は ok を表示するかどうかのカウント
                     52:        // a0/a1        work
                     53:        // a3   検査対象命令の次の位置 (Fライン例外から戻るのに使用)
                     54:        // a4   元のFライン例外ハンドラ置き場
                     55: ?>
                     56: <?php
                     57:        // regs がターゲットのFPcr。
                     58:        // C..FPCR
                     59:        // S..FPSR
                     60:        // I..FPIAR の3ビット。
                     61:        // 右辺がそのターゲットの時に使える EA。レジスタ相対は省略でいい?
                     62:        //  d..Dn
                     63:        //  a..An
                     64:        //  m..(An)
                     65:        //  +..(An)+
                     66:        //  -..-(An)
                     67:        //  i..#imm
                     68: 
                     69:        // FMOVEM EA,regs
                     70:        $table = array(
                     71:                //regs     EA
                     72:                "___"   => "dam+-i",
                     73:                "__I"   => "dam+-i",
                     74:                "_S_"   => "d.m+-i",
                     75:                "_SI"   => "..m+-i",
                     76:                "C__"   => "d.m+-i",
                     77:                "C_I"   => "..m+-i",
                     78:                "CS_"   => "..m+-i",
                     79:                "CSI"   => "..m+-i",
                     80:        );
                     81:        foreach ($table as $regs => $eastr) {
                     82:                $ealist = preg_split("//", $eastr, -1, PREG_SPLIT_NO_EMPTY);
                     83:                for ($id = 0; $id < 6; $id++) {
                     84:                        $ea = $eastr[$id];
                     85:                        if (0) printf("regs='{$regs}' id=${id} ea={$ea}\n");
                     86: 
                     87:                        if ($ea == ".") {
                     88:                                // 許されない組み合わせ。例外が出ることを確認
                     89:                                subr_fail("to", $regs, $id);
                     90:                        } else {
                     91:                                // アクセス可能な場合のテスト
                     92:                                subr_success_to($regs, $id);
                     93:                        }
                     94:                }
                     95:        }
                     96: 
                     97:        // FMOVEM regs,EA
                     98:        foreach ($table as $regs => $eastr_src) {
                     99:                // EA が dst になる時は #imm は無効
                    100:                $eastr = preg_replace("/i/", ".", $eastr_src);
                    101: 
                    102:                $ealist = preg_split("//", $eastr, -1, PREG_SPLIT_NO_EMPTY);
                    103:                for ($id = 0; $id < 6; $id++) {
                    104:                        $ea = $eastr[$id];
                    105:                        if (0) printf("regs='{$regs}' id=${id} ea={$ea}\n");
                    106: 
                    107:                        if ($ea == ".") {
                    108:                                // 許されない組み合わせ。例外が出ることを確認
                    109:                                subr_fail("from", $regs, $id);
                    110:                        } else {
                    111:                                // アクセス可能な場合のテスト
                    112:                                subr_success_from($regs, $id);
                    113:                        }
                    114:                }
                    115:        }
                    116: ?>
                    117: <?php
                    118: // 1行を出力する。引数は printf のように fmt... で指定可能。
                    119: // 改行はこちらで付加する。
                    120: function out()
                    121: {
                    122:        $args = func_get_args();
                    123:        $fmt = array_shift($args);
                    124:        print vsprintf($fmt, $args);
                    125:        print "\n";
                    126: }
                    127: 
                    128: // regs の省略記号を数値形式に
                    129: function reg2num($str)
                    130: {
                    131:        $n = 0;
                    132:        if (preg_match("/I/", $str))
                    133:                $n += 1;
                    134:        if (preg_match("/S/", $str))
                    135:                $n += 2;
                    136:        if (preg_match("/C/", $str))
                    137:                $n += 4;
                    138:        return $n;
                    139: }
                    140: 
                    141: // regs 数値形式をニーモニックに
                    142: function regnum2mnemonic($regnum)
                    143: {
                    144:        if ($regnum == 0)
                    145:                return "nofpc";
                    146: 
                    147:        $list = array();
                    148:        if ($regnum & 4)
                    149:                $list[] = "fpcr";
                    150:        if ($regnum & 2)
                    151:                $list[] = "fpsr";
                    152:        if ($regnum & 1)
                    153:                $list[] = "fpiar";
1.1.1.3   root      154:        return implode("/", $list);
1.1       root      155: }
                    156: 
                    157: // regs 数値形式から転送レジスタ数に
                    158: function regnum2count($regnum)
                    159: {
                    160:        $counts = array(0, 1, 1, 2, 1, 2, 2, 3);
                    161:        return $counts[$regnum];
                    162: }
                    163: 
                    164: // regs 数値形式からマスクを返す。
                    165: // regs は1ビットだけ立っていること。
                    166: // %100=FPCR, %010=FPSR, %001=FPIAR
                    167: function regmask($regnum)
                    168: {
                    169:        $masks = array(
                    170:                /*0*/   0,
                    171:                /*1*/   0xffffffff,     // FPIAR
                    172:                /*2*/   0x0ffffff8,     // FPSR
                    173:                /*3*/   0,
                    174:                /*4*/   0x0000fff0,     // FPCR
                    175:        );
                    176:        return $masks[$regnum];
                    177: }
                    178: 
                    179: // EA 番号から命令ワードに。n はすべて0
                    180: function eanum2word($id)
                    181: {
                    182:        switch ($id) {
                    183:         case 0:        // D0
                    184:                return 0 << 3;
                    185:         case 1:        // A0
                    186:                return 1 << 3;
                    187:         case 2:        // (A0)
                    188:                return 2 << 3;
                    189:         case 3:        // (A0)+
                    190:                return 3 << 3;
                    191:         case 4:        // -(An)
                    192:                return 4 << 3;
                    193:         case 5:        // #imm
                    194:                return 0x3c;
                    195:        }
                    196: }
                    197: 
                    198: // EA 番号をラベル文字列に。
                    199: function eanum2label($id)
                    200: {
                    201:        $idstr = array(
                    202:                0 => "dn",
                    203:                1 => "an",
                    204:                2 => "anin",
                    205:                3 => "anpi",
                    206:                4 => "anpd",
                    207:                5 => "imm",
                    208:        );
                    209:        return $idstr[$id];
                    210: }
                    211: 
                    212: // EA 番号をニーモニックに。
                    213: function eanum2mnem($id, $n = 0)
                    214: {
                    215:        switch ($id) {
                    216:         case 0:        return "d{$n}";
                    217:         case 1:        return "a{$n}";
                    218:         case 2:        return "(a{$n})";
                    219:         case 3:        return "(a{$n})+";
                    220:         case 4:        return "-(a{$n})";
1.1.1.3   root      221:         case 5:        return "#imm";
1.1       root      222:        }
1.1.1.3   root      223:        return "";
1.1       root      224: }
                    225: 
1.1.1.3   root      226: function addfunc($name, $dir, $mnem, $cpureg)
1.1       root      227: {
                    228:        global $funclist;
                    229: 
1.1.1.3   root      230:        if ($cpureg == "#imm") {
                    231:                // $cpureg の #imm は常に1つだが
                    232:                // ニーモニック表記では対向と数を合わせるか。
                    233:                $cpureg = preg_replace(',([^/]+),', "#imm", $mnem);
                    234:        }
                    235:        $text = "fmovem.l ";
                    236:        if ($dir == "to") {
                    237:                $text .= "{$cpureg},{$mnem}";
                    238:        } else {
                    239:                $text .= "{$mnem},{$cpureg}";
                    240:        }
                    241: 
                    242:        $funclist[$name] = $text;
1.1       root      243:        out("test_{$name}:");
                    244: }
                    245: 
                    246: // 結果表示のサブルーチンコールを出力
                    247: function out_result($msg, $exp, $act)
                    248: {
                    249:        out("   pea.l   {$msg}(pc)");
                    250:        out("   move.l  {$exp},-(sp)");
                    251:        out("   move.l  {$act},-(sp)");
                    252:        out("   bsr     result");
                    253:        out("   lea.l   12(sp),sp");
                    254: }
                    255: 
1.1.1.3   root      256: // 許されない組み合わせのテスト。hard の時だけ検査する。
1.1       root      257: // Fライン例外が起きることをチェックする。
                    258: function subr_fail($dir, $regs, $id)
                    259: {
1.1.1.3   root      260:        $cpureg = eanum2mnem($id);
1.1       root      261:        $regnum = reg2num($regs);
                    262:        $mnem = regnum2mnemonic($regnum);
                    263:        $label = eanum2label($id);
                    264: 
                    265:        $funcname = ($dir == "to")
                    266:                ? "fmovem_{$label}_to_{$regs}"
                    267:                : "fmovem_{$regs}_to_{$label}";
1.1.1.3   root      268:        addfunc($funcname, $dir, $mnem, $cpureg);
1.1       root      269: 
                    270:        $w1 = 0xf200 | eanum2word($id);
                    271:        $w2 = 0x8000 | ($regnum << 10);
                    272:        if ($dir == "from")
                    273:                $w2 |= 0x2000;
                    274: 
1.1.1.3   root      275:        out("   tst.b   is_hard(pc)");
                    276:        out("   bne             @f");
                    277:        out("   rts");
                    278:        out("@@:");
                    279:        out("   PRINT   msg_{$funcname}");
1.1.1.4 ! root      280:        out("   bsr     set_fline");
1.1       root      281:        out("   moveq.l #0,d7");
                    282:        out("   lea.l   @f,a3");
                    283:        // アセンブルできない可能性があるので命令はバイナリを出力。
                    284:        out("   .dc.w   $%04x, $%04x", $w1, $w2);
                    285:        out("@@:");
                    286: 
1.1.1.4 ! root      287:        out("   bsr     restore_fline");
1.1       root      288:        // 例外が起きるはずなので D7 が非ゼロなら成功(次へ)
                    289:        out("   tst.l   d7");
                    290:        out("   bne     @f");
                    291:        out("   PRINT   msg_fail_notrap");
                    292:        out("   rts");
                    293:        out("@@:");
                    294:        out("   PRINT   msg_oktrap");
                    295:        out("   rts");
                    296:        out("");
                    297: }
                    298: 
                    299: // アクセス可能な場合のテスト。FMOVEM <ea>,<FPcr>
                    300: function subr_success_to($regs, $id)
                    301: {
1.1.1.3   root      302:        $cpureg = eanum2mnem($id);
1.1       root      303:        $regnum = reg2num($regs);
                    304:        $mnem = regnum2mnemonic($regnum);
                    305:        $label = eanum2label($id);
                    306: 
                    307:        $funcname = "fmovem_{$label}_to_{$regs}";
1.1.1.3   root      308:        addfunc($funcname, "to", $mnem, $cpureg);
                    309:        out("   PRINT   msg_{$funcname}");
1.1       root      310: 
                    311:        $w1 = 0xf200 | eanum2word($id);
                    312:        $w2 = 0x8000 | ($regnum << 10);
                    313:        // count は指定されたレジスタ数 (0..3)
                    314:        // txcount は転送するレジスタ数 (1..3)
                    315:        $count = regnum2count($regnum);
                    316:        $txcount = ($count == 0) ? 1 : $count;
                    317: 
                    318:        // FPcr を空にしておく
                    319:        out("   fmove.l #0,fpcr");
                    320:        out("   fmove.l #0,fpsr");
                    321:        out("   fmove.l #0,fpiar");
                    322:        // 準備
                    323:        switch ($id) {
                    324:         case 0:        // Dn (singleのみ)
                    325:                out("   move.l  #\$55555555,d0");
                    326:                break;
                    327:         case 1:        // An (singleのみ)
                    328:                out("   move.l  #\$55555555,a0");
                    329:                break;
                    330:         case 2:        // (An)
                    331:         case 3:        // (An)+
                    332:         case 4:        // -(An)
                    333:                out("   move.l  #\$55555555,workarea");
                    334:                if ($count >= 2)
                    335:                        out("   move.l  #\$aaaaaaaa,workarea+4");
                    336:                if ($count == 3)
                    337:                        out("   move.l  #\$33333333,workarea+8");
                    338: 
                    339:                if ($id == 4) {
                    340:                        // 後ろ基準
                    341:                        // nofpc でも転送は発生する
                    342:                        out("   lea.l   workarea+%d(pc),a0", $txcount * 4);
                    343:                } else {
                    344:                        // 前から
                    345:                        out("   lea.l   workarea(pc),a0");
                    346:                }
                    347:                break;
                    348:         case 5:        // #imm
                    349:                $cpureg = "#\$55555555";
                    350:                if ($count >= 2)
                    351:                        $cpureg .= ",#\$aaaaaaaa";
                    352:                if ($count == 3)
                    353:                        $cpureg .= ",#\$33333333";
                    354:                break;
                    355:        }
                    356: 
1.1.1.4 ! root      357:        out("   bsr     set_fline");
1.1       root      358:        out("   moveq.l #0,d7");
                    359:        out("   lea.l   @f,a3");
                    360:        // 実行
                    361:        if ($mnem == "nofpc") {
                    362:                out("   .dc.w   $%04x, $%04x", $w1, $w2);
                    363:                // #imm,nofpc はアセンブル出来ないのでここで即値をおく
                    364:                if ($id == 5/*imm*/ && $count == 0) {
                    365:                        out("   .dc.l \$55555555");
                    366:                }
                    367:        } else {
                    368:                out("   fmovem.l {$cpureg},{$mnem}");
                    369:        }
                    370:        out("@@:");
                    371: 
1.1.1.4 ! root      372:        out("   bsr     restore_fline");
1.1       root      373:        // 例外は起きないはずなので D7 はゼロなら成功(次へ)
                    374:        out("   tst.l   d7");
                    375:        out("   beq     @f");
                    376:        out("   PRINT   msg_fail_trap");
                    377:        out("   rts");
                    378:        out("@@:");
                    379: 
                    380:        // 検証
                    381:        $expected = array(
                    382:                0x55555555,
                    383:                0xaaaaaaaa,
                    384:                0x33333333,
                    385:        );
                    386:        $i = 0;
                    387: 
                    388:        // An の変化量が正しいか。
                    389:        // この後のレジスタの検証で A0 を使うのでその前に行う。
                    390:        // (An) なら workarea から変化しない
                    391:        // (An)+ なら workarea+count*4
                    392:        // -(An) なら workarea に戻ってくる (最初にオフセットつけてるので)
                    393:        switch ($id) {
                    394:         case 2:        // (An)
                    395:         case 4:        // -(An)
                    396:                out("   lea.l   workarea(pc),a1");
                    397:                out("   cmpa.l  a1,a0");
                    398:                out("   beq     @f");
                    399:                out_result("msg_fail_addr", "a1", "a0");
                    400:                out("@@:");
                    401:                break;
                    402:         case 3:        // (An)+
                    403:                out("   lea.l workarea+%d(pc),a1", $txcount * 4);
                    404:                out("   cmpa.l  a1,a0");
                    405:                out("   beq     @f");
                    406:                out_result("msg_fail_addr", "a1", "a0");
                    407:                out("@@:");
                    408:                break;
                    409:        }
                    410: 
                    411:        // FPCR
                    412:        out("   fmove.l fpcr,d0");
                    413:        if (($regnum & 4)) {
                    414:                out("   move.l  #$%08x,d1", $expected[$i] & regmask(4));
                    415:                $i++;
                    416:        } else {
                    417:                out("   moveq.l #0,d1");
                    418:        }
                    419:        out("   cmp.l   d1,d0");
                    420:        out("   beq     @f");
                    421:        out_result("msg_fail_cr", "d1", "d0");
                    422:        out("@@:");
                    423: 
                    424:        // FPSR
                    425:        out("   fmove.l fpsr,d0");
                    426:        if (($regnum & 2)) {
                    427:                out("   move.l  #$%08x,d1", $expected[$i] & regmask(2));
                    428:                $i++;
                    429:        } else {
                    430:                out("   moveq.l #0,d1");
                    431:        }
                    432:        out("   cmp.l   d1,d0");
                    433:        out("   beq     @f");
                    434:        out_result("msg_fail_sr", "d1", "d0");
                    435:        out("@@:");
                    436: 
                    437:        // FPIAR
                    438:        out("   fmove.l fpiar,a0");
                    439:        // fmovem *,nofpc は FPIAR が受け取ってしまうようだ
                    440:        if (($regnum & 1) || $regnum == 0) {
                    441:                out("   move.l  #$%08x,a1", $expected[$i] & regmask(1));
                    442:                $i++;
                    443:        } else {
1.1.1.4 ! root      444:                out("   suba.l  a1,a1");
1.1       root      445:        }
                    446:        out("   cmpa.l  a1,a0");
                    447:        out("   beq     @f");
                    448:        out_result("msg_fail_ir", "a1", "a0");
                    449:        out("@@:");
                    450: 
                    451:        out("   tst.l   d7");
                    452:        out("   bne     @f");
                    453:        out("   PRINT   msg_ok");
                    454:        out("@@:");
                    455:        out("   rts");
                    456:        out("");
                    457: }
                    458: 
                    459: // アクセス可能な場合のテスト。FMOVEM <FPcr>,<ea>
                    460: function subr_success_from($regs, $id)
                    461: {
1.1.1.3   root      462:        $cpureg = eanum2mnem($id);
1.1       root      463:        $regnum = reg2num($regs);
                    464:        $mnem = regnum2mnemonic($regnum);
                    465:        $label = eanum2label($id);
                    466: 
                    467:        $funcname = "fmovem_{$regs}_to_{$label}";
1.1.1.3   root      468:        addfunc($funcname, "from", $mnem, $cpureg);
                    469:        out("   PRINT   msg_{$funcname}");
1.1       root      470: 
                    471:        $w1 = 0xf200 | eanum2word($id);
                    472:        $w2 = 0xa000 | ($regnum << 10);
                    473:        // count は指定されたレジスタ数 (0..3)
                    474:        // txcount は転送するレジスタ数 (1..3)
                    475:        $count = regnum2count($regnum);
                    476:        $txcount = ($count == 0) ? 1 : $count;
                    477: 
                    478:        // FPcr に初期値をセット
                    479:        // nofpc の時は FPIAR
                    480:        $expected = array(
                    481:                0x55555555,
                    482:                0xaaaaaaaa,
                    483:                0x33333333,
                    484:        );
                    485:        $i = 0;
                    486:        out("   fmove.l #$%08x,fpcr", ($regnum & 4) ? $expected[$i++] : 0);
                    487:        out("   fmove.l #$%08x,fpsr", ($regnum & 2) ? $expected[$i++] : 0);
                    488:        out("   fmove.l #$%08x,fpiar",
                    489:                (($regnum & 1) || $count == 0) ? $expected[$i++] : 0);
                    490: 
                    491:        // 準備
                    492:        switch ($id) {
                    493:         case 2:        // (An)
                    494:         case 3:        // (An)+
                    495:                out("   lea.l   workarea(pc),a0");
                    496:                break;
                    497:         case 4:        // -(An)
                    498:                // nofpc でも転送は発生する
                    499:                out("   lea.l   workarea+%d(pc),a0", $txcount * 4);
                    500:                break;
                    501:         case 5:        // #imm は dst にならない
                    502:                break;
                    503:        }
                    504: 
1.1.1.4 ! root      505:        out("   bsr     set_fline");
1.1       root      506:        out("   moveq.l #0,d7");
                    507:        out("   lea.l   @f,a3");
                    508:        // 実行
                    509:        if ($mnem == "nofpc")
                    510:                out("   .dc.w   $%04x, $%04x", $w1, $w2);
                    511:        else
                    512:                out("   fmovem.l {$mnem},{$cpureg}");
                    513:        out("@@:");
                    514: 
1.1.1.4 ! root      515:        out("   bsr     restore_fline");
1.1       root      516:        // 例外は起きないはずなので D7 はゼロなら成功(次へ)
                    517:        out("   tst.l   d7");
                    518:        out("   beq     @f");
                    519:        out("   PRINT   msg_fail_trap");
                    520:        out("   rts");
                    521:        out("@@:");
                    522: 
                    523:        // 検証
                    524: 
                    525:        // An の変化量が正しいか
                    526:        // (An) なら workarea から変化しない
                    527:        // (An)+ なら workarea+count*4
                    528:        // -(An) なら workarea に戻ってくる (最初にオフセットつけてるので)
                    529:        switch ($id) {
                    530:         case 2:        // (An)
                    531:         case 4:        // -(An)
                    532:                out("   lea.l   workarea(pc),a1");
                    533:                out("   cmpa.l  a1,a0");
                    534:                out("   beq     @f");
                    535:                out_result("msg_fail_addr", "a1", "a0");
                    536:                out("@@:");
                    537:                break;
                    538:         case 3:        // (An)+
                    539:                out("   lea.l workarea+%d(pc),a1", $txcount * 4);
                    540:                out("   cmpa.l  a1,a0");
                    541:                out("   beq     @f");
                    542:                out_result("msg_fail_addr", "a1", "a0");
                    543:                out("@@:");
                    544:                break;
                    545:        }
                    546: 
                    547:        $i = 0;
                    548:        switch ($id) {
                    549:         case 0:        // Dn
                    550:                for ($r = 4; $r >= 1; $r >>= 1) {
                    551:                        // 各 fpn の該当する時か、nofpc なら FPIAR
                    552:                        if (($regnum & $r) || ($r == 1 && $count == 0)) {
                    553:                                out("   move.l  #$%08x,d1", $expected[$i] & regmask($r));
                    554:                                $i++;
                    555:                                out("   cmp.l   d1,d0");
                    556:                                out("   beq     @f");
1.1.1.4 ! root      557:                                out_result("msg_fail_dst", "d1", "d0");
1.1       root      558:                                out("@@:");
                    559:                        }
                    560:                }
                    561:                break;
                    562:         case 1:        // An
                    563:                for ($r = 4; $r >= 1; $r >>= 1) {
                    564:                        // 各 fpn の該当する時か、nofpc なら FPIAR
                    565:                        if (($regnum & $r) || ($r == 1 && $count == 0)) {
                    566:                                out("   movea.l #$%08x,a1", $expected[$i] & regmask($r));
                    567:                                $i++;
                    568:                                out("   cmp.l   a1,a0");
                    569:                                out("   beq     @f");
1.1.1.4 ! root      570:                                out_result("msg_fail_dst", "a1", "a0");
1.1       root      571:                                out("@@:");
                    572:                        }
                    573:                }
                    574:                break;
                    575:         case 2:        // (An)
                    576:         case 3:        // (An)+
                    577:         case 4:        // -(An)
                    578:                for ($r = 4; $r >= 1; $r >>= 1) {
                    579:                        // 各 fpn の該当する時か、nofpc なら FPIAR
                    580:                        if (($regnum & $r) || ($r == 1 && $count == 0)) {
                    581:                                out("   move.l  #$%08x,d1", $expected[$i] & regmask($r));
                    582:                                out("   cmp.l   workarea+%d,d1", $i * 4);
                    583:                                $i++;
                    584:                                out("   beq     @f");
1.1.1.4 ! root      585:                                out_result("msg_fail_dst",
        !           586:                                        "d1", sprintf("workarea+%d", $i * 4));
1.1       root      587:                                out("@@:");
                    588:                        }
                    589:                }
                    590:                break;
                    591:        }
                    592: 
                    593:        out("   tst.l   d7");
                    594:        out("   bne     @f");
                    595:        out("   PRINT   msg_ok");
                    596:        out("@@:");
                    597:        out("   rts");
                    598:        out("");
                    599: }
                    600: ?>
1.1.1.3   root      601: start2:
1.1       root      602:        clr.l   -(sp)
                    603:        DOS     _SUPER
1.1.1.4 ! root      604:        movem.l d7/a3-a4,-(sp)
1.1.1.3   root      605:        ; rough argument check
                    606:        cmpi.b  #4,(a2)+        ; strlen(arg)>=4 ?
                    607:        bcs     @f
                    608:        cmpi.l  #$68617264,(a2) ; "hard"
                    609:        seq.b   is_hard
                    610: @@:
                    611:        tst.b   is_hard(pc)
                    612:        beq             disp_easy
                    613: disp_hard:
                    614:        PRINT   msg_hard
                    615:        bra             @f
                    616: disp_easy:
                    617:        PRINT   msg_easy
                    618: @@:
1.1       root      619: <?php
1.1.1.3   root      620:        foreach ($funclist as $name => $text) {
                    621:                // FPcr が1つもないケースは hard の時だけ実行。
                    622:                $undef_case = preg_match("/____/", $name);
                    623:                if ($undef_case) {
                    624:                        out("   tst.b   is_hard(pc)");
                    625:                        out("   beq             @f");
                    626:                }
1.1       root      627:                out("   bsr     test_{$name}");
1.1.1.3   root      628:                if ($undef_case) {
                    629:                        out("@@:");
                    630:                }
1.1       root      631:        }
                    632: ?>
1.1.1.4 ! root      633:        movem.l (sp)+,d7/a3-a4
1.1       root      634:        DOS     _EXIT
                    635: 
                    636: ; 結果表示
                    637: ; スタックには、メッセージ、期待値、実際の値の順で積む。
                    638: result:
                    639:        link    a6,#0
                    640:        movem.l d0/a0,-(sp)
                    641: 
                    642:        move.l  8+8(a6),-(sp)
                    643:        DOS     _PRINT
                    644:        addq.l  #4,sp
                    645: 
                    646:        move.l  8+4(a6),d0
                    647:        lea.l   buf(pc),a0
                    648:        bsr     hexstr_long
                    649:        PRINT   buf
                    650:        PRINT   msg_but
                    651: 
1.1.1.3   root      652:        move.l  8+0(a6),d0
1.1       root      653:        lea.l   buf(pc),a0
                    654:        bsr     hexstr_long
                    655:        PRINT   buf
                    656:        PRINT   msg_crlf
                    657: 
                    658:        addq.l  #1,d7   ; errcnt
                    659:        movem.l (sp)+,d0/a0
                    660:        unlk    a6
                    661:        rts
                    662: 
1.1.1.4 ! root      663: ; Fライン例外をテスト用のものに差し替える。
        !           664: ; 変更前のアドレスを a4 に格納する。
        !           665: ; a1 は破壊する。
        !           666: set_fline:
        !           667:        movem.l d0-d1,-(sp)
        !           668:        moveq.l #$b,d1
        !           669:        lea.l   fline_handler(pc),a1
        !           670:        IOCS    _B_INTVCS
        !           671:        movea.l d0,a4
        !           672:        movem.l (sp)+,d0-d1
        !           673:        rts
        !           674: 
        !           675: ; Fライン例外を元に戻す。
        !           676: ; a1 は破壊する。
        !           677: restore_fline:
        !           678:        movem.l d0-d1,-(sp)
        !           679:        moveq.l #$b,d1
        !           680:        movea.l a4,a1
        !           681:        IOCS    _B_INTVCS
        !           682:        movem.l (sp)+,d0-d1
        !           683:        rts
        !           684: 
1.1       root      685: ; Fライン例外ハンドラ
                    686: ; a3 に戻りアドレスをセットしてあること
                    687: ; d7 を 1 にして帰る
                    688: fline_handler:
                    689:        moveq.l #1,d7
                    690:        move.l  a3,2(sp)
                    691:        rte
                    692: 
1.1.1.3   root      693: msg_hard:      .dc.b   "hard mode",$d,$a,0
                    694: msg_easy:      .dc.b   "easy mode",$d,$a,0
1.1       root      695: msg_oktrap:    .dc.b   $9,"ok(trap)",$d,$a,0, 0,0
                    696: msg_fail_notrap:       .dc.b   $9,"FAIL: trap expected but not occured",$d,$a,0
                    697: msg_fail_trap: .dc.b   $9,"FAIL: unexpected trap occured",$d,$a,0
                    698: 
                    699: msg_ok:                .dc.b   $9,"ok",$d,$a,0
                    700: msg_fail_cr:   .dc.b   $9,"FAIL: fpcr expects ",0
                    701: msg_fail_sr:   .dc.b   $9,"FAIL: fpsr expects ",0
                    702: msg_fail_ir:   .dc.b   $9,"FAIL: fpiar expects ",0
                    703: msg_fail_addr: .dc.b   $9,"FAIL: an expects ",0
1.1.1.4 ! root      704: msg_fail_dst:  .dc.b   $9,"FAIL: dst expects ",0
1.1       root      705: msg_but:       .dc.b   " but ",0
                    706: msg_crlf:      .dc.b   $d,$a,0
                    707: 
                    708: 
                    709: <?php
1.1.1.3   root      710:        foreach ($funclist as $name => $text) {
                    711:                out("msg_{$name}:       .dc.b   \"{$text}\",0");
1.1       root      712:        }
                    713: ?>
                    714: 
                    715:        .data
                    716:        .even
                    717: workarea:      .ds.b   24
1.1.1.3   root      718: buf:           .ds.b   20
                    719: is_hard:       .ds.b   1
1.1       root      720: 
                    721:        .end    start

unix.superglobalmegacorp.com

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