MinCamlの配列を生成するRP2350コードを出力
配列のテストコード。
code:sample/array_test.ml
let a = Array.make 3 5 in
let _ = a.(0) <- 4649 in
let _ = a.(1) <- 5963 in
let _ = a.(2) <- 246911 in
let p = 3.14 in
let b = (Array.make 4 1.23) in
let _ = print_float b.(0); print_newline () in
let _ = print_float b.(1); print_newline () in
let _ = print_float b.(2); print_newline () in
let _ = print_float b.(3); print_newline () in
let _ = b.(0) <- p in
let _ = b.(1) <- p *. p in
let _ = b.(2) <- p *. p *. p in
let _ = b.(3) <- p *. p *. p *. p in
(* print int array *)
print_int a.(0); (* => 4649 *)
print_newline ();
print_int a.(1); (* => 5963 *)
print_newline ();
print_int a.(2); (* => 249611 *)
print_newline ();
(* print float array *)
print_float b.(0); (* => 3.14 *)
print_newline ();
print_float b.(1); (* => 9.859600 *)
print_newline ();
print_float b.(2); (* => 30.959144 *)
print_newline ();
print_float b.(3); (* => 97.21171216 *)
print_newline ()
まずは整数の配列だけ対応する。
code:diff
commit e05627fea66dcc69c18ee05a26aefc283142d53b
Author: takashi hatakeyama <takashi.hatakeyama@gmail.com>
Date: Thu May 7 12:51:46 2026 +0900
整数の配列が動いた
diff --git a/RP2350/emit.ml b/RP2350/emit.ml
index 6ff2c67..fccbc07 100644
--- a/RP2350/emit.ml
+++ b/RP2350/emit.ml
@@ -78,9 +78,9 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
| NonTail(x), Slw(y, V(z)) -> Printf.fprintf oc "\tslw\t%s, %s, %s\n" (reg x) (reg y) (reg z)
| NonTail(x), Slw(y, C(z)) -> Printf.fprintf oc "\tslwi\t%s, %s, %d\n" (reg x) (reg y) z
| NonTail(x), Lwz(y, V(z)) -> Printf.fprintf oc "\tlwzx\t%s, %s, %s\n" (reg x) (reg y) (reg z)
- | NonTail(x), Lwz(y, C(z)) -> Printf.fprintf oc "\tlwz\t%s, %d(%s)\n" (reg x) z (reg y)
+ | NonTail(x), Lwz(y, C(z)) -> Printf.fprintf oc "\tldr %s, %s, %d\n" (reg x) (reg y) z | NonTail(_), Stw(x, y, V(z)) -> Printf.fprintf oc "\tstwx\t%s, %s, %s\n" (reg x) (reg y) (reg z)
- | NonTail(_), Stw(x, y, C(z)) -> Printf.fprintf oc "\tstw\t%s, %d(%s)\n" (reg x) z (reg y)
+ | NonTail(_), Stw(x, y, C(z)) -> Printf.fprintf oc "\tstr %s, %s, %d\n" (reg x) (reg y) z | NonTail(x), FMr(y) when x = y -> ()
| NonTail(x), FMr(y) -> Printf.fprintf oc "\tfmr\t%s, %s\n" (reg x) (reg y)
| NonTail(x), FNeg(y) -> Printf.fprintf oc "\tfneg\t%s, %s\n" (reg x) (reg y)
diff --git a/RP2350/libmincaml.S b/RP2350/libmincaml.S
index b6e58b8..9592fe1 100644
--- a/RP2350/libmincaml.S
+++ b/RP2350/libmincaml.S
@@ -1,7 +1,23 @@
.text
.syntax unified
.thumb
- .globl foo
-foo:
- movs r0, 123
- bx lr
+ .fpu fpv5-sp-d16
+ .align 1
+// create_array
+// r0: number of elements
+// r1: initial value
+ .globl min_caml_create_array
+min_caml_create_array:
+ mov r12, r0 // r12 = number of elements
+ mov r0, r11 // r0 = hp
+min_caml_create_array_loop:
+ // if number of elements = 0
+ beq min_caml_create_array_exit
+ // if number of elements > 0
+ str r1, r11 // store initial value at hp + add r11, r11, #4 // hp = hp + 4 + subs r12, r12, #1 // number of elements = number of elements - 1 + b min_caml_create_array_loop
+min_caml_create_array_exit:
+ bx lr
diff --git a/sample/array_test.ml b/sample/array_test.ml
new file mode 100644
index 0000000..d010710
--- /dev/null
+++ b/sample/array_test.ml
@@ -0,0 +1,32 @@
+let a = Array.make 3 5 in
+let _ = a.(0) <- 4649 in
+let _ = a.(1) <- 5963 in
+let _ = a.(2) <- 246911 in
+
+(* print int array *)
+print_int a.(0); (* => 4649 *)
+print_newline ();
+print_int a.(1); (* => 5963 *)
+print_newline ();
+print_int a.(2); (* => 249611 *)
+print_newline ()
code:diff
diff --git a/Makefile b/Makefile
index 3ad2bdb..453e68b 100644
--- a/Makefile
+++ b/Makefile
@@ -55,8 +55,8 @@ do_test: $(TESTS:%=test/%.cmp)
test/%.s: $(RESULT) test/%.ml
./$(RESULT) test/$*
-test/%.elf: test/%.s startup.c stub.c libmincaml.S
- $(TGT_CC) $(TGT_CFLAGS) $(TGT_LDFLAGS) -o $@ $^
+test/%.elf: test/%.s startup.c stub.c libmincaml.S linker.ld
+ $(TGT_CC) $(TGT_CFLAGS) $(TGT_LDFLAGS) -o $@ $< startup.c stub.c libmincaml.S
test/%.res: test/%.elf
qemu-system-arm \
-machine mps2-an505 \
@@ -73,8 +73,8 @@ test/%.cmp: test/%.res test/%.ans
sample/%.s: sample/%.ml
./$(RESULT) sample/$*
-sample/%.elf: sample/%.s startup.c stub.c libmincaml.S
- $(TGT_CC) $(TGT_CFLAGS) $(TGT_LDFLAGS) -o $@ $^
+sample/%.elf: sample/%.s startup.c stub.c libmincaml.S linker.ld
+ $(TGT_CC) $(TGT_CFLAGS) $(TGT_LDFLAGS) -o $@ $< startup.c stub.c libmincaml.S
sample/%.res: sample/%.elf
qemu-system-arm \
-machine mps2-an505 \
diff --git a/RP2350/emit.ml b/RP2350/emit.ml
index fccbc07..57bad2c 100644
--- a/RP2350/emit.ml
+++ b/RP2350/emit.ml
@@ -89,9 +89,9 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
| NonTail(x), FMul(y, z) -> Printf.fprintf oc "\tfmul\t%s, %s, %s\n" (reg x) (reg y) (reg z)
| NonTail(x), FDiv(y, z) -> Printf.fprintf oc "\tfdiv\t%s, %s, %s\n" (reg x) (reg y) (reg z)
| NonTail(x), Lfd(y, V(z)) -> Printf.fprintf oc "\tlfdx\t%s, %s, %s\n" (reg x) (reg y) (reg z)
- | NonTail(x), Lfd(y, C(z)) -> Printf.fprintf oc "\tlfd\t%s, %d(%s)\n" (reg x) z (reg y)
+ | NonTail(x), Lfd(y, C(z)) -> Printf.fprintf oc "\tvldr.32 %s, %s, %d\n" (reg x) (reg y) z | NonTail(_), Stfd(x, y, V(z)) -> Printf.fprintf oc "\tstfdx\t%s, %s, %s\n" (reg x) (reg y) (reg z)
- | NonTail(_), Stfd(x, y, C(z)) -> Printf.fprintf oc "\tstfd\t%s, %d(%s)\n" (reg x) z (reg y)
+ | NonTail(_), Stfd(x, y, C(z)) -> Printf.fprintf oc "\tvstr.32 %s, %s, %d\n" (reg x) (reg y) z | NonTail(_), Comment(s) -> Printf.fprintf oc "#\t%s\n" s
(* 退避の仮想命令の実装 (caml2html: emit_save) *)
| NonTail(_), Save(x, y) when List.mem x allregs && not (S.mem y !stackset) ->
@@ -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 "\tvstr %s, %s, %d\n" (reg x) (reg reg_sp) (offset y) + Printf.fprintf oc "\tvstr.32 %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 "\tvldr %s, %s, %d\n" (reg x) (reg reg_sp) (offset y) + Printf.fprintf oc "\tvldr.32 %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);
diff --git a/RP2350/libmincaml.S b/RP2350/libmincaml.S
index 9592fe1..ea520f9 100644
--- a/RP2350/libmincaml.S
+++ b/RP2350/libmincaml.S
@@ -3,12 +3,13 @@
.thumb
.fpu fpv5-sp-d16
.align 1
+
// create_array
// r0: number of elements
// r1: initial value
.globl min_caml_create_array
min_caml_create_array:
- mov r12, r0 // r12 = number of elements
+ mov r12, r0 // r12 = number of elements
mov r0, r11 // r0 = hp
min_caml_create_array_loop:
// if number of elements = 0
@@ -21,3 +22,29 @@ min_caml_create_array_loop:
b min_caml_create_array_loop
min_caml_create_array_exit:
bx lr
+
+// create_float_array
+// r0: number of elements
+// s0: initial value
+ .globl min_caml_create_float_array
+min_caml_create_float_array:
+ mov r12, r0 // r12 = number of elements
+ mov r0, r11 // r0 = hp (return value)
+min_caml_create_float_array_loop:
+ beq min_caml_create_float_array_exit
+ vstr.32 s0, r11 // store float initial value at hp + add r11, r11, #4 // hp = hp + 4 + subs r12, r12, #1 // number of elements - 1 + b min_caml_create_float_array_loop
+min_caml_create_float_array_exit:
+ bx lr
+
+// int_of_float
+// r0: float value
+// return: int value
+ .globl min_caml_int_of_float
+min_caml_int_of_float:
+ vcvt.s32.f32 s0, s0
+ vmov r0, s0
+ bx lr
diff --git a/RP2350/virtual.ml b/RP2350/virtual.ml
index 3752289..f0d173c 100644
--- a/RP2350/virtual.ml
+++ b/RP2350/virtual.ml
@@ -122,7 +122,7 @@ let rec g env = function (* 式の仮想マシンコード生成 (caml2html: vir
(match M.find x env with
| Type.Array(Type.Unit) -> Ans(Nop)
| Type.Array(Type.Float) ->
- Let((offset, Type.Int), Slw(y, C(3)),
+ Let((offset, Type.Int), Slw(y, C(2)),
Ans(Lfd(x, V(offset))))
| Type.Array(_) ->
Let((offset, Type.Int), Slw(y, C(2)),
@@ -133,7 +133,7 @@ let rec g env = function (* 式の仮想マシンコード生成 (caml2html: vir
(match M.find x env with
| Type.Array(Type.Unit) -> Ans(Nop)
| Type.Array(Type.Float) ->
- Let((offset, Type.Int), Slw(y, C(3)),
+ Let((offset, Type.Int), Slw(y, C(2)),
Ans(Stfd(z, x, V(offset))))
| Type.Array(_) ->
Let((offset, Type.Int), Slw(y, C(2)),
diff --git a/linker.ld b/linker.ld
index 819a0fb..1deac05 100644
--- a/linker.ld
+++ b/linker.ld
@@ -6,6 +6,12 @@ MEMORY
RAM (rwx) : ORIGIN = 0x80000000, LENGTH = 8M
}
+PHDRS
+{
+ text PT_LOAD FLAGS(5);
+ data PT_LOAD FLAGS(6);
+}
+
_estack = ORIGIN(RAM) + LENGTH(RAM);
SECTIONS
@@ -13,7 +19,7 @@ SECTIONS
.isr_vector :
{
KEEP(*(.isr_vector))
- } > FLASH
+ } > FLASH :text
.text :
{
@@ -21,7 +27,7 @@ SECTIONS
*(.rodata*)
. = ALIGN(4);
_etext = .;
- } > FLASH
+ } > FLASH :text
.data : AT(_etext)
{
@@ -30,11 +36,11 @@ SECTIONS
*(.data*)
. = ALIGN(4);
_edata = .;
- } > RAM
+ } > RAM :data
_sidata = LOADADDR(.data);
- .bss :
+ .bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = .;
@@ -42,5 +48,5 @@ SECTIONS
*(COMMON)
. = ALIGN(4);
_ebss = .;
- } > RAM
+ } > RAM :NONE
}
diff --git a/qemu.mk b/qemu.mk
index eeca352..7fdacc3 100644
--- a/qemu.mk
+++ b/qemu.mk
@@ -20,8 +20,8 @@ LDFLAGS = \
test/%.o: test/%.S
$(CC) $(CFLAGS) -c -o $@ $<
-test/%.elf: test/%.o startup.c stub.c libmincaml.S
- $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^
+test/%.elf: test/%.o startup.c stub.c libmincaml.S linker.ld
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< startup.c stub.c libmincaml.S
test/%.res: test/%.elf
qemu-system-arm \
diff --git a/sample/array_test.ml b/sample/array_test.ml
index d010710..d6678aa 100644
--- a/sample/array_test.ml
+++ b/sample/array_test.ml
@@ -2,31 +2,11 @@ let a = Array.make 3 5 in
let _ = a.(0) <- 4649 in
let _ = a.(1) <- 5963 in
let _ = a.(2) <- 246911 in
-(* let p = 3.14 in
-let b = (Array.make 4 1.23) in
-let _ = print_float b.(0); print_newline () in
-let _ = print_float b.(1); print_newline () in
-let _ = print_float b.(2); print_newline () in
-let _ = print_float b.(3); print_newline () in
-let _ = b.(0) <- p in
-let _ = b.(1) <- p *. p in
-let _ = b.(2) <- p *. p *. p in
-let _ = b.(3) <- p *. p *. p *. p in
-*)
(* print int array *)
print_int a.(0); (* => 4649 *)
print_newline ();
print_int a.(1); (* => 5963 *)
print_newline ();
-print_int a.(2); (* => 249611 *)
+print_int a.(2); (* => 246911 *)
print_newline ()
-(* print float array *)
-(* print_float b.(0); (* => 3.14 *)
-print_newline ();
-print_float b.(1); (* => 9.859600 *)
-print_newline ();
-print_float b.(2); (* => 30.959144 *)
-print_newline ();
-print_float b.(3); (* => 97.21171216 *)
-print_newline () *)
diff --git a/sample/float_array_test.ml b/sample/float_array_test.ml
new file mode 100644
index 0000000..8e2654b
--- /dev/null
+++ b/sample/float_array_test.ml
@@ -0,0 +1,18 @@
+let a = (Array.make 4 1.23) in
+let _ = print_int (int_of_float a.(0)); print_newline () in (* => 1 *)
+let _ = print_int (int_of_float a.(1)); print_newline () in (* => 1 *)
+let _ = print_int (int_of_float a.(2)); print_newline () in (* => 1 *)
+let _ = print_int (int_of_float a.(3)); print_newline () in (* => 1 *)
+let p = 3.14 in
+let _ = a.(0) <- p in
+let _ = a.(1) <- p *. p in
+let _ = a.(2) <- p *. p *. p in
+let _ = a.(3) <- p *. p *. p *. p in
+print_int (int_of_float a.(0)); (* => 3 *)
+print_newline ();
+print_int (int_of_float a.(1)); (* => 9 *)
+print_newline ();
+print_int (int_of_float a.(2)); (* => 30 *)
+print_newline ();
+print_int (int_of_float a.(3)); (* => 97 *)
+print_newline ()
diff --git a/sample/float_if.ml b/sample/float_if.ml
index 0bda31b..512a5ca 100644
--- a/sample/float_if.ml
+++ b/sample/float_if.ml
@@ -34,8 +34,8 @@ test2 a b;
print_newline ();
(* QEMUのバグ(?)回避のためのコード *)
-if a < b then print_int 1 else print_int 0;
-print_newline ();
+(* if a < b then print_int 1 else print_int 0;
+print_newline (); *)
test3 a b;
print_newline ();
diff --git a/stub.c b/stub.c
index 3d37b66..b8287b3 100644
--- a/stub.c
+++ b/stub.c
@@ -89,10 +89,6 @@ void min_caml_print_newline(void) {
uart_putc('\n');
}
-int min_caml_int_of_float(float f) {
- return (int)f;
-}
-
int main(void) {
uart_init();
オリジナルのMinCamlの浮動小数点数は8バイト(倍精度)だが、RP2350対応版は4バイト(単精度)なので以下の修正を行なった。同様の修正が必要な場合は気をつけてね。
code:diff
--- a/RP2350/virtual.ml
+++ b/RP2350/virtual.ml
@@ -122,7 +122,7 @@ let rec g env = function (* 式の仮想マシンコード生成 (caml2html: vir
(match M.find x env with
| Type.Array(Type.Unit) -> Ans(Nop)
| Type.Array(Type.Float) ->
- Let((offset, Type.Int), Slw(y, C(3)),
+ Let((offset, Type.Int), Slw(y, C(2)),
Ans(Lfd(x, V(offset))))
| Type.Array(_) ->
Let((offset, Type.Int), Slw(y, C(2)),
@@ -133,7 +133,7 @@ let rec g env = function (* 式の仮想マシンコード生成 (caml2html: vir
(match M.find x env with
| Type.Array(Type.Unit) -> Ans(Nop)
| Type.Array(Type.Float) ->
- Let((offset, Type.Int), Slw(y, C(3)),
+ Let((offset, Type.Int), Slw(y, C(2)),
Ans(Stfd(z, x, V(offset))))
| Type.Array(_) ->
Let((offset, Type.Int), Slw(y, C(2)),