1

Arm mov には、即値が 2 の倍数で回転された 8 ビットでなければならないという制限があります。次のように記述できます。

mov ip, #0x5000

しかし、次のように書くことはできません。

mov ip, #0x5001

0x5000 は 0x5000 + 1 として分割できます。私の意味では、有効な即値と小さな数の合計です。

では、与えられた 32 ビットの数値について、最も近い有効な即値をすばやく見つけるにはどうすればよいでしょうか? このような:

uint32 find_imm(uint32 src, bool less_than_src) {
...
}

// x is 0x5000
uint32 x = find_imm(0x5001, true);
4

2 に答える 2

2

それは非常に簡単です。それらの間の距離を見てください。0x5001 = 0b101000000000001. 有効桁数は 15 桁なので、8 ビットの即値あたり 2 つの命令が必要です。また、ゼロ 0x80000001 が十分にあり、それを 0x88000000 または 0x00000003 の周りに回転させる場合は、テストに回転を入れることを忘れないでください。これは、測定値間の距離からわずか 2 桁です。したがって、即時を取り、1 型テスト間の距離を実行し、1 ステップ回転し、テストを再度実行し、可能なすべての (逆) 回転が発生するまで繰り返し、命令の数が最も少ないものの 1 つを使用します/即時。

gnu は既にこれを行っており、gas はオープン ソースであるため、必要に応じてコードを取得できます。ロード アドレス トリックを使用する場合:

ldr rd,=const

その const が単一の即値移動命令で解決できる場合は、それを次のようにエンコードします。

mov rd,#const

それができない場合は、単語を置く場所を見つけようとし、それを PC の相対負荷としてエンコードします。

ldr rd,[pc,#offset]
...
.word const
于 2013-07-20T13:11:28.390 に答える
1

値を構築する方法を見つけるための単純なルールや関数はありません。値が即値から簡単にロードできる範囲を超えると、通常、即値から構築するのではなく、データ セクションで定義してメモリからロードすることによってロードします。

2 つの即値から値を構築する場合は、次のようなさまざまな操作を検討する必要があります。

  • 2 つの即時を追加します。
  • 2 つの即値を減算します。
  • 2 つの即値の乗算。
  • 32 ビット レジスタを複数のレーンに分割する一部の「SIMD」命令など、より難解な命令。

3 つの即時値に移動する必要がある場合は、さらに組み合わせがあります。検索を減らす可能性のあるパターンをいくつか見つけることができますが、その一部は「力ずくの」検索のままです。一般に、複雑な命令シーケンスを使用しても意味がありません。メモリ内の準備された場所からデータをロードするだけでよいからです。

ARM アセンブラには、これを支援する命令形式があります。

LDR Rd, =const

アセンブラはこれを確認すると、const値をリテラル プールに配置し、プールから値をロードする命令を生成します。別のアセンブラを使用している場合、命令形式が同じではない可能性がありますが、必要なコードを手動で記述できます。

于 2013-07-20T12:45:12.343 に答える