浮動小数点数の比較を行うRP2350コードを出力
from Raspberry Pi Pico2でCPU実験のレイトレを動かしたい
以下の、浮動小数点数の比較を実装した。
code:sample/float_if.ml
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;
print_newline ();
test2 a b;
print_newline ();
(* QEMUのバグ(?)回避のためのコード *)
if a < b then print_int 1 else print_int 0;
print_newline ();
test3 a b;
print_newline ();
test4 b a;
print_newline ();
print_int (test5 a a);
print_newline ()
以下実装。
code:diff
diff --git a/Makefile b/Makefile
index 727e705..3ad2bdb 100644
--- a/Makefile
+++ b/Makefile
@@ -82,6 +82,8 @@ sample/%.res: sample/%.elf
-m 16M \
-nographic \
-monitor none \
+ -d in_asm \
+ -D logfile.txt \
-kernel $<
.PRECIOUS: test/%.s test/% test/%.res test/%.ans test/%.cmp
diff --git a/RP2350/emit.ml b/RP2350/emit.ml
index 58e9f8f..6ff2c67 100644
--- a/RP2350/emit.ml
+++ b/RP2350/emit.ml
@@ -99,14 +99,14 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
Printf.fprintf oc "\tstr %s, %s, %d\n" (reg x) (reg reg_sp) (offset y)
| 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 "\tvstr %s, %s, %d\n" (reg x) (reg reg_sp) (offset y)
| NonTail(_), Save(x, y) -> assert (S.mem y !stackset); ()
(* 復帰の仮想命令の実装 (caml2html: emit_restore) *)
| NonTail(x), Restore(y) when List.mem x allregs ->
Printf.fprintf oc "\tldr %s, %s, %d\n" (reg x) (reg reg_sp) (offset y)
| 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 "\tvldr %s, %s, %d\n" (reg x) (reg reg_sp) (offset y)
(* 末尾だったら計算結果を第一レジスタにセットしてリターン (caml2html: emit_tailret) *)
| Tail, (Nop | Stw _ | Stfd _ | Comment _ | Save _ as exp) ->
g' oc (NonTail(Id.gentmp Type.Unit), exp);
@@ -142,10 +142,12 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
Printf.fprintf oc "\tcmp %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);
+ Printf.fprintf oc "\tvcmp.f32 %s, %s\n" (reg x) (reg y);
+ Printf.fprintf oc "\tvmrs APSR_nzcv, FPSCR\n";
g'_tail_if oc e1 e2 "beq" "bne"
| Tail, IfFLE(x, y, e1, e2) ->
- Printf.fprintf oc "\tfcmpu\tcr7, %s, %s\n" (reg x) (reg y);
+ Printf.fprintf oc "\tvcmp.f32 %s, %s\n" (reg x) (reg y);
+ Printf.fprintf oc "\tvmrs APSR_nzcv, FPSCR\n";
g'_tail_if oc e1 e2 "ble" "bgt"
| NonTail(z), IfEq(x, V(y), e1, e2) ->
Printf.fprintf oc "\tcmpw\tcr7, %s, %s\n" (reg x) (reg y);
@@ -246,7 +248,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 "\tvmov %s, %s\n" (reg fr) (reg z))
(shuffle reg_fsw zfrs)
let h oc { name = Id.L(x); args = _; fargs = _; body = e; ret = _ } =
@@ -269,7 +271,7 @@ let f oc (Prog(data, fundefs, e)) =
Printf.fprintf oc "\t.syntax unified\n";
Printf.fprintf oc "\t.thumb\n";
Printf.fprintf oc "\t.fpu fpv5-sp-d16\n";
- Printf.fprintf oc "\t.align 2\n";
+ Printf.fprintf oc "\t.align 1\n";
Printf.fprintf oc "\t.globl min_caml_start\n";
List.iter (fun fundef -> h oc fundef) fundefs;
Printf.fprintf oc "min_caml_start: # main entry point\n";
diff --git a/sample/float_if.ml b/sample/float_if.ml
new file mode 100644
index 0000000..0bda31b
--- /dev/null
+++ b/sample/float_if.ml
@@ -0,0 +1,45 @@
+ 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;
+print_newline ();
+test2 a b;
+print_newline ();
+
+(* QEMUのバグ(?)回避のためのコード *)
+if a < b then print_int 1 else print_int 0;
+print_newline ();
+
+test3 a b;
+print_newline ();
+test4 b a;
+print_newline ();
+print_int (test5 a a);
+print_newline ()
QEMUのバグなのか、以下のコードを消すとQEMUがバグって終了してしまう。実機では動いているので、当面は様子見。
code:ml
(* QEMUのバグ(?)回避のためのコード *)
if a < b then print_int 1 else print_int 0;
print_newline ();