hlorenzi / customasm

💻 An assembler for custom, user-defined instruction sets! https://hlorenzi.github.io/customasm/web/
Apache License 2.0
719 stars 56 forks source link

(Ease of Use) IEEE-754 32 and 64 bit decimal values in assembler #92

Open MSlockbo opened 3 years ago

MSlockbo commented 3 years ago

This is not exactly a necessary feature.

It seems there is not exactly a good way of representing a floating point value in the Assembler without converting it to a hex value first.

Say I wanted to do something such as this: mov r1, #1.1

The assembler does not recognize 1.1 as a valid value so to store it correctly I would have to store it like this: mov r1, #0x3f8ccccd ; hexadecimal IEEE-754 32-bit representation of 1.1

I don't know how easy this will be to implement with the assembler since mov r1, #1.1 is ambiguous with it's bit depth.

Fortunately most instruction sets do not actually support commands like this or have type specifiers such as ARM with vmul.f32 and vmul.f64. I think a good starting point would be to add a data directive for it. So for example:

; code:
#df32 1.1
#df64 1.1

; output:
3F 8C CC CD
3F F1 99 99 99 99 99 9A

This would at least allow easily defining a float in memory and then being able to move it around. This would also work really well with x86 for example which does not allow floating point operations on registers and it's floating point operations take memory locations.

hlorenzi commented 3 years ago

Yeah, this is why I've been putting off fractional number support. Another issue is that there's the split between fixed- and floating-point representations, so we'd need more ways to disambiguate between the two. Maybe we should be using suffixes to specify the format? Such as:

#d 1.1_f32 ; IEEE 32-bit float
#d 2.2_f64 ; IEEE 64-bit float
#d 3.3_fx16p16 ; 16.16 fixed-point
#d 4.4_fs3p28 ; custom signed 3-bit exponent 28-bit mantissa floating-point format?!

It gets complicated very quickly. What if you need to convert between formats, or do arithmetic? I'd need a whole custom floating-point arithmetic library to handle these. We could also ignore these extra features and just implement basic literal support, which the assembler could simply reinterpret as integers internally.

Or maybe all fractional literals could be infinite-precision (like integer literals already are), and you must use "function syntax" to convert them down to a fixed-size representation before using them elsewhere. Like so:

#d f32(1.5)
#d f64(0x12ab.34cd)
MSlockbo commented 3 years ago

If you make all fractional literals infinite precision, reducing them down into each format isn't as bad as having to interpret each one differently. You could also support multiple custom formats like say for whatever reason I wanted to do make an unsigned 16 bit float with a 4 bit exponent and 12 bit mantissa, or a 32 bit fixed precision with an 8 bit int and 24 bit fraction.

You could probably get away with reading in the decimal and fraction parts separately using f64s and then when a conversion comes along run a bit conversion using the two.

I did do a little bit of reading on this and parsing these values is a lot trickier than I thought it was. I was only really thinking of the IEEE format since that is supported natively by rust.

MSlockbo commented 3 years ago

The only issue I would see is whether to prioritize the int part or the fraction part when converting.

If you prioritize the int part all you have to do to combine two IEEE 64 into one IEEE 32 or 64 or whatever format float it is, fit the integer part into the new storage type first and then shift the fraction right by the difference in exponents, then run a logical or with the two mantissas.

To do this with a fixed precision value you just slap the mantissa bits of the fraction part shifted by the exponent into the right hand side of the result and convert the int part into an i64 and slap that into the left hand side of the result.

soweli-Luna commented 3 years ago

what about a way users could define their own formats? you could have something similar to #ruledef to define a custom data format which could allow users to do whatever bit manipulation or arithmetic they need to represent whatever data format they want.. certainly not the most convenient method, but it would be extremely versatile

ProxyPlayerHD commented 3 years ago

what about a way users could define their own formats? you could have something similar to #ruledef to define a custom data format which could allow users to do whatever bit manipulation or arithmetic they need to represent whatever data format they want.. certainly not the most convenient method, but it would be extremely versatile

that would be awesome as you could also have custom pre/sufixes for binary, hexadecimal, decimal, etc

soweli-Luna commented 3 years ago

what about a way users could define their own formats? you could have something similar to #ruledef to define a custom data format which could allow users to do whatever bit manipulation or arithmetic they need to represent whatever data format they want.. certainly not the most convenient method, but it would be extremely versatile

that would be awesome as you could also have custom pre/sufixes for binary, hexadecimal, decimal, etc

I think he's implementing it

I suggested it again in #93 and he expressed interest and now hasn't said anything for 15 days, which I think means he's thinking of how it could be implemented