Armの命令セットとNEON拡張


# このアドベントカレンダーのスコープ、対象読者について
 - この記事は[ひとりNEONアドベントカレンダー2020](https://qiita.com/advent-calendar/2020/neon-only) 1日目の記事です。
 - [目次](https://qiita.com/advent-calendar/2020/neon-only)にも書きましたが、あくまで手島個人の知識の範囲内で書くので、すべて公開情報がもとになっています。
 - 個人で趣味の範囲で書くので、筆者の勤務先とは無関係です
 - 一人advent calendarなので、省エネモードがモットーになってます。悪しからず。
 - Arm v8.4、SVEと行ったArmの現在進行形の拡張に関しては実機が手元に無いこともあって、あまり深入りはしない予定
 - 実際のコードはアセンブラではなく、GCCのintrinsicをもとに解説する
 - C/C++のコードからNEON命令を使うコードを解説するので、それが読めるぐらいの読者を想定。

# 本日のトピック

 - いきなり「NEONとは」、と飛び込んでもわからない人が居ると思うので、第1日目は概要を説明しようと思います。
 - 「命令セット」「アーキテクチャ」と言った単語がわからない方はまずは @kaityo256 先生の [CPUのキーワード(ブランド、命令セット、マイクロアーキテクチャ、拡張命令セット)の説明](https://qiita.com/kaityo256/items/656bac4c3871031a4448) という良記事を読んでからお入り下さい。

# Armの命令セットとNEON拡張
 - Armの命令セットはv6、v7、v8と進化してきてます。v8で64bit対応が入り、NEONが標準命令セット入りしました。
 - Armv7では、NEONは拡張命令セットという位置づけだったので、今プログラムが走ってるCPU上でサポートされているかどうかはプログラム内で実行時に判定する必要がありました。
 - で、最近のArm(ちょっと主語がでかい)にはだいたいNEONが付いています。Raspberry Pi 2以降発売されたLinuxが動くSBCでは、NEON無しというSoCにはまずお目にかかれません。
 - ここらへんは、`/proc/cpuinfo`を確認するとわかります

```
$ cat /proc/cpuinfo
processor       : 0
model name      : ARMv7 Processor rev 5 (v7l)
BogoMIPS        : 38.40
Features        : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm 
CPU implementer : 0x41
CPU architecture: 7
CPU variant     : 0x0
CPU part        : 0xc07
CPU revision    : 5
(略)
```
 - 上記はRaspberry Pi 2上の`/proc/cpuinfo`です。
 - 4コアのCPUが載ってますが、情報は1コア分だけ掲載しました。
 - この `Features`の欄に`neon`と記載されており、これがNEON拡張命令が提供されていることを表します。
 - プログラム上から確認する場合は `/proc/self/auxv` にバイナリで書かれており、こちらをチェックすればNEON拡張命令に対応しているCPUか分かります。

# でNEONってなんなの？
 - NEONはArmのSIMD拡張命令セットです。
 - Single Instruction Multiple Dataの略で、複数のデータに対し、同じ処理を実行できます。
 - Intelで言うところの、SSE、AVXと同じポジションにいるのがArmのNEONです。
 - NEONが提供されているCPUでは、64bit幅のレジスタが32本提供されており、これらのレジスタに対してSIMD命令を発行できます。
     - Armv7もしくは32bit版Armでは、64bit幅のレジスタは0番と1番のように、`2n`番と`2n+1`番をつなげて、最大16本の128bit幅レジスタとして利用することもできます。
     - Aarch64、Armv8もしくは64bit版Armでは32本の128bit幅レジスタが提供され、128bitの内、下位64bitを64bit幅レジスタとして利用できます。
 - 実際に提供されてる命令は複数あるのですが、微妙に細かい挙動の違いがある、似た命令が大量にあるので、それらを片っ端から解説していきます。


# まとめ
 - NEONの位置づけを説明しました。
 - 明日も私の担当で、実際にNEONのコードを書く下準備を解説します


# NEON に関する参考文献
 - https://developer.arm.com/architectures/instruction-sets/simd-isas/neon/intrinsics
   - Arm本家のページにあるNEON命令リファレンスページ。
   - 基本的に本アドベントカレンダーはこのページに載っている命令の逆引き的なのを紹介していく。
 - https://documentation-service.arm.com/static/6193910683e60c5c768e2789?token=
    - NEON 命令の一覧が入ったPDF
 - https://szeged.github.io/nevada/
    - オンラインでNEONの挙動を確認できるシミュレータ
    - 32本の64bit幅レジスタが目視できるのが格好良い
 - https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/coding-for-neon---part-1-load-and-stores
    - Arm本家の技術ブログで、NEONの使い方を紹介したブログ記事
    - 多分本アドベントカレンダーより100倍わかり易い
 - https://github.com/opencv/opencv/blob/master/modules/core/include/opencv2/core/hal/intrin_neon.hpp
    - 筆者がよく使うOpenCV内でよく使われているNEONの実装参考例。
    - 教科書的な使い方を紹介するのが命令リファレンスだとすれば、この`intrin_neon.hpp`は、実際に画像処理/Computer Visionで使われる処理をSIMD実装した、有益な参考ヘッダファイル
    - 本アドベントカレンダーでも、OpenCVで使われている実装例を紹介することが多々あると思う。
 - https://w0.hatenablog.com/entries/2016/09/01
 - https://w0.hatenablog.com/entry/2019/04/18/001608
    - tanakamura先生によるSVEの解説。
    - SVEわかりません。
 - 個人的メモ
   - https://www.aps-web.jp/academy/ca/230/
   - https://github.com/kondors1995/platform_external_clang/blob/af1dacacb12f2732169a7276e0f4f90822ddd21f/test/CodeGen/arm-v8.1a-neon-intrinsics.c