レイトレをRP2350で動かす
from Raspberry Pi Pico2でCPU実験のレイトレを動かしたい
レイトレをQEMU上で動かしてみる。
globals.sを用意
code:globals.s
.data
.comm min_caml_objects, 480, 3
.comm min_caml_size, 16, 3
.comm min_caml_dbg, 8, 3
.comm min_caml_screen, 24, 3
.comm min_caml_vp, 24, 3
.comm min_caml_view, 24, 3
.comm min_caml_light, 24, 3
.comm min_caml_cos_v, 16, 3
.comm min_caml_sin_v, 16, 3
.comm min_caml_beam, 8, 3
.comm min_caml_and_net, 400, 3
.comm min_caml_or_net, 8, 3
.comm min_caml_temp, 112, 3
.comm min_caml_cs_temp, 128, 3
.comm min_caml_solver_dist, 8, 3
.comm min_caml_vscan, 24, 3
.comm min_caml_intsec_rectside, 8, 3
.comm min_caml_tmin, 8, 3
.comm min_caml_crashed_point, 24, 3
.comm min_caml_crashed_object, 8, 3
.comm min_caml_end_flag, 8, 3
.comm min_caml_viewpoint, 24, 3
.comm min_caml_nvector, 24, 3
.comm min_caml_rgb, 24, 3
.comm min_caml_texture_color, 24, 3
.comm min_caml_solver_w_vec, 24, 3
.comm min_caml_chkinside_p, 24, 3
.comm min_caml_isoutside_q, 24, 3
.comm min_caml_nvector_w, 24, 3
.comm min_caml_scan_d, 8, 3
.comm min_caml_scan_offset, 8, 3
.comm min_caml_scan_sscany, 8, 3
.comm min_caml_scan_met1, 8, 3
.comm min_caml_wscan, 24, 3
RP2350/globals.s の用意と Makefile の修正
AArch64 の時に用意した globals.s を、min-rt/RP2350/globals.s へ配置し、Makefile を修正。min-rt をビルドできるようにする。
code:diff
diff --git a/min-rt/Makefile b/min-rt/Makefile
index 7157ccd..3db1403 100644
--- a/min-rt/Makefile
+++ b/min-rt/Makefile
@@ -23,7 +23,7 @@ ppmdiff: ppm.ml diff.ml
time ./min-rt.min-caml < $< > $@.tmp
mv $@.tmp $@
min-rt.min-caml: min-rt.s globals.s ../libmincaml.S ../stub.c
- gcc -m32 -g -O2 -Wall $^ -lm -o min-rt.min-caml
+ 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 min-rt.min-caml
min-rt.s: min-rt.ml ../min-caml
../min-caml -inline 100 min-rt
@@ -72,10 +72,10 @@ globals.cmx: miniMLRuntime.cmx
globals.cmo: miniMLRuntime.cmi
min-rt_b: min-rt.cmo globals.cmo miniMLRuntime.cmo
- ocamlc -g -o min-rt_b miniMLRuntime.cmo globals.cmo min-rt.cmo
+ ocamlc -g -o min-rt_b miniMLRuntime.cmo globals.cmo min-rt.cmo
min-rt: min-rt.cmx globals.cmx miniMLRuntime.cmx
- ocamlopt -unsafe -inline 100 -o min-rt miniMLRuntime.cmx globals.cmx min-rt.cmx
+ ocamlopt -unsafe -inline 100 -o min-rt miniMLRuntime.cmx globals.cmx min-rt.cmx
miniMLRuntime.cmi: miniMLRuntime.mli
ocamlc -c miniMLRuntime.mli
diff --git a/min-rt/RP2350/globals.s b/min-rt/RP2350/globals.s
new file mode 100644
index 0000000..89a22e8
--- /dev/null
+++ b/min-rt/RP2350/globals.s
@@ -0,0 +1,36 @@
+ .data
+ .comm min_caml_objects, 480, 3
+ .comm min_caml_size, 16, 3
+ .comm min_caml_dbg, 8, 3
+ .comm min_caml_screen, 24, 3
+ .comm min_caml_vp, 24, 3
+ .comm min_caml_view, 24, 3
+ .comm min_caml_light, 24, 3
+ .comm min_caml_cos_v, 16, 3
+ .comm min_caml_sin_v, 16, 3
+ .comm min_caml_beam, 8, 3
+ .comm min_caml_and_net, 400, 3
+ .comm min_caml_or_net, 8, 3
+ .comm min_caml_temp, 112, 3
+ .comm min_caml_cs_temp, 128, 3
+ .comm min_caml_solver_dist, 8, 3
+ .comm min_caml_vscan, 24, 3
+ .comm min_caml_intsec_rectside, 8, 3
+ .comm min_caml_tmin, 8, 3
+ .comm min_caml_crashed_point, 24, 3
+ .comm min_caml_crashed_object, 8, 3
+ .comm min_caml_end_flag, 8, 3
+ .comm min_caml_viewpoint, 24, 3
+ .comm min_caml_nvector, 24, 3
+ .comm min_caml_rgb, 24, 3
+ .comm min_caml_texture_color, 24, 3
+ .comm min_caml_solver_w_vec, 24, 3
+ .comm min_caml_chkinside_p, 24, 3
+ .comm min_caml_isoutside_q, 24, 3
+ .comm min_caml_nvector_w, 24, 3
+ .comm min_caml_scan_d, 8, 3
+ .comm min_caml_scan_offset, 8, 3
+ .comm min_caml_scan_sscany, 8, 3
+ .comm min_caml_scan_met1, 8, 3
+ .comm min_caml_wscan, 24, 3
+
min-rt をビルド
$ make -C .. clean min-caml && make clean min-rt.min-caml
Error: offset out of range
ldr r12, =l.10763 のようなラベルアドレスロードで以下のようなエラーが大量に発生。
code:sh
min-rt.s:8258: Error: offset out of range
min-rt.s:8273: Error: offset out of range
min-rt.s:8277: Error: offset out of range
min-rt.s:8285: Error: offset out of range
min-rt.s:8289: Error: offset out of range
min-rt.s:8290: Error: offset out of range
ldr r12, =l.10763 で指定可能な範囲を超えてるみたい。以下のように修正して対応
code:diff
diff --git a/RP2350/emit.ml b/RP2350/emit.ml
index 3f918b1..f9da492 100644
--- a/RP2350/emit.ml
+++ b/RP2350/emit.ml
@@ -32,9 +32,8 @@ let reg r =
let load_label r label =
let r' = reg r in
- Printf.sprintf
- "\tldr %s, =%s\n"
- r' label
+ Printf.sprintf "\tmovw %s, #:lower16:%s\n\tmovt %s, #:upper16:%s\n"
+ r' label r' label
(* 関数呼び出しのために引数を並べ替える(register shuffling) (caml2html: emit_shuffle) *)
let rec shuffle sw xys =
fneg, fcomp 系のエラー
このへんの、PowerPC向けの命令をRP2350向けに修正
code:sh
min-rt.s:235: Error: bad instruction fneg s0,s0'
min-rt.s:317: Error: bad instruction fneg s0,s0'
min-rt.s:500: Error: bad instruction fcmpu cr7,s1,s0'
min-rt.s:676: Error: bad instruction fcmpu cr7,s1,s0'
min-rt.s:686: Error: bad instruction fcmpu cr7,s0,s1'
min-rt.s:705: Error: bad instruction fcmpu cr7,s1,s0'
min-rt.s:715: Error: bad instruction fcmpu cr7,s0,s1'
min-rt.s:734: Error: bad instruction fcmpu cr7,s1,s0'
min-rt.s:744: Error: bad instruction fcmpu cr7,s0,s1'
min-rt.s:792: Error: bad instruction fneg s0,s0'
min-rt.s:1010: Error: bad instruction fneg s0,s0'
code:diff
diff --git a/RP2350/emit.ml b/RP2350/emit.ml
index f9da492..beb1f2d 100644
--- a/RP2350/emit.ml
+++ b/RP2350/emit.ml
@@ -81,8 +81,8 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
| NonTail(_), Stw(x, y, V(z)) -> Printf.fprintf oc "\tstr %s, %s, %s\n" (reg x) (reg y) (reg z)
| 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)
+ | NonTail(x), FMr(y) -> Printf.fprintf oc "\tvmov %s, %s\n" (reg x) (reg y)
+ | NonTail(x), FNeg(y) -> Printf.fprintf oc "\tvneg.f32 %s, %s\n" (reg x) (reg y)
| NonTail(x), FAdd(y, z) -> Printf.fprintf oc "\tvadd.f32 %s, %s, %s\n" (reg x) (reg y) (reg z)
| NonTail(x), FSub(y, z) -> Printf.fprintf oc "\tvsub.f32 %s, %s, %s\n" (reg x) (reg y) (reg z)
| NonTail(x), FMul(y, z) -> Printf.fprintf oc "\tvmul.f32 %s, %s, %s\n" (reg x) (reg y) (reg z)
@@ -155,28 +155,30 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
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);
+ Printf.fprintf oc "\tcmp %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 "\tcmp %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) ->
- Printf.fprintf oc "\tcmpw\tcr7, %s, %s\n" (reg x) (reg y);
+ Printf.fprintf oc "\tcmp %s, %s\n" (reg x) (reg y);
g'_non_tail_if oc (NonTail(z)) e1 e2 "ble" "bgt"
| NonTail(z), IfLE(x, C(y), e1, e2) ->
Printf.fprintf oc "\tcmp %s, %d\n" (reg x) y;
g'_non_tail_if oc (NonTail(z)) e1 e2 "ble" "bgt"
| NonTail(z), IfGE(x, V(y), e1, e2) ->
- Printf.fprintf oc "\tcmpw\tcr7, %s, %s\n" (reg x) (reg y);
+ Printf.fprintf oc "\tcmp %s, %s\n" (reg x) (reg y);
g'_non_tail_if oc (NonTail(z)) e1 e2 "bge" "blt"
| NonTail(z), IfGE(x, C(y), e1, e2) ->
Printf.fprintf oc "\tcmp %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);
+ Printf.fprintf oc "\tvcmp.f32 %s, %s\n" (reg x) (reg y);
+ Printf.fprintf oc "\tvmrs APSR_nzcv, FPSCR\n";
g'_non_tail_if oc (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);
+ Printf.fprintf oc "\tvcmp.f32 %s, %s\n" (reg x) (reg y);
+ Printf.fprintf oc "\tvmrs APSR_nzcv, FPSCR\n";
g'_non_tail_if oc (NonTail(z)) e1 e2 "ble" "bgt"
(* 関数呼び出しの仮想命令の実装 (caml2html: emit_call) *)
| Tail, CallCls(x, ys, zs) -> (* 末尾呼び出し (caml2html: emit_tailcall) *)
@@ -215,7 +217,7 @@ and g' oc = function (* 各命令のアセンブリ生成 (caml2html: emit_gprim
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 "\tvmov %s, %s\n" (reg a) (reg fregs.(0));
Printf.fprintf oc "\tmov lr, %s\n" (reg reg_tmp)
and g'_tail_if oc e1 e2 b bn =
let b_else = Id.genid (b ^ "_else") in
出力画像をテキスト形式に変更
バイナリ形式のP6形式だと取り扱いが面倒なので、テキスト形式のP3形式を出力するように修正。
code:diff
diff --git a/min-rt/min-rt.ml b/min-rt/min-rt.ml
index 3b426f2..57ce527 100644
--- a/min-rt/min-rt.ml
+++ b/min-rt/min-rt.ml
@@ -1140,23 +1140,30 @@ in
(
let red = int_of_float rgb.(0) in
let red = if red > 255 then 255 else red in
- print_byte red;
+ print_int red;
+ (* print_byte red; *)
let green = int_of_float rgb.(1) in
let green = if green > 255 then 255 else green in
- print_byte green;
+ print_int green;
+ (* print_byte green; *)
let blue = int_of_float rgb.(2) in
let blue = if blue > 255 then 255 else blue in
- print_byte blue
+ print_int blue
+ (* print_byte blue *)
)
in
(*MINCAML*)let rec write_ppm_header _ =
(*NOMINCAML let write_ppm_header _ =*)
(
+ (* P6形式 => P3形式 *)
print_byte 80; (* 'P' *)
+ print_byte (48 + 3); (* 48 = '0' *)
+ (*
print_byte (48 + 6); (* 48 = '0' *)
+ *)
print_byte 10;
print_int size.(0);
print_byte 32;
出力画像のサイズを小さくする
768*768は大きすぎるので、10*10ぐらいにする。
code:diff
diff --git a/min-rt/min-rt.ml b/min-rt/min-rt.ml
index 57ce527..379924e 100644
--- a/min-rt/min-rt.ml
+++ b/min-rt/min-rt.ml
@@ -1265,4 +1265,4 @@ in
)
in
-rt 768 768 false
+rt 10 10 false
レイトレを実行
code:sh
$ make -C .. clean min-caml && make clean min-rt.min-caml
$ qemu-system-arm -machine mps2-an505 -cpu cortex-m33 -m 16M -nographic -monitor none -kernel min-rt.min-caml < ball.sld | tee ball.ppm
10x10のボールができた!
https://gyazo.com/fa6e52ce5b158916c5edaee7c802d674