*参照元 [#lb6f0e91]
#backlinks

*説明 [#ff8c41b0]
-パス: [[linux-2.6.33/arch/x86/include/asm/bitops.h]]

-指定されたビット位置の値をテストする。
--ビット位置が可変(変数など)の場合に使用する。


**引数 [#fb4980d7]
-int nr
--ビット位置
-volatile const unsigned long *addr
--評価対象の unsigned long 値のポインタ


**返り値 [#lcee7600]
-int
--ビットがセットされている場合 -1、ビットがセットされていない場合 0


**参考 [#hf705d6a]


*実装 [#m69a8723]
 static inline int variable_test_bit(int nr, volatile const unsigned long *addr)
 {
 	int oldbit;
 
 	asm volatile("bt %2,%1\n\t"
 		     "sbb %0,%0"
 		     : "=r" (oldbit)
 		     : "m" (*(unsigned long *)addr), "Ir" (nr));
 
-1行目: bt にて addr の nr ビット目の値が CF にストアされる。
-2行目: sbb にて %0(oldbit) = %0 - %0 - CF が計算される。
%0 - %0 は当然 0 なので、計算結果は CF のみで決まる。
なぜ sbb 命令かというと、CF フラグを見るための分岐命令を排除するため。
-2行目: sbb にて %0(oldbit を割り当てるレジスタのこと) に
%0 - %0 - CF が計算結果が格納される。
%0 - %0 は 0 のため、計算結果は CF のみで決まる。
cmp, jmp, mov でも実現できるが、sbb 命令を使えば CF フラグの結果による分岐命令を排除できるからである。
--CF = 1(ビットが 1 だったとき): %0(oldbit) = -1
--CF = 0(ビットが 0 だったとき): %0(oldbit) = 0

-x86 では有名なハックのようで、おそらく昔はこの方法が速かった(?)のでしょう。
-最近の IA32 アーキテクチャだと sbb 命令は遅いようです。
--[[http://download.intel.com/jp/developer/jpdoc/ia32.pdf]]
--[[http://slashdot.jp/~kmra/journal/464748]]

 	return oldbit;
 }


*コメント [#z5166ed3]

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS