浮動小数点まわりのエラーに対応
from Raspberry Pi Pico2でCPU実験のレイトレを動かしたい
浮動小数点まわりでエラーが発生することがあるので、CodexのGPT-5.5に丸投げして解決した。
このへんの知識が弱過ぎるのでもうちょっとちゃんと理解したいね。
code:text
調査して修正しました。原因は float_if の浮動小数点比較ではなく、ELF のロードセグメント配置でした。
回避コードを消すと .text が少し小さくなり、ld が .data と 5MB の .bss を同じ PT_LOAD にまとめます。その形だと QEMU の -kernel ELF ローダが崩れ、Reset_Handler の実体が 0x0000 として実行され、最終的に PC=0 の HardFault/lockup になります。回避コードは偶然 .text サイズをずらして .bss が別セグメントになっていただけでした。
対応として linker.ld(/Users/thata/src/min-caml-rp2350/linker.ld:9) に PHDRS を追加し、linker.ld(/Users/thata/src/min-caml-rp2350/linker.ld:43) の .bss を NOLOAD かつ :NONE にして QEMU にロードさせないようにしました。startup.c が _sbss から _ebss をゼロ初期化するので問題ありません。
あわせて Makefile(/Users/thata/src/min-caml-rp2350/Makefile:58) と qemu.mk(/Users/thata/src/min-caml-rp2350/qemu.mk:23) で linker.ld 変更時に再リンクされるようにしました。sample/float_if.ml は回避コードをコメントアウトした状態です。
確認済み:
- make -B sample/float_if.elf
- QEMU 実行で 1 が 5 行出力されることを確認
- readelf -l で .bss が PT_LOAD から外れていることを確認
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/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/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 ();
修正後のlinker.ld
code:linker.ld
ENTRY(Reset_Handler)
MEMORY
{
FLASH (rx) : ORIGIN = 0x10000000, LENGTH = 512K
RAM (rwx) : ORIGIN = 0x80000000, LENGTH = 8M
}
PHDRS
{
text PT_LOAD FLAGS(5);
data PT_LOAD FLAGS(6);
}
_estack = ORIGIN(RAM) + LENGTH(RAM);
SECTIONS
{
.isr_vector :
{
KEEP(*(.isr_vector))
} > FLASH :text
.text :
{
*(.text*)
*(.rodata*)
. = ALIGN(4);
_etext = .;
} > FLASH :text
.data : AT(_etext)
{
. = ALIGN(4);
_sdata = .;
*(.data*)
. = ALIGN(4);
_edata = .;
} > RAM :data
_sidata = LOADADDR(.data);
.bss (NOLOAD) :
{
. = ALIGN(4);
_sbss = .;
*(.bss*)
*(COMMON)
. = ALIGN(4);
_ebss = .;
} > RAM :NONE
}