浮動小数点数のレジスタ間移動命令()
浮動小数点数のロード/ストア命令はメモリとレジスタ間のコピーですが、 浮動小数点数をレジスタとレジスタ間でコピーする命令としてムーブ命令があります。 整数レジスタ、浮動小数点レジスタ、ベクトルレジスタが格納する浮動小数点数をレジスタ - レジスタ間で自由自在にコピーできるようになります。
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 |
0000 | 2.000000 | 4.000000 | 8.000000 | 16.000000 | 0.1250000 | 0.250000 | 0.500000 | 1.000000 |
0001 | 2.125000 | 4.250000 | 8.500000 | 17.000000 | 0.1328125 | 0.265625 | 0.531250 | 1.062500 |
0010 | 2.250000 | 4.500000 | 9.000000 | 18.000000 | 0.1406250 | 0.281250 | 0.562500 | 1.125000 |
0011 | 2.375000 | 4.750000 | 9.500000 | 19.000000 | 0.1484375 | 0.296875 | 0.593750 | 1.187500 |
0100 | 2.500000 | 5.000000 | 10.000000 | 20.000000 | 0.1562500 | 0.312500 | 0.625000 | 1.250000 |
0101 | 2.625000 | 5.250000 | 10.500000 | 21.000000 | 0.1640625 | 0.328125 | 0.656250 | 1.312500 |
0110 | 2.750000 | 5.500000 | 11.000000 | 22.000000 | 0.1718750 | 0.343750 | 0.687500 | 1.375000 |
0111 | 2.875000 | 5.750000 | 11.500000 | 23.000000 | 0.1796875 | 0.359375 | 0.718750 | 1.437500 |
1000 | 3.000000 | 6.000000 | 12.000000 | 24.000000 | 0.1875000 | 0.375000 | 0.750000 | 1.500000 |
1001 | 3.125000 | 6.250000 | 12.500000 | 25.000000 | 0.1953125 | 0.390625 | 0.781250 | 1.562500 |
1010 | 3.250000 | 6.500000 | 13.000000 | 26.000000 | 0.2031250 | 0.406250 | 0.812500 | 1.625000 |
1011 | 3.375000 | 6.750000 | 13.500000 | 27.000000 | 0.2109375 | 0.421875 | 0.843750 | 1.687500 |
1100 | 3.500000 | 7.000000 | 14.000000 | 28.000000 | 0.2187500 | 0.437500 | 0.875000 | 1.750000 |
1101 | 3.625000 | 7.250000 | 14.500000 | 29.000000 | 0.2265625 | 0.453125 | 0.906250 | 1.812500 |
1110 | 3.750000 | 7.500000 | 15.000000 | 30.000000 | 0.2343750 | 0.468750 | 0.937500 | 1.875000 |
1111 | 3.875000 | 7.750000 | 15.500000 | 31.000000 | 0.2421875 | 0.484375 | 0.968750 | 1.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 | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
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 | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
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 | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
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 | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 09 | 08 | 07 | 06 | 05 | 04 | 03 | 02 | 01 | 00 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
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) の整数レジスタ、浮動小数点レジスタ、ベクトルレジスタを使って、浮動小数点数をメモリ - レジスタ間、レジスタ - レジスタ間で自由自在に移動できるようになりました。レジスタに値を設定できるようになると後は演算だけです。