[インデックス 13318] ファイルの概要
このコミットは、Go言語のARMアーキテクチャ向けツールチェイン(アセンブラ、コンパイラ、リンカ)に、新しい乗算命令であるMULW{T,B}
およびMULAW{T,B}
のサポートを追加し、既存のMULA
命令の逆アセンブル表示を修正するものです。これにより、ARMv5TE以降のプロセッサでこれらの命令をGoプログラムから利用できるようになります。
コミット
commit a0084b3494423057c9f702d952c8df88dd9a9317
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Fri Jun 8 02:42:28 2012 +0800
cmd/5a, cmd/5l: add MULW{T,B} and MULAW{T,B} support for ARM
Supported in ARMv5TE and above.
Also corrected MULA disassembly listing.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6265045
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/a0084b3494423057c9f702d952c8df88dd9a9317
元コミット内容
cmd/5a, cmd/5l: add MULW{T,B} and MULAW{T,B} support for ARM
Supported in ARMv5TE and above.
Also corrected MULA disassembly listing.
変更の背景
このコミットの背景には、Go言語がサポートするARMアーキテクチャの命令セットを最新化し、より効率的なコード生成を可能にするという目的があります。特に、MULW
およびMULAW
命令は、ARMv5TE以降のプロセッサで利用可能な拡張乗算命令であり、これらをGoのツールチェインでサポートすることで、特定の数値計算処理のパフォーマンス向上が期待されます。
また、既存のMULA
命令の逆アセンブル表示に誤りがあったため、その修正も同時に行われています。これは、デバッグやコード解析の正確性を保証するために重要な修正です。
前提知識の解説
ARMアーキテクチャと命令セット
ARM(Advanced RISC Machine)は、モバイルデバイスや組み込みシステムで広く使用されているRISC(Reduced Instruction Set Computer)プロセッサアーキテクチャです。ARMプロセッサは、その低消費電力と高性能のバランスから、スマートフォン、タブレット、IoTデバイスなど、多岐にわたる分野で採用されています。
ARM命令セットは、基本的なデータ処理、メモリアクセス、フロー制御命令に加え、特定のタスクを効率化するための拡張命令を含んでいます。
乗算命令
ARMアーキテクチャには、様々な乗算命令が存在します。
MUL
(Multiply): 32ビットのレジスタ値を乗算し、結果の下位32ビットを別のレジスタに格納します。MLA
(Multiply Accumulate): 2つのレジスタ値を乗算し、その結果に3番目のレジスタ値を加算(アキュムレート)し、最終結果をレジスタに格納します。これはRd = (Rm * Rs) + Rn
の形式で、積和演算を1命令で行うため、デジタル信号処理(DSP)などで頻繁に利用されます。MULL
(Multiply Long): 2つの32ビット値を乗算し、64ビットの結果を2つのレジスタに格納します(上位32ビットと下位32ビット)。MULA
(Multiply Accumulate Long): 2つの32ビット値を乗算し、その64ビットの結果に64ビットの値を加算し、最終的な64ビットの結果を2つのレジスタに格納します。
拡張乗算命令 (MULW
, MULAW
)
ARMv5TE以降のアーキテクチャでは、より効率的な乗算命令が導入されました。
MULW
(Multiply Word): 32ビットの乗算命令で、結果の上位または下位ワードを効率的に取得するためのバリアントが存在します。MULWT
(Multiply Word Top): 乗算結果の上位ワードを取得します。MULWB
(Multiply Word Bottom): 乗算結果の下位ワードを取得します。
MULAW
(Multiply Accumulate Word):MULW
と同様に、乗算結果に加算を行う命令です。MULAWT
(Multiply Accumulate Word Top): 乗算結果の上位ワードに加算します。MULAWB
(Multiply Accumulate Word Bottom): 乗算結果の下位ワードに加算します。
これらの命令は、特に64ビットの結果を扱う必要がある場合や、積和演算を効率的に行いたい場合に有用です。
Go言語のツールチェイン
Go言語のコンパイルプロセスは、主に以下のコンポーネントで構成されます。
cmd/5a
(Assembler): ARMアーキテクチャ向けのアセンブラ。アセンブリ言語で書かれたコードを機械語に変換します。cmd/5g
(Compiler): Go言語のソースコードをARMアーキテクチャ向けのオブジェクトコードにコンパイルします。cmd/5l
(Linker): オブジェクトファイルを結合し、実行可能なバイナリを生成します。src/libmach
: Goのツールチェインが使用する低レベルの機械語操作ライブラリ。
これらのツールは、Goプログラムが特定のアーキテクチャ上で正しく動作するために密接に連携しています。
Yacc/BisonとLex/Flex
a.y
ファイルはYacc(Yet Another Compiler Compiler)またはBisonで生成されたパーサの定義ファイルです。Yaccは文法規則に基づいて構文解析器を生成するツールで、lex.c
はLex(Lexical Analyzer Generator)またはFlexで生成された字句解析器のコードです。これらはコンパイラやアセンブラのフロントエンドで、ソースコードをトークンに分割し、そのトークン列が文法的に正しいかを解析するために使用されます。
技術的詳細
このコミットは、GoのARMツールチェインにおける命令認識、コード生成、および逆アセンブルの各フェーズにわたる変更を含んでいます。
-
アセンブラ (
cmd/5a
) の変更:src/cmd/5a/a.y
: アセンブラの文法定義ファイル。MULW{T,B}
およびMULAW{T,B}
命令の新しい構文規則が追加されます。特に、MULA
命令のコメントが修正され、新しいD_REGREG2
タイプが導入されています。これは、MULA
や新しいMULAW
命令が複数のレジスタをオペランドとして取る形式を適切に処理するためのものです。src/cmd/5a/lex.c
: 字句解析器の定義ファイル。新しい命令(MULWT
,MULWB
,MULAWT
,MULAWB
)がトークンとして認識されるように追加されます。また、D_REGREG2
タイプがzaddr
関数で処理されるように変更されています。src/cmd/5a/y.tab.c
: Yaccによって生成されたパーサのC言語ソースコード。a.y
の変更に伴い、行番号の更新や、D_REGREG2
タイプへの変更が反映されています。
-
コンパイラ (
cmd/5g
) の変更:src/cmd/5g/cgen64.c
: 64ビットコード生成に関連するファイル。D_REGREG
がD_REGREG2
に変更されており、これは64ビット乗算命令のオペランド処理の変更を示唆しています。src/cmd/5g/gobj.c
: オブジェクトファイル生成に関連するファイル。D_REGREG2
がzaddr
関数で処理されるように追加されています。src/cmd/5g/list.c
: リスティング(逆アセンブル)生成に関連するファイル。D_REGREG2
タイプのオペランドの表示形式が定義されています。これにより、新しい命令の逆アセンブルが正しく表示されるようになります。src/cmd/5g/peep.c
: 命令の最適化(peephole optimization)に関連するファイル。D_REGREG
だけでなくD_REGREG2
も考慮するように変更されており、最適化パスが新しい命令タイプを正しく扱えるようになります。src/cmd/5g/reg.c
: レジスタ割り当てに関連するファイル。D_REGREG2
がレジスタ使用状況の追跡に追加されています。
-
リンカ (
cmd/5l
) の変更:src/cmd/5l/5.out.h
: ARMアーキテクチャ向けの命令コード定義ファイル。新しい命令(AMULWT
,AMULWB
,AMULAWT
,AMULAWB
)の定数と、新しいオペランドタイプD_REGREG2
が追加されています。src/cmd/5l/asm.c
: アセンブリコードから機械語への変換を行うファイル。新しい命令MULW{T,B}
およびMULAW{T,B}
の機械語エンコーディングロジックが追加されています。特に、oprrr
関数にこれらの命令のオペコードが定義されています。src/cmd/5l/l.h
: リンカの内部ヘッダファイル。新しいオペランドタイプC_REGREG2
が追加されています。src/cmd/5l/list.c
: リンカのリスティング生成に関連するファイル。D_REGREG2
タイプのオペランドの表示形式が定義されています。src/cmd/5l/obj.c
: オブジェクトファイルの読み書きに関連するファイル。D_REGREG2
がzaddr
関数で処理されるように追加されています。src/cmd/5l/optab.c
: 命令の最適化テーブル。新しい命令とそれに対応するオペランドタイプが追加されています。特に、AMULA
命令がC_REGREG2
タイプを使用するように修正されています。src/cmd/5l/span.c
: コード生成の最終段階で命令の配置やジャンプの解決を行うファイル。aclass
関数でD_REGREG2
がC_REGREG2
にマッピングされるように追加されています。また、buildop
関数で新しい乗算命令のオペランド範囲が定義されています。
-
ライブラリ (
src/libmach
) の変更:src/libmach/5obj.c
: Goのツールチェインが使用する低レベルの機械語操作ライブラリ。D_REGREG2
がaddr
関数で処理されるように追加されています。
これらの変更は、GoのARMツールチェインが新しい命令を正しく解析、コンパイル、リンク、そして逆アセンブルできるようにするために不可欠です。特に、D_REGREG2
という新しいオペランドタイプの導入は、複数のレジスタを組み合わせた複雑なオペランド形式を扱うための重要な変更点です。
コアとなるコードの変更箇所
src/cmd/5a/a.y
--- a/src/cmd/5a/a.y
+++ b/src/cmd/5a/a.y
@@ -286,18 +286,19 @@ inst:
\toutcode(AWORD, Always, &nullgen, NREG, &g);
}
/*
- * MULL hi,lo,r1,r2
+ * MULL r1,r2,(hi,lo)
*/
|\tLTYPEM cond reg ',' reg ',' regreg
{
\toutcode($1, $2, &$3, $5.reg, &$7);
}
/*
- * MULA hi,lo,r1,r2
+ * MULA r1,r2,r3,r4: (r1*r2+r3) & 0xffffffff -> r4
+ * MULAW{T,B} r1,r2,r3,r4
*/
|\tLTYPEN cond reg ',' reg ',' reg ',' spreg
{
-\t\t$7.type = D_REGREG;
+\t\t$7.type = D_REGREG2;
\t$7.offset = $9;
\toutcode($1, $2, &$3, $5.reg, &$7);
}
src/cmd/5a/lex.c
--- a/src/cmd/5a/lex.c
+++ b/src/cmd/5a/lex.c
@@ -408,6 +408,11 @@ struct
"UNDEF", LTYPEE, AUNDEF,
"CLZ", LTYPE2, ACLZ,
+ "MULWT", LTYPE1, AMULWT,
+ "MULWB", LTYPE1, AMULWB,
+ "MULAWT", LTYPEN, AMULAWT,
+ "MULAWB", LTYPEN, AMULAWB,
+
0
};
@@ -511,6 +516,7 @@ zaddr(Gen *a, int s)
break;
case D_REGREG:
+ case D_REGREG2:
Bputc(&obuf, a->offset);
break;
src/cmd/5l/5.out.h
--- a/src/cmd/5l/5.out.h
+++ b/src/cmd/5l/5.out.h
@@ -189,6 +189,11 @@ enum as
ACLZ,
+ AMULWT,
+ AMULWB,
+ AMULAWT,
+ AMULAWB,
+
ALAST,
};
@@ -242,12 +247,14 @@ enum as
#define D_SHIFT (D_NONE+19)
#define D_FPCR (D_NONE+20)
-#define D_REGREG (D_NONE+21)
+#define D_REGREG (D_NONE+21) // (reg, reg)
#define D_ADDR (D_NONE+22)
#define D_SBIG (D_NONE+23)
#define D_CONST2 (D_NONE+24)
+#define D_REGREG2 (D_NONE+25) // reg, reg
+
/* name */
#define D_EXTERN (D_NONE+3)
#define D_STATIC (D_NONE+4)
src/cmd/5l/asm.c
--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -1806,6 +1806,19 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p-
\to1 |= p->to.reg << 12;
\to1 |= p->from.reg;
break;
+ case 98: /* MULW{T,B} Rs, Rm, Rd */
+ \to1 = oprrr(p->as, p->scond);
+ \to1 |= p->to.reg << 16;
+ \to1 |= p->from.reg << 8;
+ \to1 |= p->reg;
+ break;
+ case 99: /* MULAW{T,B} Rs, Rm, Rn, Rd */
+ \to1 = oprrr(p->as, p->scond);
+ \to1 |= p->to.reg << 12;
+ \to1 |= p->from.reg << 8;
+ \to1 |= p->reg;
+ \to1 |= p->to.offset << 16;
+ break;
}
out[0] = o1;
@@ -1967,6 +1980,15 @@ oprrr(int a, int sc)
case ACLZ:
// CLZ doesn't support .S
return (o & (0xf<<28)) | (0x16f<<16) | (0xf1<<4);
+
+ case AMULWT:
+ return (o & (0xf<<28)) | (0x12 << 20) | (0xe<<4);
+ case AMULWB:
+ return (o & (0xf<<28)) | (0x12 << 20) | (0xa<<4);
+ case AMULAWT:
+ return (o & (0xf<<28)) | (0x12 << 20) | (0xc<<4);
+ case AMULAWB:
+ return (o & (0xf<<28)) | (0x12 << 20) | (0x8<<4);
}
diag("bad rrr %d", a);
prasm(curp);
コアとなるコードの解説
src/cmd/5a/a.y
の変更
このファイルはアセンブラの文法定義を記述しており、Yacc/Bisonによってパーサが生成されます。
変更点としては、MULA
命令のコメントが修正され、そのオペランドの型がD_REGREG
からD_REGREG2
に変更されています。これは、MULA
命令がr1,r2,r3,r4
という形式で、r1*r2+r3
の結果をr4
に格納するという、より詳細な説明が追加されたことを示しています。また、新しいMULAW{T,B}
命令もこのLTYPEN
という文法規則に合致するように定義されています。D_REGREG2
は、複数のレジスタを組み合わせたオペランドを表現するための新しい内部型です。
src/cmd/5a/lex.c
の変更
このファイルは字句解析器の定義を記述しており、Lex/Flexによって字句解析器が生成されます。
変更点としては、新しい命令であるMULWT
, MULWB
, MULAWT
, MULAWB
がキーワードとして追加され、それぞれに対応する内部的な命令コード(AMULWT
, AMULWB
, AMULAWT
, AMULAWB
)が割り当てられています。これにより、アセンブラはこれらの新しい命令を正しく認識できるようになります。
また、zaddr
関数において、D_REGREG2
タイプがD_REGREG
と同様に処理されるように追加されています。これは、これらのオペランドタイプがレジスタペアを表現するために使用されることを示唆しています。
src/cmd/5l/5.out.h
の変更
このヘッダファイルは、GoのARMツールチェインが使用する命令コードとオペランドタイプの定義を含んでいます。
変更点としては、新しい命令であるAMULWT
, AMULWB
, AMULAWT
, AMULAWB
の列挙型が追加されています。
さらに、新しいオペランドタイプD_REGREG2
が定義されています。既存のD_REGREG
が(reg, reg)
というコメントで示されているのに対し、D_REGREG2
もreg, reg
とコメントされており、これらがレジスタペアを表現する際に使用されることが分かります。この新しいタイプは、特にMULA
やMULAW
のような複数のレジスタをオペランドとして取る命令の処理をより明確にするために導入されたと考えられます。
src/cmd/5l/asm.c
の変更
このファイルは、アセンブリ命令を実際の機械語(バイナリコード)に変換するロジックを含んでいます。
変更点としては、MULW{T,B}
(ケース98)とMULAW{T,B}
(ケース99)命令の機械語エンコーディングロジックが追加されています。これらの命令は、ソースレジスタ(p->from.reg
)、デスティネーションレジスタ(p->to.reg
)、および追加のレジスタ(p->reg
、p->to.offset
)を特定のビット位置に配置して機械語を生成します。
また、oprrr
関数に、これらの新しい命令(AMULWT
, AMULWB
, AMULAWT
, AMULAWB
)に対応するARM命令のオペコードが定義されています。これらのオペコードは、ARM命令セットの特定のビットパターンに対応しており、命令の種類や動作を決定します。
これらの変更により、GoのARMツールチェインは、新しい乗算命令を正しくアセンブルし、実行可能なバイナリに含めることができるようになります。
関連リンク
- ARM Architecture Reference Manual (ARM命令セットの詳細な情報源)
- Go Language Documentation
参考にした情報源リンク
- Go言語のソースコード
- ARM Architecture Reference Manual
- Yacc/Bison Documentation
- Lex/Flex Documentation
- Gerrit Change 6265045 (GoのGerritレビューシステムでのこのコミットのレビューページ)
- ARM Assembly Language Programming (一般的なARMアセンブリプログラミングに関する情報)
- ARMv5TE Instruction Set (ARMv5TE命令セットの概要)# [インデックス 13318] ファイルの概要
このコミットは、Go言語のARMアーキテクチャ向けツールチェイン(アセンブラ、コンパイラ、リンカ)に、新しい乗算命令であるMULW{T,B}
およびMULAW{T,B}
のサポートを追加し、既存のMULA
命令の逆アセンブル表示を修正するものです。これにより、ARMv5TE以降のプロセッサでこれらの命令をGoプログラムから利用できるようになります。
コミット
commit a0084b3494423057c9f702d952c8df88dd9a9317
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Fri Jun 8 02:42:28 2012 +0800
cmd/5a, cmd/5l: add MULW{T,B} and MULAW{T,B} support for ARM
Supported in ARMv5TE and above.
Also corrected MULA disassembly listing.
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/6265045
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/a0084b3494423057c9f702d952c8df88dd9a9317
元コミット内容
cmd/5a, cmd/5l: add MULW{T,B} and MULAW{T,B} support for ARM
Supported in ARMv5TE and above.
Also corrected MULA disassembly listing.
変更の背景
このコミットの背景には、Go言語がサポートするARMアーキテクチャの命令セットを最新化し、より効率的なコード生成を可能にするという目的があります。特に、MULW
およびMULAW
命令は、ARMv5TE以降のプロセッサで利用可能な拡張乗算命令であり、これらをGoのツールチェインでサポートすることで、特定の数値計算処理のパフォーマンス向上が期待されます。
また、既存のMULA
命令の逆アセンブル表示に誤りがあったため、その修正も同時に行われています。これは、デバッグやコード解析の正確性を保証するために重要な修正です。
前提知識の解説
ARMアーキテクチャと命令セット
ARM(Advanced RISC Machine)は、モバイルデバイスや組み込みシステムで広く使用されているRISC(Reduced Instruction Set Computer)プロセッサアーキテクチャです。ARMプロセッサは、その低消費電力と高性能のバランスから、スマートフォン、タブレット、IoTデバイスなど、多岐にわたる分野で採用されています。
ARM命令セットは、基本的なデータ処理、メモリアクセス、フロー制御命令に加え、特定のタスクを効率化するための拡張命令を含んでいます。
乗算命令
ARMアーキテクチャには、様々な乗算命令が存在します。
MUL
(Multiply): 32ビットのレジスタ値を乗算し、結果の下位32ビットを別のレジスタに格納します。MLA
(Multiply Accumulate): 2つのレジスタ値を乗算し、その結果に3番目のレジスタ値を加算(アキュムレート)し、最終結果をレジスタに格納します。これはRd = (Rm * Rs) + Rn
の形式で、積和演算を1命令で行うため、デジタル信号処理(DSP)などで頻繁に利用されます。MULL
(Multiply Long): 2つの32ビット値を乗算し、64ビットの結果を2つのレジスタに格納します(上位32ビットと下位32ビット)。MULA
(Multiply Accumulate Long): 2つの32ビット値を乗算し、その64ビットの結果に64ビットの値を加算し、最終的な64ビットの結果を2つのレジスタに格納します。
拡張乗算命令 (MULW
, MULAW
)
ARMv5TE以降のアーキテクチャでは、より効率的な乗算命令が導入されました。
MULW
(Multiply Word): 32ビットの乗算命令で、結果の上位または下位ワードを効率的に取得するためのバリアントが存在します。MULWT
(Multiply Word Top): 乗算結果の上位ワードを取得します。MULWB
(Multiply Word Bottom): 乗算結果の下位ワードを取得します。
MULAW
(Multiply Accumulate Word):MULW
と同様に、乗算結果に加算を行う命令です。MULAWT
(Multiply Accumulate Word Top): 乗算結果の上位ワードに加算します。MULAWB
(Multiply Accumulate Word Bottom): 乗算結果の下位ワードに加算します。
これらの命令は、特に64ビットの結果を扱う必要がある場合や、積和演算を効率的に行いたい場合に有用です。
Go言語のツールチェイン
Go言語のコンパイルプロセスは、主に以下のコンポーネントで構成されます。
cmd/5a
(Assembler): ARMアーキテクチャ向けのアセンブラ。アセンブリ言語で書かれたコードを機械語に変換します。cmd/5g
(Compiler): Go言語のソースコードをARMアーキテクチャ向けのオブジェクトコードにコンパイルします。cmd/5l
(Linker): オブジェクトファイルを結合し、実行可能なバイナリを生成します。src/libmach
: Goのツールチェインが使用する低レベルの機械語操作ライブラリ。
これらのツールは、Goプログラムが特定のアーキテクチャ上で正しく動作するために密接に連携しています。
Yacc/BisonとLex/Flex
a.y
ファイルはYacc(Yet Another Compiler Compiler)またはBisonで生成されたパーサの定義ファイルです。Yaccは文法規則に基づいて構文解析器を生成するツールで、lex.c
はLex(Lexical Analyzer Generator)またはFlexで生成された字句解析器のコードです。これらはコンパイラやアセンブラのフロントエンドで、ソースコードをトークンに分割し、そのトークン列が文法的に正しいかを解析するために使用されます。
技術的詳細
このコミットは、GoのARMツールチェインにおける命令認識、コード生成、および逆アセンブルの各フェーズにわたる変更を含んでいます。
-
アセンブラ (
cmd/5a
) の変更:src/cmd/5a/a.y
: アセンブラの文法定義ファイル。MULW{T,B}
およびMULAW{T,B}
命令の新しい構文規則が追加されます。特に、MULA
命令のコメントが修正され、新しいD_REGREG2
タイプが導入されています。これは、MULA
や新しいMULAW
命令が複数のレジスタをオペランドとして取る形式を適切に処理するためのものです。src/cmd/5a/lex.c
: 字句解析器の定義ファイル。新しい命令(MULWT
,MULWB
,MULAWT
,MULAWB
)がトークンとして認識されるように追加されます。また、D_REGREG2
タイプがzaddr
関数で処理されるように変更されています。src/cmd/5a/y.tab.c
: Yaccによって生成されたパーサのC言語ソースコード。a.y
の変更に伴い、行番号の更新や、D_REGREG2
タイプへの変更が反映されています。
-
コンパイラ (
cmd/5g
) の変更:src/cmd/5g/cgen64.c
: 64ビットコード生成に関連するファイル。D_REGREG
がD_REGREG2
に変更されており、これは64ビット乗算命令のオペランド処理の変更を示唆しています。src/cmd/5g/gobj.c
: オブジェクトファイル生成に関連するファイル。D_REGREG2
がzaddr
関数で処理されるように追加されています。src/cmd/5g/list.c
: リスティング(逆アセンブル)生成に関連するファイル。D_REGREG2
タイプのオペランドの表示形式が定義されています。これにより、新しい命令の逆アセンブルが正しく表示されるようになります。src/cmd/5g/peep.c
: 命令の最適化(peephole optimization)に関連するファイル。D_REGREG
だけでなくD_REGREG2
も考慮するように変更されており、最適化パスが新しい命令タイプを正しく扱えるようになります。src/cmd/5g/reg.c
: レジスタ割り当てに関連するファイル。D_REGREG2
がレジスタ使用状況の追跡に追加されています。
-
リンカ (
cmd/5l
) の変更:src/cmd/5l/5.out.h
: ARMアーキテクチャ向けの命令コード定義ファイル。新しい命令(AMULWT
,AMULWB
,AMULAWT
,AMULAWB
)の定数と、新しいオペランドタイプD_REGREG2
が追加されています。src/cmd/5l/asm.c
: アセンブリコードから機械語への変換を行うファイル。新しい命令MULW{T,B}
およびMULAW{T,B}
の機械語エンコーディングロジックが追加されています。特に、oprrr
関数にこれらの命令のオペコードが定義されています。src/cmd/5l/l.h
: リンカの内部ヘッダファイル。新しいオペランドタイプC_REGREG2
が追加されています。src/cmd/5l/list.c
: リンカのリスティング生成に関連するファイル。D_REGREG2
タイプのオペランドの表示形式が定義されています。src/cmd/5l/obj.c
: オブジェクトファイルの読み書きに関連するファイル。D_REGREG2
がzaddr
関数で処理されるように追加されています。src/cmd/5l/optab.c
: 命令の最適化テーブル。新しい命令とそれに対応するオペランドタイプが追加されています。特に、AMULA
命令がC_REGREG2
タイプを使用するように修正されています。src/cmd/5l/span.c
: コード生成の最終段階で命令の配置やジャンプの解決を行うファイル。aclass
関数でD_REGREG2
がC_REGREG2
にマッピングされるように追加されています。また、buildop
関数で新しい乗算命令のオペランド範囲が定義されています。
-
ライブラリ (
src/libmach
) の変更:src/libmach/5obj.c
: Goのツールチェインが使用する低レベルの機械語操作ライブラリ。D_REGREG2
がaddr
関数で処理されるように追加されています。
これらの変更は、GoのARMツールチェインが新しい命令を正しく解析、コンパイル、リンク、そして逆アセンブルできるようにするために不可欠です。特に、D_REGREG2
という新しいオペランドタイプの導入は、複数のレジスタを組み合わせた複雑なオペランド形式を扱うための重要な変更点です。
コアとなるコードの変更箇所
src/cmd/5a/a.y
--- a/src/cmd/5a/a.y
+++ b/src/cmd/5a/a.y
@@ -286,18 +286,19 @@ inst:
\toutcode(AWORD, Always, &nullgen, NREG, &g);
}
/*
- * MULL hi,lo,r1,r2
+ * MULL r1,r2,(hi,lo)
*/
|\tLTYPEM cond reg ',' reg ',' regreg
{
\toutcode($1, $2, &$3, $5.reg, &$7);
}
/*
- * MULA hi,lo,r1,r2
+ * MULA r1,r2,r3,r4: (r1*r2+r3) & 0xffffffff -> r4
+ * MULAW{T,B} r1,r2,r3,r4
*/
|\tLTYPEN cond reg ',' reg ',' reg ',' spreg
{
-\t\t$7.type = D_REGREG;
+\t\t$7.type = D_REGREG2;
\t$7.offset = $9;
\toutcode($1, $2, &$3, $5.reg, &$7);
}
src/cmd/5a/lex.c
--- a/src/cmd/5a/lex.c
+++ b/src/cmd/5a/lex.c
@@ -408,6 +408,11 @@ struct
"UNDEF", LTYPEE, AUNDEF,
"CLZ", LTYPE2, ACLZ,
+ "MULWT", LTYPE1, AMULWT,
+ "MULWB", LTYPE1, AMULWB,
+ "MULAWT", LTYPEN, AMULAWT,
+ "MULAWB", LTYPEN, AMULAWB,
+
0
};
@@ -511,6 +516,7 @@ zaddr(Gen *a, int s)
break;
case D_REGREG:
+ case D_REGREG2:
Bputc(&obuf, a->offset);
break;
src/cmd/5l/5.out.h
--- a/src/cmd/5l/5.out.h
+++ b/src/cmd/5l/5.out.h
@@ -189,6 +189,11 @@ enum as
ACLZ,
+ AMULWT,
+ AMULWB,
+ AMULAWT,
+ AMULAWB,
+
ALAST,
};
@@ -242,12 +247,14 @@ enum as
#define D_SHIFT (D_NONE+19)
#define D_FPCR (D_NONE+20)
-#define D_REGREG (D_NONE+21)
+#define D_REGREG (D_NONE+21) // (reg, reg)
#define D_ADDR (D_NONE+22)
#define D_SBIG (D_NONE+23)
#define D_CONST2 (D_NONE+24)
+#define D_REGREG2 (D_NONE+25) // reg, reg
+
/* name */
#define D_EXTERN (D_NONE+3)
#define D_STATIC (D_NONE+4)
src/cmd/5l/asm.c
--- a/src/cmd/5l/asm.c
+++ b/src/cmd/5l/asm.c
@@ -1806,6 +1806,19 @@ if(debug['G']) print("%ux: %s: arm %d\n", (uint32)(p->pc), p->from.sym->name, p-
\to1 |= p->to.reg << 12;
\to1 |= p->from.reg;
break;
+ case 98: /* MULW{T,B} Rs, Rm, Rd */
+ \to1 = oprrr(p->as, p->scond);
+ \to1 |= p->to.reg << 16;
+ \to1 |= p->from.reg << 8;
+ \to1 |= p->reg;
+ break;
+ case 99: /* MULAW{T,B} Rs, Rm, Rn, Rd */
+ \to1 = oprrr(p->as, p->scond);
+ \to1 |= p->to.reg << 12;
+ \to1 |= p->from.reg << 8;
+ \to1 |= p->reg;
+ \to1 |= p->to.offset << 16;
+ break;
}
out[0] = o1;
@@ -1967,6 +1980,15 @@ oprrr(int a, int sc)
case ACLZ:
// CLZ doesn't support .S
return (o & (0xf<<28)) | (0x16f<<16) | (0xf1<<4);
+
+ case AMULWT:
+ return (o & (0xf<<28)) | (0x12 << 20) | (0xe<<4);
+ case AMULWB:
+ return (o & (0xf<<28)) | (0x12 << 20) | (0xa<<4);
+ case AMULAWT:
+ return (o & (0xf<<28)) | (0x12 << 20) | (0xc<<4);
+ case AMULAWB:
+ return (o & (0xf<<28)) | (0x12 << 20) | (0x8<<4);
}
diag("bad rrr %d", a);
prasm(curp);
コアとなるコードの解説
src/cmd/5a/a.y
の変更
このファイルはアセンブラの文法定義を記述しており、Yacc/Bisonによってパーサが生成されます。
変更点としては、MULA
命令のコメントが修正され、そのオペランドの型がD_REGREG
からD_REGREG2
に変更されています。これは、MULA
命令がr1,r2,r3,r4
という形式で、r1*r2+r3
の結果をr4
に格納するという、より詳細な説明が追加されたことを示しています。また、新しいMULAW{T,B}
命令もこのLTYPEN
という文法規則に合致するように定義されています。D_REGREG2
は、複数のレジスタを組み合わせたオペランドを表現するための新しい内部型です。
src/cmd/5a/lex.c
の変更
このファイルは字句解析器の定義を記述しており、Lex/Flexによって字句解析器が生成されます。
変更点としては、新しい命令であるMULWT
, MULWB
, MULAWT
, MULAWB
がキーワードとして追加され、それぞれに対応する内部的な命令コード(AMULWT
, AMULWB
, AMULAWT
, AMULAWB
)が割り当てられています。これにより、アセンブラはこれらの新しい命令を正しく認識できるようになります。
また、zaddr
関数において、D_REGREG2
タイプがD_REGREG
と同様に処理されるように追加されています。これは、これらのオペランドタイプがレジスタペアを表現するために使用されることを示唆しています。
src/cmd/5l/5.out.h
の変更
このヘッダファイルは、GoのARMツールチェインが使用する命令コードとオペランドタイプの定義を含んでいます。
変更点としては、新しい命令であるAMULWT
, AMULWB
, AMULAWT
, AMULAWB
の列挙型が追加されています。
さらに、新しいオペランドタイプD_REGREG2
が定義されています。既存のD_REGREG
が(reg, reg)
というコメントで示されているのに対し、D_REGREG2
もreg, reg
とコメントされており、これらがレジスタペアを表現する際に使用されることが分かります。この新しいタイプは、特にMULA
やMULAW
のような複数のレジスタをオペランドとして取る命令の処理をより明確にするために導入されたと考えられます。
src/cmd/5l/asm.c
の変更
このファイルは、アセンブリ命令を実際の機械語(バイナリコード)に変換するロジックを含んでいます。
変更点としては、MULW{T,B}
(ケース98)とMULAW{T,B}
(ケース99)命令の機械語エンコーディングロジックが追加されています。これらの命令は、ソースレジスタ(p->from.reg
)、デスティネーションレジスタ(p->to.reg
)、および追加のレジスタ(p->reg
、p->to.offset
)を特定のビット位置に配置して機械語を生成します。
また、oprrr
関数に、これらの新しい命令(AMULWT
, AMULWB
, AMULAWT
, AMULAWB
)に対応するARM命令のオペコードが定義されています。これらのオペコードは、ARM命令セットの特定のビットパターンに対応しており、命令の種類や動作を決定します。
これらの変更により、GoのARMツールチェインは、新しい乗算命令を正しくアセンブルし、実行可能なバイナリに含めることができるようになります。
関連リンク
- ARM Architecture Reference Manual (ARM命令セットの詳細な情報源)
- Go Language Documentation
参考にした情報源リンク
- Go言語のソースコード
- ARM Architecture Reference Manual
- Yacc/Bison Documentation
- Lex/Flex Documentation
- Gerrit Change 6265045 (GoのGerritレビューシステムでのこのコミットのレビューページ)
- ARM Assembly Language Programming (一般的なARMアセンブリプログラミングに関する情報)
- ARMv5TE Instruction Set (ARMv5TE命令セットの概要)