浮動小数点数の比較を行うRISC-Vコードを出力
RV32Fの比較命令
浮動小数点数を比較した上での分岐処理は、浮動小数点数の比較命令(FEQ.S FLT.S FLE.S)と整数の分岐命令(BEQ BNE)を組み合わせて行う。
こんな感じ
code:diff
| Tail, IfFEq(x, y, e1, e2) ->
- Printf.fprintf oc "\tfcmpu\tcr7@, %s, %s\n" (reg x) (reg y);
- g'_tail_if oc e1 e2 "beq" "bne"
+ (* 新しい if 実装済み(浮動小数点数対応) *)
+ Printf.fprintf oc "\tfeq.s %s, %s, %s\n" (reg reg_tmp) (reg x) (reg y);
+ Printf.fprintf oc "\taddi %s, zero, 1\n" (reg reg_tmp2);
+ g'_tail_if_new oc (reg reg_tmp) (reg reg_tmp2) e1 e2 "beq" "bne"
reg_tmp2 を追加
浮動小数点数の比較の際に必要になったので reg_tmp2 を追加した
全体の diff
code:diff
diff --git a/RV32/asm.ml b/RV32/asm.ml
index e085eaf..0389933 100644
--- a/RV32/asm.ml
+++ b/RV32/asm.ml
@@ -83,7 +83,7 @@ let regs = (* Array.init 27 (fun i -> Printf.sprintf "_R_%d" i) *)
[|
"%a0"; "%a1"; "%a2"; "%a3"; "%a4"; "%a5"; "%a6"; "%a7";
"%s1"; "%s2"; "%s3"; "%s4"; "%s5"; "%s6"; "%s7"; "%s8"; "%s9";
- "%t1"; "%t2"; "%t3"; "%t4"; "%t5"; "%t6"
+ "%t2"; "%t3"; "%t4"; "%t5"; "%t6"
|]
let fregs =
[|
@@ -101,6 +101,7 @@ let reg_fsw = fregs.(Array.length fregs - 1) (* temporary for swap *)
let reg_sp = "%s10" (* stack pointer *)
let reg_hp = "%s11" (* heap pointer (caml2html: sparcasm_reghp) *)
let reg_tmp = "%t0" (* t0 を tmp として使ってみる *)
+let reg_tmp2 = "%t1" (* t1 を tmp2 として使ってみる *)
let is_reg x = (x.0 = '%') (* super-tenuki *)
diff --git a/RV32/asm.mli b/RV32/asm.mli
index 5e62d4c..7333694 100644
--- a/RV32/asm.mli
+++ b/RV32/asm.mli
@@ -14,7 +14,7 @@ and exp =
| Slw of Id.t * id_or_imm
| Lwz of Id.t * id_or_imm
| Stw of Id.t * Id.t * id_or_imm
- | FMr of Id.t
+ | FMr of Id.t
| FNeg of Id.t
| FAdd of Id.t * Id.t
| FSub of Id.t * Id.t
@@ -50,6 +50,7 @@ val reg_fsw : Id.t
val reg_hp : Id.t
val reg_sp : Id.t
val reg_tmp : Id.t
+val reg_tmp2 : Id.t
val is_reg : Id.t -> bool
val fv : t -> Id.t list
diff --git a/RV32/emit.ml b/RV32/emit.ml
index a72fa35..590bcb3 100644
--- a/RV32/emit.ml
+++ b/RV32/emit.ml
@@ -104,14 +104,14 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
Printf.fprintf oc "\tsw %s, %d(%s)\n" (reg x) (offset y) (reg reg_sp)
| NonTail(_), Save(x, y) when List.mem x allfregs && not (S.mem y !stackset) ->
savef y;
- Printf.fprintf oc "\tstfd\t%s, %d(%s)\n" (reg x) (offset y) (reg reg_sp)
+ Printf.fprintf oc "\tfsw %s, %d(%s)\n" (reg x) (offset y) (reg reg_sp)
| NonTail(_), Save(x, y) -> assert (S.mem y !stackset); ()
(* 復帰の仮想命令の実装 (caml2html: emit_restore) *)
| NonTail(x), Restore(y) when List.mem x allregs ->
Printf.fprintf oc "\tlw %s, %d(%s)\n" (reg x) (offset y) (reg reg_sp)
| NonTail(x), Restore(y) ->
assert (List.mem x allfregs);
- Printf.fprintf oc "\tlfd\t%s, %d(%s)\n" (reg x) (offset y) (reg reg_sp)
+ Printf.fprintf oc "\tflw %s, %d(%s)\n" (reg x) (offset y) (reg reg_sp)
(* 末尾だったら計算結果を第一レジスタにセットしてリターン (caml2html: emit_tailret) *)
| Tail, (Nop | Stw _ | Stfd _ | Comment _ | Save _ as exp) ->
g' oc (NonTail(Id.gentmp Type.Unit), exp);
@@ -146,19 +146,23 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
Printf.fprintf oc "\tcmpw\tcr7@, %s, %s\n" (reg x) (reg y);
g'_tail_if oc e1 e2 "bge" "blt"
| Tail, IfGE(x, C(y), e1, e2) ->
- Printf.fprintf oc "\tcmpwi\tcr7@, %s, %d\n" (reg x) y;
+ Printf.fprintf oc "\tcmpwi\tcr7@@@@, %s, %d\n" (reg x) y;
g'_tail_if oc e1 e2 "bge" "blt"
| Tail, IfFEq(x, y, e1, e2) ->
- Printf.fprintf oc "\tfcmpu\tcr7@, %s, %s\n" (reg x) (reg y);
- g'_tail_if oc e1 e2 "beq" "bne"
+ (* 新しい if 実装済み(浮動小数点数対応) *)
+ Printf.fprintf oc "\tfeq.s %s, %s, %s\n" (reg reg_tmp) (reg x) (reg y);
+ Printf.fprintf oc "\taddi %s, zero, 1\n" (reg reg_tmp2);
+ g'_tail_if_new oc (reg reg_tmp) (reg reg_tmp2) e1 e2 "beq" "bne"
| Tail, IfFLE(x, y, e1, e2) ->
- Printf.fprintf oc "\tfcmpu\tcr7@, %s, %s\n" (reg x) (reg y);
- g'_tail_if oc e1 e2 "ble" "bgt"
+ (* 新しい if 実装済み(浮動小数点数対応) *)
+ Printf.fprintf oc "\tfle.s %s, %s, %s\n" (reg reg_tmp) (reg x) (reg y);
+ Printf.fprintf oc "\taddi %s, zero, 1\n" (reg reg_tmp2);
+ g'_tail_if_new oc (reg reg_tmp) (reg reg_tmp2) e1 e2 "beq" "bne"
| NonTail(z), IfEq(x, V(y), e1, e2) ->
- Printf.fprintf oc "\tcmpw\tcr7@@, %s, %s\n" (reg x) (reg y);
+ Printf.fprintf oc "\tcmpw\tcr7@@IfEq, %s, %s\n" (reg x) (reg y);
g'_non_tail_if oc (NonTail(z)) e1 e2 "beq" "bne"
| NonTail(z), IfEq(x, C(y), e1, e2) ->
- Printf.fprintf oc "\tcmpwi\tcr7@@, %s, %d\n" (reg x) y;
+ Printf.fprintf oc "\tcmpwi\tcr7@@IfEq, %s, %d\n" (reg x) y;
g'_non_tail_if oc (NonTail(z)) e1 e2 "beq" "bne"
| NonTail(z), IfLE(x, V(y), e1, e2) ->
(* 新しい if 実装済み *)
@@ -173,8 +177,10 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
Printf.fprintf oc "\tcmpwi\tcr7@@, %s, %d\n" (reg x) y;
g'_non_tail_if oc (NonTail(z)) e1 e2 "bge" "blt"
| NonTail(z), IfFEq(x, y, e1, e2) ->
- Printf.fprintf oc "\tfcmpu\tcr7@@, %s, %s\n" (reg x) (reg y);
- g'_non_tail_if oc (NonTail(z)) e1 e2 "beq" "bne"
+ (* 新しい if 実装済み(浮動小数点数対応) *)
+ Printf.fprintf oc "\tfeq.s %s, %s, %s\n" (reg reg_tmp) (reg x) (reg y);
+ Printf.fprintf oc "\taddi %s, zero, 1\n" (reg reg_tmp2);
+ g'_non_tail_if_new oc (reg reg_tmp) (reg reg_tmp2) (NonTail(z)) e1 e2 "beq" "bne"
| NonTail(z), IfFLE(x, y, e1, e2) ->
Printf.fprintf oc "\tfcmpu\tcr7@@, %s, %s\n" (reg x) (reg y);
g'_non_tail_if oc (NonTail(z)) e1 e2 "ble" "bgt"
@@ -248,7 +254,7 @@ and g'_non_tail_if_new oc x y dest e1 e2 b bn =
let stackset_back = !stackset in
g oc (dest, e1);
let stackset1 = !stackset in
- Printf.fprintf oc "\tb\t%s\n" b_cont;
+ Printf.fprintf oc "\tj %s\n" b_cont;
Printf.fprintf oc "%s:\n" b_else;
stackset := stackset_back;
g oc (dest, e2);
@@ -284,7 +290,7 @@ and g'_args oc x_reg_cl ys zs =
(0, [])
zs in
List.iter
- (fun (z, fr) -> Printf.fprintf oc "\tfmr\t%s, %s\n" (reg fr) (reg z))
+ (fun (z, fr) -> Printf.fprintf oc "\tfmv.s %s, %s\n" (reg fr) (reg z))
(shuffle reg_fsw zfrs)
let h oc { name = Id.L(x); args = _; fargs = _; body = e; ret = _ } =
diff --git a/main.ml b/main.ml
index 09d0960..20ae647 100644
--- a/main.ml
+++ b/main.ml
@@ -1,4 +1,5 @@
-let limit = ref 1000
+let limit = ref 0
+(* let limit = ref 1000 *)
let rec iter n e = (* 最適化処理をくりかえす (caml2html: main_iter) *)
Format.eprintf "iteration %d@." n;
diff --git a/test/float_if.ml b/test/float_if.ml
new file mode 100644
index 0000000..7a38b67
--- /dev/null
+++ b/test/float_if.ml
@@ -0,0 +1,36 @@
+let a = 1.23 in
+let b = 2.45 in
+let rec test1 x y =
+ (* IfFEq で真の場合 *)
+ if x = y then
+ print_int 1
+ else
+ print_int 0 in
+let rec test2 x y =
+ (* IfFEq で偽の場合 *)
+ if x = y then
+ print_int 0
+ else
+ print_int 1 in
+let rec test3 x y =
+ (* IfFLE で真の場合 *)
+ if x <= y then
+ print_int 1
+ else
+ print_int 0 in
+let rec test4 x y =
+ (* IfFLE で偽の場合 *)
+ if x <= y then
+ print_int 0
+ else
+ print_int 1 in
+let rec test5 x y =
+ if x = y then 1 else 0
+in
+
+test1 a a;
+test2 a b;
+test3 a b;
+test4 b a;
+print_int (test5 a a);
+print_newline ()