https://github.com/akkartik/mu/blob/main/linux/409print-float-hex.mu

      1 # quick-n-dirty way to print out floats in hex
      2 # https://www.exploringbinary.com/hexadecimal-floating-point-constants
      3
      4 # example:
      5 #   0.5 = 0x3f000000 = 0011| 1111 | 0000 | 0000 | 0000 | 0000 | 0000 | 0000
      6 #                    = 0 | 01111110 | 00000000000000000000000
      7 #                      +   exponent   mantissa
      8 #                    = 0 | 00000000000000000000000 | 01111110
      9 #                          mantissa                  exponent
     10 #                    = 0 | 000000000000000000000000 | 01111110
     11 #                          zero-pad mantissa          exponent
     12 #                   =   +1.000000                   P -01
     13 fn test-print-float-hex-normal {
     14   var screen-on-stack: screen
     15   var screen/esi: (addr screen) <- address screen-on-stack
     16   initialize-screen screen, 5, 0x20  # 32 columns should be more than enough
     17   # 0.5
     18   var half/xmm0: float <- rational 1, 2
     19   print-float-hex screen, half
     20   check-screen-row screen, 1, "1.000000P-01 ", "F - test-print-float-hex-normal 0.5"
     21   # 0.25
     22   clear-screen screen
     23   var quarter/xmm0: float <- rational 1, 4
     24   print-float-hex screen, quarter
     25   check-screen-row screen, 1, "1.000000P-02 ", "F - test-print-float-hex-normal 0.25"
     26   # 0.75
     27   clear-screen screen
     28   var three-quarters/xmm0: float <- rational 3, 4
     29   print-float-hex screen, three-quarters
     30   check-screen-row screen, 1, "1.800000P-01 ", "F - test-print-float-hex-normal 0.75"
     31   # 0.1
     32   clear-screen screen
     33   var tenth/xmm0: float <- rational 1, 0xa
     34   print-float-hex screen, tenth
     35   check-screen-row screen, 1, "1.99999aP-04 ", "F - test-print-float-hex-normal 0.1"
     36 }
     37
     38 fn test-print-float-hex-integer {
     39   var screen-on-stack: screen
     40   var screen/esi: (addr screen) <- address screen-on-stack
     41   initialize-screen screen, 5, 0x20  # 32 columns should be more than enough
     42   # 1
     43   var one-f/xmm0: float <- rational 1, 1
     44   print-float-hex screen, one-f
     45   check-screen-row screen, 1, "1.000000P00 ", "F - test-print-float-hex-integer 1"
     46   # 2
     47   clear-screen screen
     48   var two-f/xmm0: float <- rational 2, 1
     49   print-float-hex screen, two-f
     50   check-screen-row screen, 1, "1.000000P01 ", "F - test-print-float-hex-integer 2"
     51   # 10
     52   clear-screen screen
     53   var ten-f/xmm0: float <- rational 0xa, 1
     54   print-float-hex screen, ten-f
     55   check-screen-row screen, 1, "1.400000P03 ", "F - test-print-float-hex-integer 10"
     56   # -10
     57   clear-screen screen
     58   var minus-ten-f/xmm0: float <- rational -0xa, 1
     59   print-float-hex screen, minus-ten-f
     60   check-screen-row screen, 1, "-1.400000P03 ", "F - test-print-float-hex-integer -10"
     61 }
     62
     63 fn test-print-float-hex-zero {
     64   var screen-on-stack: screen
     65   var screen/esi: (addr screen) <- address screen-on-stack
     66   initialize-screen screen, 5, 0x20  # 32 columns should be more than enough
     67   var zero: float
     68   print-float-hex screen, zero
     69   check-screen-row screen, 1, "0 ", "F - test-print-float-hex-zero"
     70 }
     71
     72 fn test-print-float-hex-negative-zero {
     73   var screen-on-stack: screen
     74   var screen/esi: (addr screen) <- address screen-on-stack
     75   initialize-screen screen, 5, 0x20  # 32 columns should be more than enough
     76   var n: int
     77   copy-to n, 0x80000000
     78   var negative-zero/xmm0: float <- reinterpret n
     79   print-float-hex screen, negative-zero
     80   check-screen-row screen, 1, "-0 ", "F - test-print-float-hex-negative-zero"
     81 }
     82
     83 fn test-print-float-hex-infinity {
     84   var screen-on-stack: screen
     85   var screen/esi: (addr screen) <- address screen-on-stack
     86   initialize-screen screen, 5, 0x20  # 32 columns should be more than enough
     87   var n: int
     88   #          0|11111111|00000000000000000000000
     89   #          0111|1111|1000|0000|0000|0000|0000|0000
     90   copy-to n, 0x7f800000
     91   var infinity/xmm0: float <- reinterpret n
     92   print-float-hex screen, infinity
     93   check-screen-row screen, 1, "Inf ", "F - test-print-float-hex-infinity"
     94 }
     95
     96 fn test-print-float-hex-negative-infinity {
     97   var screen-on-stack: screen
     98   var screen/esi: (addr screen) <- address screen-on-stack
     99   initialize-screen screen, 5, 0x20  # 32 columns should be more than enough
    100   var n: int
    101   copy-to n, 0xff800000
    102   var negative-infinity/xmm0: float <- reinterpret n
    103   print-float-hex screen, negative-infinity
    104   check-screen-row screen, 1, "-Inf ", "F - test-print-float-hex-negative-infinity"
    105 }
    106
    107 fn test-print-float-hex-not-a-number {
    108   var screen-on-stack: screen
    109   var screen/esi: (addr screen) <- address screen-on-stack
    110   initialize-screen screen, 5, 0x20  # 32 columns should be more than enough
    111   var n: int
    112   copy-to n, 0xffffffff  # exponent must be all 1's, and mantissa must be non-zero
    113   var negative-infinity/xmm0: float <- reinterpret n
    114   print-float-hex screen, negative-infinity
    115   check-screen-row screen, 1, "NaN ", "F - test-print-float-hex-not-a-number"
    116 }
    117
    118 fn print-float-hex screen: (addr screen), n: float {
    119   # - special names
    120   var bits/eax: int <- reinterpret n
    121   compare bits, 0
    122   {
    123     break-if-!=
    124     print-string screen, "0"
    125     return
    126   }
    127   compare bits, 0x80000000
    128   {
    129     break-if-!=
    130     print-string screen, "-0"
    131     return
    132   }
    133   compare bits, 0x7f800000
    134   {
    135     break-if-!=
    136     print-string screen, "Inf"
    137     return
    138   }
    139   compare bits, 0xff800000
    140   {
    141     break-if-!=
    142     print-string screen, "-Inf"
    143     return
    144   }
    145   var exponent/ecx: int <- copy bits
    146   exponent <- shift-right 0x17  # 23 bits of mantissa
    147   exponent <- and 0xff
    148   exponent <- subtract 0x7f
    149   compare exponent, 0x80
    150   {
    151     break-if-!=
    152     print-string screen, "NaN"
    153     return
    154   }
    155   # - regular numbers
    156   var sign/edx: int <- copy bits
    157   sign <- shift-right 0x1f
    158   {
    159     compare sign, 1
    160     break-if-!=
    161     print-string screen, "-"
    162   }
    163   $print-float-hex:leading-digit: {
    164     # check for subnormal numbers
    165     compare exponent, -0x7f
    166     {
    167       break-if-!=
    168       print-string screen, "0."
    169       exponent <- increment
    170       break $print-float-hex:leading-digit
    171     }
    172     # normal numbers
    173     print-string screen, "1."
    174   }
    175   var mantissa/ebx: int <- copy bits
    176   mantissa <- and 0x7fffff
    177   mantissa <- shift-left 1  # pad to whole nibbles
    178   print-int32-hex-bits screen, mantissa, 0x18
    179   # print exponent
    180   print-string screen, "P"
    181   compare exponent, 0
    182   {
    183     break-if->=
    184     print-string screen, "-"
    185   }
    186   var exp-magnitude/eax: int <- abs exponent
    187   print-int32-hex-bits screen, exp-magnitude, 8
    188 }
    189
    190 #? fn main -> _/ebx: int {
    191 #?   run-tests
    192 #? #?   test-print-float-hex-negative-zero
    193 #? #?   print-int32-hex 0, 0
    194 #? #?   test-print-float-hex-normal
    195 #?   return 0
    196 #? }