浮動小数点数を扱うRP2350コードを出力
#MinCaml #RP2350
from Raspberry Pi Pico2でCPU実験のレイトレを動かしたい
ひとまず以下のコードを動くようにしたい。
code:sample/pi.ml
let pi = 3.1415 in
print_int (int_of_float pi);
print_newline()
ビルドコマンド
code:sh
touch sample/pi.ml && make min-caml min-caml.top sample/pi.res
以下のようなエラーが出力される。
code:sh
arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -mfpu=fpv5-sp-d16 -mfloat-abi=hard -ffreestanding -nostdlib -Wall -Wextra -O2 -T linker.ld -nostdlib -Wl,-Map=main.map -o sample/pi.elf sample/pi.s startup.c stub.c libmincaml.S
sample/pi.s: Assembler messages:
sample/pi.s:2: Error: unknown pseudo-op: `.literal8'
sample/pi.s:16: Error: bad instruction `lis r12,ha16(l.8)'
sample/pi.s:17: Error: bad instruction `addi r12,r12,lo16(l.8)'
sample/pi.s:18: Error: bad instruction `lfd f0,0(r12)'
make: *** sample/pi.elf Error 1
浮動小数点数のコードの書き方の参考に、以下のCのコードからアセンブリコードを出力
code:c
#include <stdio.h>
void main() {
const float pi = 3.14;
printf("%d\n", (int)pi);
return;
}
Cのソースからアセンブリコードを出力
code:sh
$ arm-none-eabi-gcc -mcpu=cortex-m33 -mthumb -mfpu=fpv5-sp-d16 -mfloat-abi=hard -O0 -S test.c -o test.s
code:asm
.cpu cortex-m33
.eabi_attribute 27, 1
.eabi_attribute 28, 1
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 1
.eabi_attribute 30, 6
.eabi_attribute 34, 1
.eabi_attribute 18, 4
.file "test.c"
.text
.section .rodata
.align 2
.LC0:
.ascii "%d\012\000"
.text
.align 1
.global main
.arch armv8-m.main
.arch_extension dsp
.syntax unified
.thumb
.thumb_func
.fpu fpv5-sp-d16
.type main, %function
main:
@ args = 0, pretend = 0, frame = 8
@ frame_needed = 1, uses_anonymous_args = 0
push {r7, lr}
sub sp, sp, #8
add r7, sp, #0
ldr r3, .L3
str r3, r7, #4 @ float
vldr.32 s15, r7, #4
vcvt.s32.f32 s15, s15
vmov r1, s15 @ int
ldr r0, .L3+4
bl printf
nop
adds r7, r7, #8
mov sp, r7
@ sp needed
pop {r7, pc}
.L4:
.align 2
.L3:
.word 1078523331
.word .LC0
.size main, .-main
.ident "GCC: (GNU Arm Embedded Toolchain 10.3-2021.07) 10.3.1 20210621 (release)"
対応した
code:diff
diff --git a/RP2350/asm.ml b/RP2350/asm.ml
index b7672ad..0b78ae3 100644
--- a/RP2350/asm.ml
+++ b/RP2350/asm.ml
@@ -46,7 +46,7 @@ let seq(e1, e2) = Let((Id.gentmp Type.Unit, Type.Unit), e1, e2)
(* 汎用レジスタのうちのR0からR9を使用(R10はMinCamlスタック、R11はMinCamlヒープに用いる) *)
let regs =
"%r0"; "%r1"; "%r3"; "%r4"; "%r5"; "%r6"; "%r7"; "%r8"; "%r9" |
-let fregs = Array.init 32 (fun i -> Printf.sprintf "%%f%d" i)
+let fregs = Array.init 32 (fun i -> Printf.sprintf "%%s%d" i)
let allregs = Array.to_list regs
let allfregs = Array.to_list fregs
let reg_cl = regs.(Array.length regs - 1) (* closure address (caml2html: sparcasm_regcl) *)
diff --git a/RP2350/emit.ml b/RP2350/emit.ml
index 4f313e8..b100b66 100644
--- a/RP2350/emit.ml
+++ b/RP2350/emit.ml
@@ -2,6 +2,7 @@ open Asm
external gethi : float -> int32 = "gethi"
external getlo : float -> int32 = "getlo"
+external getf : float -> int32 = "getf"
let stackset = ref S.empty (* すでにSaveされた変数の集合 (caml2html: emit_stackset) *)
let stackmap = ref [] (* Saveされた変数の、スタックにおける位置 (caml2html: emit_stackmap) *)
@@ -32,8 +33,8 @@ let reg r =
let load_label r label =
let r' = reg r in
Printf.sprintf
- "\tlis\t%s, ha16(%s)\n\taddi\t%s, %s, lo16(%s)\n"
- r' label r' r' label
+ "\tldr %s, =%s\n"
+ r' label
(* 関数呼び出しのために引数を並べ替える(register shuffling) (caml2html: emit_shuffle) *)
let rec shuffle sw xys =
@@ -62,7 +63,8 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
| NonTail(x), Li(i) -> Printf.fprintf oc "\tldr %s, =%d\n" (reg x) i
| NonTail(x), FLi(Id.L(l)) ->
let s = load_label (reg reg_tmp) l in
- Printf.fprintf oc "%s\tlfd\t%s, 0(%s)\n" s (reg x) (reg reg_tmp)
+ Printf.fprintf oc "%s" s;
+ Printf.fprintf oc "\tvldr.32 %s, %s\n" (reg x) (reg reg_tmp)
| NonTail(x), SetL(Id.L(y)) ->
let s = load_label x y in
Printf.fprintf oc "%s" s
@@ -256,17 +258,18 @@ let h oc { name = Id.L(x); args = _; fargs = _; body = e; ret = _ } =
let f oc (Prog(data, fundefs, e)) =
Format.eprintf "generating assembly...@.";
if data <> [] then
- (Printf.fprintf oc "\t.data\n\t.literal8\n";
+ (Printf.fprintf oc "\t.data\n";
List.iter
(fun (Id.L(x), d) ->
- Printf.fprintf oc "\t.align 3\n";
+ Printf.fprintf oc "\t.align 2\n";
Printf.fprintf oc "%s:\t # %f\n" x d;
- Printf.fprintf oc "\t.long\t%ld\n" (gethi d);
- Printf.fprintf oc "\t.long\t%ld\n" (getlo d))
+ Printf.fprintf oc "\t.long\t%ld\n" (getf d))
data);
Printf.fprintf oc "\t.text\n";
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.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/float.c b/float.c
index 1165150..f260f0e 100644
--- a/float.c
+++ b/float.c
@@ -19,3 +19,14 @@ value getlo(value v) {
d.d = Double_val(v);
return caml_copy_int32(d.i1);
}
+
+ typedef union {
+ int32_t i2;
+ float f;
+ } flt;
+
+ value getf(value v) {
+ flt f;
+ f.f = Double_val(v);
+ return caml_copy_int32(f.i0);
+ }
diff --git a/sample/pi.ml b/sample/pi.ml
new file mode 100644
index 0000000..bf9c551
--- /dev/null
+++ b/sample/pi.ml
@@ -0,0 +1,3 @@
+let pi = 3.1415 in
+print_int (int_of_float pi);
+print_newline()
diff --git a/stub.c b/stub.c
index 32a89ff..1388380 100644
--- a/stub.c
+++ b/stub.c
@@ -87,6 +87,10 @@ 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();
実行してみる。
code:sh
$ touch sample/pi.ml && make clean min-caml min-caml.top sample/pi.res
...
qemu-system-arm \
-machine mps2-an505 \
-cpu cortex-m33 \
-m 16M \
-nographic \
-monitor none \
-kernel sample/pi.elf
Hello from QEMU mps2-an505 Cortex-M33!
3
参考
test/float.ml をワンパス通した
https://github.com/thata/min-caml/commit/0ecad6439ddf99bc8ad0de1bd7119c1274873a07
Add test/pi
https://github.com/thata/min-caml/commit/feaf98d72e79bf56216d17bb72b4b6a7a67dd0f8
浮動小数点の比較命令を実装中
https://github.com/thata/min-caml/commit/e3153f1245c8fbfb4867b00bbc23d33aa08c0e85
浮動小数点数の比較命令のつづき
https://github.com/thata/min-caml/commit/0c83e20c5c406a9978cb025109fefed02e73e7b5
test/float.mlを動くようにした
https://github.com/thata/min-caml/commit/bf7dcd018cd461a27f6e8938167067a1a9100227