3 ; [sign] 1.[23bits] E[8bits(n-127)]
5 ; SEEEEEEE Emmmmmmm mmmmmmmm mmmmmmmm
12 ; Special values (xxx != 0):
14 ; s1111111 10000000 00000000 00000000 infinity
15 ; s1111111 1xxxxxxx xxxxxxxx xxxxxxxx NaN
16 ; s0000000 00000000 00000000 00000000 zero
17 ; s0000000 0xxxxxxx xxxxxxxx xxxxxxxx denormals
19 ; Note that CMPtype is "signed char" for rl78
28 ;; Negate the floating point value.
29 ;; Input at [SP+4]..[SP+7].
41 ;; ------------------internal functions used by later code --------------
43 START_FUNC __int_isnan
45 ;; [HL] points to value, returns Z if it's a NaN
54 ret ; return NZ if not NaN
68 START_FUNC __int_eithernan
70 ;; call from toplevel functions, returns Z if either number is a NaN,
71 ;; or NZ if both are OK.
86 END_FUNC __int_eithernan
88 START_FUNC __int_iszero
90 ;; [HL] points to value, returns Z if it's zero
101 START_FUNC __int_cmpsf
103 ;; This is always called from some other function here,
104 ;; so the stack offsets are adjusted accordingly.
106 ;; X [SP+8] <=> Y [SP+12] : <a> <=> 0
119 ;; At this point, both args are zero.
128 ;; At least one arg is non-zero so we can just compare magnitudes.
129 ;; Args are [HL] and [HL+4].
141 1: ;; Signs the same, compare magnitude. It's safe to lump
142 ;; the sign bits, exponent, and mantissa together here, since they're
143 ;; stored in the right sequence.
146 bc $ybig_cmpsf ; branch if X < Y
147 bnz $xbig_cmpsf ; branch if X > Y
151 bc $ybig_cmpsf ; branch if X < Y
152 bnz $xbig_cmpsf ; branch if X > Y
157 xbig_cmpsf: ; |X| > |Y| so return A = 1 if pos, 0xff if neg
162 ybig_cmpsf: ; |X| < |Y| so return A = 0xff if pos, 1 if neg
171 ;; ----------------------------------------------------------
174 ;; This functions calculates "A <=> B". That is, if A is less than B
175 ;; they return -1, if A is greater than B, they return 1, and if A
176 ;; and B are equal they return 0. If either argument is NaN the
177 ;; behaviour is undefined.
179 ;; Input at [SP+4]..[SP+7].
182 call $!__int_eithernan
195 ;; ----------------------------------------------------------
197 ;; These functions are all basically the same as ___cmpsf2
198 ;; except that they define how they handle NaNs.
201 ;; Returns zero iff neither argument is NaN
202 ;; and both arguments are equal.
203 START_ANOTHER_FUNC ___nesf2
204 ;; Returns non-zero iff either argument is NaN or the arguments are
205 ;; unequal. Effectively __nesf2 is the same as __eqsf2
206 START_ANOTHER_FUNC ___lesf2
207 ;; Returns a value less than or equal to zero if neither
208 ;; argument is NaN, and the first is less than or equal to the second.
209 START_ANOTHER_FUNC ___ltsf2
210 ;; Returns a value less than zero if neither argument is
211 ;; NaN, and the first is strictly less than the second.
213 ;; Input at [SP+4]..[SP+7].
220 START_ANOTHER_FUNC __int_cmp_common
222 call $!__int_eithernan
224 ;; return value (pre-filled-in below) for "either is nan"
231 END_ANOTHER_FUNC __int_cmp_common
232 END_ANOTHER_FUNC ___ltsf2
233 END_ANOTHER_FUNC ___lesf2
234 END_ANOTHER_FUNC ___nesf2
238 ;; Returns a value greater than or equal to zero if neither argument
239 ;; is a NaN and the first is greater than or equal to the second.
240 START_ANOTHER_FUNC ___gtsf2
241 ;; Returns a value greater than zero if neither argument
242 ;; is NaN, and the first is strictly greater than the second.
247 END_ANOTHER_FUNC ___gtsf2
250 ;; ----------------------------------------------------------
252 START_FUNC ___unordsf2
253 ;; Returns a nonzero value if either argument is NaN, otherwise 0.
255 call $!__int_eithernan
257 sknz ; this is from the call, not the movw
263 ;; ----------------------------------------------------------
265 START_FUNC ___fixsfsi
266 ;; Converts its floating point argument into a signed long,
267 ;; rounding toward zero.
268 ;; The behaviour with NaNs and Infinities is not well defined.
269 ;; We choose to return 0 for NaNs, -INTMAX for -inf and INTMAX for +inf.
270 ;; This matches the behaviour of the C function in libgcc2.c.
272 ;; Input at [SP+4]..[SP+7], result is in (lsb) R8..R11 (msb).
274 ;; Special case handling for infinities as __fixunssfsi
275 ;; will not give us the values that we want.
292 ;; Load the value into r10:r11:X:A
297 ;; If the value is positive we can just use __fixunssfsi
298 bf a.7, $__int_fixunssfsi
300 ;; Otherwise we negate the value, call __fixunssfsi and
301 ;; then negate its result.
303 call $!__int_fixunssfsi
314 ;; Check for a positive result (which should only happen when
315 ;; __fixunssfsi returns UINTMAX or 0). In such cases just return 0.
325 START_FUNC ___fixunssfsi
326 ;; Converts its floating point argument into an unsigned long
327 ;; rounding towards zero. Negative arguments all become zero.
328 ;; We choose to return 0 for NaNs and -inf, but UINTMAX for +inf.
329 ;; This matches the behaviour of the C function in libgcc2.c.
331 ;; Input at [SP+4]..[SP+7], result is in (lsb) R8..R11 (msb)
333 ;; Get the input value.
338 ;; Fall through into the internal function.
340 .global __int_fixunssfsi
342 ;; Input in (lsb) r10.r11.x.a (msb).
344 ;; Test for a negative input. We shift the other bits at the
345 ;; same time so that A ends up holding the whole exponent:
348 ;; SEEEEEEE EMMMMMMM MMMMMMMM MMMMMMMM
352 ;; EEEEEEEE MMMMMMM0 MMMMMMMM MMMMMMMM
362 ;; An exponent of -1 is either a NaN or infinity.
365 ;; For NaN we return 0. For infinity we return UINTMAX.
372 6: movw r8, #-1 ; -1 => UINT_MAX
376 ;; If the exponent is negative the value is < 1 and so the
377 ;; converted value is 0. Note we must allow for the bias
378 ;; applied to the exponent. Thus a value of 127 in the
379 ;; EEEEEEEE bits actually represents an exponent of 0, whilst
380 ;; a value less than 127 actually represents a negative exponent.
381 ;; Also if the EEEEEEEE bits are all zero then this represents
382 ;; either a denormal value or 0.0. Either way for these values
387 ;; A now holds the bias adjusted exponent, which is known to be >= 0.
388 ;; If the exponent is > 31 then the conversion will overflow.
392 ;; Save the exponent in H. We increment it by one because we want
393 ;; to be sure that the loop below will always execute at least once.
397 ;; Get the top 24 bits of the mantissa into A:X:R10
398 ;; Include the implicit 1-bit that is inherent in the IEEE fp format.
401 ;; EEEEEEEE MMMMMMM0 MMMMMMMM MMMMMMMM
404 ;; EEEEEEEE 1MMMMMMM MMMMMMMM MMMMMMMM
416 ;; Shift bits from the mantissa (A:X:R10) into (B:C:R12:R13),
417 ;; decrementing the exponent as we go.
420 ;; MMMMMMMM MMMMMMMM MMMMMMMM xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
421 ;; A X R10 B C R12 R13
423 ;; MMMMMMMM MMMMMMMM MMMMMMM0 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxM
424 ;; A X R10 B C R12 R13
426 ;; MMMMMMMM MMMMMMMM MMMMMM00 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxMM
427 ;; A X R10 B C R12 R13
449 ;; Result is currently in (lsb) r13.r12. c. b. (msb),
450 ;; Move it into (lsb) r8. r9. r10. r11 (msb).
466 END_FUNC ___fixunssfsi
468 ;; ------------------------------------------------------------------------
470 START_FUNC ___floatsisf
471 ;; Converts its signed long argument into a floating point.
472 ;; Argument in [SP+4]..[SP+7]. Result in R8..R11.
479 ;; Test the sign bit. If the value is positive then drop into
480 ;; the unsigned conversion routine.
483 ;; If negative convert to positive ...
493 ;; If the result is negative then the input was 0x80000000 and
494 ;; we want to return -0.0, which will not happen if we call
495 ;; __int_floatunsisf.
498 ;; Call the unsigned conversion routine.
499 call $!__int_floatunsisf
501 ;; Negate the result.
507 1: ;; Return -0.0 aka 0xcf000000
517 START_ANOTHER_FUNC ___floatunsisf
518 ;; Converts its unsigned long argument into a floating point.
519 ;; Argument in [SP+4]..[SP+7]. Result in R8..R11.
526 2: ;; Internal entry point from __floatsisf
527 ;; Input in AX (high) and BC (low)
528 .global __int_floatunsisf
531 ;; Special case handling for zero.
544 1: ;; Pre-load the loop count/exponent.
545 ;; Exponents are biased by 0x80 and we start the loop knowing that
546 ;; we are going to skip the highest set bit. Hence the highest value
547 ;; that we can get for the exponent is 0x1e (bits from input) + 0x80 = 0x9e.
550 ;; Move bits off the top of AX:BC until we hit a 1 bit.
551 ;; Decrement the count of remaining bits as we go.
559 ;; Ignore the first one bit - it is implicit in the IEEE format.
560 ;; The count of remaining bits is the exponent.
562 ;; Assemble the final floating point value. We have...
564 ;; EEEEEEEE MMMMMMMM MMMMMMMM MMMMMMMM xxxxxxxx
567 ;; 0EEEEEEE EMMMMMMM MMMMMMMM MMMMMMMM
579 ;; If the bottom bit of B was set before we shifted it out then we
580 ;; need to round the result up. Unless none of the bits in C are set.
581 ;; In this case we are exactly half-way between two values, and we
582 ;; round towards an even value. We round up by increasing the
583 ;; mantissa by 1. If this results in a zero mantissa we have to
584 ;; increment the exponent. We round down by ignoring the dropped bits.
591 5: ;; Round the mantissa up by 1.
607 END_ANOTHER_FUNC ___floatunsisf
608 END_FUNC ___floatsisf