|GBDK libraries documentation|
|Prev||Chapter 5. Libraries||Next|
The number encoding used in GBDK was chosen make fp operations easier to implement. Unfortunatly it doesnt conform to any standards but it does help speed the routines. The high byte contains the sign and exponent, while the lower three bytes contain the mantissa.
The most significant bit of the exponent is the sign bit which is set if the number is negative. The lower seven bits are the exponent biased around 0x40. The mantissa is normalised and includes the normally implicit one in the most significant bit. Note that the mantissa for a negative number is not in twos complement. A zero is represented by either by both the mantissa and exponent being zero.
41 800000 - sign = 0 (positive), exponent equals 2^(0x41-0x40) = 2^1 = 2, mantissa = 0.800000 = 0.5 so the number is +1 * 2 * 0.5 or '1'
C4 A00000 - sign = 1 (negative), exponent equals 2^(0x44-0x40) = 2^(4) = 16, mantissa = 0.A00000 = 0.625 so the number is -1 * 16 * 0.625 or '-10'
The core floating point library functions fadd, fdiv, fsub and fmul were originally based on the algorithims in HI-TECH Software 's free CP/M C compiler. However the code has been almost completly re-written and optimised and now only bears a passing resemblance to HI-TECH's code.
The left hand argument to a function is stored in HLDE and the right hand on the top of the stack. Most functions use static scratch registers in RAM which unfortunatly means that they arnt re-enterant. As almost all of the functions in this section take floats as parameters and return floats, the format is different to the following sections.
Perform a floating point addition on HLDE and the floating point number on the stack, returining the result in HLDE with the stack number removed.
The two operands are recovered and the stack unjunked. The sign is removed from both operands and the magnitudes compared. If the difference in magnitude is greater than 24 bits then the greater number is returned. If not, the smaller number is shifted right and its magnitude increased until both have the same magnitude. If an operand was originally negative, its magnitude is negated. The magnitudes are added and the new mantissa computed.
Subtract the floating point number on the stack from the value in HLDE, returning the result in HLDE
The sign bit on the stack operand is toggled which negates the right operand. Execution then falls through to .fadd32
Performs a floating point multiplication on the number in HLDE and the one on the stack. Returns the result in HLDE with the stack operand removed.
The product is stored in HLBC, the right hand operand in DE.ft1.ft0 and the left hand operand in .fw. First the product is zeroed then a multiplication is done on the mantissas of the two operands. The multiply is a standard (right shift - add if carry) but uses a few tricks to keep the result within 32 bits instead of the maximum 48. HLDE is then shifted down until H is zero. The number of shifts is added to the exponents of the two operands to give the resultant exponent. Finally the sign bit is computed by a XOR of the signs of the operands.
Divide the floating point number in HLDE by the value on the stack. Return witht the result in HLDE and the stack unjunked.
The divisor is stored in HLBC, the dividend in DE.fw1.fw0 and the quotent in .q. The mantissa of the dividend is divided by the mantissa of the divisor. This uses the standard compare - subtract if less than - multiply by two method. The quotient is then copied into HLDE and rotated right until H is zero. The exponent is calculated by adding the number of shifts to the exponent of the left operand and subtracting the exponent of the right operand. The sign bit is calculated using an XOR of the sign of the operands.
|Libraries||Up||Full screen graphics - drawing.h|