Cortex-M3命令セットには、LDREX / STREX命令のファミリーがあり、場所がLDREX命令で読み取られた場合、次のSTREX命令は、アドレスが変更されていないことがわかっている場合にのみ、そのアドレスに書き込むことができます。通常、その効果は、LDREX以降に割り込み(ARM用語では「例外」)が発生していなければSTREXは成功しますが、それ以外の場合は失敗します。
Cortex M0でそのような動作をシミュレートする最も実用的な方法は何ですか?M3用のCコードを書いて、M0に移植できるようにしたいと思います。M3では、次のように言うことができます。
__inline void do_inc(unsigned int * dat) {{ while(__ strex(__ ldrex(dat)+1、dat)){} }
アトミックインクリメントを実行します。Cortex-M0で同様の機能を実現するために私が考えることができる唯一の方法は、次のいずれかです。
- 「ldrex」で例外を無効にし、「strex」と「clrex」で例外を再度有効にします。ただし、すべての「ldrex」の直後に「strex」または「clrex」を続ける必要があります。
- 「ldrex」、「strex」、および「clrex」をRAM内の非常に小さなルーチンにし、「ldrex」の1つの命令を「strr1、[r2]」または「movr0、#1」にパッチします。「ldrex」ルーチンに「str」命令を「strex」ルーチンにプラグインさせ、「clrex」ルーチンに「mov r0、#1」をプラグインさせます。「ldrex」シーケンス呼び出し「clrex」を無効にする可能性のあるすべての例外があります。
ldrex / strex関数の使用方法によっては、割り込みを無効にすることは合理的に機能する可能性がありますが、「load-exclusive」のセマンティクスを変更して、それが放棄された場合に悪い副作用を引き起こすようにするのは厄介なようです。コードパッチのアイデアは、目的のセマンティクスを実現するように見えますが、不格好なようです。
(ところで、副次的な質問:M3のSTREXが単にフラグを設定するのではなく、成功/失敗の表示をレジスタに格納するのはなぜですか?実際の動作では、オペコードに4ビットの追加が必要であり、成功を保持するためにレジスタが使用可能である必要があります/ failure表示であり、成功したかどうかを判断するために「cmp r0、#0」を使用する必要があります。コンパイラーは、レジスターで結果を取得しなかった場合、STREX組み込み関数を適切に処理できないと予想されましたか。キャリーをレジスターに入れるには、2つの短い指示が必要です。)