riscv / riscv-isa-manual

RISC-V Instruction Set Manual
https://riscv.org/
Creative Commons Attribution 4.0 International
3.57k stars 619 forks source link

Does the instruction FLI.S need to exhibit floating-point values at the assembly level? #980

Closed majin2020 closed 1 year ago

majin2020 commented 1 year ago

hi @aswaterman , I have some doubts about the fli instruction.

I'm not sure. If the number 0-31 is used instead of the value in Chapter 25 of "Table 25.1: Immediate values loaded by the FLI.S instruction", how can this reflect the actual floating point of the load at the instruction level? Is it more appropriate to use fli.h ft1, -1.0instead of fli.h ft1, 0?

Perhaps both options should be taken into account. While supporting the lookup of the values in the table by passing 0-31(RS1), it should also support the loading of accurate floating-point values to reflect the actual floating-point operation at the assembly level.

I think it may be more appropriate to embody the specific decimal floating-point number at the assembly level.

This has a similar example on arm architecture. ARMv8 Instruction Set Overview

image

Looking forward to your reply, thanks :)

aswaterman commented 1 year ago

No, 0-31 are not supported.

majin2020 commented 1 year ago

hi @a4lg This seems to be different from what I understand :)

I am trying to support the "zfa" extension in riscv-gcc, provided that I rely on your binutils-gdb patch for the "zfa" extension, but there seems to be some doubts here.

a4lg commented 1 year ago

@majin2022 Current draft spec says:

The preferred assembly syntax for entries 1, 30, and 31 is min, inf, and nan, respectively. For entries 0 through 29 (including entry 1), the assembler will accept decimal constants in C-like syntax.

Preferred syntax supports:

and my zfa branch of GNU Binutils supports all of these (and any constant expression that are evaluated to 0-29 as a GNU extension).

So, I think @aswaterman is pointing that 30 and 31 are not supported.

pdonahue-ventana commented 1 year ago

I think that the confusion is about what "decimal constant" means. The assembler syntax is to use the decimal value in the "Value" column and not the 5b decimal number in the rs1 column. There are special cases for the three entries that don't have decimal representations (infinity and NaN) and the minimum positive normal number (which might not have a finite decimal representation, I'm not sure).

aswaterman commented 1 year ago

What @pdonahue-ventana said re: using the decimal value in the "Value" column. I didn't think the spec was ambiguous, but if you have a suggestion for how to clarify it, I'm all ears.

nick-knight commented 1 year ago

the minimum positive normal number (which might not have a finite decimal representation, I'm not sure).

A rational number $p/q$, in lowest terms, has a terminating expansion in base $b$ if each prime factor of $q$ divides $b$. In the case of a binary floating-point number, $q$ is a product of $2$ s, and $2$ divides $b=10$. (In the case $q=1$, it's an empty product, so divisibility holds vacuously.)

majin2020 commented 1 year ago

I think the minimum positive normal numbe :

  1. When the type is _Float16 , it is equal to 6.104E-5.
  2. When the type is _Float32 , it is equal to 1.1754944e-38.
  3. When the type is _Float64 , it is equal to 1.1754943508222875E-38.

I got it through floating-point binary, and although I don't know if my understanding is correct, I think the compiler output assembly should include similar specific decimal floating-point values.

a4lg commented 1 year ago

@majin2022 I don't agree. Despite that it is technically possible, it suffers from small numbers (min and around... 2 through 5) because of interpretation of inexact floating point numbers. Index numbers are clearer in semantics and interpretation.

majin2020 commented 1 year ago

@aswaterman @a4lg Well, then I can understand that, except for a few special cases, should the rest be represented using decimal floating-point values? For example fli.h ft1, -1.0 , fli.h ft1, 0.0625 , etc.

:)

a4lg commented 1 year ago

@majin2022 Mixing different but similar looking semantics - table index numbers and actual numbers is what I never want to proceed (your original proposal I don't agree - using actual numbers (only) is far better than that). For instance, such confusing cases will happen:

fli.s fa0, 2    # to load the value by index 2 (actual value: 2^(-16))
fli.s fa0, 2.0  # to load the value 2.0 (table index 20)
topperc commented 1 year ago

When the type is _Float64 , it is equal to 1.1754943508222875E-38.

The minimum positive normal for _Float64 should be 2.2250738585072014 × 10−308 with a lot more decimal places.

majin2020 commented 1 year ago

@topperc Yeah, I realized you were right :)

In addition, @a4lg can we consider the binutils of zfa to be combined into the upstream? As far as I know, llvm is basically combined into the upstream, except for the FLI instruction. I initially implemented the gcc compiler part about zfa based on your patch.

a4lg commented 1 year ago

@majin2022 If that's possible, I would but... currently, upstream merge to Binutils / GCC requires an extension to be at least frozen. There's a discussion about relaxing the requirement but I think this is not happened yet.

joshua-arch1 commented 1 year ago

@a4lg My llvm-mc patches for Zfa have been accepted and merge into llvm upstream. https://reviews.llvm.org/D140460 https://reviews.llvm.org/D141984

There are some differences between my implementation and your binutils/gcc implementation. First, it seems that you didn't support 30 and 31 as an index number for FLI while llvm-mc can accept. Second, as @topperc said, the minimum positive normal for _Float64 should be 2.2250738585072014 × 10−308. It seems that Binutils didn't add support for these minimum values.

a4lg commented 1 year ago

@joshua-arch1 LLVM experimental support is helpful but... really? Supporting two different formats (some values conflict!) seems too confusing as I mentioned earlier and I felt only supporting table index is sufficient.

Even if we do support floating point constants, I think we have to remove table index-based syntax to avoid confusion.

topperc commented 1 year ago

I removed the index support from LLVM due to it being ambiguous. Only floating point values with decimal point are supported.

a4lg commented 1 year ago

@topperc Okay, then (I am not a fan of floating point immediates but) I can understand the LLVM's position.

To be sure, I want at least @aswaterman and Kito to hear about what operand we should support for FLI (table index [as my GNU Binutils' test patchset] or floating point immediates [as LLVM's experimental support]).

aswaterman commented 1 year ago

@a4lg Sorry that I haven't had time to revisit this thread recently. I've spoken recently with both @topperc and Kito on this topic, so my input is probably redundant with theirs.

majin2020 commented 1 year ago

Although 0, min, 2-29, inf and nan are easier to implement, I think fmov instructions for such assignments should reflect specific floating-point values at the assembly level, rather than looking up tables in spec. At present, I have written a simple patch on gcc according to 0, min, 2-29, inf and nan, which may need to be improved, depending on the binutils implementation.

a4lg commented 1 year ago

@aswaterman @majin2022 @topperc Okay, I'll reflect this later (I will make my GNU Binutils patchset to support floating point immediates instead).

kito-cheng commented 1 year ago

FYI: https://github.com/riscv-non-isa/riscv-asm-manual/pull/85