--- nono/exp/fmovemn.php 2026/04/29 17:04:28 1.1 +++ nono/exp/fmovemn.php 2026/04/29 17:05:28 1.1.1.3 @@ -1,11 +1,31 @@ ; ; nono -; Copyright (C) 2019 isaki@NetBSD.org +; Copyright (C) 2020 nono project ; +; Redistribution and use in source and binary forms, with or without +; modification, are permitted provided that the following conditions +; are met: +; 1. Redistributions of source code must retain the above copyright +; notice, this list of conditions and the following disclaimer. +; 2. Redistributions in binary form must reproduce the above copyright +; notice, this list of conditions and the following disclaimer in the +; documentation and/or other materials provided with the distribution. +; +; THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +; IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +; OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +; IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +; INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +; BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +; AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +; OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +; OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +; SUCH DAMAGE. ; How to compile: -; > has fmovem_n.has -; > hlk fmovem_n.o si_util.o +; > has fmovemn.has +; > hlk fmovemn.o si_util.o .xref hexstr_long .include doscall.mac @@ -30,6 +50,9 @@ RESTORE_FLINE_TRAP .macro .text .even +start: + bra start2 + "..m+..", // fmovem EA,fp1-fp2 - 1/* to FP, pred, dynamic */ => "..m+..", // fmovem EA,d6 - 2/* to FP, ctrl, static */ => "..m+..", // fmovem EA,fp1-fp2 - 3/* to FP, ctrl, dynamic */ => "..m+..", // fmovem EA,d6 - 4/* from FP, pred, static */ => "..m.-.", // fmovem fp1-fp2,EA - 5/* from FP, pred, dynamic */ => "..m.-.", // fmovem d6,EA - 6/* from FP, ctrl, static */ => "..m.-.", // fmovem fp1-fp2,EA - 7/* from FP, ctrl, dynamic */ => "..m.-.", // fmovem d6,EA + // '.' はこの EA はドキュメントにないので検査しない (easy)。 + // '!' はこの EA は例外が起きることを検査する (hard)。 + $srctable = array( + // easy hard + // mode2,1 dam+-rxwpi dam+-rxwpi + 0/*toFP, pred*/ => ".......... !!m+!rxwp!", + 1/*toFP, ctrl*/ => "..m+.rxwp. !!m+!rxwp!", + 2/*fromFP, pred*/ => "....-..... !!m!-rxw!!", + 3/*fromFP, ctrl*/ => "..m..rxw.. !!m!-rxw!!", ); - foreach ($table as $mode => $eastr) { - $ealist = preg_split("//", $eastr, -1, PREG_SPLIT_NO_EMPTY); - for ($id = 0; $id < 6; $id++) { - $ea = $ealist[$id]; - if ($ea == ".") { - // 許されない組み合わせ - subr_fail($mode, $id); - } else { - if ($mode < 4) { - subr_to($mode, $id); + foreach ($srctable as $mode21 => $eastr) { + list($easy_str, $hard_str) = preg_split('/\s+/', $eastr); + $easy_ea = preg_split("//", $easy_str, -1, PREG_SPLIT_NO_EMPTY); + $hard_ea = preg_split("//", $hard_str, -1, PREG_SPLIT_NO_EMPTY); + for ($mode0 = 0; $mode0 <= 1; $mode0++) { + $mode = $mode21 * 2 + $mode0; + // …のはずだが rxwpi の検査は + // 追加の命令ワード部分を生バイナリで用意しないといけないため + // ちょっと保留。 + for ($id = 0; $id < 5; $id++) { + $ee = $easy_ea[$id]; + $eh = $hard_ea[$id]; + $is_easy = ($ee != '.'); // easy でも検査するか? + if ($eh == "!") { + // 許されない組み合わせの命令。 + subr_fail($mode, $id, $is_easy); } else { - subr_from($mode, $id); + if ($mode < 4) { + subr_to($mode, $id, $is_easy); + } else { + subr_from($mode, $id, $is_easy); + } } } } @@ -89,6 +118,7 @@ function out() // mode 番号(下2bit)からラベル文字列に。 function mode2label($mode) { + $rv = ""; $rv .= (($mode & 2) == 0) ? "pred" : "ctrl"; $rv .= (($mode & 1) == 0) ? "_sta" : "_dyn"; return $rv; @@ -112,18 +142,26 @@ function mode2fplist($mode) function eanum2word($id) { switch ($id) { - case 0: // D0 - return 0 << 3; - case 1: // A0 - return 1 << 3; - case 2: // (A0) - return 2 << 3; - case 3: // (A0)+ - return 3 << 3; - case 4: // -(A0) - return 4 << 3; - case 5: // #imm - return 0x3c; + case 0: // d: D0 + return 000; + case 1: // a: A0 + return 010; + case 2: // m: (A0) + return 020; + case 3: // +: (A0)+ + return 030; + case 4: // -: -(A0) + return 040; + case 5: // r: d16(An) + return 050; + case 6: // x: d8(An,IX) + return 060; + case 7: // w: Abs + return 070; + case 8: // p: (PC,IX) + return 072; + case 9: // i: #imm + return 074; } } @@ -136,7 +174,11 @@ function eanum2label($id) 2 => "anin", 3 => "anpi", 4 => "anpd", - 5 => "imm", + 5 => "anid", + 6 => "anix", + 7 => "abs", + 8 => "pcix", + 9 => "imm", ); return $idstr[$id]; } @@ -150,14 +192,51 @@ function eanum2mnem($id, $n = 0) case 2: return "(a{$n})"; case 3: return "(a{$n})+"; case 4: return "-(a{$n})"; + case 5: return "d16(a{$n})"; + case 6: return "d8(a{$n},ix)"; + case 7: return "abs"; + case 8: return "(pc,ix)"; + case 9: return "#imm"; } + return ""; } -function addfunc($name) +function addfunc($name, $mode, $cpureg, $is_easy) { global $funclist; + global $easylist; + + $text = "fmovem.l "; + switch ($mode) { + case 0: + case 2: + $text .= "{$cpureg},fplist"; + break; + case 1: + case 3: + $text .= "{$cpureg},d6"; + break; + case 4: + case 6: + $text .= "fplist,{$cpureg}"; + break; + case 5: + case 7: + $text .= "d6,{$cpureg}"; + break; + case "nofpn": + $text .= "nofpn,{$cpureg}"; + break; + case "illegal": + // ニーモニックでは伝わらない… + $text .= "{$cpureg},d6_illegal"; + break; + } - $funclist[] = $name; + $funclist[$name] = $text; + if ($is_easy) { + $easylist[$name] = true; + } out("test_{$name}:"); out(" PRINT msg_{$name}"); } @@ -174,15 +253,16 @@ function out_result($msg, $exp, $act) // 許されない組み合わせのテスト。 // Fライン例外が起きることをチェックする。 -function subr_fail($mode, $id) +function subr_fail($mode, $id, $is_easy) { $modestr = mode2label($mode); $ealabel = eanum2label($id); + $cpureg = eanum2mnem($id); $funcname = ($mode & 4) == 0 ? "fmovem_{$ealabel}_to_fpn_{$modestr}" : "fmovem_fpn_to_{$ealabel}_{$modestr}"; - addfunc($funcname); + addfunc($funcname, $mode, $cpureg, $is_easy); $w1 = 0xf200 | eanum2word($id); $w2 = 0xc060 | ($mode << 11); @@ -207,13 +287,14 @@ function subr_fail($mode, $id) } // 実行できる組み合わせなら動作確認。EA to FPn -function subr_to($mode, $id) +function subr_to($mode, $id, $is_easy) { $modestr = mode2label($mode); $ealabel = eanum2label($id); + $cpureg = eanum2mnem($id); $funcname = "fmovem_{$ealabel}_to_fpn_{$modestr}"; - addfunc($funcname); + addfunc($funcname, $mode, $cpureg, $is_easy); $w1 = 0xf200 | eanum2word($id); $w2 = 0xc060 | ($mode << 11); @@ -291,13 +372,14 @@ function subr_to($mode, $id) } // 実行できる組み合わせなら動作確認。FPn to EA -function subr_from($mode, $id) +function subr_from($mode, $id, $is_easy) { $modestr = mode2label($mode); $ealabel = eanum2label($id); + $cpureg = eanum2mnem($id); $funcname = "fmovem_fpn_to_{$ealabel}_{$modestr}"; - addfunc($funcname); + addfunc($funcname, $mode, $cpureg, $is_easy); $w1 = 0xf200 | eanum2word($id); $w2 = 0xc060 | ($mode << 11); @@ -389,7 +471,7 @@ function subr_from($mode, $id) +addfunc("fmovem_nofpn", "nofpn", "(a0)", false); ?> lea.l initdata(pc),a0 +addfunc("fmovem_illegal_dyn", "illegal", "(a0)", false); ?> lea.l initdata(pc),a0 // lea.l $0000002c.l,a5 だと has.x に絶対アドレッシングだと // 怒られてしまうため仕方なく ?> -start: +start2: clr.l -(sp) DOS _SUPER movem.l d6-d7/a2-a5,-(sp) moveq.l #$2c,d0 ; alternate of "lea.l $2c,a5" move.l d0,a5 ; + moveq.l #0,d0 + fmove.l d0,fpcr ; Init FPCR, especially round mode and round prec. + + ; rough argument check + ;moveq.l #0,d0 ; d0 is already cleared. + cmpi.b #4,(a2)+ ; strlen(arg)<4 ? + bcs @f + cmpi.l #$68617264,(a2) ; "hard" + seq.b d0 +@@: + tst.b d0 + bne hardmode +easymode: + PRINT msg_easy + $dummy) { + out(" bsr test_{$name}"); + } +?> + bra done + +hardmode: + PRINT msg_hard $text) { out(" bsr test_{$name}"); } ?> + +done: movem.l (sp)+,d6-d7/a2-a5 DOS _EXIT @@ -587,6 +694,8 @@ srcdata: zerodata: .dc.l $0, $0, $0 +msg_hard: .dc.b "hard mode",$d,$a,0 +msg_easy: .dc.b "easy mode",$d,$a,0 msg_oktrap: .dc.b $9,"ok(trap)",$d,$a,0, 0,0 msg_fail_notrap: .dc.b $9,"FAIL: trap expected but not occured",$d,$a,0 msg_fail_trap: .dc.b $9,"FAIL: unexpected trap occured",$d,$a,0 @@ -607,14 +716,14 @@ msg_but: .dc.b " but ",0 msg_crlf: .dc.b $d,$a,0 $text) { + out("msg_{$name}: .dc.b \"{$text}\",0"); } ?> .data .even workarea: .ds.b 24 -buf: .dc.b 64 +buf: .ds.b 64 .end start