メモリカウント高速化

CPUのL2チェッカを改変してTualatinも載るようになったRvII26ですが、もうひとつ大きな不満があります。
それは「メモリカウントが非常に遅い」コト。
ということで今回はメモリチェックの簡素化による高速終了を目指します。

メモリチェック個所の確認

メモリチェックもITF内の処理なので前回同様BANK4.BINを解析します。
ですが、範囲が広く一箇所にまとまっていないので余り詳しく解説できません(謝
ポイントのみを例示していくことにするのでご勘弁ください。
メモリチェックの基本ルーチンは

:0E5B B80800          mov     ax,0008   ; メモリチェックループ前処理
:0E5E 8ED8            mov     ds,ax
:0E60 C606440010      mov     byte ptr [0044],10
:0E65 C606470000      mov     byte ptr [0047],00
:0E6A 66BA00001000    mov     edx,00100000
:0E70 8AF7            mov     dh,bh
:0E72 B008            mov     al,08     ; メモリチェックループ入り口
:0E74 E637            out     37,al     ; パリティチェック有効:8255コマンド

から

:0FF2 668BC2          mov     eax,edx
:0FF5 66C1E810        shr     eax,10
:0FF9 3DF0FF          cmp     ax,FFF0   ; チェック終了?
:0FFC 7303            jnb     1001      ; (YES)ループ終了
:0FFE E971FE          jmp     0E72      ; (NO )チェック継続
	

のループが主となっています。(もちろんこの後もECCチェック等あるのですが)
よって、このループの中で行われている処理を簡略化すればメモリチェックも高速になるというわけですね。

8倍速化

ではさっそく始めます。
PC-9821のメモリチェックは、128KBごとのチェックポイントに対しデータの書き込みと検証を行うことが基本になっています。
そこでこのチェック間隔を広げることでループ回数を減らそうという考えです。
N.Y氏のサイトにもありますが

:0FA2 B80800          mov     ax,0008
:0FA5 8ED8            mov     ds,ax
:0FA7 8006440002      add     byte ptr [0044],02
:0FAC 8016470000      adc     byte ptr [0047],00
:0FB1 6681C200000200  add     edx,00020000
:0FB8 B070            mov     al,70
:0FBA E6A1            out     A1,al
:0FBC B057            mov     al,57
:0FBE E6A3            out     A3,al
:0FC0 B020            mov     al,20
:0FC2 E6A5            out     A5,al
:0FC4 E4A9            in      al,A9
:0FC6 A880            test    al,80
:0FC8 BCCE0F          mov     sp,0FCE
:0FCB E96BFC          jmp     0C39
:0FCE EB22            jmp     0FF2
:0FD0 90              nop     
	

ここがそうで、このロジックで次のチェック位置を決定しています。
0044h〜0048hがワークエリアでlong形式のデータとして格納され、同じ内容がedxレジスタにも入ります。
よって[0044]に加算している02hとedxレジスタに加えている00020000hを変更すればOKです。
8倍速なので02=>10、00020000=>00100000です。

しかし、これだけではカウント終了後に再びカウントが始まってしまいます。
これを回避するにはPCIレジスタのエラー通知を不可にする必要があります。
powerx氏の掲示板でまりも氏が解説してくれていますのでご覧になってください。
実際の修正ポイントは

:42A8 4600FC          db      46h,00h,0FCh  ; REG 46の設定値 FC=>F8
:4323 4600FC          db      46h,00h,0FCh  ; REG 46の設定値 FC=>F8
	

の2箇所あります。

さらにもう一か所、レジスタ47hをチェックしているルーチンがあります。

:1E6E A804            test    al,04
:1E70 241B            and     al,1B         ; REG 47hのエラー検出を潰す
:1E72 FFE5            jmp     bp
	

これでOKですね。

もうすこし欲張る

上記処理を施した場合、512MB搭載で約20秒になるかと思います。
実際、SCSI機器のスピンアップを待つ時間もあるのでこれでも良いと思いますが、もう少し早くしたい気分です。
powerx氏のサイトやN.Y氏のサイトではメモリーフィルと確認ルーチンをパスする手法が記載されていますが、nicoは別のアプローチでやりました。

:0EEC 6633C0          xor     eax,eax
:0EEF 6766268947F4    mov     es:[edi-0C],eax
:0EF5 66B801000000    mov     eax,00000001
:0EFB 6766268907      mov     es:[edi],eax
:0F00 66F7D0          not     eax
:0F03 6766268947F4    mov     es:[edi-0C],eax
:0F09 66F7D0          not     eax
:0F0C 6766263907      cmp     es:[edi],eax
:0F11 7407            jz      0F1A
:0F13 6683C704        add     edi,+04
:0F17 E92301          jmp     103D
:0F1A 66F7D0          not     eax
:0F1D 6766263947F4    cmp     es:[edi-0C],eax
:0F23 7407            jz      0F2C
:0F25 6683EF08        sub     edi,+08
:0F29 E91101          jmp     103D
:0F2C 66F7D0          not     eax
:0F2F 66D1E0          shl     eax,01
:0F32 73C7            jnb     0EFB
というチェックを
:0F32 7200            jb      0F34
としてループしないよう変更し、

:0F34 B009            mov     al,09
:0F36 E637            out     37,al
の後を
:0F38 EB68            jmp     0FA2
としてスキップしました。
	

これで更に3倍程度早くなります。
512MB実装で約7秒。なかなか気分が良いものです


Valid CSS! Valid HTML 4.01 Strict