From 68fb3a601c63192a741ee9e02f4aabd6db3fa1db Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Mon, 15 Dec 2025 12:50:04 +0100 Subject: [PATCH] etnaviv: isa: Add assembler support for infinity and NaN immediates Implement parsing and encoding of special floating-point values for both 20-bit (f20) and 16-bit (f16) immediate formats: inf:f20 - Positive infinity (imm_val=0x7f800, imm_type=0) -inf:f20 - Negative infinity (imm_val=0xff800, imm_type=0) nan:f20 - Quiet NaN (imm_val=0x7fc00, imm_type=0) -nan:f20 - Negative NaN (imm_val=0xffc00, imm_type=0) inf:f16 - Positive infinity (imm_val=0x7c00, imm_type=3) -inf:f16 - Negative infinity (imm_val=0xfc00, imm_type=3) nan:f16 - Quiet NaN (imm_val=0x7fff, imm_type=3) -nan:f16 - Negative NaN (imm_val=0xffff, imm_type=3) The f20 format stores the upper 20 bits of an IEEE 754 single-precision float. The f16 format stores the 16-bit half-float value directly. This enables round-trip assembly of shaders containing these special values, which can appear in GPU command streams captured from the proprietary driver. Signed-off-by: Christian Gmeiner Reviewed-by: @LingMan Part-of: --- src/etnaviv/isa/parser.rs | 60 +++++++++++++++++++++++++++++-- src/etnaviv/isa/static_rules.pest | 24 +++++++++++-- src/etnaviv/isa/tests/disasm.cpp | 13 ++++++- 3 files changed, 92 insertions(+), 5 deletions(-) diff --git a/src/etnaviv/isa/parser.rs b/src/etnaviv/isa/parser.rs index f4a1bfd00c8..880151a264b 100644 --- a/src/etnaviv/isa/parser.rs +++ b/src/etnaviv/isa/parser.rs @@ -219,13 +219,69 @@ fn fill_source(pair: Pair, src: &mut etna_inst_src) { src.__bindgen_anon_1.__bindgen_anon_1.set_reg(r); } } - Rule::Immediate_Minus_Nan => { + Rule::Immediate_inf_float => { src.set_rgroup(isa_reg_group::ISA_REG_GROUP_IMMED); let imm_struct = unsafe { &mut src.__bindgen_anon_1.__bindgen_anon_2 }; imm_struct.set_imm_type(0); - imm_struct.set_imm_val(0xfffff); + imm_struct.set_imm_val(0x7f800); + } + Rule::Immediate_neg_inf_float => { + src.set_rgroup(isa_reg_group::ISA_REG_GROUP_IMMED); + + let imm_struct = unsafe { &mut src.__bindgen_anon_1.__bindgen_anon_2 }; + + imm_struct.set_imm_type(0); + imm_struct.set_imm_val(0xff800); + } + Rule::Immediate_inf_half_float => { + src.set_rgroup(isa_reg_group::ISA_REG_GROUP_IMMED); + + let imm_struct = unsafe { &mut src.__bindgen_anon_1.__bindgen_anon_2 }; + + imm_struct.set_imm_type(3); + imm_struct.set_imm_val(0x7c00); + } + Rule::Immediate_neg_inf_half_float => { + src.set_rgroup(isa_reg_group::ISA_REG_GROUP_IMMED); + + let imm_struct = unsafe { &mut src.__bindgen_anon_1.__bindgen_anon_2 }; + + imm_struct.set_imm_type(3); + imm_struct.set_imm_val(0xfc00); + } + Rule::Immediate_nan_float => { + src.set_rgroup(isa_reg_group::ISA_REG_GROUP_IMMED); + + let imm_struct = unsafe { &mut src.__bindgen_anon_1.__bindgen_anon_2 }; + + imm_struct.set_imm_type(0); + imm_struct.set_imm_val(0x7fc00); + } + Rule::Immediate_neg_nan_float => { + src.set_rgroup(isa_reg_group::ISA_REG_GROUP_IMMED); + + let imm_struct = unsafe { &mut src.__bindgen_anon_1.__bindgen_anon_2 }; + + imm_struct.set_imm_type(0); + imm_struct.set_imm_val(0xffc00); + } + Rule::Immediate_nan_half_float => { + src.set_rgroup(isa_reg_group::ISA_REG_GROUP_IMMED); + + let imm_struct = unsafe { &mut src.__bindgen_anon_1.__bindgen_anon_2 }; + + imm_struct.set_imm_type(3); + imm_struct.set_imm_val(0x7fff); + } + Rule::Immediate_neg_nan_half_float => { + src.set_rgroup(isa_reg_group::ISA_REG_GROUP_IMMED); + + let imm_struct = unsafe { &mut src.__bindgen_anon_1.__bindgen_anon_2 }; + + imm_struct.set_imm_type(3); + imm_struct.set_imm_val(0xffff); } Rule::Immediate_float => { let value: f32 = parse_numeric(item); diff --git a/src/etnaviv/isa/static_rules.pest b/src/etnaviv/isa/static_rules.pest index f84f3a5837b..0ae2b64adef 100644 --- a/src/etnaviv/isa/static_rules.pest +++ b/src/etnaviv/isa/static_rules.pest @@ -22,12 +22,32 @@ DestVoid = { "void" } Negate = { "-" } Absolute = { "|" } -Immediate_Minus_Nan = @{ Negate ~ "nan" } +Immediate_inf_float = @{ "inf" ~ ":f20" } +Immediate_neg_inf_float = @{ "-inf" ~ ":f20" } +Immediate_inf_half_float = @{ "inf" ~ ":f16" } +Immediate_neg_inf_half_float = @{ "-inf" ~ ":f16" } +Immediate_nan_float = @{ "nan" ~ ":f20" } +Immediate_neg_nan_float = @{ "-nan" ~ ":f20" } +Immediate_nan_half_float = @{ "nan" ~ ":f16" } +Immediate_neg_nan_half_float = @{ "-nan" ~ ":f16" } Immediate_float = @{ Negate? ~ ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT+ ~ ":f20" } Immediate_half_float = @{ Negate? ~ ASCII_DIGIT+ ~ "." ~ ASCII_DIGIT+ ~ ":f16" } Immediate_uint = @{ ASCII_DIGIT+ ~ ":u20" } Immediate_int = @{ Negate? ~ ASCII_DIGIT+ ~ ":s20" } -Immediate = _{ Immediate_Minus_Nan | Immediate_float | Immediate_half_float | Immediate_uint | Immediate_int } +Immediate = _{ + Immediate_inf_float | + Immediate_neg_inf_float | + Immediate_inf_half_float | + Immediate_neg_inf_half_float | + Immediate_nan_float | + Immediate_neg_nan_float | + Immediate_nan_half_float | + Immediate_neg_nan_half_float | + Immediate_float | + Immediate_half_float | + Immediate_uint | + Immediate_int + } Register = @{ ASCII_DIGIT+ } DstRegister = ${ "t" ~ Register ~ RegAddressingMode? ~ Wrmask? } diff --git a/src/etnaviv/isa/tests/disasm.cpp b/src/etnaviv/isa/tests/disasm.cpp index 81ca19e988b..3cdd023a595 100644 --- a/src/etnaviv/isa/tests/disasm.cpp +++ b/src/etnaviv/isa/tests/disasm.cpp @@ -287,7 +287,7 @@ INSTANTIATE_TEST_SUITE_P(ImmediateValues, DisasmTest, disasm_state{ {0x00801001, 0x7e000805, 0x00000038, 0x00800008}, "add.rtz t0.x___, 0.500000:f20, void, |t0.xxxx|\n"}, /* type: 0 */ disasm_state{ {0x00811131, 0x95401804, 0x00aa0060, 0x76fffffa}, "cmp.le.t0 t1.x___, |th1.yyyy|, u0.yyyy, -1:s20\n"}, /* type: 1 */ disasm_state{ {0x0080101a, 0x00001804, 0x40010000, 0x78000018}, "rshift.s32 t0.x___, t1.xxxx, void, 1:u20\n"}, /* type: 2*/ - disasm_state{ {0x020211b1, 0x00001804, 0x01fe0040, 0x7c1fdffa}, "cmp.ne t2.__z_, t1.xxxx, u0.wwww, -nan:f16\n", FLAG_FAILING_ASM} /* type: 3 */ + disasm_state{ {0x020211b1, 0x00001804, 0x01fe0040, 0x7c1fdffa}, "cmp.ne t2.__z_, t1.xxxx, u0.wwww, -nan:f16\n"} /* type: 3 */ ) ); // clang-format on @@ -422,3 +422,14 @@ INSTANTIATE_TEST_SUITE_P(SwizzleVariants, DisasmTest, ) ); // clang-format on + +// clang-format off +INSTANTIATE_TEST_SUITE_P(InfNaN, DisasmTest, + testing::Values( + disasm_state{ {0x00811009, 0x00000004, 0x00000000, 0x70ff0008}, "mov t1.x___, void, void, inf:f20\n"}, + disasm_state{ {0x00811009, 0x00000004, 0x00000000, 0x72ff0008}, "mov t1.x___, void, void, -inf:f20\n"}, + disasm_state{ {0x00811009, 0x00000004, 0x00000000, 0x70ff8008}, "mov t1.x___, void, void, nan:f20\n"}, + disasm_state{ {0x00811009, 0x00000004, 0x00000000, 0x72ff8008}, "mov t1.x___, void, void, -nan:f20\n"} + ) +); +// clang-format on