新版FM音源プログラム (21)

STM32F4 シリーズには、「Adaptive real-time accelerator」(ART Accelerator) と称するフラッシュ・メモリ読み出しのためのキャッシュ機構が備えられています。
フラッシュの読み出し幅は 128 ビット (16 バイト) で、フラッシュ上の命令 (I-Code) に対しては 64 ライン分の命令キャッシュが用意されており、プリフェッチされた命令が格納されます。
命令キャッシュ・メモリ容量としては、16 × 64 = 1024 バイトとなり、90 バイト足らずの calc_slot() 関数は全体がキャッシュ・メモリ内におさまります。
フラッシュ上のデータ (D-Code) に対しては 8 ライン分のデータ・キャッシュが用意されています。

続きを読む

新版FM音源プログラム (20)

Cortex-M4 用の結果では、フラッシュのキャッシュ機構の構成が同じ STM32F446 と STM32F407 とがほぼ同じ結果で、別のキャッシュ機構を持つ STM32F303 がやや異なる結果となりました。
PSoC5LP にはフラッシュのキャッシュのヒット/ミスの回数を計測するレジスタがあり、それを利用して測定すると、サイン波テーブルをフラッシュ上に置いた場合と、SRAM 上に置いた場合との差が非常にきれいに現れました。
ARMv7-M アーキテクチャ (Cortex-M3/M4) 用にコンパイルしたアセンブリ言語プログラムのオブジェクトを逆アセンブルしたものを下に示します。

続きを読む

新版FM音源プログラム (18)

アセンブリ言語によるスロット (オペレータ) 計算プログラムでは、ARMv6-M (Cortex-M0) の 16 ビット Thumb 命令を主に使うこととし、ARMv7-M (Cortex-M3/M4) に対しては一部を 32 ビット Thumb2 命令で記述することにより効率化しています。
以下に、その「一部分」を示します。

続きを読む

新版FM音源プログラム (17)

armcc の「エンベデッド・アセンブラ」では、関数まるごとアセンブリ言語で記述し、関数冒頭のレジスタ・セーブや、関数最後のレジスタ・リストアやリターン命令まですべてを記述する必要がありました。
gcc の「インライン・アセンブラ」では、C 言語での記述に混ざって「asm 文」が存在し、関数のプロローグ/エピローグ・コードは asm 文内では記述する必要がなく、C 側で自動的に生成されます。
また、デフォルトでは最適化の対象になっています。 (最適化オフにも設定できます)
アセンブラ命令も「裸」で記述することはできず、文字列の中に「閉じ込め」られた形で記述します。
下に gcc のインライン・アセンブラ機能を使って書いたプログラム・リストを示します。 (2018 年 2 月 28 日追記: ラベルを「ローカル・ラベル」(数字のみで構成されるラベル) に変更しました)
(2018 年 3 月 2 日追記: パイプライン・ストール解消のためプログラムの一部を変更しました)

続きを読む

新版FM音源プログラム (16)

オペレータ処理をアセンブリ言語で書く場合、C プログラム・ソースの構造体アクセスの

  o_p->ph_acc 

のような表現は、アセンブリ言語ソースとしては最終的には

 ldr r2, [r0, #4] 

のように「定数オフセット」にまで変換される必要があります。
C プログラム・ソースと独立してソースをアセンブラに喰わせる場合には、C 側で構造体のメンバの配置に変更があった場合にはアセンブリ言語ソースでの定義を手作業で修正する必要があります。
そのような事態を避けるため、「インライン・アセンブラ」のような、C コンパイラの機能に含まれたアセンブリ言語機能を利用することにしました。
ARM/Keil の μVison (armcc)では「エンベデッド・アセンブラ」、gcc では「インライン・アセンブラ」を使っています。
armcc 版のソースを下に示します。 (2018 年 3 月 2 日追記: 2 ヵ所ある

  ldrsh   r3, [r5, r3]

の部分でパイプライン・ストールが生じていたのを命令の順序の入れ替えにより解消しました。)

続きを読む

新版FM音源プログラム (15)

今回は各種のチップ/コンパイラの組み合わせのオブジェクトに対する逆アセンブル・リストを掲載します。
もとの C ソース・ファイルでの記述を少し変えると、コンパイル後のオブジェクトはかなり大きく変化するので、あまり細部に渡る追及はしないでおきます。
μVision V5.21a (armcc コンパイラ) でコンパイルした calc_slot() 関数を逆アセンブルしたものを下に示します。
Cortex-M4 コアの STM32F446、STM32F407、STM32F303 に共通です。

続きを読む