https://github.com/akkartik/mu/blob/master/408print-float.mu
  1 # quick-n-dirty way to print out floats in hex
  2 
  3 # examples:
  4 #   0.5 = 0x3f000000 = 0011| 1111 | 0000 | 0000 | 0000 | 0000 | 0000 | 0000
  5 #                    = 0 | 01111110 | 00000000000000000000000
  6 #                      +   exponent   mantissa
  7 #                    = 0 | 00000000000000000000000 | 01111110
  8 #                          mantissa                  exponent
  9 #                    = 0 | 000000000000000000000000 | 01111110
 10 #                          zero-pad mantissa          exponent
 11 #                   =   +1.000000                   P -01
 12 fn test-print-float-normal {
 13   var screen-on-stack: screen
 14   var screen/esi: (addr screen) <- address screen-on-stack
 15   initialize-screen screen, 5, 0x20  # 32 columns should be more than enough
 16   # print 0.5
 17   var one/eax: int <- copy 1
 18   var half/xmm0: float <- convert one
 19   var two/eax: int <- copy 2
 20   var two-f/xmm1: float <- convert two
 21   half <- divide two-f
 22   print-float screen, half
 23   #
 24   check-screen-row screen, 1, "1.000000P-01 ", "F - test-print-float-normal"
 25 }
 26 
 27 fn test-print-float-zero {
 28   var screen-on-stack: screen
 29   var screen/esi: (addr screen) <- address screen-on-stack
 30   initialize-screen screen, 5, 0x20  # 32 columns should be more than enough
 31   # print 0
 32   var zero: float
 33   print-float screen, zero
 34   #
 35   check-screen-row screen, 1, "0 ", "F - test-print-float-zero"
 36 }
 37 
 38 fn test-print-float-negative-zero {
 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   # print 0
 43   var n: int
 44   copy-to n, 0x80000000
 45   var negative-zero/xmm0: float <- reinterpret n
 46   print-float screen, negative-zero
 47   #
 48   check-screen-row screen, 1, "-0 ", "F - test-print-float-negative-zero"
 49 }
 50 
 51 fn test-print-float-infinity {
 52   var screen-on-stack: screen
 53   var screen/esi: (addr screen) <- address screen-on-stack
 54   initialize-screen screen, 5, 0x20  # 32 columns should be more than enough
 55   # print
 56   var n: int
 57   #          0|11111111|00000000000000000000000
 58   #          0111|1111|1000|0000|0000|0000|0000|0000
 59   copy-to n, 0x7f800000
 60   var infinity/xmm0: float <- reinterpret n
 61   print-float screen, infinity
 62   #
 63   check-screen-row screen, 1, "Inf ", "F - test-print-float-infinity"
 64 }
 65 
 66 fn test-print-float-negative-infinity {
 67   var screen-on-stack: screen
 68   var screen/esi: (addr screen) <- address screen-on-stack
 69   initialize-screen screen, 5, 0x20  # 32 columns should be more than enough
 70   # print
 71   var n: int
 72   copy-to n, 0xff800000
 73   var negative-infinity/xmm0: float <- reinterpret n
 74   print-float screen, negative-infinity
 75   #
 76   check-screen-row screen, 1, "-Inf ", "F - test-print-float-negative-infinity"
 77 }
 78 
 79 fn test-print-float-not-a-number {
 80   var screen-on-stack: screen
 81   var screen/esi: (addr screen) <- address screen-on-stack
 82   initialize-screen screen, 5, 0x20  # 32 columns should be more than enough
 83   # print
 84   var n: int
 85   copy-to n, 0xffffffff  # exponent must be all 1's, and mantissa must be non-zero
 86   var negative-infinity/xmm0: float <- reinterpret n
 87   print-float screen, negative-infinity
 88   #
 89   check-screen-row screen, 1, "Nan ", "F - test-print-float-not-a-number"
 90 }
 91 
 92 fn print-float screen: (addr screen), n: float {
 93 $print-float:body: {
 94   # - special names
 95   var bits/eax: int <- reinterpret n
 96   compare bits, 0
 97   {
 98     break-if-!=
 99     print-string screen, "0"
100     break $print-float:body
101   }
102   compare bits, 0x80000000
103   {
104     break-if-!=
105     print-string screen, "-0"
106     break $print-float:body
107   }
108   compare bits, 0x7f800000
109   {
110     break-if-!=
111     print-string screen, "Inf"
112     break $print-float:body
113   }
114   compare bits, 0xff800000
115   {
116     break-if-!=
117     print-string screen, "-Inf"
118     break $print-float:body
119   }
120   var exponent/ecx: int <- copy bits
121   exponent <- shift-right 0x17  # 23 bits of mantissa
122   exponent <- and 0xff
123   compare exponent, 0xff
124   {
125     break-if-!=
126     print-string screen, "Nan"
127     break $print-float:body
128   }
129   # - regular numbers
130   var sign/edx: int <- copy bits
131   sign <- shift-right 0x1f
132   {
133     compare sign, 1
134     break-if-!=
135     print-string screen, "-"
136   }
137   $print-float:leading-digit: {
138     # check for subnormal numbers
139     compare exponent, 0
140     {
141       break-if-!=
142       print-string screen, "0."
143       exponent <- increment
144       break $print-float:leading-digit
145     }
146     # normal numbers
147     print-string screen, "1."
148   }
149   var mantissa/ebx: int <- copy bits
150   mantissa <- and 0x7fffff
151   print-int32-hex-bits screen, mantissa, 0x18
152   # print exponent
153   print-string screen, "P"
154   exponent <- subtract 0x7f
155   compare exponent, 0
156   {
157     break-if->=
158     print-string screen, "-"
159   }
160   var exp-magnitude/eax: int <- abs exponent
161   print-int32-hex-bits screen, exp-magnitude, 8
162 }
163 }
164 
165 #? fn main -> r/ebx: int {
166 #?   run-tests
167 #? #?   test-print-float-negative-zero
168 #? #?   print-int32-hex 0, 0
169 #? #?   test-print-float-normal
170 #?   r <- copy 0
171 #? }