浮動小数点数のレジスタ間移動命令()

浮動小数点数のロード/ストア命令はメモリとレジスタ間のコピーですが、 浮動小数点数をレジスタとレジスタ間でコピーする命令としてムーブ命令があります。 整数レジスタ、浮動小数点レジスタ、ベクトルレジスタが格納する浮動小数点数をレジスタ - レジスタ間で自由自在にコピーできるようになります。

FMOV

FMOV(レジスタ)

単精度浮動小数点レジスタ (Sn) から単精度浮動小数点レジスタ (Sd) へコピーを行います。 また、倍精度浮動小数点レジスタ(Dn) から倍精度浮動小数点レジスタ(Dd) へコピーを行います。数値の変換は行われません。

FMOV  Sd, Sn    // 単精度
FMOV  Dd, Dn    // 倍精度

FMOV(汎用)

整数型の汎用レジスタと浮動小数点レジスタ間のコピーを行います。数値の変換は行われません。

FMOV  Sd, Wn        // 32 ビットから単精度へ
FMOV  Wd, Sn        // 単精度から 32 ビットへ
FMOV  Dd, Xn        // 64 ビットから倍精度へ
FMOV  Vd.D[1], Xn   // 64 ビットから 128 ビットの上位半分
FMOV  Xd, Dn        // 倍精度から 64 ビットへ
FMOV  Xd, Vn.D[1]   // 128 ビットの上位半分から 64 ビット

FMOV(定数)

8 ビットの浮動小数点定数 (イミディエート) を浮動小数点レジスタに代入します。

FMOV  Sd, #imm8    // 単精度
FMOV  Dd, #imm8    // 倍精度

imm8 は 8 ビットの即値定数で、3ビットの指数部を持つ正規化された4ビット精度の符号付き浮動小数点定数です。符号1ビットに続いて符号部3ビット、仮数部4ビットで以下の表の値が可能です。

- 指数部3ビット
仮数部 000 001 010 011 100 101 110 111
00002.0000004.0000008.00000016.0000000.12500000.2500000.5000001.000000
00012.1250004.2500008.50000017.0000000.13281250.2656250.5312501.062500
00102.2500004.5000009.00000018.0000000.14062500.2812500.5625001.125000
00112.3750004.7500009.50000019.0000000.14843750.2968750.5937501.187500
01002.5000005.00000010.00000020.0000000.15625000.3125000.6250001.250000
01012.6250005.25000010.50000021.0000000.16406250.3281250.6562501.312500
01102.7500005.50000011.00000022.0000000.17187500.3437500.6875001.375000
01112.8750005.75000011.50000023.0000000.17968750.3593750.7187501.437500
10003.0000006.00000012.00000024.0000000.18750000.3750000.7500001.500000
10013.1250006.25000012.50000025.0000000.19531250.3906250.7812501.562500
10103.2500006.50000013.00000026.0000000.20312500.4062500.8125001.625000
10113.3750006.75000013.50000027.0000000.21093750.4218750.8437501.687500
11003.5000007.00000014.00000028.0000000.21875000.4375000.8750001.750000
11013.6250007.25000014.50000029.0000000.22656250.4531250.9062501.812500
11103.7500007.50000015.00000030.0000000.23437500.4687500.9375001.875000
11113.8750007.75000015.50000031.0000000.24218750.4843750.9687501.937500

この表の範囲の浮動小数点定数は即値として命令に埋め込むことができます。8ビットの値へはアセンブラが変換するため、ソースには浮動小数点数を使います。確認してみましょう。

.global _start
.text
_start:
        fmov    s0, 1.0          // 01110000
        bl      OutSingle
        fmov    d0, -1.0         // 11110000
        bl      OutDouble
        fmov    s0, -0.2421875   // 11001111
        bl      OutSingle
        fmov    d0, 0.2421875    // 01001111
        bl      OutDouble
        // fmov    s0, 0.810     //Error: invalid floating-point constant
        bl      Exit

OutDouble:
        stp     x0, x30, [sp, #-16]!
        bl      Double2String
        b       1f
OutSingle:
        stp     x0, x30, [sp, #-16]!
        bl      Single2String
    1:  bl      OutAsciiZ
        bl      NewLine
        ldp     x0, x30, [sp], #16
        ret
.include        "float2string.s"

上のソースをアセンブル、リンクして実行します。 fmov で指定する定数が上記の表に無いとアセンブラはエラーとなります。

$ as -o fmov.o fmov.s
$ ld -o fmov fmov.o
$ ./fmov
 1.0000000
-1.000000000000000
-2.4218750E-1
 2.421875000000000E-1

逆アセンブルして、命令のビットパターンを見てみます。8ビットの即値定数が 32 ビットの単精度浮動小数点数と 64 ビットの倍精度浮動小数点数としてレジスタに代入されています。

$ objdump -d fmov |head -n 15

fmov:     file format elf64-littleaarch64


Disassembly of section .text:

00000000004000b0 <_start>:
  4000b0:	1e2e1000 	fmov	s0, #1.000000000000000000e+00
  4000b4:	9400000b 	bl	4000e0 <OutSingle>
  4000b8:	1e7e1000 	fmov	d0, #-1.000000000000000000e+00
  4000bc:	94000006 	bl	4000d4 <OutDouble>
  4000c0:	1e39f000 	fmov	s0, #-2.421875000000000000e-01
  4000c4:	94000007 	bl	4000e0 <OutSingle>
  4000c8:	1e69f000 	fmov	d0, #2.421875000000000000e-01
  4000cc:	94000002 	bl	4000d4 <OutDouble>

FMOV(ベクトル)

8 ビットの浮動小数点定数 (イミディエート) をベクトルレジスタの全要素に代入します。

FMOV  Vd.2S, #imm8    // 単精度
FMOV  Vd.4S, #imm8    // 単精度
FMOV  Vd.2D, #imm8    // 倍精度

imm8 は 8 ビットの即値定数で、3ビットの指数部を持つ正規化された4ビット精度の符号付き浮動小数点定数です。符号1ビットに続いて符号部3ビット、仮数部4ビットで上記の表の値が可能です。 ベクトルレジスタへの定数の代入も試してみましょう。

.global _start
.text
_start:
        fmov    v1.2s, 1.0       // 01110000
        dup     s0, v1.s[0]
        bl      OutSingle
        fmov    v2.2d, -1.0      // 11110000
        dup     d0, v2.d[0]
        bl      OutDouble
        fmov    v3.4s, -0.2421875  // 11001111
        dup     s0, v3.s[3]
        bl      OutSingle
        fmov    v4.2d, 0.2421875   // 01001111
        dup     d0, v4.d[1]
        bl      OutDouble
        bl      Exit

OutDouble:
        stp     x0, x30, [sp, #-16]!
        bl      Double2String
        b       1f
OutSingle:
        stp     x0, x30, [sp, #-16]!
        bl      Single2String
    1:  bl      OutAsciiZ
        bl      NewLine
        ldp     x0, x30, [sp], #16
        ret
.include        "float2string.s"

上のソースをアセンブル、リンクして実行します。

$ as -o vfmov.o vfmov.s
$ ld -o vfmov vfmov.o
$ ./vfmov
1.0000000
-1.000000000000000
-2.4218750E-1
 2.421875000000000E-1

命令に含まれる8ビットの定数は次のように2つに分かれて埋め込まれます。

$ objdump -d vfmov |head -n 20
抜粋
  4000b0:	0f03f601 	fmov	v1.2s, #1.000000000000000000e+00
  4000bc:	6f07f602 	fmov	v2.2d, #-1.000000000000000000e+00
  4000c8:	4f06f5e3 	fmov	v3.4s, #-2.421875000000000000e-01
  4000d4:	6f02f5e4 	fmov	v4.2d, #2.421875000000000000e-01
命令のエンコード
FMOV 313029 282726 252423 222120 191817 161514 131211 100908 070605 040302 0100
FMOV (reg) 0 0 0 1 1 1 1 0 0 x 1 0 0 0 0 0 0 1 0 0 0 0 Rn Rd
FMOV (general) z 0 0 1 1 1 1 0 type 1 0 x 1 1 x 0 0 0 0 0 0 Rn Rd
FMOV (imm) 0 0 0 1 1 1 1 0 0 x 1 imm8 1 0 0 0 0 0 0 0 Rd
FMOV (vec) 0 Q op 0 1 1 1 1 0 0 0 0 0 a b c 1 1 1 1 0 1 d e f g h Rd

DUP

DUP(スカラ)

ベクタレジスタの要素の1つからスカラレジスタに内容をコピーします。8ビットから64ビットの要素のサイズに対応するレジスタに内容を複製(DUPlicate)します。

DUP  Bd, Vn.B [0..15]
DUP  Hd, Vn.H [0..7]
DUP  Sd, Vn.S [0..3]
DUP  Dd, Vn.D [0..1]

コピー先レジスタには 8 ビットから 64 ビットのスカラレジスタとして B、H、S、D を指定することができます。 d にはレジスタ番号を 0 ~ 31 の範囲で指定します。 コピー元はベクタレジスタの要素を配列の形式で指定します。n にはレジスタ番号を 0 ~ 31 の範囲で指定します。

DUP(ベクタ)

ベクタレジスタの1要素をベクタレジスタの 指定したすべての要素にコピー。 します。

DUP  Vd.8B,  Vn.B[0..15]
DUP  Vd.16B, Vn.B[0..15]
DUP  Vd.4H,  Vn.H[0..7]
DUP  Vd.8H,  Vn.H[0..7]
DUP  Vd.2S,  Vn.S[0..3]
DUP  Vd.4S,  Vn.S[0..3]
DUP  Vd.2D,  Vn.D[0..1]

コピー先レジスタにはベクタレジスタを 8 ビットから 64 ビットの複数要素を指定します。 d にはレジスタ番号を 0 ~ 31 の範囲で指定します。 コピー元はベクタレジスタの要素を配列の形式で指定します。n にはレジスタ番号を 0 ~ 31 の範囲で指定します。


DUP(汎用)

ベクタレジスタの要素に対応する汎用整数レジスタの下位ビットをベクタレジスタの 指定したすべての要素にコピー します。

DUP  Vd.8B,  Wn
DUP  Vd.16B, Wn
DUP	 Vd.4H,	 Wn
DUP	 Vd.8H,	 Wn
DUP	 Vd.2S,	 Wn
DUP	 Vd.4S,	 Wn
DUP	 Vd.2D,	 Xn

コピー先レジスタにはベクタレジスタを 8 ビットから 64 ビットの複数要素を指定します。 d にはレジスタ番号を 0 ~ 31 の範囲で指定します。 コピー元は汎用レジスタを指定します。n にはレジスタ番号を 0 ~ 31 の範囲で指定します。

命令のエンコード
DUP 313029 282726 252423 222120 191817 161514 131211 100908 070605 040302 0100
DUP (Scalar) 0 1 0 1 1 1 1 0 0 0 0 imm5 0 0 0 0 0 1 Rn Rd
DUP (Vector) 0 Q 0 0 1 1 1 0 0 0 0 imm5 0 0 0 0 0 1 Rn Rd
DUP (general) 0 Q 0 0 1 1 1 0 0 0 0 imm5 0 0 0 0 1 1 Rn Rd

INS

INS(ベクタ要素)

ベクタレジスタの指定した要素から別のベクタレジスタの指定した要素に内容をコピー(挿入) します。 コピー先のベクタレジスタの指定した要素以外は変化しません。 別名として MOV も使われます。

INS  Vd.B[0..15], Vn.B[0..15]
INS	 Vd.H[0..7],  Vn.H[0..7]
INS	 Vd.S[0..3],  Vn.S[0..3]
INS	 Vd.D[0..1],  Vn.D[0..1]

INS(汎用)

汎用整数レジスタ (の下位ビット) をベクタレジスタの要素にコピーします。

INS  Vd.B[0..15], Wn
INS	 Vd.H[0..7],  Wn
INS	 Vd.S[0..3],  Wn
INS	 Vd.D[0..1],  Xn

n にはコピー元の汎用レジスタの番号を 0 ~ 30 の範囲で指定するか、ゼロレジスタ ZR (31) を指定します。

命令のエンコード
INS 313029 282726 252423 222120 191817 161514 131211 100908 070605 040302 0100
INS (element) 0 1 1 0 1 1 1 0 0 0 0 imm5 0 imm4 1 Rn Rd
INS (general) 0 1 0 0 1 1 1 0 0 0 0 imm5 0 0 0 1 1 1 Rn Rd

UMOV/SMOV

UMOV

ベクタレジスタの指定した要素を汎用整数レジスタへゼロ拡張してコピーします。

UMOV Wd, Vn.B[0..15]    // MOV Wd, Vn.B[0..15]
UMOV Wd, Vn.H[0..7]     // MOV Wd, Vn.H[0..7]
UMOV Wd, Vn.S[0..3]     // MOV Wd, Vn.S[0..3]
UMOV Xd, Vn.D[0..1]     // MOV Xd, Vn.D[0..1]

SMOV

ベクタレジスタの指定した要素を汎用整数レジスタへ符号拡張してコピーします。 符号拡張してコピーするため、コピー元よりコピー先のサイズが大きい必要があります。

SMOV Wd, Vn.B[0..15]
SMOV Wd, Vn.H[0..7] 
SMOV Xd, Vn.B[0..15]
SMOV Xd, Vn.H[0..7] 
SMOV Xd, Vn.S[0..3] 
命令のエンコード
SMOV 313029 282726 252423 222120 191817 161514 131211 100908 070605 040302 0100
UMOV 0 Q 0 0 1 1 1 0 0 0 0 imm5 0 0 1 1 1 1 Rn Rd
SMOV 0 Q 0 0 1 1 1 0 0 0 0 imm5 0 0 1 0 1 1 Rn Rd

前々回の11. 浮動小数点数のロード/ストア命令 と前回の12. ベクトルのロード/ストア命令と合わせて、Arm64(AArch64) の整数レジスタ、浮動小数点レジスタ、ベクトルレジスタを使って、浮動小数点数をメモリ - レジスタ間、レジスタ - レジスタ間で自由自在に移動できるようになりました。レジスタに値を設定できるようになると後は演算だけです。


続く...



このページの目次