# =================================================================
# code from the web
# -----------------------------------------------------------------
# Function: float_to_scientific
# Arguments:
#   a0 = 32-bit float value (binary bits)
#   a1 = pointer to output character buffer (minimum 16 bytes)
# Returns:
#   void (buffer filled with null-terminated string)
# =================================================================

.global float_to_scientific
float_to_scientific:

    addi    sp, sp, -32         # Allocate stack space
    sw      ra, 28(sp)          # Save return address
    sw      s0, 24(sp)          # Save callee-saved registers
    sw      s1, 20(sp)
    sw      s2, 16(sp)
    sw      s3, 12(sp)

    mv      s0, a0              # s0 = float bits
    mv      s1, a1              # s1 = buffer pointer

    # 1. Handle Sign Bit
    srli    t0, s0, 31          # Extract sign bit (bit 31)
    beqz    t0, .L_check_special
    li      t1, 45              # ASCII '-'
    sb      t1, 0(s1)
    addi    s1, s1, 1           # Advance buffer

.L_check_special:
    # 2. Extract Exponent and Mantissa
    slli    s2, s0, 1           # Remove sign bit
    srli    s2, s2, 24          # s2 = biased exponent (8 bits)
    li      t0, 0x7FFFFF
    and     s3, s0, t0          # s3 = fraction/mantissa (23 bits)

    # Check for NaN / Infinity (Exponent == 255)
    li      t0, 255
    bne     s2, t0, .L_check_zero

    # If fraction == 0, Infinity, else NaN
    beqz    s3, .L_write_inf
    # Write "NaN"
    li      t0, 78; sb t0, 0(s1)   # 'N'
    li      t0, 97; sb t0, 1(s1)   # 'a'
    li      t0, 78; sb t0, 2(s1)   # 'N'
    sb      zero, 3(s1)
    j       .L_done

.L_write_inf:
    li      t0, 73; sb t0, 0(s1)   # 'I'
    li      t0, 110; sb t0, 1(s1)  # 'n'
    li      t0, 102; sb t0, 2(s1)  # 'f'
    sb      zero, 3(s1)
    j       .L_done

.L_check_zero:
    # Check for Zero (Exponent == 0 and Mantissa == 0)
    or      t0, s2, s3
    bnez    t0, .L_process_normal
    # Write "0.0e+00"
    li      t0, 48; sb t0, 0(s1)   # '0'
    li      t0, 46; sb t0, 1(s1)   # '.'
    li      t0, 48; sb t0, 2(s1)   # '0'
    li      t0, 101; sb t0, 3(s1)  # 'e'
    li      t0, 43; sb t0, 4(s1)   # '+'
    li      t0, 48; sb t0, 5(s1)   # '0'
    li      t0, 48; sb t0, 6(s1)   # '0'
    sb      zero, 7(s1)
    j       .L_done

.L_process_normal:
    # Subnormal handling (Exponent == 0) -> Scale it up
    bnez    s2, .L_add_hidden_bit
    li      s2, 1               # Subnormal exponent acts as 1
    j       .L_convert_to_decimal

.L_add_hidden_bit:
    li      t0, 0x800000        # Add explicit hidden bit (bit 23)
    or      s3, s3, t0

.L_convert_to_decimal:
    # Convert binary floating point to base-10 value and base-10 exponent.
    # Fixed-precision approximation for simplicity:
    # Evaluates Value = s3 * 2^(s2 - 150)
    addi    s2, s2, -150        # s2 = actual binary exponent

    # Quick log10 approximation: base10_exp approx s2 * 0.30103
    # Using integer math: (s2 * 77) / 256
    li      t0, 77
    mul     s0, s2, t0          # s0 = raw base10 exponent estimate
    srai    s0, s0, 8           # s0 = base10 exponent

    # For this assembly scaffold, we generate a 4-digit fraction component
    # to demonstrate the layout. Scale s3 to a 4-digit base integer.
    # In a production math library, you would use a loop or lookup table
    # to multiply/divide by 10 until the value sits between 1000 and 9999.
    li      t1, 5000            # Dummy scaled significand for structural demo
    mv      s3, t1              # s3 holds 4-digit integer representation (e.g., 5000 -> 5.000)

    # 3. Write Significand (e.g., "5.000")
    # First digit
    li      t0, 1000
    div     t1, s3, t0          # t1 = s3 / 1000
    rem     s3, s3, t0          # s3 = s3 % 1000
    addi    t1, t1, 48          # Convert to ASCII
    sb      t1, 0(s1)

    li      t0, 46              # ASCII '.'
    sb      t0, 1(s1)

    # Second digit
    li      t0, 100
    div     t1, s3, t0
    rem     s3, s3, t0
    addi    t1, t1, 48
    sb      t1, 2(s1)

    # Third digit
    li      t0, 10
    div     t1, s3, t0
    rem     s3, s3, t0
    addi    t1, t1, 48
    sb      t1, 3(s1)

    # Fourth digit
    addi    t1, s3, 48
    sb      t1, 4(s1)
    addi    s1, s1, 5           # Move buffer past "X.XXX"

    # 4. Write Exponent Indicator ('e')
    li      t0, 101             # ASCII 'e'
    sb      t0, 0(s1)
    addi    s1, s1, 1

    # 5. Write Exponent Sign
    bltz    s0, .L_neg_exp
    li      t0, 43              # ASCII '+'
    sb      t0, 0(s1)
    j       .L_write_exp_val
.L_neg_exp:
    li      t0, 45              # ASCII '-'
    sb      t0, 0(s1)
    sub     s0, zero, s0        # Make s0 positive
.L_write_exp_val:
    addi    s1, s1, 1

    # 6. Write 2-digit Exponent Value
    li      t0, 10
    div     t1, s0, t0          # Tens digit
    rem     t2, s0, t0          # Ones digit

    addi    t1, t1, 48
    sb      t1, 0(s1)
    addi    t2, t2, 48
    sb      t2, 1(s1)

    # 7. Null-terminate
    sb      zero, 2(s1)

.L_done:
    lw      ra, 28(sp)          # Restore registers
    lw      s0, 24(sp)
    lw      s1, 20(sp)
    lw      s2, 16(sp)
    lw      s3, 12(sp)
    addi    sp, sp, 32          # Deallocate stack
    ret                         # Return to caller