https://github.com/akkartik/mu/blob/main/baremetal/412render-float-decimal.mu
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 fn test-render-float-decimal-normal {
26 var screen-on-stack: screen
27 var screen/esi: (addr screen) <- address screen-on-stack
28 initialize-screen screen, 0x20, 5
29
30 var half/xmm0: float <- rational 1, 2
31 var dummy/eax: int <- render-float-decimal screen, half, 3/precision, 0, 0, 3/fg, 0/bg
32 check-screen-row screen, 0/y, "0.5 ", "F - test-render-float-decimal-normal 0.5"
33
34 clear-screen screen
35 var quarter/xmm0: float <- rational 1, 4
36 var dummy/eax: int <- render-float-decimal screen, quarter, 3/precision, 0, 0, 3/fg, 0/bg
37 check-screen-row screen, 0/y, "0.25 ", "F - test-render-float-decimal-normal 0.25"
38
39 clear-screen screen
40 var three-quarters/xmm0: float <- rational 3, 4
41 var dummy/eax: int <- render-float-decimal screen, three-quarters, 3/precision, 0, 0, 3/fg, 0/bg
42 check-screen-row screen, 0/y, "0.75 ", "F - test-render-float-decimal-normal 0.75"
43
44 clear-screen screen
45 var eighth/xmm0: float <- rational 1, 8
46 var dummy/eax: int <- render-float-decimal screen, eighth, 3/precision, 0, 0, 3/fg, 0/bg
47 check-screen-row screen, 0/y, "0.125 ", "F - test-render-float-decimal-normal 0.125"
48
49 clear-screen screen
50 var sixteenth/xmm0: float <- rational 1, 0x10
51 var dummy/eax: int <- render-float-decimal screen, sixteenth, 3/precision, 0, 0, 3/fg, 0/bg
52 check-screen-row screen, 0/y, "6.25e-2 ", "F - test-render-float-decimal-normal 0.0625"
53
54 clear-screen screen
55 var two-f/xmm0: float <- rational 2, 1
56 var sqrt-2/xmm0: float <- square-root two-f
57 var dummy/eax: int <- render-float-decimal screen, sqrt-2, 3/precision, 0, 0, 3/fg, 0/bg
58 check-screen-row screen, 0/y, "1.414 ", "F - test-render-float-decimal-normal √2"
59 }
60
61
62 fn test-render-float-decimal-integer {
63 var screen-on-stack: screen
64 var screen/esi: (addr screen) <- address screen-on-stack
65 initialize-screen screen, 0x20, 5
66
67 var one-f/xmm0: float <- rational 1, 1
68 var dummy/eax: int <- render-float-decimal screen, one-f, 3/precision, 0, 0, 3/fg, 0/bg
69 check-screen-row screen, 0/y, "1 ", "F - test-render-float-decimal-integer 1"
70
71 clear-screen screen
72 var two-f/xmm0: float <- rational 2, 1
73 var dummy/eax: int <- render-float-decimal screen, two-f, 3/precision, 0, 0, 3/fg, 0/bg
74 check-screen-row screen, 0/y, "2 ", "F - test-render-float-decimal-integer 2"
75
76 clear-screen screen
77 var ten-f/xmm0: float <- rational 0xa, 1
78 var dummy/eax: int <- render-float-decimal screen, ten-f, 3/precision, 0, 0, 3/fg, 0/bg
79 check-screen-row screen, 0/y, "10 ", "F - test-render-float-decimal-integer 10"
80
81 clear-screen screen
82 var minus-ten-f/xmm0: float <- rational -0xa, 1
83 var dummy/eax: int <- render-float-decimal screen, minus-ten-f, 3/precision, 0, 0, 3/fg, 0/bg
84 check-screen-row screen, 0/y, "-10 ", "F - test-render-float-decimal-integer -10"
85
86 clear-screen screen
87 var minus-ten-f/xmm0: float <- rational 0x3e7, 1
88 var dummy/eax: int <- render-float-decimal screen, minus-ten-f, 3/precision, 0, 0, 3/fg, 0/bg
89 check-screen-row screen, 0/y, "999 ", "F - test-render-float-decimal-integer 1000"
90
91 clear-screen screen
92 var minus-ten-f/xmm0: float <- rational 0x3e8, 1
93 var dummy/eax: int <- render-float-decimal screen, minus-ten-f, 3/precision, 0, 0, 3/fg, 0/bg
94 check-screen-row screen, 0/y, "1.00e3 ", "F - test-render-float-decimal-integer 1000"
95
96 clear-screen screen
97 var hundred-thousand/eax: int <- copy 0x186a0
98 var hundred-thousand-f/xmm0: float <- convert hundred-thousand
99 var dummy/eax: int <- render-float-decimal screen, hundred-thousand-f, 3/precision, 0, 0, 3/fg, 0/bg
100 check-screen-row screen, 0/y, "1.00e5 ", "F - test-render-float-decimal-integer 100,000"
101 }
102
103 fn test-render-float-decimal-zero {
104 var screen-on-stack: screen
105 var screen/esi: (addr screen) <- address screen-on-stack
106 initialize-screen screen, 0x20, 5
107 var zero: float
108 var dummy/eax: int <- render-float-decimal screen, zero, 3/precision, 0, 0, 3/fg, 0/bg
109 check-screen-row screen, 0/y, "0 ", "F - test-render-float-decimal-zero"
110 }
111
112 fn test-render-float-decimal-negative-zero {
113 var screen-on-stack: screen
114 var screen/esi: (addr screen) <- address screen-on-stack
115 initialize-screen screen, 0x20, 5
116 var n: int
117 copy-to n, 0x80000000
118 var negative-zero/xmm0: float <- reinterpret n
119 var dummy/eax: int <- render-float-decimal screen, negative-zero, 3/precision, 0, 0, 3/fg, 0/bg
120 check-screen-row screen, 0/y, "-0 ", "F - test-render-float-decimal-negative-zero"
121 }
122
123 fn test-render-float-decimal-infinity {
124 var screen-on-stack: screen
125 var screen/esi: (addr screen) <- address screen-on-stack
126 initialize-screen screen, 0x20, 5
127 var n: int
128
129
130 copy-to n, 0x7f800000
131 var infinity/xmm0: float <- reinterpret n
132 var dummy/eax: int <- render-float-decimal screen, infinity, 3/precision, 0, 0, 3/fg, 0/bg
133 check-screen-row screen, 0/y, "Inf ", "F - test-render-float-decimal-infinity"
134 }
135
136 fn test-render-float-decimal-negative-infinity {
137 var screen-on-stack: screen
138 var screen/esi: (addr screen) <- address screen-on-stack
139 initialize-screen screen, 0x20, 5
140 var n: int
141 copy-to n, 0xff800000
142 var negative-infinity/xmm0: float <- reinterpret n
143 var dummy/eax: int <- render-float-decimal screen, negative-infinity, 3/precision, 0, 0, 3/fg, 0/bg
144 check-screen-row screen, 0/y, "-Inf ", "F - test-render-float-decimal-negative-infinity"
145 }
146
147 fn test-render-float-decimal-not-a-number {
148 var screen-on-stack: screen
149 var screen/esi: (addr screen) <- address screen-on-stack
150 initialize-screen screen, 0x20, 5
151 var n: int
152 copy-to n, 0xffffffff
153 var nan/xmm0: float <- reinterpret n
154 var dummy/eax: int <- render-float-decimal screen, nan, 3/precision, 0, 0, 3/fg, 0/bg
155 check-screen-row screen, 0/y, "NaN ", "F - test-render-float-decimal-not-a-number"
156 }
157
158
159 fn render-float-decimal screen: (addr screen), in: float, precision: int, x: int, y: int, color: int, background-color: int -> _/eax: int {
160
161 var bits/eax: int <- reinterpret in
162 compare bits, 0
163 {
164 break-if-!=
165 var new-x/eax: int <- draw-text-rightward-over-full-screen screen, "0", x, y, color, background-color
166 return new-x
167 }
168 compare bits, 0x80000000
169 {
170 break-if-!=
171 var new-x/eax: int <- draw-text-rightward-over-full-screen screen, "-0", x, y, color, background-color
172 return new-x
173 }
174 compare bits, 0x7f800000
175 {
176 break-if-!=
177 var new-x/eax: int <- draw-text-rightward-over-full-screen screen, "Inf", x, y, color, background-color
178 return new-x
179 }
180 compare bits, 0xff800000
181 {
182 break-if-!=
183 var new-x/eax: int <- draw-text-rightward-over-full-screen screen, "-Inf", x, y, color, background-color
184 return new-x
185 }
186 var exponent/ecx: int <- copy bits
187 exponent <- shift-right 0x17
188 exponent <- and 0xff
189 exponent <- subtract 0x7f
190 compare exponent, 0x80
191 {
192 break-if-!=
193 var new-x/eax: int <- draw-text-rightward-over-full-screen screen, "NaN", x, y, color, background-color
194 return new-x
195 }
196
197 var sign/edx: int <- copy bits
198 sign <- shift-right 0x1f
199 {
200 compare sign, 1
201 break-if-!=
202 draw-code-point screen, 0x2d/minus, x, y, color, background-color
203 increment x
204 }
205
206
207 var v/ebx: int <- copy bits
208 v <- and 0x7fffff
209 v <- or 0x00800000
210
211 var e/ecx: int <- copy exponent
212 e <- subtract 0x17
213
214
215
216 var buf-storage: (array byte 0x7f)
217 var buf/edi: (addr array byte) <- address buf-storage
218 var n/eax: int <- decimal-digits v, buf
219
220
221 reverse-digits buf, n
222
223
224 {
225 compare e, 0
226 break-if-<=
227 n <- double-array-of-decimal-digits buf, n
228 e <- decrement
229 loop
230 }
231
232 var dp/edx: int <- copy n
233
234
235 {
236 compare e, 0
237 break-if->=
238 n, dp <- halve-array-of-decimal-digits buf, n, dp
239 e <- increment
240 loop
241 }
242
243 var new-x/eax: int <- render-float-buffer screen, buf, n, dp, precision, x, y, color, background-color
244 return new-x
245 }
246
247
248
249 fn decimal-digits n: int, _buf: (addr array byte) -> _/eax: int {
250 var buf/edi: (addr array byte) <- copy _buf
251 var i/ecx: int <- copy 0
252 var curr/eax: int <- copy n
253 var curr-byte/edx: int <- copy 0
254 {
255 compare curr, 0
256 break-if-=
257 curr, curr-byte <- integer-divide curr, 0xa
258 var dest/ebx: (addr byte) <- index buf, i
259 copy-byte-to *dest, curr-byte
260 i <- increment
261 loop
262 }
263 return i
264 }
265
266 fn reverse-digits _buf: (addr array byte), n: int {
267 var buf/esi: (addr array byte) <- copy _buf
268 var left/ecx: int <- copy 0
269 var right/edx: int <- copy n
270 right <- decrement
271 {
272 compare left, right
273 break-if->=
274 {
275 var l-a/ecx: (addr byte) <- index buf, left
276 var r-a/edx: (addr byte) <- index buf, right
277 var l/ebx: byte <- copy-byte *l-a
278 var r/eax: byte <- copy-byte *r-a
279 copy-byte-to *l-a, r
280 copy-byte-to *r-a, l
281 }
282 left <- increment
283 right <- decrement
284 loop
285 }
286 }
287
288 fn double-array-of-decimal-digits _buf: (addr array byte), _n: int -> _/eax: int {
289 var buf/edi: (addr array byte) <- copy _buf
290
291 var delta/edx: int <- copy 0
292 {
293 var curr/ebx: (addr byte) <- index buf, 0
294 var tmp/eax: byte <- copy-byte *curr
295 compare tmp, 5
296 break-if-<
297 delta <- copy 1
298 }
299
300 var x/eax: int <- copy 0
301 var i/ecx: int <- copy _n
302 i <- decrement
303 {
304 compare i, 0
305 break-if-<=
306
307 {
308 var tmp/ecx: (addr byte) <- index buf, i
309 var tmp2/ecx: byte <- copy-byte *tmp
310 x <- add tmp2
311 x <- add tmp2
312 }
313
314 {
315 var dest-index/ecx: int <- copy i
316 dest-index <- add delta
317 var dest/edi: (addr byte) <- index buf, dest-index
318 var next-digit/edx: int <- copy 0
319 x, next-digit <- integer-divide x, 0xa
320 copy-byte-to *dest, next-digit
321 }
322
323 i <- decrement
324 loop
325 }
326
327 var n/eax: int <- copy _n
328 compare delta, 1
329 {
330 break-if-!=
331 var curr/ebx: (addr byte) <- index buf, 0
332 var one/edx: int <- copy 1
333 copy-byte-to *curr, one
334 n <- increment
335 }
336 return n
337 }
338
339 fn halve-array-of-decimal-digits _buf: (addr array byte), _n: int, _dp: int -> _/eax: int, _/edx: int {
340 var buf/edi: (addr array byte) <- copy _buf
341 var n/eax: int <- copy _n
342 var dp/edx: int <- copy _dp
343
344 {
345
346 var right-index/ecx: int <- copy n
347 right-index <- decrement
348 var right-a/ecx: (addr byte) <- index buf, right-index
349 var right/ecx: byte <- copy-byte *right-a
350 var right-int/ecx: int <- copy right
351 var remainder/edx: int <- copy 0
352 {
353 var dummy/eax: int <- copy 0
354 dummy, remainder <- integer-divide right-int, 2
355 }
356 compare remainder, 0
357 break-if-=
358
359 var next-a/ecx: (addr byte) <- index buf, n
360 var zero/edx: byte <- copy 0
361 copy-byte-to *next-a, zero
362
363 n <- increment
364 }
365
366 var delta/ebx: int <- copy 0
367 var x/esi: int <- copy 0
368 {
369
370 var left/ecx: (addr byte) <- index buf, 0
371 var src/ecx: byte <- copy-byte *left
372 compare src, 2
373 break-if->=
374
375 delta <- copy 1
376 x <- copy src
377
378 n <- decrement
379
380 dp <- decrement
381 }
382
383 var i/ecx: int <- copy 0
384 {
385 compare i, n
386 break-if->=
387
388 {
389 var ten/edx: int <- copy 0xa
390 x <- multiply ten
391 var src-index/edx: int <- copy i
392 src-index <- add delta
393 var src-a/edx: (addr byte) <- index buf, src-index
394 var src/edx: byte <- copy-byte *src-a
395 x <- add src
396 }
397
398 {
399 var quotient/eax: int <- copy 0
400 var remainder/edx: int <- copy 0
401 quotient, remainder <- integer-divide x, 2
402 x <- copy remainder
403 var dest/edx: (addr byte) <- index buf, i
404 copy-byte-to *dest, quotient
405 }
406
407 i <- increment
408 loop
409 }
410 return n, dp
411 }
412
413 fn render-float-buffer screen: (addr screen), _buf: (addr array byte), n: int, dp: int, precision: int, x: int, y: int, color: int, background-color: int -> _/eax: int {
414 var buf/edi: (addr array byte) <- copy _buf
415 {
416 compare dp, 0
417 break-if->=
418 var new-x/eax: int <- render-float-buffer-in-scientific-notation screen, buf, n, dp, precision, x, y, color, background-color
419 return new-x
420 }
421 {
422 var dp2/eax: int <- copy dp
423 compare dp2, precision
424 break-if-<=
425 var new-x/eax: int <- render-float-buffer-in-scientific-notation screen, buf, n, dp, precision, x, y, color, background-color
426 return new-x
427 }
428 {
429 compare dp, 0
430 break-if-!=
431 draw-code-point screen, 0x30/0, x, y, color, background-color
432 increment x
433 }
434 var i/eax: int <- copy 0
435
436 var limit/edx: int <- copy dp
437 limit <- add 3
438 {
439 compare limit, n
440 break-if-<=
441 limit <- copy n
442 }
443 {
444 compare i, limit
445 break-if->=
446
447 compare i, dp
448 {
449 break-if-!=
450 draw-code-point screen, 0x2e/decimal-point, x, y, color, background-color
451 increment x
452 }
453 var curr-a/ecx: (addr byte) <- index buf, i
454 var curr/ecx: byte <- copy-byte *curr-a
455 curr <- add 0x30/0
456 var curr-grapheme/ecx: grapheme <- copy curr
457 draw-grapheme screen, curr-grapheme, x, y, color, background-color
458 increment x
459 i <- increment
460 loop
461 }
462 return x
463 }
464
465 fn render-float-buffer-in-scientific-notation screen: (addr screen), _buf: (addr array byte), n: int, dp: int, precision: int, x: int, y: int, color: int, background-color: int -> _/eax: int {
466 var buf/edi: (addr array byte) <- copy _buf
467 var i/eax: int <- copy 0
468 {
469 compare i, n
470 break-if->=
471 compare i, precision
472 break-if->=
473 compare i, 1
474 {
475 break-if-!=
476 draw-code-point screen, 0x2e/decimal-point, x, y, color, background-color
477 increment x
478 }
479 var curr-a/ecx: (addr byte) <- index buf, i
480 var curr/ecx: byte <- copy-byte *curr-a
481 curr <- add 0x30/0
482 var curr-grapheme/ecx: grapheme <- copy curr
483 draw-grapheme screen, curr-grapheme, x, y, color, background-color
484 increment x
485
486 i <- increment
487 loop
488 }
489 draw-code-point screen, 0x65/e, x, y, color, background-color
490 increment x
491 decrement dp
492 var new-x/eax: int <- copy 0
493 var new-y/ecx: int <- copy 0
494 new-x, new-y <- draw-int32-decimal-wrapping-right-then-down-over-full-screen screen, dp, x, y, color, background-color
495 return new-x
496 }
497
498
499
500 fn float-size in: float, precision: int -> _/eax: int {
501
502 var bits/eax: int <- reinterpret in
503 compare bits, 0
504 {
505 break-if-!=
506 return 1
507 }
508 compare bits, 0x80000000
509 {
510 break-if-!=
511 return 2
512 }
513 compare bits, 0x7f800000
514 {
515 break-if-!=
516 return 3
517 }
518 compare bits, 0xff800000
519 {
520 break-if-!=
521 return 4
522 }
523 var exponent/ecx: int <- copy bits
524 exponent <- shift-right 0x17
525 exponent <- and 0xff
526 exponent <- subtract 0x7f
527 compare exponent, 0x80
528 {
529 break-if-!=
530 return 3
531 }
532
533
534 var v/ebx: int <- copy bits
535 v <- and 0x7fffff
536 v <- or 0x00800000
537
538 var e/ecx: int <- copy exponent
539 e <- subtract 0x17
540
541
542 var buf-storage: (array byte 0x7f)
543 var buf/edi: (addr array byte) <- address buf-storage
544 var n/eax: int <- decimal-digits v, buf
545 reverse-digits buf, n
546
547
548 {
549 compare e, 0
550 break-if-<=
551 n <- double-array-of-decimal-digits buf, n
552 e <- decrement
553 loop
554 }
555
556 var dp/edx: int <- copy n
557
558
559 {
560 compare e, 0
561 break-if->=
562 n, dp <- halve-array-of-decimal-digits buf, n, dp
563 e <- increment
564 loop
565 }
566
567 compare dp, 0
568 {
569 break-if->=
570 return 8
571 }
572 {
573 var dp2/eax: int <- copy dp
574 compare dp2, precision
575 break-if-<=
576 return 8
577 }
578
579
580 var result/ecx: int <- copy dp
581 result <- add 3
582 {
583 compare result, n
584 break-if-<=
585 result <- copy n
586 }
587
588
589 compare dp, n
590 {
591 break-if->=
592 result <- increment
593 }
594
595
596 var sign/edx: int <- reinterpret in
597 sign <- shift-right 0x1f
598 {
599 compare sign, 1
600 break-if-!=
601 result <- increment
602 }
603 return result
604 }