私はエミュレーションプログラミングを学ぼうとしています。私は CHIP-8 エミュレーター、40 歳未満の命令を実行し、自分の音楽のために生きてきました。私は今、SNES のようなもう少し複雑なことをしたいと考えています。私が直面している問題は、膨大な数の CPU 命令です。wiki.SuperFamicom.org 65c816の説明書一覧を見ると、後頭部の痛みのように見えます。また、さまざまなインターネット ページで、CPU がエミュレーターの中で最も実装しやすい部分であるというメモをあちこちで見てきました。
自分のやり方が間違っていたので大変だったのだろうと思い、周りを見回して簡単な実装を見つけました。SNES エミュレーターを 15 分で作成できます。これは約 900 行のコードです。簡単に作業できます。
というわけで、15分ほどでSNES Emulatorのソースから、CPUの命令がどこにあるのかを見つけました。見た目は思っていたよりずっとシンプル。よくわかりませんが、大量のコードとは対照的に、数行のコードです。私が最初に気付くのは、指示にはそれぞれ 1 つの含意しかないということです。スーパーファミコンの表を見ると、
ADC #const
ADC (_db_),X
ADC (_db_,X)
ADC addr
ADC long
...
そして、(私が思うに)それらすべてのエミュレータソースは次のとおりです。
// Note: op 0x100 means "NMI", 0x101 means "Reset", 0x102 means "IRQ". They are implemented in terms of "BRK".
// User is responsible for ensuring that WB() will not store into memory while Reset is being processed.
unsigned addr=0, d=0, t=0xFF, c=0, sb=0, pbits = op<0x100 ? 0x30 : 0x20;
// Define the opcode decoding matrix, which decides which micro-operations constitute
// any particular opcode. (Note: The PLA of 6502 works on a slightly different principle.)
const unsigned o8 = op / 32, o8m = 1u << (op%32);
// Fetch op'th item from a bitstring encoded in a data-specific variant of base64,
// where each character transmits 8 bits of information rather than 6.
// This peculiar encoding was chosen to reduce the source code size.
// Enum temporaries are used in order to ensure compile-time evaluation.
#define t(w8,w7,w6,w5,w4,w3,w2,w1,w0) if( \
(o8<1?w0##u : o8<2?w1##u : o8<3?w2##u : o8<4?w3##u : \
o8<5?w4##u : o8<6?w5##u : o8<7?w6##u : o8<8?w7##u : w8##u) & o8m)
t(0,0xAAAAAAAA,0x00000000,0x00000000,0x00000000,0xAAAAA2AA,0x00000000,0x00000000,0x00000000) { c = t; t += A + P.C; P.V = (c^t) & (A^t) & 0x80; P.C = t & 0x100; }
要するに、私の一般的な質問:
- CPU 命令の驚異的な宇宙パワーを小さなコードに凝縮
15 分間のソースで SNES エミュレーターに固有の質問 (上記に投稿された部分):
- 命令をどのように
t(0, 0xAAAAAAAA, 0x00000000, ....)
解析しますか? ステートメントは表示if
されますが、引数の番号がどこから来たのか、またはそれらがコード全体に何を意味するのかわかりません。 - なぜ?
o8 = op / 32
_o8m = 1u << (op%32)
- 2 バイトのオペランドを持つ、または3 バイトのオペランドを持つ
ADC
hasのオペコード。そして、コードは両方のケースを含意しますか?ADC #const
ADC addr
t(0, 0xAAAAAAAA, ...)
私が尋ねている間:
dp
、_dp_
およびsr
に表示されるADC dp
、ADC (_dp_)
およびは何をADC sr,S
意味しますか?ADC (_dp_,X)
とはどう違いADC dp,X
ますか?(上記の質問を考えると、おそらく冗長です。)