トップ 差分 一覧 ソース 検索 ヘルプ RSS ログイン

fd1094_hardware_note

調査環境は以下の通りです。

  • 猫屋敷解析機の実機調査向けカスタム版
  • FD1094 実機 (主に 317-0127A)

68000 の端子に任意の信号を送りながら調査しました。中身を分解したわけではありません。

block diagram 予想図

調査の結果この図のような構成になっていると予想されます。


今回の調査で判明した既知の解析情報と異なる部分は instruction detector で、この機能について詳しく説明します。

FD1094 block

おおまかな分け方として、下記の点が言えるでしょう。

  • 68000 core から外部へは databus と FC 以外は同じ仕様
  • read 用 databus は read cycle data controller を介す
    • この block は 68000 core から出る外部向け信号を取り込んでおり、 68000 での中間的なデータは使っていない

  FC の出力

内部的には 68000 同様の FC 信号を利用しており、外部向けへ加工して出力しているものと思われます。

  • CPU SPACE: 内部:3'b111 -> 外部:3'b111
  • CPU SPACE 以外: 外部:3'b000
    • user/supervisor data: 内部:3'bx01-> 外部:3'b000
    • user/supervisor program: 内部:3'bx10-> 外部:3'b000

read cycle data controller

  decrypter

この機能は external read data を条件に従って bitwise operation を行います。

  • CPU address を元に static RAM address を生成
  • CPU address を元に static RAM data を instrction detector へ出力 (図では flag)
  • static RAM data と instrction detector からの state register (図では state) を元に中間データを生成

bitwise operation は現状の解析情報で問題ありません。

  instruction detector

この機能は decrypter から入力された中間データと bus の状況を元に internal read data への出力と state register の出力と更新を行います。

  • 中間データを元に下記の命令を検出する
    • ALL PC-relative addressing instruction
    • JMP/JSR/Bcc/DBcc instruction (flag で使用可能か制御できる)
    • RTE instruction
  • CPU bus control から下記の memory cycle の検出
    • interrupt acknowledge cycle
    • read memory cycle

  命令検出

この機能は CPU のバスの情報をもとに動作していますが、命令の検出は非常に単純です。68000 の命令は複数の word で構成されていますが、この機能で 1 word 単位だけの単純な検出です。

例1) RTE

move.w #0x4e73,d0 (内部:0x303c 0x4e73) でも 2 word 目の 0x4e73 をRTE として検出。

このため実際に使われているソフトではこのような命令を生成しないように回避をしています。

例2) BRA

move.w 0x126000,d0 (内部:0x3039 0x0012 0x6000) でも 3 word 目の 0x6000 を BRA として検出。0x6000 として渡すには flag の設定が必要。


  PC-relative addressing instruction

PC-relative addressing は様々な理由から使用が禁止されており、このブロックがこの data を検出した場合は下記の動作を行います。

  • internal read data を 0xffff にして CPU へ渡す
  • memory read cycle 終了後, 1つ前の instrcution data を元に state register を更新

state register の更新条件

cmpi.l #0xnnmmffff,d0 の実行と説明されていますがこれは正確ではありません。 PC-relative instruction の検出が必要な条件であり、 cmpi.l (内部:0x0c80) は必要ありません。

これを元に調査したところ、既存のソフトでは cmpi.l #$nnmmffff,d0 の 3 word 目は外部から 0x013b が渡されます(注)。 decrypter 部では外部データとして 0x0000 から 0x1fff を渡されると RAM の data に無関係で簡単な復号が行われます。その中で PC-relative addressing を含むのは 0x013a と 0x013b の2つです。(0x013a と 0x013b は RAM に無関係かつ内部と外部の値が同じです)

注:ソフトを10個ほど調査しましたが、すべて外部 data は 0x013b でした。0x013b 以外の PC-relative addressing でも state resgister は更新できますが、実際に使用したソフトはないと思われます。

prefetch とレジスタ更新

PC-relative addressing の調査のために命令は下記のように記述し、別の不具合を見つけました。

  tst.b  0x4000ffff  ;0a39 0000 013b
  pea    testvalue.l ;0e79 xxxx yyyy
  rts                ;0e75

  • この命令は xxxx と yyyy を変更しながらループにして実行します。
  • tst.b は state register の更新のために使う命令です。
    • 2 word 目に state register の値をいれて初期化します。
    • 3 word 目に 0x013b を含めます。
  • pea testvalue.l の出力を収集します。
    • xxxx の値は state register 0x00 として出力します。
    • xxxx の値が pc-relative の場合、xxxx に対する出力は 0xffff になり, state register が 0x79 になると予想されていました。
    • 実際の yyyy の値の出力は state register 0x79 にはならず、 0xff になっていました。

この命令実行を memory cycle 単位で調査しました。

access   fc  address data ULDS
------------------------------
xxxREAD  0.6 000008  0a39 00
xxxREAD  0.6 00000a  0100 00
xxxREAD  0.6 00000c  013b 00
xxxREAD  0.6 00000e  0879 00 prefetch
xxxREAD  0.5 00fffe  tttt 10 access for tst.b
xxxREAD  0.6 000010  xxxx 00
xxxREAD  0.6 000012  yyyy 00
xxxREAD  0.6 000014  0e75 00
MEMWRITE 0.5 ff4000  ffff 00
MEMWRITE 0.5 ff4002  YYYY 00
xxxREAD  0.6 000016  0e71 00 discard prefetch
xxxREAD  0.6 ff4000  0000 00
xxxREAD  0.6 ff4002  0008 00
xxxREAD  0.6 000008  0a39 00

重要なのが address 0x00ffff への参照で、pea 命令の 1 word 目を読んでから、 tst.b のメモリアクセスを行います。 xxxx が pc-relative addressing の場合は yyyy の出力から state register が切り替わった値になります。

ここで xxxx を 0x013a に固定し、 tttt と yyyy の値の相関性を調査したところ、 tttt の値は命令として復号した値が state register に入り、yyyy の出力に影響することがわかりました。instruction detector 内部では1つ前の decrypter から渡された復号データを FC, UDS, LDS, 0xffff補正の値に無条件で保持し、更新パラメータとして使用します。

  • tttt の復号パラメータ
    • 外部データバス16bitすべて. bit15:8 も有効.
    • CPU address:0x00fffe -> static RAM address:0x1fff, data:0xf0
    • 内部 FC は 5 なので、この復号値は CPU には渡されない
    • detector が CPU へ渡す補正値の 0xffff ではなく decrypter の出力値を保持し、state register の値として利用する
      • 外部 0x013b (decrypter:0x013b (pc-relative), detector:0xffff) を渡したところ, state register は 0x3b に更新された
      • 外部 0x6090, (decrypter:0x60b3 (bra, 禁止設定), detector:0xffff) を渡したところ, state register は 0xb3 に更新された
  • 予想しづらいこの挙動は以下の2通りで回避できます。
    • tst.b 0x000ffff と pea の間に nop 命令を挿入し、 pea 命令読み込み前に memory access を起こす
    • tst.b 0x000ffff を or.l #0x0100ffff,d0 に変更し、 memory access をしない

prefetch 破棄の対応

68000 には prefetch 機能がありますが、このブロックでは prefetch の破棄も検出出来ません。例えば RTS 命令を実行するとき、 CPU は RTS の次の word の data を読み込んだあとに破棄します。破棄されるはずの data が PC-relative を検出した場合も通常通り state register の更新が行われます。 (この場合 pc-relative の前の instruction data は 0x4e75 なので state register は 0x75 になる)

このため実際に使われているソフトでは RTS (外部:0x0e75, 内部:0x4e75) のあとに nop 命令 (外部:0x0e71, 内部:0x4e71) をいれているものがいくつか存在します。

  JMP/JSR/Bcc/DBcc instruction

Jump, Branch の命令は解析防止のためなのか使用フラグが RAM data に含まれています。

  • 使用フラグが禁止の場合は internal read data を 0xffff にして CPU へ渡す
    • state register の更新は行われません。
  • 使用フラグが許可の場合は中間データを加工せずにCPU へ渡す
    • JMP, JSR の PC-relative addressing は利用可能で、 state register も更新されない

実際のソフトでは禁止フラグを元に 0xffff を CPU core に渡すことはありませんが、動作させてみたところ state register の更新は行われませんでした。
例えば lea 0xffffc000,A0 (外部 0x41f9 0xffff 0xc000) の 2 word 目は decrypter から 0xffff が渡される data を利用しています。

  RTE instruction

RTE 命令は RAM 未参照データで 外部:0x0e73 → 内部:0x4e73 に復号され, IRQ mode register が更新されます。

  • memory read cycle 終了後, state register (IRQ mode) を更新 (=0)

  interrupt acknowledge cycle

外部割り込みを受け付けると IRQ mode register が更新されます。

  • interrupt acknowledge cycle 終了後, state register (IRQ mode) を更新 (=1)

  data selector

この block では decrypter を介したデータを CPU に渡すか制御します。

  • FC bit 1:0 == 2'b10 の場合は復号データを渡す
  • それ以外の FC では外部データを加工せずに渡す (注:interrupt acknowledge cycle も含む)

調査したところ System16A のみ、 interrupt acknowledge cycle に databus と dtack を有効にして vector number を CPU へ渡しています。他のハードウェアではすべて autovector を利用していました。