CPUの珍命令

EDIT: [はてなブックマークのエントリ](https://b.hatena.ne.jp/entry/s/qiita.com/okuoku/items/29e6395d5398a91c96ce) だと `ABCD` (BCD加算) や `DJNZ` (ループ命令) が人気なようだ(Wikipediaしばりなもんで...) 。6502によくある `JSR` / `RET` が対応しないコーディングや、Z80で `PUSH` を目的外利用するような例は入れても良かったのかも。 DOOMの例を追加。

----

Wikipediaに個別ページができちゃうくらい有名な命令のメモ。

# きっかけ

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">このソースコードは現在の倫理上一般的でない表現が使われている箇所については当時の内容を尊重して掲載しています</p>&mdash; ほうめい　マイコンで遊んでばっかりで (@houmei) <a href="https://twitter.com/houmei/status/1282953695659884544?ref_src=twsrc%5Etfw">July 14, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

を受けて、

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">6809の命令のことですね。わかります　&gt;RT</p>&mdash; Miura Hideki (@miura1729) <a href="https://twitter.com/miura1729/status/1282955894951604224?ref_src=twsrc%5Etfw">July 14, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">１つのCPU命令が独立したWikipediaのページを持っているのってこれだけじゃないだろうか？　<a href="https://t.co/WibPAxoXf9">https://t.co/WibPAxoXf9</a></p>&mdash; Miura Hideki (@miura1729) <a href="https://twitter.com/miura1729/status/1282958110064128000?ref_src=twsrc%5Etfw">July 14, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 


実際にはHCFやNOPくらいはページはあるだろうと思ったけど、 **Wikipediaにページがあるほど有名な命令** ってのは中々珍しい命令と言えるのかもしれない。

# フフフ...Sign EXtend!

- https://en.wikipedia.org/wiki/SEX_(computing)

最初のツイートで挙げられている `SEX` (Sign EXtention) 命令は6809等に見られる命令で、この手の話をするときに99割話題に出ると言える。もちろんCPUは文字列を処理するのではないので、仕様書とかアセンブラでこの命令が何と呼ばれているかが全てになるが、

http://www.bitsavers.org/components/motorola/6809/M6809PM.rev0_May83.pdf

![コメント 2020-07-14 195027.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67446/8ccee6af-414e-d055-2495-84c8fd1bd173.png)

実際に載っている。

Wikipediaの他の用法も興味深い。エンディアンネスをアーキテクチャの性別(sex)とする表現が過去に存在したらしい。同性でないと情報交換に適さないというのは少々直感に反するかもしれない。

- https://github.com/RandalLinden/DOOM-FX/blob/64dbf50be8353ffcd66b36d9b98326f6f84a2106/source/rlmove4.a#L206
 - スーパーファミコン版DOOMのソースコードにあるSuperFXでの `sex` -- このDOOMは自作の開発環境で書かれている(ref. https://gamingreinvented.com/interview/lets-interview-dragons-lair-doom-and-bleem-developer-randy-linden/ )ので名称自体が公式なのかは何とも言えないが多くの文献が同様の命名をしている。

# EIEIO

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">つ <a href="https://t.co/rJn2LChdoh">https://t.co/rJn2LChdoh</a> <a href="https://t.co/c7j3D2jxdN">https://t.co/c7j3D2jxdN</a></p>&mdash; Kazuho Oku (@kazuho) <a href="https://twitter.com/kazuho/status/1282975179245629441?ref_src=twsrc%5Etfw">July 14, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

`eieio` はPowerPCのバリア命令の一種で、アーキテクチャ文書では `sync` と並んで解説されている。この命令はPowerPCの命令解説である PowerPC Virtual Environment Architecture Book II には39回も登場する。そんな大事な命令をギャグみたいな命名して良いのか。。

単純に大文字で書くとerrnoっぽいと思った思った人も多いかもしれないが、 **GNU HurdにはマジでEIEIOというerrnoが存在する** 。

- https://www.gnu.org/software/hurd/faq/eieio.html
 - FAQのエントリ
- http://git.savannah.gnu.org/cgit/hurd/glibc.git/tree/sysdeps/mach/hurd/bits/errno.h?id=212c386ddfa97a8c77572d7fcc617d078030d565#n124
 - glibcソース内での宣言

# CPUID

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">こんなのもありますね。<a href="https://t.co/n9YrXi4hqd">https://t.co/n9YrXi4hqd</a></p>&mdash; Electrelic (@electrelic) <a href="https://twitter.com/electrelic/status/1282963472276353025?ref_src=twsrc%5Etfw">July 14, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

やっとまともな命令だ！ `CPUID` 命令はIA-32系のプロセサでCPU種別等をレジスタに格納させるために使用する。この命令はプログラムに対して利用可能なCPU拡張命令を通知するのに使用されるため、仮想化が可能であったりとかなり厚遇されている。(Wikipediaの記事もかなり長い)

... まともじゃない用法としては、 `CPUID` 命令はシリアライズ命令とされているため、Out-Of-Order動作をするCPUのパフォーマンス測定のために推奨されている時期が存在した。当然そのような方法では正確にはならないので、専用の命令 `RDTSCP` が導入されている。

- https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/ia-32-ia-64-benchmark-code-execution-paper.pdf
 - Variance Introduced by CPUID and Improvements with RTDSCP Instruction 章で、この問題について説明している

ちなみに `RDTSC` の方はTime Stamp Counter( https://en.wikipedia.org/?title=RDTSC&redirect=no )のリダイレクトとなっている。

# HCF(自爆命令)

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">もう一つこんなのも。<a href="https://t.co/zR4QEfP2QG">https://t.co/zR4QEfP2QG</a></p>&mdash; Electrelic (@electrelic) <a href="https://twitter.com/electrelic/status/1282969997208195072?ref_src=twsrc%5Etfw">July 14, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

HCF(~~Hold~~ Halt-and-Catch-Fire)は、実行するとプロセッサが(リセットしない限り)復帰不可能な形で停止する未公開命令で、6800で特にそう呼ばれたとされる。特に6502では12のHCF命令が知られている。

- http://visual6502.org/wiki/index.php?title=6502_all_256_Opcodes
 - `KIL` 命令が相当する
- https://www.pagetable.com/?p=39
 - How MOS 6502 Illegal Opcodes really work

Wikipediaの記事では他のCPU事例についても触れていて興味深い。また、この記事からはx86の(正当な)命令である `HLT` の記事( https://en.wikipedia.org/wiki/HLT_(x86_instruction) )へのリンクがある。

# NOP

- https://en.wikipedia.org/wiki/NOP_(code)

HCFと同様に何もしない命令ではあるがより一般的に、かつ、安全に何もしない命令としては `NOP` がある。Wikipediaのページにあるように、大抵のプロセッサでは `NOP` という名前で呼んでいるが、MMIX(クヌースによる命令セット)では `SWYM` http://mmix.cs.hm.edu/doc/instructions/swym.html と呼んでいる。

x86の `NOP` は `0x90` に割り当てられていて、これは本来 `xchg ax,ax` (`ax`レジスタと `ax` レジスタを交換する)命令、つまり **"事実上"何もしないだけ** の命令であった。これがAMD64では(本来の `xchg` 挙動だと部分レジスタアクセスになるなど都合が悪いので)本当に何もしない命令として再定義され元の `xchg` の意味が失われている。

さらに、パディングに使う等の目的で、 `NOP` を **合計9種類も** 定義している:

- https://software.intel.com/content/www/us/en/develop/download/intel-64-and-ia-32-architectures-sdm-combined-volumes-1-2a-2b-2c-2d-3a-3b-3c-3d-and-4.html

![コメント 2020-07-14 221427.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67446/9f4dde90-f968-82ca-15db-42b47b65dbbe.png)

元々 `xchg` で実現されていたように、結果的に何もしない命令というのはいくらでも考えられるが、CPU内部の予測機構にやさしいバリエーションを定義しておくことには意味があると言える。

# x86の正当/未公開な命令

... もっとも、Wikipediaにはx86の命令というカテゴリ https://en.wikipedia.org/wiki/Category:X86_instructions が存在する。

個人的なお気に入りは `LOADALL` 命令( https://en.wikipedia.org/wiki/LOADALL )で、この未公開命令は本来内部ステートである特殊レジスタ類も含めてまるごとメモリから読み取らせることができる。 **超あぶねぇ。** この命令は286/386時代に ~~HIMEM.SYS~~ EMM386のような特殊なメモリ/CPUコンテキスト処理が必要なシチュエーションで使われた。

みんな水をあんまり特殊な物質だとは思っていないのと同じように、x86の異常性をみんなあんまり普段は意識していない気がする。`MOV`命令はそれ単体でチューリング完全ということでesolang Wikiに載ってる( https://esolangs.org/wiki/Mov )し、すごいシンプルな命令であるところの `PUSH SP` の結果が8086/8088とそれ以外で互換性が無いんだぞ！

# かんそう

命令単体が面白いというのはなかなかレアなのかなと思った。NOPが9種類もの表現手法があるとか、実行したら死ぬ命令が(Pentiumの世代くらいまで)普通にバグとして存在したとかはあるものの、やっぱりCPUアーキテクチャ全体の面白さを伝えきれないな。と。

最近のIntelの調子悪さとかApple Silicon(ARMとは呼ばない)とかソフトバンクがArmと売りそうとか最近プロセッサのトピックは面白いので何かネタを見つけて書きたいところ。。以前の [4 + 4命令プロセッサを作る実験](https://qiita.com/okuoku/items/3dd2da20f46c2e63286f) 以来そういうネタをやってないので。。