Zfinx 対応 cross gcc¶
6th AI Edge Contest の課題で用いた RISC-V CPU には fpu を搭載したが、ハードウェア規模を抑えるために fp レジスタを設けず、整数レジスタを用いる Zfinx 仕様準拠とした。
ただし、fmadd/fmsub 命令は実装しなかった。fma 命令は 3オペランドであり、改修規模が大きくなるためである。
'Zfinx' に対応した cross-gcc は以下の場所で公開されているが、fma 命令の発生を抑止する -mno_fmul_add
のようなコンパイルオプションは risc-v port には無いようなので、fma 命令を発生しないようにする patch を作って対応することにした。
cross-gcc Zfinx build 手順¶
-
source tree のセットアップ
$ cd {path-to}/riscv-zfinx $ git clone https://github.com/riscv/riscv-gnu-toolchain $ cd riscv-gnu-toolchain $ git submodule update --init --recursive $ cd .. $ cp riscv-gnu-toolchain zfinx -r $ sh setup-zfinx.sh $ cd zfinx
setup-zfinx.sh
#!/bin/sh cd zfinx cd riscv-gcc git remote add zfinx https://github.com/pz9115/riscv-gcc.git git fetch zfinx git checkout zfinx/riscv-gcc-10.2.0-zfinx cd ../riscv-binutils git remote add zfinx https://github.com/pz9115/riscv-binutils-gdb.git git fetch zfinx git checkout zfinx/riscv-binutils-2.35-zfinx #cd ../qemu #git remote add plct-qemu https://github.com/isrc-cas/plct-qemu.git #git fetch plct-qemu #git checkout plct-qemu/plct-zfinx-dev #git reset --hard d73c46e4a84e47ffc61b8bf7c378b1383e7316b5 cd ..
-
build install (multi lib)
/opt/rv32e/ にインストールされる。$ ./configure --prefix=/opt/rv32e/ --disable-linux --with-arch=rv32emczfinx --with-abi=ilp32e \ --with-multilib-generator="rv32emczfinx-ilp32e--;rv32emzfinx-ilp32e--;rv32emc-ilp32e--;rv32em-ilp32e--" $ make -j8 newlib
multilib 指定により、rv32emczfinx, rv32emzfinx, rv32emc, rv32em の各設定に対応した library がインストールされる。
fma 命令を発生させない patch¶
gcc の各種マシンへの移植コードは、ソースツリー zfinx/riscv-gcc/gcc/config/ にまとまっている。risc-v は zfinx/riscv-gcc/gcc/config/riscv/ である。
移植コードの中で、特に最終的なアセンプラ命令の生成条件が記述されているのは、zfinx/riscv-gcc/gcc/config/riscv/riscv.md (Machine description) ファイルであり、この中に記述されている fmadd/fmsub 命令の生成条件を disable することで、fmadd/fmsub を発生しないコンパイラにすることができる。
以下、今回の修正箇所である。アセンブラ命令 'fmadd' などを生成する条件が記述されており、disable したい命令の生成条件式に "&& 0" を加えたのみである。
fma 命令 disable patch
diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 99cd6c64397..4db2e18346c 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -817,7 +817,7 @@
(define_insn "sqrt<mode>2"
[(set (match_operand:ANYF 0 "register_operand" "=f")
(sqrt:ANYF (match_operand:ANYF 1 "register_operand" " f")))]
- "(TARGET_HARD_FLOAT || TARGET_ZFINX || TARGET_ZDINX) && TARGET_FDIV"
+ "(TARGET_HARD_FLOAT || TARGET_ZFINX || TARGET_ZDINX) && TARGET_FDIV && 0"
{
return "fsqrt.<fmt>\t%0,%1";
}
@@ -832,7 +832,7 @@
(fma:ANYF (match_operand:ANYF 1 "register_operand" " f")
(match_operand:ANYF 2 "register_operand" " f")
(match_operand:ANYF 3 "register_operand" " f")))]
- "TARGET_HARD_FLOAT || TARGET_ZFINX || TARGET_ZDINX"
+ "(TARGET_HARD_FLOAT || TARGET_ZFINX || TARGET_ZDINX) && 0"
"fmadd.<fmt>\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
(set_attr "mode" "<UNITMODE>")])
@@ -843,7 +843,7 @@
(fma:ANYF (match_operand:ANYF 1 "register_operand" " f")
(match_operand:ANYF 2 "register_operand" " f")
(neg:ANYF (match_operand:ANYF 3 "register_operand" " f"))))]
- "TARGET_HARD_FLOAT || TARGET_ZFINX || TARGET_ZDINX"
+ "(TARGET_HARD_FLOAT || TARGET_ZFINX || TARGET_ZDINX) && 0"
"fmsub.<fmt>\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
(set_attr "mode" "<UNITMODE>")])
@@ -855,7 +855,7 @@
(neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
(match_operand:ANYF 2 "register_operand" " f")
(neg:ANYF (match_operand:ANYF 3 "register_operand" " f"))))]
- "TARGET_HARD_FLOAT || TARGET_ZFINX || TARGET_ZDINX"
+ "(TARGET_HARD_FLOAT || TARGET_ZFINX || TARGET_ZDINX) && 0"
"fnmadd.<fmt>\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
(set_attr "mode" "<UNITMODE>")])
@@ -867,7 +867,7 @@
(neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
(match_operand:ANYF 2 "register_operand" " f")
(match_operand:ANYF 3 "register_operand" " f")))]
- "TARGET_HARD_FLOAT || TARGET_ZFINX || TARGET_ZDINX"
+ "(TARGET_HARD_FLOAT || TARGET_ZFINX || TARGET_ZDINX) && 0"
"fnmsub.<fmt>\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
(set_attr "mode" "<UNITMODE>")])
@@ -880,7 +880,7 @@
(neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
(match_operand:ANYF 2 "register_operand" " f")
(neg:ANYF (match_operand:ANYF 3 "register_operand" " f")))))]
- "(TARGET_HARD_FLOAT || TARGET_ZFINX || TARGET_ZDINX) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
+ "(TARGET_HARD_FLOAT || TARGET_ZFINX || TARGET_ZDINX) && !HONOR_SIGNED_ZEROS (<MODE>mode) && 0"
"fmadd.<fmt>\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
(set_attr "mode" "<UNITMODE>")])
@@ -893,7 +893,7 @@
(neg:ANYF (match_operand:ANYF 1 "register_operand" " f"))
(match_operand:ANYF 2 "register_operand" " f")
(match_operand:ANYF 3 "register_operand" " f"))))]
- "(TARGET_HARD_FLOAT || TARGET_ZFINX || TARGET_ZDINX) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
+ "(TARGET_HARD_FLOAT || TARGET_ZFINX || TARGET_ZDINX) && !HONOR_SIGNED_ZEROS (<MODE>mode) && 0"
"fmsub.<fmt>\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
(set_attr "mode" "<UNITMODE>")])
@@ -906,7 +906,7 @@
(match_operand:ANYF 1 "register_operand" " f")
(match_operand:ANYF 2 "register_operand" " f")
(match_operand:ANYF 3 "register_operand" " f"))))]
- "(TARGET_HARD_FLOAT || TARGET_ZFINX || TARGET_ZDINX) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
+ "(TARGET_HARD_FLOAT || TARGET_ZFINX || TARGET_ZDINX) && !HONOR_SIGNED_ZEROS (<MODE>mode) && 0"
"fnmadd.<fmt>\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
(set_attr "mode" "<UNITMODE>")])
@@ -919,7 +919,7 @@
(match_operand:ANYF 1 "register_operand" " f")
(match_operand:ANYF 2 "register_operand" " f")
(neg:ANYF (match_operand:ANYF 3 "register_operand" " f")))))]
- "(TARGET_HARD_FLOAT || TARGET_ZFINX || TARGET_ZDINX) && !HONOR_SIGNED_ZEROS (<MODE>mode)"
+ "(TARGET_HARD_FLOAT || TARGET_ZFINX || TARGET_ZDINX) && !HONOR_SIGNED_ZEROS (<MODE>mode) && 0"
"fnmsub.<fmt>\t%0,%1,%2,%3"
[(set_attr "type" "fmadd")
(set_attr "mode" "<UNITMODE>")])