Convert Hex Integer to 32 bit Float (ASM)
Here's a little snippet of PPC ASM I made that will convert your Hex integer to a IEEE-754 32 bit standard Float

The integer can only be a byte or halfword, and it must NOT be negative.

Implementing negatives (neg. halfs and bytes) shouldn't be that difficult. However, adding the ability to do words too, may be a bit of a pain.

This is written to be as a subroutine (via a function call), you will need to add LR storage plus stack pushing and popping.

Args: r3 = Integer to convert
Return Value: r3 = the Float, or -1 for error

Raw ASM:
5464001F 40A20030
38A0001F 38C0007F
7C640034 7CE42850
7D263A14 5529B810
20870017 7C632030
5463027E 7D231B78
48000008 3860FFFF

# Check For Negative Value, and Check if Halfword/Byte wasn't Used #

clrrwi. r4, r3, 16
bne+ skip_conversion #Not doing words or negative values

# Set Static Register Values #

li r5, 31 #Used for formula to calculate amount to add to the Bias
li r6, 127 #This is the IEEE 754 Bias Standard

# Start Conversion, Count Leading Zeros, Give Variable of Bias Equation #

cntlzw r4, r3 #Count the leading zeros til first 1
subf r7, r4, r5 #This will give us the amount to add to the Bias

# Calculate Final Bias, Store Bias to Bits 1 thru 8 #

add r9, r6, r7 #Add to bias
slwi r9, r9, 23 #Shift the Bias over to bits 1 thru 8, bit 0 is reserved

# Calculate where to Store Fraction Bits at Beginning of Mantissa #

subfic r4, r7, 23 #This will give amount of left-hand shift to place fraction bits at beginning of mantissa
slw r3, r3, r4 #Execute the shift
clrlwi r3, r3, 9 #Get rid of possible '1' bit that is left in bit 8's spot

# Final Step, Insert the Mantissa Bits #

or r3, r9, r3 #Place Mantissa bits with all other bits now. Use logical OR to not erase all of our progress
b the_end

li r3, -1

This is cool
Super Mario Eclipse, what Super Mario Sunshine could've been.
If you want a crack at this to put in negative values, you need to subtract FROM the bias (instead of adding to it). Then you need implement adding in the sign bit (bit 0 being the value 1) to the final result. This may cause some shifting issues that will need to be adjusted.
The PowerPC Compiler Writer's Guide contains a number of helpful algorithms, including a conversion for 32-bit signed integer to float, so any integer between 0x80000000 and 0x7FFFFFFF is supported. I modified that code to work by itself and then turned it into a proper function:

lis r4, 0x4330
stw r4, -0x8 (r1)
lis r4, 0x8000
stw r4, -0x4 (r1)
lfd f2, -0x8 (r1) # load magic double into f2
xoris r3, r3, 0x8000 # flip sign bit
stw r3, -0x4 (r1) # store lower half (upper half already stored)
lfd f1, -0x8 (r1)
fsub f1, f1, f2 # complete conversion

The parameter for this function (passed via r3) would be the integer you wish to convert, and the return value (placed in f1) would be the converted float.

Also note that I used the red zone (area beneath the stack) to store/load values temporarily, this is safe to do in this case as no function calls exist between the store and load operations.

To be fair, your code is definitely more clever than mine, as you actually bothered to learn how floats work instead of just copying code from the web. However, since this one works for negative values and words, I thought it would be useful too.
Nice! That compilers guide is amazing. Thank you for the link. I'll add it to the ASM Links/References thread in the Resources sub forum.
(08-23-2019, 01:38 AM)Vega Wrote: Nice! That compilers guide is amazing. Thank you for the link. I'll add it to the ASM Links/References thread in the Resources sub forum.
I agree. Also, it is likely that Mario Kart Wii uses functions similar to the ones from that guide, so perhaps using Ghidra you could find the actual addresses of those functions in memory.

Forum Jump:

Users browsing this thread: 1 Guest(s)