arm32 float linkage

This commit is contained in:
kalsprite
2026-08-14 18:25:12 -07:00
parent 9047c60ec1
commit ee033f7ee8

View File

@@ -1067,8 +1067,8 @@ quo_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 {
return quaternion(w=t0, x=t1, y=t2, z=t3)
}
@(link_name="__truncsfhf2", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
truncsfhf2 :: proc "c" (value: f32) -> __float16 {
@(private="file")
f32_to_f16 :: proc "contextless" (value: f32) -> __float16 {
v: struct #raw_union { i: u32, f: f32 }
i, s, e, m: i32
@@ -1124,18 +1124,8 @@ truncsfhf2 :: proc "c" (value: f32) -> __float16 {
}
}
@(link_name="__aeabi_d2h", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
aeabi_d2h :: proc "c" (value: f64) -> __float16 {
return truncsfhf2(f32(value))
}
@(link_name="__truncdfhf2", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
truncdfhf2 :: proc "c" (value: f64) -> __float16 {
return truncsfhf2(f32(value))
}
@(link_name="__gnu_h2f_ieee", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
gnu_h2f_ieee :: proc "c" (value_: __float16) -> f32 {
@(private="file")
f16_to_f32 :: proc "contextless" (value_: __float16) -> f32 {
fp32 :: struct #raw_union { u: u32, f: f32 }
value := transmute(u16)value_
@@ -1154,14 +1144,56 @@ gnu_h2f_ieee :: proc "c" (value_: __float16) -> f32 {
}
// The conversion helpers below are libgcc / compiler-rt entry points, so their calling convention
// is compiler-rt's and not the target's ordinary one. On ARM they take and return their values in
// the core registers even though the target is AAPCS-VFP, where an ordinary `proc "c"` float
// travels in `s0`. clang's call sites move the value out of the VFP register and back around the
// call:
//
// vmov r0, s0 ; bl __gnu_h2f_ieee ; vmov s0, r0
//
// Typing the boundary as integers is what puts them in the same registers. Declared as floats they
// land in `s0` at both ends and every `_Float16` conversion in C code linked against this runtime
// reads whatever the other register happened to hold. Everywhere else the helpers really do take
// and return floats, so only arm32 changes shape.
when ODIN_ARCH == .arm32 {
__f16_abi :: u16
__f32_abi :: u32
__f64_abi :: u64
} else {
__f16_abi :: __float16
__f32_abi :: f32
__f64_abi :: f64
}
@(link_name="__truncsfhf2", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
truncsfhf2 :: proc "c" (value: __f32_abi) -> __f16_abi {
return transmute(__f16_abi)f32_to_f16(transmute(f32)value)
}
@(link_name="__gnu_f2h_ieee", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
gnu_f2h_ieee :: proc "c" (value: f32) -> __float16 {
return truncsfhf2(value)
gnu_f2h_ieee :: proc "c" (value: __f32_abi) -> __f16_abi {
return transmute(__f16_abi)f32_to_f16(transmute(f32)value)
}
@(link_name="__aeabi_d2h", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
aeabi_d2h :: proc "c" (value: __f64_abi) -> __f16_abi {
return transmute(__f16_abi)f32_to_f16(f32(transmute(f64)value))
}
@(link_name="__truncdfhf2", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
truncdfhf2 :: proc "c" (value: __f64_abi) -> __f16_abi {
return transmute(__f16_abi)f32_to_f16(f32(transmute(f64)value))
}
@(link_name="__gnu_h2f_ieee", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
gnu_h2f_ieee :: proc "c" (value: __f16_abi) -> __f32_abi {
return transmute(__f32_abi)f16_to_f32(transmute(__float16)value)
}
@(link_name="__extendhfsf2", linkage=RUNTIME_LINKAGE, require=RUNTIME_REQUIRE)
extendhfsf2 :: proc "c" (value: __float16) -> f32 {
return gnu_h2f_ieee(value)
extendhfsf2 :: proc "c" (value: __f16_abi) -> __f32_abi {
return transmute(__f32_abi)f16_to_f32(transmute(__float16)value)
}
when .Address in ODIN_SANITIZER_FLAGS {