Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 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ツールチェインにおける命令認識、コード生成、および逆アセンブルの各フェーズにわたる変更を含んでいます。

  1. アセンブラ (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タイプへの変更が反映されています。
  2. コンパイラ (cmd/5g) の変更:

    • src/cmd/5g/cgen64.c: 64ビットコード生成に関連するファイル。D_REGREGD_REGREG2に変更されており、これは64ビット乗算命令のオペランド処理の変更を示唆しています。
    • src/cmd/5g/gobj.c: オブジェクトファイル生成に関連するファイル。D_REGREG2zaddr関数で処理されるように追加されています。
    • 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がレジスタ使用状況の追跡に追加されています。
  3. リンカ (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_REGREG2zaddr関数で処理されるように追加されています。
    • src/cmd/5l/optab.c: 命令の最適化テーブル。新しい命令とそれに対応するオペランドタイプが追加されています。特に、AMULA命令がC_REGREG2タイプを使用するように修正されています。
    • src/cmd/5l/span.c: コード生成の最終段階で命令の配置やジャンプの解決を行うファイル。aclass関数でD_REGREG2C_REGREG2にマッピングされるように追加されています。また、buildop関数で新しい乗算命令のオペランド範囲が定義されています。
  4. ライブラリ (src/libmach) の変更:

    • src/libmach/5obj.c: Goのツールチェインが使用する低レベルの機械語操作ライブラリ。D_REGREG2addr関数で処理されるように追加されています。

これらの変更は、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_REGREG2reg, regとコメントされており、これらがレジスタペアを表現する際に使用されることが分かります。この新しいタイプは、特にMULAMULAWのような複数のレジスタをオペランドとして取る命令の処理をより明確にするために導入されたと考えられます。

src/cmd/5l/asm.c の変更

このファイルは、アセンブリ命令を実際の機械語(バイナリコード)に変換するロジックを含んでいます。 変更点としては、MULW{T,B}(ケース98)とMULAW{T,B}(ケース99)命令の機械語エンコーディングロジックが追加されています。これらの命令は、ソースレジスタ(p->from.reg)、デスティネーションレジスタ(p->to.reg)、および追加のレジスタ(p->regp->to.offset)を特定のビット位置に配置して機械語を生成します。 また、oprrr関数に、これらの新しい命令(AMULWT, AMULWB, AMULAWT, AMULAWB)に対応するARM命令のオペコードが定義されています。これらのオペコードは、ARM命令セットの特定のビットパターンに対応しており、命令の種類や動作を決定します。

これらの変更により、GoのARMツールチェインは、新しい乗算命令を正しくアセンブルし、実行可能なバイナリに含めることができるようになります。

関連リンク

参考にした情報源リンク

このコミットは、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ツールチェインにおける命令認識、コード生成、および逆アセンブルの各フェーズにわたる変更を含んでいます。

  1. アセンブラ (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タイプへの変更が反映されています。
  2. コンパイラ (cmd/5g) の変更:

    • src/cmd/5g/cgen64.c: 64ビットコード生成に関連するファイル。D_REGREGD_REGREG2に変更されており、これは64ビット乗算命令のオペランド処理の変更を示唆しています。
    • src/cmd/5g/gobj.c: オブジェクトファイル生成に関連するファイル。D_REGREG2zaddr関数で処理されるように追加されています。
    • 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がレジスタ使用状況の追跡に追加されています。
  3. リンカ (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_REGREG2zaddr関数で処理されるように追加されています。
    • src/cmd/5l/optab.c: 命令の最適化テーブル。新しい命令とそれに対応するオペランドタイプが追加されています。特に、AMULA命令がC_REGREG2タイプを使用するように修正されています。
    • src/cmd/5l/span.c: コード生成の最終段階で命令の配置やジャンプの解決を行うファイル。aclass関数でD_REGREG2C_REGREG2にマッピングされるように追加されています。また、buildop関数で新しい乗算命令のオペランド範囲が定義されています。
  4. ライブラリ (src/libmach) の変更:

    • src/libmach/5obj.c: Goのツールチェインが使用する低レベルの機械語操作ライブラリ。D_REGREG2addr関数で処理されるように追加されています。

これらの変更は、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_REGREG2reg, regとコメントされており、これらがレジスタペアを表現する際に使用されることが分かります。この新しいタイプは、特にMULAMULAWのような複数のレジスタをオペランドとして取る命令の処理をより明確にするために導入されたと考えられます。

src/cmd/5l/asm.c の変更

このファイルは、アセンブリ命令を実際の機械語(バイナリコード)に変換するロジックを含んでいます。 変更点としては、MULW{T,B}(ケース98)とMULAW{T,B}(ケース99)命令の機械語エンコーディングロジックが追加されています。これらの命令は、ソースレジスタ(p->from.reg)、デスティネーションレジスタ(p->to.reg)、および追加のレジスタ(p->regp->to.offset)を特定のビット位置に配置して機械語を生成します。 また、oprrr関数に、これらの新しい命令(AMULWT, AMULWB, AMULAWT, AMULAWB)に対応するARM命令のオペコードが定義されています。これらのオペコードは、ARM命令セットの特定のビットパターンに対応しており、命令の種類や動作を決定します。

これらの変更により、GoのARMツールチェインは、新しい乗算命令を正しくアセンブルし、実行可能なバイナリに含めることができるようになります。

関連リンク

参考にした情報源リンク