test/* をRP2350で動かす
from Raspberry Pi Pico2でCPU実験のレイトレを動かしたい
test 以下のプログラムをひと通り動かした。
動いた
test/ack.ml
test/adder.ml
test/adder2.ml
test/cls-bug.ml
test/cls-rec.ml
test/even-odd.ml
test/fib.ml
test/float.ml(結果が微妙に違うけど、単精度と倍精度の違いかな?まあ良しとする)
test/gcd.ml
test/print.ml
test/shuffle.ml
test/spill.ml
test/spill3.ml
test/sum-tail.ml
test/sum.ml
test/cls-bug2.ml
test/cls-reg-bug.ml
test/funcomp.ml
test/inprod-loop.ml
test/inprod-rec.ml
test/inprod.ml
test/join-reg.ml
test/join-reg2.ml
test/join-stack.ml
test/join-stack2.ml
test/join-stack3.ml
test/matmul-flat.ml
test/matmul.ml
test/non-tail-if.ml
test/non-tail-if2.ml
test/spill2.ml
test/ack.ml
code:diff
diff --git a/RP2350/emit.ml b/RP2350/emit.ml
index 57bad2c..b397ccb 100644
--- a/RP2350/emit.ml
+++ b/RP2350/emit.ml
@@ -72,7 +72,7 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
| NonTail(x), Mr(y) -> Printf.fprintf oc "\tmov %s, %s\n" (reg x) (reg y)
| NonTail(x), Neg(y) -> Printf.fprintf oc "\tneg\t%s, %s\n" (reg x) (reg y)
| NonTail(x), Add(y, V(z)) -> Printf.fprintf oc "\tadd\t%s, %s, %s\n" (reg x) (reg y) (reg z)
- | NonTail(x), Add(y, C(z)) -> Printf.fprintf oc "\taddi\t%s, %s, %d\n" (reg x) (reg y) z
+ | NonTail(x), Add(y, C(z)) -> Printf.fprintf oc "\tadd %s, %s, #%d\n" (reg x) (reg y) z
| NonTail(x), Sub(y, V(z)) -> Printf.fprintf oc "\tsub %s, %s, %s\n" (reg x) (reg y) (reg z)
| NonTail(x), Sub(y, C(z)) -> Printf.fprintf oc "\tsub %s, %s, %d\n" (reg x) (reg y) z
| NonTail(x), Slw(y, V(z)) -> Printf.fprintf oc "\tslw\t%s, %s, %s\n" (reg x) (reg y) (reg z)
@@ -186,14 +186,14 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
g'_args oc (x, reg_cl) ys zs;
let ss = stacksize () in
Printf.fprintf oc "\tstw\t%s, %d(%s)\n" (reg reg_tmp) (ss - 4) (reg reg_sp);
- Printf.fprintf oc "\taddi\t%s, %s, %d\n" (reg reg_sp) (reg reg_sp) ss;
+ Printf.fprintf oc "\tadd %s, %s, #%d\n" (reg reg_sp) (reg reg_sp) ss;
Printf.fprintf oc "\tlwz\t%s, 0(%s)\n" (reg reg_tmp) (reg reg_cl);
Printf.fprintf oc "\tmtctr\t%s\n" (reg reg_tmp);
Printf.fprintf oc "\tbctrl\n";
Printf.fprintf oc "\tsubi\t%s, %s, %d\n" (reg reg_sp) (reg reg_sp) ss;
Printf.fprintf oc "\tlwz\t%s, %d(%s)\n" (reg reg_tmp) (ss - 4) (reg reg_sp);
if List.mem a allregs && a <> regs.(0) then
- Printf.fprintf oc "\tmr\t%s, %s\n" (reg a) (reg regs.(0))
+ Printf.fprintf oc "\tmov %s, %s\n" (reg a) (reg regs.(0))
else if List.mem a allfregs && a <> fregs.(0) then
Printf.fprintf oc "\tfmr\t%s, %s\n" (reg a) (reg fregs.(0));
Printf.fprintf oc "\tmtlr\t%s\n" (reg reg_tmp)
@@ -207,7 +207,7 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
Printf.fprintf oc "\tsub %s, %s, #%d\n" (reg reg_sp) (reg reg_sp) ss;
Printf.fprintf oc "\tldr %s, %s, #%d\n" (reg reg_tmp) (reg reg_sp) (ss - 4);
if List.mem a allregs && a <> regs.(0) then
- Printf.fprintf oc "\tmr\t%s, %s\n" (reg a) (reg regs.(0))
+ Printf.fprintf oc "\tmov %s, %s\n" (reg a) (reg regs.(0))
else if List.mem a allfregs && a <> fregs.(0) then
Printf.fprintf oc "\tfmr\t%s, %s\n" (reg a) (reg fregs.(0));
Printf.fprintf oc "\tmov lr, %s\n" (reg reg_tmp)
test/float.ml
ライブラリ関数をいくつか追加。
code:diff
diff --git a/stub.c b/stub.c
index b8287b3..860596a 100644
--- a/stub.c
+++ b/stub.c
@@ -89,6 +89,43 @@ void min_caml_print_newline(void) {
uart_putc('\n');
}
+float min_caml_abs_float(float x) {
+ return (x < 0.0f) ? -x : x;
+}
+
+float min_caml_sqrt(float x) {
+ if (x < 0.0f) {
+ return 0.0f; // or handle error as needed
+ }
+ float guess = x / 2.0f;
+ for (int i = 0; i < 10; i++) { // simple Newton's method
+ guess = (guess + x / guess) / 2.0f;
+ }
+ return guess;
+}
+
+float min_caml_cos(float x) {
+ // Simple Taylor series approximation for cos(x)
+ float term = 1.0f;
+ float sum = term;
+ for (int n = 1; n < 10; n++) {
+ term *= -x * x / (2 * n * (2 * n - 1));
+ sum += term;
+ }
+ return sum;
+}
+
+float min_caml_sin(float x) {
+ // Simple Taylor series approximation for sin(x)
+ float term = x;
+ float sum = term;
+ for (int n = 1; n < 10; n++) {
+ term *= -x * x / (2 * n * (2 * n + 1));
+ sum += term;
+ }
+ return sum;
+}
+
int main(void) {
uart_init();
test/adder.ml
クロージャを扱うテストプログラム。
code:test/adder.ml
let rec make_adder x =
let rec adder y = x + y in
adder in
print_int ((make_adder 3) 7)
クロージャまわりの修正が必要そう
参考
test/adder.ml をRISC-Vで動かす
クロージャを使ったプログラムのAArch64コードを出力
クロージャが動いた
https://x.com/htkymtks/status/1634931260182392832
adder.11 のアドレスが取得できれば優勝できそう。どう書けばいいんだ?
https://x.com/htkymtks/status/1624323322220781568?s=20
adr x2, adder.11 で adder.11 のアドレスが取れたよー!!
https://x.com/htkymtks/status/1624338756252893185?s=20
中間コードを確認。
code:sh
$ rlwrap ./min-caml.top
# let src = "let rec make_adder x = let rec adder y = x + y in adder in print_int ((make_adder 3) 7)" in Virtual.f (Closure.f (Alpha.f (KNormal.f (Typing.f (MyParser.exp MyLexer.token (Lexing.from_string src))))));;
free variable print_int assumed as external
free variable(s) x.6 found in function adder.11
function adder.11 cannot be directly applied in fact
directly applying make_adder.5
eliminating closure(s) make_adder.5
- : Asm.prog =
Asm.Prog ([],
[{Asm.name = Id.L "adder.11"; args = "y.12"; fargs = [];
body =
Asm.Let (("x.6", Type.Int), Asm.Lwz ("adder.11", Asm.C 4),
Asm.Ans (Asm.Add ("x.6", Asm.V "y.12")));
ret = Type.Int};
{Asm.name = Id.L "make_adder.5"; args = "x.6"; fargs = [];
body =
Asm.Let (("adder.11", Type.Fun (Type.Int, Type.Int)), Asm.Mr "%r11",
Asm.Let (("%r11", Type.Int), Asm.Add ("%r11", Asm.C 8),
Asm.Let (("l.14", Type.Int), Asm.SetL (Id.L "adder.11"),
Asm.Let (("Tu15", Type.Unit), Asm.Stw ("l.14", "adder.11", Asm.C 0),
Asm.Let (("Tu13", Type.Unit), Asm.Stw ("x.6", "adder.11", Asm.C 4),
Asm.Ans (Asm.Mr "adder.11"))))));
ret = Type.Fun (Type.Int, Type.Int)}],
Asm.Let (("Ti1.10", Type.Int), Asm.Li 3,
Asm.Let (("Tf2.8", Type.Fun (Type.Int, Type.Int)),
Asm.CallDir (Id.L "make_adder.5", "Ti1.10", []),
Asm.Let (("Ti3.9", Type.Int), Asm.Li 7,
Asm.Let (("Ti4.7", Type.Int), Asm.CallCls ("Tf2.8", "Ti3.9", []),
Asm.Ans (Asm.CallDir (Id.L "min_caml_print_int", "Ti4.7", [])))))))
修正した。
code:diff
diff --git a/RP2350/emit.ml b/RP2350/emit.ml
index 69fcc24..94740a2 100644
--- a/RP2350/emit.ml
+++ b/RP2350/emit.ml
@@ -182,21 +182,22 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
g'_args oc [] ys zs;
Printf.fprintf oc "\tb\t%s\n" x
| NonTail(a), CallCls(x, ys, zs) ->
- Printf.fprintf oc "\tmflr\t%s\n" (reg reg_tmp);
+ Printf.fprintf oc "\tmov %s, lr\n" (reg reg_tmp);
g'_args oc (x, reg_cl) ys zs;
let ss = stacksize () in
- Printf.fprintf oc "\tstw\t%s, %d(%s)\n" (reg reg_tmp) (ss - 4) (reg reg_sp);
+ Printf.fprintf oc "\tstr %s, %s, #%d\n" (reg reg_tmp) (reg reg_sp) (ss - 4);
Printf.fprintf oc "\tadd %s, %s, #%d\n" (reg reg_sp) (reg reg_sp) ss;
- Printf.fprintf oc "\tlwz\t%s, 0(%s)\n" (reg reg_tmp) (reg reg_cl);
- Printf.fprintf oc "\tmtctr\t%s\n" (reg reg_tmp);
- Printf.fprintf oc "\tbctrl\n";
- Printf.fprintf oc "\tsubi\t%s, %s, %d\n" (reg reg_sp) (reg reg_sp) ss;
- Printf.fprintf oc "\tlwz\t%s, %d(%s)\n" (reg reg_tmp) (ss - 4) (reg reg_sp);
+ Printf.fprintf oc "\tldr %s, %s\n" (reg reg_tmp) (reg reg_cl);
+ Printf.fprintf oc "\tblx %s\n" (reg reg_tmp);
+ (* Printf.fprintf oc "\tmtctr\t%s\n" (reg reg_tmp);
+ Printf.fprintf oc "\tbctrl\n"; *)
+ Printf.fprintf oc "\tsub %s, %s, %d\n" (reg reg_sp) (reg reg_sp) ss;
+ Printf.fprintf oc "\tldr %s, %s, #%d\n" (reg reg_tmp) (reg reg_sp) (ss - 4);
if List.mem a allregs && a <> regs.(0) then
Printf.fprintf oc "\tmov %s, %s\n" (reg a) (reg regs.(0))
else if List.mem a allfregs && a <> fregs.(0) then
- Printf.fprintf oc "\tfmr\t%s, %s\n" (reg a) (reg fregs.(0));
- Printf.fprintf oc "\tmtlr\t%s\n" (reg reg_tmp)
+ Printf.fprintf oc "\tvmov %s, %s\n" (reg a) (reg fregs.(0));
+ Printf.fprintf oc "\tmov lr, %s\n" (reg reg_tmp)
| (NonTail(a), CallDir(Id.L(x), ys, zs)) ->
Printf.fprintf oc "\tmov %s, lr\n" (reg reg_tmp);
g'_args oc [] ys zs;
@@ -252,6 +253,7 @@ and g'_args oc x_reg_cl ys zs =
(shuffle reg_fsw zfrs)
let h oc { name = Id.L(x); args = _; fargs = _; body = e; ret = _ } =
+ Printf.fprintf oc "\t.thumb_func\n";
Printf.fprintf oc "%s:\n" x;
stackset := S.empty;
stackmap := [];
動かなくて困ってたのだけど、ChatGPT が言うように .thumb_func をつけたら動いた。
code:diff
diff --git a/RP2350/emit.ml b/RP2350/emit.ml
index 9298b65..94740a2 100644
--- a/RP2350/emit.ml
+++ b/RP2350/emit.ml
@@ -253,6 +253,7 @@ and g'_args oc x_reg_cl ys zs =
(shuffle reg_fsw zfrs)
let h oc { name = Id.L(x); args = _; fargs = _; body = e; ret = _ } =
+ Printf.fprintf oc "\t.thumb_func\n";
Printf.fprintf oc "%s:\n" x;
stackset := S.empty;
stackmap := [];
test/cls-reg-bug.ml
末尾呼び出しなのに「blx」なのが原因で動かなかった。「bx」に修正した。
code:diff
diff --git a/RP2350/emit.ml b/RP2350/emit.ml
index 4114b32..7f2bd59 100644
--- a/RP2350/emit.ml
+++ b/RP2350/emit.ml
@@ -177,7 +177,7 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
| Tail, CallCls(x, ys, zs) -> (* 末尾呼び出し (caml2html: emit_tailcall) *)
g'_args oc (x, reg_cl) ys zs;
Printf.fprintf oc "\tldr %s, %s\n" (reg reg_sw) (reg reg_cl);
- Printf.fprintf oc "\tblx %s\n" (reg reg_sw);
+ Printf.fprintf oc "\tbx %s\n" (reg reg_sw);
| Tail, CallDir(Id.L(x), ys, zs) -> (* 末尾呼び出し *)
g'_args oc [] ys zs;
Printf.fprintf oc "\tb\t%s\n" x
メモ
MinCamlとOCamlを一緒に動かすスクリプト
code:sh
PRG="even-odd" && ocaml "test/${PRG}.ml" && make clean min-caml "test/${PRG}.res"