0
0

Intel と AMD で違う(?) BSF/BSR 命令

Last updated at Posted at 2020-01-23

BSF/BSR で入力がゼロだったとき、出力は

  • Intel: 未定義
  • AMD: 変更されない

と、ドキュメントではなっている。

CPU の構造を考えると、条件代入命令 (CMOVcc) と同じで、パイプラインの終わりにある、書き込みステージの動作(出力レジスタへの代入)を行わないこと(ただしフラグ レジスタは更新)になりそうな気がする。

Intel も AMD も同じ動作になると思うので、手元の Core i7-8700B [コンパイラは g++]で試してみる。

sample.cpp
#include <iostream>
#include <iomanip>

using namespace std;

// int int_log2(unsigned x, int z=-1)
// 出力: (int)log2(x)
//      x が 0 の場合、z を返す

// Intel 仕様向け
int int_log2_intel(unsigned x, int z=-1)
{
    int b;
    asm("bsrl %2,%0;"  // b = BSR(x);
        "cmovz %1,%0"  // if (x == 0) b = z;
        : "=r" (b), "+r" (z) : "r" (x));
    return b;
}

// AMD 仕様向け
int int_log2_amd(unsigned x, int z=-1)
{
    asm("bsrl %1,%0" : "+r" (z) : "r" (x));
    return z;
}

// メイン関数
int main(int argc, char **argv)
{
    cout << showbase << right;
    for (int b = -1; b < 32; b++)
    {
        unsigned x = (b >= 0) ? (1 << b) : 0;
        cout << "int_log2(" << hex << setw(10) << x << ")"
             << " = " << dec << setw(2) << int_log2_intel(x)
             << ", "  << dec << setw(2) << int_log2_amd(x)
             << endl;
    }
    return 0;
}

をコンパイルして、実行すると

$ g++ -O3 -o sample sample.cpp
$ ./sample
int_log2(         0) = -1, -1
int_log2(       0x1) =  0,  0
int_log2(       0x2) =  1,  1
int_log2(       0x4) =  2,  2
int_log2(       0x8) =  3,  3
int_log2(      0x10) =  4,  4
int_log2(      0x20) =  5,  5
int_log2(      0x40) =  6,  6
int_log2(      0x80) =  7,  7
int_log2(     0x100) =  8,  8
int_log2(     0x200) =  9,  9
int_log2(     0x400) = 10, 10
int_log2(     0x800) = 11, 11
int_log2(    0x1000) = 12, 12
int_log2(    0x2000) = 13, 13
int_log2(    0x4000) = 14, 14
int_log2(    0x8000) = 15, 15
int_log2(   0x10000) = 16, 16
int_log2(   0x20000) = 17, 17
int_log2(   0x40000) = 18, 18
int_log2(   0x80000) = 19, 19
int_log2(  0x100000) = 20, 20
int_log2(  0x200000) = 21, 21
int_log2(  0x400000) = 22, 22
int_log2(  0x800000) = 23, 23
int_log2( 0x1000000) = 24, 24
int_log2( 0x2000000) = 25, 25
int_log2( 0x4000000) = 26, 26
int_log2( 0x8000000) = 27, 27
int_log2(0x10000000) = 28, 28
int_log2(0x20000000) = 29, 29
int_log2(0x40000000) = 30, 30
int_log2(0x80000000) = 31, 31

となった。手元の Intel CPU では AMD 仕様向けの処理でよさそうです。

AMD 仕様向けの処理がダメな CPU があるのなら、どれなのか知りたい...

追記: 80486 の初期バージョンが該当するらしい

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0