web-dev-qa-db-ja.com

Cプログラマーの観点から見たARMアーキテクチャーの違いは?

私はARMのプログラミングにかなり慣れていません。 ARMv4、ARMv5、ARMv6などのようないくつかのアーキテクチャがあることに気づきました。これらの違いは何ですか?それらには異なる命令セットまたは動作がありますか?

最も重要なことは、ARMv6用にCコードをコンパイルした場合、ARMv5で実行できるのでしょうか。 ARMv6で実行されているARMv5コードはどうですか?それとも、カーネルアセンブリコードを書いている場合にのみ違いを心配する必要がありますか?

30
Jay Conrod

ARMの世界は少し厄介です。

Cプログラマーにとって、物事は単純です。すべてのARMアーキテクチャーは、フラットなアドレス指定プログラミングモデルを備えた通常の32ビットを提供します。 Cソースコードを使用している限り、表示される唯一の違いはエンディアンとパフォーマンスです。ほとんどのARMプロセッサ(古いモデルでも)は、ビッグエンディアンとリトルエンディアンの両方にすることができます。次に、ロジックボードとオペレーティングシステムによって選択が行われます。優れたCコードはエンディアンニュートラル:プラットフォームのエンディアンに関係なく、正しくコンパイルおよび動作します(エンディアンニュートラルは信頼性と保守性だけでなく、パフォーマンスにも優れています:非ニュートラルコードは、異なるサイズのポインターを介して同じデータにアクセスするコードであり、これは、コンパイラーがコードを最適化するために使用する厳密なエイリアス規則に大混乱をもたらします。

binary互換性(つまり、一度コンパイルされたコードを再利用する)を考慮すると、状況はまったく異なります。


  • いくつかの命令セットがあります:
    1. 26ビットのプログラムカウンタを備えた元のARM命令セット(非常に古く、今日ではほとんど発生しません)
    2. 32ビットプログラムカウンタ(「ARMコード」と呼ばれることが多い)を備えたARM命令セット
    3. thumb命令セット(16ビットの簡略化されたオペコード)
    4. thumb-2命令セット(拡張機能付きThumb)

特定のプロセッサは、いくつかの命令セットを実装する場合があります。 ARMコードのみを知っている最新のプロセッサは、すでにかなり古い(15年)ARMv4の代表であるStrongARMです。 ARM7TDMI(ARMv4Tアーキテクチャ)は、Cortex-Mを除く後続のほとんどすべてのARMシステムと同様に、ARMとThumbの両方を認識しています。 ARMとThumbコードは、規則が変更される場所に適切な接着剤が挿入されている限り、同じアプリケーション内で一緒に混在させることができます。これはthumb interworkingと呼ばれ、Cコンパイラによって自動的に処理できます。

Cortex-M0はThumb命令のみを認識します。 「通常の」ARMプロセッサでは、オペレーティングシステムはARMコード(割り込みの処理用)を使用する必要があるため、いくつかの拡張機能を認識しています。したがって、Cortex-M0はいくつかのThumb-for-OSのことを知っています。これは、アプリケーションコードには関係ありません。

他のCortex-MはThumb-2しか知りません。 Thumb-2は、少なくともアセンブリレベルでは、ほとんどThumbと下位互換性があります。


  • 一部のアーキテクチャでは、追加の命令が追加されます。

したがって、これがARMv6用であることを示すコンパイラスイッチを使用してコードがコンパイルされた場合、コンパイラはARMv5ではなくARMv6で数少ない命令の1つを使用できます。これは、ほとんどすべてのプラットフォームで発生する一般的な状況です。たとえば、GCCを使用してPCで-march=core2フラグを使用してCコードをコンパイルすると、結果のバイナリが古いPentiumプロセッサで実行できない場合があります。


  • いくつかの呼び出し規約があります。

呼び出し規約は、関数がパラメーターと戻り値を交換する方法を指定する一連のルールです。プロセッサはそのレジスタのみを認識しており、スタックの概念はありません。呼び出し規約は、パラメーターがどのレジスターに入るのか、そしてそれらがどのようにエンコードされるのかを示します(たとえば、charパラメーターがある場合、それはレジスターの下位8ビットに入りますが、呼び出し元はクリア/署名することになっています-上位24ビットを拡張するかどうか?)。スタックの構造と配置について説明します。構造体フィールドの配置条件とパディングを正規化します。

ARMには、ATPCS(古い)とAAPCS(新しい)という2つの主要な規則があります。それらは浮動小数点値に関してはかなり異なります。整数パラメーターの場合、それらはほとんど同じです(ただし、AAPCSではより厳密なスタックアライメントが必要です)。もちろん、規則は命令セットとThumbインターワーキングの存在によって異なります。

場合によっては、ATPCSとAAPCSの両方に準拠するバイナリコードが存在する可能性がありますが、それは信頼性が低く、不一致に関する警告はありません。つまり、結論は次のとおりです。異なる呼び出し規約を使用するシステム間で真のバイナリ互換性を実現することはできません。


  • オプションのコプロセッサーがあります。

ARMアーキテクチャは、コア命令セットに独自の命令を追加するオプションの要素で拡張できます。 FPUはそのようなオプションのコプロセッサーです(そして実際にはめったに遭遇しません)。もう1つのコプロセッサーはNEONです。これは、いくつかの新しいARMプロセッサーにあるSIMD命令セットです。

コプロセッサーを使用するコードは、オペレーティングシステムが対応するオペコードをトラップし、ソフトウェアでコプロセッサーをエミュレートしない限り、そのコプロセッサーを備えていないプロセッサーでは実行されません(これは、ATPCS呼び出しを使用するときに浮動小数点引数で発生することです。慣例であり、slow)です。


要約すると、Cコードがある場合は、それを再コンパイルします。別のアーキテクチャまたはシステム用にコンパイルされたコードを再利用しようとしないでください。

35
Thomas Pornin

これを考えてみてくださいARM vs ARM wintelコンピューターとintelmacのようなものです。両方のコンピューターに同じIntelチップ(ファミリー)があると仮定してください。 Cコードの一部を一度コンパイルして、両方のプロセッサで問題なく実行できます。プログラムが異なる場所と理由は、Intelプロセッサとは関係ありませんが、その周囲のチップとマザーボード、およびこの場合はオペレーティングシステムと関係があります。 。

ARM vs ARMの違いのほとんどはコアではなく、コアを取り巻くベンダー固有のロジックです。したがって、Cの場合、これは質問の誤謬です。コードは、標準のapi呼び出しを呼び出すアプリケーションであり、arm、intel、powerpcなどでコンパイルする必要があります。アプリケーションがオンチップまたはオンボードの周辺機器と通信するようになると、プロセッサの種類に関係なく、1つのボード、1つのチップが異なります。その結果、Cコードはそのチップまたはマザーボード用に作成する必要があります。ARMv6用にバイナリをコンパイルすると、ARMv4で未定義と見なされる命令が発生する可能性があり、実行されます。ARMv4用にコンパイルすると、ARMv6が実行されます。それは大丈夫です。

せいぜい、このアプリケーションスペースにいる場合は、パフォーマンスの違いだけが表示される可能性があります。そのうちのいくつかは、コンパイラオプションの選択に関係しています。そして時々あなたはあなたのコードを手伝うことができます。可能な限り、除算と浮動小数点を避けることをお勧めします。私は掛け算が好きではありませんが、押された場合、割り算の代わりに掛け算を取ります。 x86は、アラインされていないアクセスで私たちを台無しにしてしまいました。アラインされたI/Oから始めれば、アラインされたアクセスを好む他のチップに入るとき、またはさまざまなオペレーティングシステムやブートローダーは、ARMが反応するように構成しますが、x86で慣れているものはありません。同様に、この習慣を維持すると、x86コードの実行速度が大幅に向上します。

ARM ARM(google:ARMアーキテクチャリファレンスマニュアル、多くの場所で無料でダウンロードできます。 、現在のrevが何であるか、rev Iか何かがわからない)ARM命令セットを参照して、ほとんどの命令がすべてのコアでサポートされていることを確認します。分割やバイトスワップなど。コア間に恐れるものは何もないことがわかります。

システムの観点から考えると、wintelとintelmacです。 ARMはチップを製造せ​​ず、コアを製造してライセンス供与します。チップにARMを使用するほとんどのベンダーは、独自の特別なソースを使用しています。真ん中に同じプロセッサを搭載したwintelとmacのようですが、プロセッサが触れて使用しなければならないすべてのものに関しては完全に異なります。ARM core、= ARMペリフェラル、フローティングポイントユニット、キャッシュなどを販売しています。たとえば、同じARMv4があったとしてもごくわずかです。コードが違いに触れた場合、問題が発生します。

ARM ARM)に加えて、チップのアーム部分にはTRM(テクニカルリファレンスマニュアル)がありますが、コンポーネントのtrmが間違っている場合TRMには、レジスタの説明など、ARM ARMがないが、アプリケーションに住んでいる場合はそうではない)などの情報が含まれている可能性があります。おそらくそれらのいずれも必要としないスペース、またはARM ARM。ARM ARMは、教育目的に適しています。アラインされていないアクセスを分割または使用したくない理由を理解する。

5
old_timer

ARM自体は、ユーザーコードに固執する限り、かなり互換性があります(もちろんカーネルコードは異なります)。ホストされたOS環境では、ARMv5(ARM926プロセッサ)に固執する可能性があります。

大きな違いは次のとおりです。

  1. キャッシュの動作は大きく異なります。一部のARMのキャッシュは仮想的にアドレス指定されているため、プロセスの切り替えが困難になる可能性があります。
  2. FPUにはいくつかのフレーバーがあります(VFP、NEONなど)。多くの小さなプロセッサにはFPUさえありません。
  3. サムモードが劇的に変更されました。 ARMv5間のThumbモードは、Thumb2(ARMv6 +)に移植できず、下位互換性もありません。
4
Yann Ramin

違いが本当に重要な場合は、ARMの公開ドキュメントからそれを理解できるはずです。

しかし、高級言語で書くことの全体的なポイントは(Cと同じくらい「高い」だけであっても)、心配しないでくださいです。あなたがするのは再コンパイルです。カーネル内であっても、アセンブリで実際に記述する必要はそれほど多くありません。そして、あなたがそうするときしなければならないアセンブリで何かを書く(つまり、最大のパフォーマンスを得るためだけではない)、それは通常、CPUの選択だけではありません(たとえば、どこに直接メモリマップされているのですか?)。

3
Karl Knechtel

一般にアーキテクチャ間で移植するときにチェックする領域の非常に迅速で汚いリスト:

  • エンディアン:ユニオンの使用、データ型のキャスト、ビットフィールド、データ共有
  • Alignment:アライメント要件だけでなく、アライメントされていない可能性のあるアクセスのパフォーマンス特性
  • メモリモデル:弱いvs強い?
  • マルチコア:コヒーレンシはどのように機能しますか?
  • その他:符号付きデータ型と符号なしデータ型、データ構造のパッキング、スタックの使用法、列挙型データ型..
2
auselen