非専門的シンギュラリティー研究所

無限に動き続けるシステムを表す方法を AI なども使って考えていきます。

X68000(29)

X68000 用の線を描画する関数をコンパイラの出力を使って書き直しました。コンパイラの出力と同じ呼び出しの形式にしておくと、この関数を使う関数をコンパイラの出力で書けるというメリットがあります。

この関数を使う関数の中で浮動小数点のファンクションコールを使うようになる予定です。

ピクセルを描画する関数(インラインアセンブラ)

スーパーバイザーモードで、ピクセルの位置と色を指定して描画します。本来は画面のモードによって切り替える必要がありますが、まだ実装していません。ピクセルごとに切り分けると負荷が大きいのでどこで切り分けるか検討中です。

asm(
    "pset_only_a:\n\t"
    "movem.l  %d0-%d2/%a0, -(%sp)\n\t"
    "move.l   20(%sp), %d1\n\t"
    "move.l   24(%sp), %d2\n\t"
    "movea.l  %d1, %a0\n\t"
    "adda.l   %d1, %a0\n\t"  // a0 = x1 * 2
    "moveq.l  #10, %d0\n\t"
    "lsl.l    %d0, %d2\n\t"  // d2 = y1 * 1024
    "adda.l   %d2, %a0\n\t"  // a0 = x1 * 2 + y1 * 1024
    "adda.l   #0xc00000, %a0\n\t" // a0 = 0xc00000 + x1 * 2 + y1 * 1024
    "move.w   28(%sp), %d0\n\t"
    "move.w   %d0, (%a0)\n\t"
    "movem.l  (%sp)+, %d0-%d2/%a0\n\t"
    "rts\n\t"
);

線を描画する関数(インラインアセンブラ)

C++ コンパイラの出力から作成しました。C++ 内部の関数を呼び出していますが、このままでも動作します。コンパイラ依存になると困るのでこのような関数は作る必要があります。

asm(
    "drawlinex_a:\n\t"
    "movem.l #7966,-(%sp)\n\t"
    "move.l 44(%sp),%a4\n\t"
    "move.l 48(%sp),%a3\n\t"
    "move.l 52(%sp),%d7\n\t"
    "move.l 56(%sp),%d6\n\t"
    "move.l 60(%sp),%d5\n\t"
    "move.l %d7,%d3\n\t"
    "sub.l %a4,%d3\n\t"
    "move.l %d6,%d4\n\t"
    "sub.l %a3,%d4\n\t"
    "move.l %d4,%d1\n\t"
    "jpl dlxxL100\n\t"
    "neg.l %d1\n\t"
    "dlxxL100:\n\t"
    "move.l %d3,%d0\n\t"
    "jpl dlxxL101\n\t"
    "neg.l %d0\n\t"
    "dlxxL101:\n\t"
    "cmp.l %d1,%d0\n\t"
    "jle dlxxL99\n\t"
    "moveq #0,%d6\n\t"
    "lea __divsi3,%a5\n\t"
    "lea pset_only_a,%a6\n\t"
    "tst.l %d3\n\t"
    "jlt dlxxL102\n\t"
    "dlxxL103:\n\t"
    "cmp.l %a4,%d7\n\t"
    "jgt dlxxL104\n\t"
    "dlxxL98:\n\t"
    "movem.l (%sp)+,#30968\n\t"
    "rts\n\t"
    "dlxxL104:\n\t"
    "move.l %d5,-(%sp)\n\t"
    "move.l %d3,-(%sp)\n\t"
    "move.l %d6,-(%sp)\n\t"
    "jsr (%a5)\n\t"
    "addq.l #8,%sp\n\t"
    "pea (%a3,%d0.l)\n\t"
    "move.l %a4,-(%sp)\n\t"
    "jsr (%a6)\n\t"
    "addq.l #1,%a4\n\t"
    "add.l %d4,%d6\n\t"
    "lea (12,%sp),%sp\n\t"
    "jra dlxxL103\n\t"
    "dlxxL105:\n\t"
    "move.l %d5,-(%sp)\n\t"
    "move.l %d3,-(%sp)\n\t"
    "move.l %d6,-(%sp)\n\t"
    "jsr (%a5)\n\t"
    "addq.l #8,%sp\n\t"
    "pea (%a3,%d0.l)\n\t"
    "move.l %a4,-(%sp)\n\t"
    "jsr (%a6)\n\t"
    "subq.l #1,%a4\n\t"
    "sub.l %d4,%d6\n\t"
    "lea (12,%sp),%sp\n\t"
    "dlxxL102:\n\t"
    "cmp.l %a4,%d7\n\t"
    "jlt dlxxL105\n\t"
    "jra dlxxL98\n\t"
    "dlxxL99:\n\t"
    "moveq #0,%d7\n\t"
    "lea __divsi3,%a5\n\t"
    "lea pset_only_a,%a6\n\t"
    "tst.l %d4\n\t"
    "jlt dlxxL107\n\t"
    "dlxxL108:\n\t"
    "cmp.l %a3,%d6\n\t"
    "jle dlxxL98\n\t"
    "move.l %d5,-(%sp)\n\t"
    "move.l %a3,-(%sp)\n\t"
    "move.l %d4,-(%sp)\n\t"
    "move.l %d7,-(%sp)\n\t"
    "jsr (%a5)\n\t"
    "addq.l #8,%sp\n\t"
    "pea (%a4,%d0.l)\n\t"
    "jsr (%a6)\n\t"
    "addq.l #1,%a3\n\t"
    "add.l %d3,%d7\n\t"
    "lea (12,%sp),%sp\n\t"
    "jra dlxxL108\n\t"
    "dlxxL110:\n\t"
    "move.l %d5,-(%sp)\n\t"
    "move.l %a3,-(%sp)\n\t"
    "move.l %d4,-(%sp)\n\t"
    "move.l %d7,-(%sp)\n\t"
    "jsr (%a5)\n\t"
    "addq.l #8,%sp\n\t"
    "pea (%a4,%d0.l)\n\t"
    "jsr (%a6)\n\t"
    "subq.l #1,%a3\n\t"
    "sub.l %d3,%d7\n\t"
    "lea (12,%sp),%sp\n\t"
    "dlxxL107:\n\t"
    "cmp.l %a3,%d6\n\t"
    "jlt dlxxL110\n\t"
    "jra dlxxL98\n\t"
);

線を描画する関数(インラインアセンブラの関数を呼び出す関数)

変数をいったん別の領域にコピーして渡しています。今のところこれ以外のやり方はわかっていません。この関数でスーパーバイザーモードに入ります。

void drawlinex(int x1, int y1, int x2, int y2, COLORREF color)
{
    asm(
        "move.l   %0, dlxxx1\n\t"
        "move.l   %1, dlxxy1\n\t"
        "move.l   %2, dlxxx2\n\t"
        "move.l   %3, dlxxy2\n\t"
        "move.w   %4, dlxxcolor\n\t"
        "clr.l	  -(%%sp)\n\t"
        "dc.w	  0xff20\n\t"      // _SUPER (スーパーバイザーモードへ)
        "move.l   %%d0, (%%sp)\n\t"

        "move.w   dlxxcolor, -(%%sp)\n\t"
        "move.l   dlxxy2, -(%%sp)\n\t"
        "move.l   dlxxx2, -(%%sp)\n\t"
        "move.l   dlxxy1, -(%%sp)\n\t"
        "move.l   dlxxx1, -(%%sp)\n\t"
        "move.l   #0, -(%%sp)\n\t"
        "jsr     drawlinex_a\n\t"
        "add.l    #22,%%sp\n\t"

        "dc.w	  0xff20\n\t"      // _SUPER (スーパーバイザーモードから戻る)
        "addq.l   #4, %%sp\n\t"
        "jmp      dlxxexit\n\t"
        "dlxxx1: dc.l 0\n\t"
        "dlxxy1: dc.l 0\n\t"
        "dlxxx2: dc.l 0\n\t"
        "dlxxy2: dc.l 0\n\t"
        "dlxxcolor: dc.w 0\n\t"
        "dlxxexit:\n\t"
        :
        : "r"(x1), "r"(y1), "r"(x2), "r"(y2), "r"(color) // 入力
        : "d0"                                           // 使用するレジスタ
        );
}