続・Intelのエンディアン変換命令?
しゅどうさんあたり調べてくれないかなぁと思って書いたんだけどサスガすぎ。確かにPrescottでえらい加速してるのはおもろいですな。NorthwoodはMicrocodeで処理してるんだろうけど、PrescottのLatency 1ってすごい。完全ハードワイヤードになったんだろうか。簡単だけど面積だけは食いそう。マジでエミュレーション対策かも。
ちなみにbswapというとhtonlとかだろうとおもって追っかけたら、LinuxもFreeBSDもinline assemblerにちゃんと落とすマクロになってる。Linux FC3はオーソドックスに、/usr/include/bits/byteswap.hに
# if !defined __i486__ && !defined __pentium__ && !defined __pentiumpro__ \ && !defined __pentium4__ # define __bswap_32(x) \ (__extension__ \ ({ register unsigned int __v, __x = (x); \ if (__builtin_constant_p (__x)) \ __v = __bswap_constant_32 (__x); \ else \ __asm__ ("rorw $8, %w0;" \ "rorl $16, %0;" \ "rorw $8, %w0" \ : "=r" (__v) \ : "0" (__x) \ : "cc"); \ __v; })) # else # define __bswap_32(x) \ (__extension__ \ ({ register unsigned int __v, __x = (x); \ if (__builtin_constant_p (__x)) \ __v = __bswap_constant_32 (__x); \ else \ __asm__ ("bswap %0" : "=r" (__v) : "0" (__x)); \ __v; })) # endif
てのがある。まぁ普通やろうとするとこうか。これに対しFreeBSD for i386は/usr/include/machine/endian.hで
#if defined(_KERNEL) && (defined(I486_CPU) || defined(I586_CPU) || defined(I686_ CPU)) && !defined(I386_CPU) #define __byte_swap_long(x) \ __extension__ ({ register u_long __X = (x); \ __asm ("bswap %0" \ : "=r" (__X) \ : "0" (__X)); \ __X; }) #else #define __byte_swap_long(x) \ __extension__ ({ register u_long __X = (x); \ __asm ("xchgb %h1, %b1\n\trorl $16, %1\n\txchgb %h1, %b1" \ : "=q" (__X) \ : "0" (__X)); \ __X; }) #endif
となってた。おおxchgb!xchg系というとreg<->memで使ってセマフォ作ることばっかり考えてしまってたが、こういう使い方もできるなぁ。いずれにせよ、bswap使わないほうが面白いという(笑)1つのレジスタを32/16/8bitに切って使えるIA-32ならではですなぁ。