[インデックス 10321] ファイルの概要
このコミットは、Go言語のツールチェーンの一部である6lリンカ(x86-64アーキテクチャ向け)のsrc/cmd/6l/optab.cファイルに対する変更です。optab.cは、アセンブリ命令とその対応する機械語オペコードの定義を管理するテーブルが含まれており、リンカがアセンブリコードを機械語に変換する際に参照します。具体的には、SIMD命令であるPSLLQ(Packed Shift Left Logical Quadword)命令のオペコード定義における誤りを修正しています。
コミット
このコミットは、PSLLQ命令(即値オペランドとXMMレジスタオペランドを持つ形式)のオペコード定義における誤りを修正し、リンカが正しい機械語を生成するようにします。これにより、GoプログラムがPSLLQ命令を使用する際に、誤った機械語が生成される問題が解消されます。
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/c8a2be8c38f252fd448d6cb957341b1590d93c7e
元コミット内容
6l: Fixes opcode for PSLLQ imm8, xmm_reg
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5340056
変更の背景
Go言語のコンパイラおよびリンカは、Goソースコードを最終的な実行可能バイナリに変換する過程で、アセンブリコードを生成し、それを機械語に変換します。この変換プロセスにおいて、各アセンブリ命令には対応する正しい機械語オペコードが割り当てられる必要があります。
PSLLQ命令は、SIMD(Single Instruction, Multiple Data)演算を行うための命令であり、特に大量のデータを並列処理する際にパフォーマンスを向上させるために使用されます。この命令には複数の形式があり、その中には即値(imm8)とXMMレジスタをオペランドとして取る形式も存在します。
Goの6lリンカのオペコード定義テーブル(optab.c)において、この特定のPSLLQ命令形式に対するオペコードが誤って定義されていました。具体的には、ModR/Mバイトの一部であるReg/Opcodeフィールドの値が誤っていたため、リンカがこの命令を処理する際に、期待される機械語とは異なるバイト列を生成してしまう可能性がありました。この誤りは、PSLLQ命令を使用するGoプログラムの実行時エラーや予期せぬ動作を引き起こす可能性があったため、修正が必要とされました。
前提知識の解説
Goコンパイラツールチェーンと6lリンカ
Go言語のプログラムは、go buildコマンドによってコンパイルされ、実行可能バイナリが生成されます。このプロセスは、いくつかの段階に分かれています。
- コンパイラ(
6gなど): Goソースコードをアセンブリコード(Plan 9アセンブリ)に変換します。 - アセンブラ(
6aなど): アセンブリコードをオブジェクトファイル(機械語)に変換します。 - リンカ(
6lなど): 複数のオブジェクトファイルやライブラリを結合し、最終的な実行可能バイナリを生成します。
6lは、x86-64アーキテクチャ(64ビットIntel/AMDプロセッサ)向けのリンカを指します。Goのツールチェーンは、ターゲットアーキテクチャに応じて6g, 6a, 6l(x86-64)、8g, 8a, 8l(x86-32)、5g, 5a, 5l(ARM)といった命名規則を使用していました。
x86-64アーキテクチャ、レジスタ、命令セット
x86-64は、IntelとAMDが開発した64ビット命令セットアーキテクチャです。このアーキテクチャは、汎用レジスタ(RAX, RBXなど)に加えて、SIMD演算に特化したレジスタセットを持っています。
- XMMレジスタ: 128ビット幅のレジスタで、SSE(Streaming SIMD Extensions)命令セットで使用されます。
PSLLQ命令のようなSIMD命令は、これらのレジスタに格納された複数のデータを一度に処理します。 - SIMD(Single Instruction, Multiple Data)命令: 一つの命令で複数のデータ要素(例: 整数、浮動小数点数)に対して同じ演算を同時に実行する命令です。これにより、画像処理、音声処理、科学技術計算など、データ並列性が高いタスクのパフォーマンスが大幅に向上します。
アセンブリ言語と機械語、オペコード
- アセンブリ言語: 人間が理解しやすいように、機械語命令をニーモニック(例:
MOV,ADD,PSLLQ)とオペランドで表現した低水準プログラミング言語です。 - 機械語: CPUが直接実行できるバイナリ形式の命令です。各アセンブリ命令は、一つまたは複数の機械語バイト列に変換されます。
- オペコード(Opcode): 機械語命令の主要部分で、CPUに実行すべき操作(例: 加算、データ移動、論理シフト)を指示するバイト列です。
- オペランド(Operand): 命令が操作するデータやその場所(レジスタ、メモリ、即値など)を指定する部分です。
- ModR/Mバイト: x86命令セットにおいて、オペランドの指定方法(レジスタ、メモリ参照)や、命令の拡張オペコード(Reg/Opcodeフィールド)をエンコードするために使用される1バイトです。ModR/Mバイトは、Mod(2ビット)、Reg/Opcode(3ビット)、R/M(3ビット)の3つのフィールドに分かれています。
- Modフィールド: オペランドがレジスタかメモリか、メモリの場合のオフセットの有無とサイズを示します。
- Reg/Opcodeフィールド: 命令によっては、このフィールドが追加のオペコードビットとして機能し、同じオペコードを持つ複数の命令を区別するために使用されます。
- R/Mフィールド: オペランドがレジスタの場合、そのレジスタ番号を示します。メモリの場合、ベースレジスタやインデックスレジスタを示します。
- SIBバイト(Scale-Index-Base Byte): ModR/Mバイトがメモリオペランドを指定し、かつ複雑なアドレス指定(スケール、インデックス、ベースレジスタ)が必要な場合に使用される追加の1バイトです。
- 即値(Immediate Value): 命令の一部として直接エンコードされる定数データです。
imm8は8ビットの即値を意味します。
PSLLQ命令
PSLLQは "Packed Shift Left Logical Quadword" の略で、SIMD命令の一つです。この命令は、XMMレジスタに格納された複数の64ビット(quadword)整数を、指定されたビット数だけ論理的に左シフトします。シフト量は即値(imm8)または別のレジスタで指定できます。
このコミットで修正された形式は、PSLLQ imm8, xmm_regであり、これはXMMレジスタの内容を、8ビットの即値で指定されたビット数だけ左シフトする命令です。
optab.cの役割
src/cmd/6l/optab.cファイルは、Go言語の6lリンカが使用するオペコードテーブルを定義しています。このテーブルは、アセンブリ命令のニーモニックと、それに対応する機械語のオペコード、オペランドの型、ModR/MバイトのReg/Opcodeフィールドの値などをマッピングしています。リンカは、このテーブルを参照してアセンブリ命令を正しい機械語に変換します。
テーブルのエントリは通常、以下のような構造を持っています(簡略化された表現):
{ 命令ニーモニック, オペランドタイプ, プレフィックス, オペコード1, オペコード2, ModR/MのReg/Opcodeフィールド, ... }
このコミットでは、PSLLQ命令の定義において、ModR/MバイトのReg/Opcodeフィールドに相当する値が誤っていたため、その値を修正しています。
技術的詳細
PSLLQ命令は、SSE2(Streaming SIMD Extensions 2)命令セットの一部として導入されました。この命令には、シフト量を即値で指定する形式と、汎用レジスタで指定する形式があります。
修正対象となったPSLLQ命令の形式は、PSLLQ xmm1, imm8(Intel構文)またはPSLLQ imm8, xmm_reg(AT&T構文)に相当します。この命令の機械語エンコーディングは、通常、以下のような構造を持ちます。
- プレフィックス:
0x66(operand size override for SSE instructions) - オペコード:
0x0F 0x73 - ModR/Mバイト: このバイトのReg/Opcodeフィールドが、
PSLLQ命令の特定のバリアント(即値シフト)を示すために使用されます。
optab.cの該当行は以下のようになっています。
{ APSLLQ,\typs,\tPy, 0xf3, 0x73,(06), Pe,0xf3, Pe,0x7e,(06) },
この行は、PSLLQ命令の複数の形式を定義しています。特に注目すべきは、Py, 0xf3, 0x73,(06)とPe,0xf3, Pe,0x7e,(06)の部分です。
PyとPeは、オペランドの型や命令のエンコーディングに関する内部的なフラグやプレフィックスを示唆しています。0xf3と0x73は、命令の主要なオペコードバイトです。(06)と(06)は、ModR/MバイトのReg/Opcodeフィールドの値を示しています。この値が、同じオペコード0x0F 0x73を持つ他の命令(例:PSRLQ,PSRAQなど)とPSLLQを区別するために使用されます。
元のコードでは、Pe,0xf3, Pe,0x7e,(06)の部分で、ModR/MバイトのReg/Opcodeフィールドが0x7eと誤って定義されていました。これは、PSLLQ命令の即値シフト形式に対しては正しくありません。正しい値は0x73であるべきです。
ModR/MバイトのReg/Opcodeフィールドは3ビットの値であり、通常は0から7までの範囲を取ります。0x7eや0x73は、この3ビットの値をエンコードした結果のバイト値の一部として解釈されます。この文脈では、06が正しいReg/Opcodeフィールドの値を示しており、0x7eや0x73は、そのReg/Opcodeフィールドを含むModR/Mバイト全体のエンコーディングの一部、または関連するオペコード拡張の一部として解釈される可能性があります。
この修正は、PSLLQ命令の即値シフト形式が、リンカによって正しく機械語に変換されることを保証します。誤ったReg/Opcodeフィールドの値は、リンカが間違った命令を生成したり、アセンブリコードの解析に失敗したりする原因となります。
コアとなるコードの変更箇所
src/cmd/6l/optab.cファイルの以下の行が変更されました。
--- a/src/cmd/6l/optab.c
+++ b/src/cmd/6l/optab.c
@@ -978,7 +978,7 @@ Optab optab[] =
{ APSHUFW,\tymshuf,\tPm, 0x70 },
{ APSLLO,\typsdq,\tPq, 0x73,(07) },
{ APSLLL,\typs,\tPy, 0xf2, 0x72,(06), Pe,0xf2, Pe,0x72,(06) },
-\t{ APSLLQ,\typs,\tPy, 0xf3, 0x73,(06), Pe,0xf3, Pe,0x7e,(06) },
+\t{ APSLLQ,\typs,\tPy, 0xf3, 0x73,(06), Pe,0xf3, Pe,0x73,(06) },
{ APSLLW,\typs,\tPy, 0xf1, 0x71,(06), Pe,0xf1, Pe,0x71,(06) },
{ APSRAL,\typs,\tPy, 0xe2, 0x72,(04), Pe,0xe2, Pe,0x72,(04) },
{ APSRAW,\typs,\tPy, 0xe1, 0x71,(04), Pe,0xe1, Pe,0x71,(04) },
コアとなるコードの解説
変更された行は、Optab optab[]配列内のPSLLQ命令の定義です。
元の行:
{ APSLLQ,\typs,\tPy, 0xf3, 0x73,(06), Pe,0xf3, Pe,0x7e,(06) },
修正後の行:
{ APSLLQ,\typs,\tPy, 0xf3, 0x73,(06), Pe,0xf3, Pe,0x73,(06) },
この変更は、PSLLQ命令の定義の後半部分、具体的にはPe,0xf3, Pe,0x7e,(06)からPe,0xf3, Pe,0x73,(06)への変更です。
APSLLQ: これはGoリンカ内部でPSLLQ命令を表す定数です。\typs: オペランドの型や命令の特性を示す内部的なフラグです。Py, 0xf3, 0x73,(06): これはPSLLQ命令のレジスタ-レジスタ形式またはメモリ-レジスタ形式のエンコーディングの一部を示していると考えられます。0xf3と0x73はオペコードバイト、(06)はModR/MバイトのReg/Opcodeフィールドの値です。Pe,0xf3, Pe,0x7e,(06)(変更前): これはPSLLQ命令の即値-レジスタ形式(PSLLQ imm8, xmm_reg)のエンコーディングの一部を示しています。ここで、0x7eが誤った値でした。Pe,0xf3, Pe,0x73,(06)(変更後):0x7eが0x73に修正されました。これにより、PSLLQ imm8, xmm_reg命令がリンカによって正しく機械語に変換されるようになります。
この修正により、PSLLQ命令の即値シフト形式が、x86-64アーキテクチャの仕様に合致する正しい機械語オペコードにマッピングされることが保証されます。これは、Goコンパイラが生成するアセンブリコードの正確性を保ち、最終的なバイナリの信頼性を向上させる上で重要な修正です。
関連リンク
- Go CL (Code Review) ページ: https://golang.org/cl/5340056
- GitHubコミットページ: https://github.com/golang/go/commit/c8a2be8c38f252fd448d6cb957341b1590d93c7e
参考にした情報源リンク
- Intel® 64 and IA-32 Architectures Software Developer’s Manuals (特にVolume 2A: Instruction Set Reference, A-M): https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html
- Go言語のソースコード(
src/cmd/6l/optab.cの歴史的なバージョン) - x86アセンブリ言語と機械語エンコーディングに関する一般的な情報源(例: Wikipedia, 各種チュートリアル)
- SIMD命令セット(SSE/AVX)に関する情報源# [インデックス 10321] ファイルの概要
このコミットは、Go言語のツールチェーンの一部である6lリンカ(x86-64アーキテクチャ向け)のsrc/cmd/6l/optab.cファイルに対する変更です。optab.cは、アセンブリ命令とその対応する機械語オペコードの定義を管理するテーブルが含まれており、リンカがアセンブリコードを機械語に変換する際に参照します。具体的には、SIMD命令であるPSLLQ(Packed Shift Left Logical Quadword)命令のオペコード定義における誤りを修正しています。
コミット
このコミットは、PSLLQ命令(即値オペランドとXMMレジスタオペランドを持つ形式)のオペコード定義における誤りを修正し、リンカが正しい機械語を生成するようにします。これにより、GoプログラムがPSLLQ命令を使用する際に、誤った機械語が生成される問題が解消されます。
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/c8a2be8c38f252fd448d6cb957341b1590d93c7e
元コミット内容
6l: Fixes opcode for PSLLQ imm8, xmm_reg
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5340056
変更の背景
Go言語のコンパイラおよびリンカは、Goソースコードを最終的な実行可能バイナリに変換する過程で、アセンブリコードを生成し、それを機械語に変換します。この変換プロセスにおいて、各アセンブリ命令には対応する正しい機械語オペコードが割り当てられる必要があります。
PSLLQ命令は、SIMD(Single Instruction, Multiple Data)演算を行うための命令であり、特に大量のデータを並列処理する際にパフォーマンスを向上させるために使用されます。この命令には複数の形式があり、その中には即値(imm8)とXMMレジスタをオペランドとして取る形式も存在します。
Goの6lリンカのオペコード定義テーブル(optab.c)において、この特定のPSLLQ命令形式に対するオペコードが誤って定義されていました。具体的には、ModR/Mバイトの一部であるReg/Opcodeフィールドの値が誤っていたため、リンカがこの命令を処理する際に、期待される機械語とは異なるバイト列を生成してしまう可能性がありました。この誤りは、PSLLQ命令を使用するGoプログラムの実行時エラーや予期せぬ動作を引き起こす可能性があったため、修正が必要とされました。
前提知識の解説
Goコンパイラツールチェーンと6lリンカ
Go言語のプログラムは、go buildコマンドによってコンパイルされ、実行可能バイナリが生成されます。このプロセスは、いくつかの段階に分かれています。
- コンパイラ(
6gなど): Goソースコードをアセンブリコード(Plan 9アセンブリ)に変換します。 - アセンブラ(
6aなど): アセンブリコードをオブジェクトファイル(機械語)に変換します。 - リンカ(
6lなど): 複数のオブジェクトファイルやライブラリを結合し、最終的な実行可能バイナリを生成します。
6lは、x86-64アーキテクチャ(64ビットIntel/AMDプロセッサ)向けのリンカを指します。Goのツールチェーンは、ターゲットアーキテクチャに応じて6g, 6a, 6l(x86-64)、8g, 8a, 8l(x86-32)、5g, 5a, 5l(ARM)といった命名規則を使用していました。
x86-64アーキテクチャ、レジスタ、命令セット
x86-64は、IntelとAMDが開発した64ビット命令セットアーキテクチャです。このアーキテクチャは、汎用レジスタ(RAX, RBXなど)に加えて、SIMD演算に特化したレジスタセットを持っています。
- XMMレジスタ: 128ビット幅のレジスタで、SSE(Streaming SIMD Extensions)命令セットで使用されます。
PSLLQ命令のようなSIMD命令は、これらのレジスタに格納された複数のデータを一度に処理します。 - SIMD(Single Instruction, Multiple Data)命令: 一つの命令で複数のデータ要素(例: 整数、浮動小数点数)に対して同じ演算を同時に実行する命令です。これにより、画像処理、音声処理、科学技術計算など、データ並列性が高いタスクのパフォーマンスが大幅に向上します。
アセンブリ言語と機械語、オペコード
- アセンブリ言語: 人間が理解しやすいように、機械語命令をニーモニック(例:
MOV,ADD,PSLLQ)とオペランドで表現した低水準プログラミング言語です。 - 機械語: CPUが直接実行できるバイナリ形式の命令です。各アセンブリ命令は、一つまたは複数の機械語バイト列に変換されます。
- オペコード(Opcode): 機械語命令の主要部分で、CPUに実行すべき操作(例: 加算、データ移動、論理シフト)を指示するバイト列です。
- オペランド(Operand): 命令が操作するデータやその場所(レジスタ、メモリ、即値など)を指定する部分です。
- ModR/Mバイト: x86命令セットにおいて、オペランドの指定方法(レジスタ、メモリ参照)や、命令の拡張オペコード(Reg/Opcodeフィールド)をエンコードするために使用される1バイトです。ModR/Mバイトは、Mod(2ビット)、Reg/Opcode(3ビット)、R/M(3ビット)の3つのフィールドに分かれています。
- Modフィールド: オペランドがレジスタかメモリか、メモリの場合のオフセットの有無とサイズを示します。
- Reg/Opcodeフィールド: 命令によっては、このフィールドが追加のオペコードビットとして機能し、同じオペコードを持つ複数の命令を区別するために使用されます。
- R/Mフィールド: オペランドがレジスタの場合、そのレジスタ番号を示します。メモリの場合、ベースレジスタやインデックスレジスタを示します。
- SIBバイト(Scale-Index-Base Byte): ModR/Mバイトがメモリオペランドを指定し、かつ複雑なアドレス指定(スケール、インデックス、ベースレジスタ)が必要な場合に使用される追加の1バイトです。
- 即値(Immediate Value): 命令の一部として直接エンコードされる定数データです。
imm8は8ビットの即値を意味します。
PSLLQ命令
PSLLQは "Packed Shift Left Logical Quadword" の略で、SIMD命令の一つです。この命令は、XMMレジスタに格納された複数の64ビット(quadword)整数を、指定されたビット数だけ論理的に左シフトします。シフト量は即値(imm8)または別のレジスタで指定できます。
このコミットで修正された形式は、PSLLQ imm8, xmm_regであり、これはXMMレジスタの内容を、8ビットの即値で指定されたビット数だけ左シフトする命令です。
optab.cの役割
src/cmd/6l/optab.cファイルは、Go言語の6lリンカが使用するオペコードテーブルを定義しています。このテーブルは、アセンブリ命令のニーモニックと、それに対応する機械語のオペコード、オペランドの型、ModR/MバイトのReg/Opcodeフィールドの値などをマッピングしています。リンカは、このテーブルを参照してアセンブリ命令を正しい機械語に変換します。
テーブルのエントリは通常、以下のような構造を持っています(簡略化された表現):
{ 命令ニーモニック, オペランドタイプ, プレフィックス, オペコード1, オペコード2, ModR/MのReg/Opcodeフィールド, ... }
このコミットでは、PSLLQ命令の定義において、ModR/MバイトのReg/Opcodeフィールドに相当する値が誤っていたため、その値を修正しています。
技術的詳細
PSLLQ命令は、SSE2(Streaming SIMD Extensions 2)命令セットの一部として導入されました。この命令には、シフト量を即値で指定する形式と、汎用レジスタで指定する形式があります。
修正対象となったPSLLQ命令の形式は、PSLLQ xmm1, imm8(Intel構文)またはPSLLQ imm8, xmm_reg(AT&T構文)に相当します。この命令の機械語エンコーディングは、通常、以下のような構造を持ちます。
- プレフィックス:
0x66(operand size override for SSE instructions) - オペコード:
0x0F 0x73 - ModR/Mバイト: このバイトのReg/Opcodeフィールドが、
PSLLQ命令の特定のバリアント(即値シフト)を示すために使用されます。
optab.cの該当行は以下のようになっています。
{ APSLLQ,\typs,\tPy, 0xf3, 0x73,(06), Pe,0xf3, Pe,0x7e,(06) },
この行は、PSLLQ命令の複数の形式を定義しています。特に注目すべきは、Py, 0xf3, 0x73,(06)とPe,0xf3, Pe,0x7e,(06)の部分です。
PyとPeは、オペランドの型や命令のエンコーディングに関する内部的なフラグやプレフィックスを示唆しています。0xf3と0x73は、命令の主要なオペコードバイトです。(06)と(06)は、ModR/MバイトのReg/Opcodeフィールドの値を示しています。この値が、同じオペコード0x0F 0x73を持つ他の命令(例:PSRLQ,PSRAQなど)とPSLLQを区別するために使用されます。
元のコードでは、Pe,0xf3, Pe,0x7e,(06)の部分で、ModR/MバイトのReg/Opcodeフィールドが0x7eと誤って定義されていました。これは、PSLLQ命令の即値シフト形式に対しては正しくありません。正しい値は0x73であるべきです。
ModR/MバイトのReg/Opcodeフィールドは3ビットの値であり、通常は0から7までの範囲を取ります。0x7eや0x73は、この3ビットの値をエンコードした結果のバイト値の一部として解釈されます。この文脈では、06が正しいReg/Opcodeフィールドの値を示しており、0x7eや0x73は、そのReg/Opcodeフィールドを含むModR/Mバイト全体のエンコーディングの一部、または関連するオペコード拡張の一部として解釈される可能性があります。
この修正は、PSLLQ命令の即値シフト形式が、リンカによって正しく機械語に変換されることを保証します。誤ったReg/Opcodeフィールドの値は、リンカが間違った命令を生成したり、アセンブリコードの解析に失敗したりする原因となります。
コアとなるコードの変更箇所
src/cmd/6l/optab.cファイルの以下の行が変更されました。
--- a/src/cmd/6l/optab.c
+++ b/src/cmd/6l/optab.c
@@ -978,7 +978,7 @@ Optab optab[] =
{ APSHUFW,\tymshuf,\tPm, 0x70 },
{ APSLLO,\typsdq,\tPq, 0x73,(07) },
{ APSLLL,\typs,\tPy, 0xf2, 0x72,(06), Pe,0xf2, Pe,0x72,(06) },
-\t{ APSLLQ,\typs,\tPy, 0xf3, 0x73,(06), Pe,0xf3, Pe,0x7e,(06) },
+\t{ APSLLQ,\typs,\tPy, 0xf3, 0x73,(06), Pe,0xf3, Pe,0x73,(06) },
{ APSLLW,\typs,\tPy, 0xf1, 0x71,(06), Pe,0xf1, Pe,0x71,(06) },
{ APSRAL,\typs,\tPy, 0xe2, 0x72,(04), Pe,0xe2, Pe,0x72,(04) },
{ APSRAW,\typs,\tPy, 0xe1, 0x71,(04), Pe,0xe1, Pe,0x71,(04) },
コアとなるコードの解説
変更された行は、Optab optab[]配列内のPSLLQ命令の定義です。
元の行:
{ APSLLQ,\typs,\tPy, 0xf3, 0x73,(06), Pe,0xf3, Pe,0x7e,(06) },
修正後の行:
{ APSLLQ,\typs,\tPy, 0xf3, 0x73,(06), Pe,0xf3, Pe,0x73,(06) },
この変更は、PSLLQ命令の定義の後半部分、具体的にはPe,0xf3, Pe,0x7e,(06)からPe,0xf3, Pe,0x73,(06)への変更です。
APSLLQ: これはGoリンカ内部でPSLLQ命令を表す定数です。\typs: オペランドの型や命令の特性を示す内部的なフラグです。Py, 0xf3, 0x73,(06): これはPSLLQ命令のレジスタ-レジスタ形式またはメモリ-レジスタ形式のエンコーディングの一部を示していると考えられます。0xf3と0x73はオペコードバイト、(06)はModR/MバイトのReg/Opcodeフィールドの値です。Pe,0xf3, Pe,0x7e,(06)(変更前): これはPSLLQ命令の即値-レジスタ形式(PSLLQ imm8, xmm_reg)のエンコーディングの一部を示しています。ここで、0x7eが誤った値でした。Pe,0xf3, Pe,0x73,(06)(変更後):0x7eが0x73に修正されました。これにより、PSLLQ imm8, xmm_reg命令がリンカによって正しく機械語に変換されるようになります。
この修正により、PSLLQ命令の即値シフト形式が、x86-64アーキテクチャの仕様に合致する正しい機械語オペコードにマッピングされることが保証されます。これは、Goコンパイラが生成するアセンブリコードの正確性を保ち、最終的なバイナリの信頼性を向上させる上で重要な修正です。
関連リンク
- Go CL (Code Review) ページ: https://golang.org/cl/5340056
- GitHubコミットページ: https://github.com/golang/go/commit/c8a2be8c38f252fd448d6cb957341b1590d93c7e
参考にした情報源リンク
- Intel® 64 and IA-32 Architectures Software Developer’s Manuals (特にVolume 2A: Instruction Set Reference, A-M): https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html
- Go言語のソースコード(
src/cmd/6l/optab.cの歴史的なバージョン) - x86アセンブリ言語と機械語エンコーディングに関する一般的な情報源(例: Wikipedia, 各種チュートリアル)
- SIMD命令セット(SSE/AVX)に関する情報源