The Optimization: Exploiting the Format

In standard integer math, multiplying by a power of two is done with a fast left shift (`SLA′). In floating-point math (Part 30), a multiplication or division by a power of two (like $2^N$ or $2^{-N}$) is even faster: it requires no change to the Mantissa (precision) and only a simple addition or subtraction to the Exponent.

The Rule:

  • Multiplication by $2^N$: Add $N$ to the Exponent.
  • Division by $2^N$: Subtract $N$ from the Exponent.

The Exponent Field

Recall that the exponent is usually stored as a biased 8-bit integer (e.g., a bias of 127 is added to the true exponent). Adjusting the number simply means adjusting this byte.

Example: Multiplying by 4 ($2^2$): You add 2 to the Exponent byte.

Z80 Implementation: Multiplication

The routine is short and extremely fast, making it one of the most optimized routines in a Z80 floating-point library.

The Steps (Simplified):

  1. Read the Exponent byte.
  2. Add the desired power of two ($N$).
  3. Write the Exponent byte back.
FLOAT_ADDR EQU 8000H         ; Assume float starts at 8000H
EXPONENT_OFFSET EQU 03H      ; Assume exponent is at offset +3

MULTIPLY_BY_FOUR:
    ; Multiply float at 8000H by 4 (i.e., add 2 to the exponent)
    
    LD   HL, FLOAT_ADDR + EXPONENT_OFFSET ; HL ← Address of the exponent byte
    LD   A, (HL)             ; A ← Current Exponent
    
    ADD  A, 02H              ; A ← Exponent + 2 (Multiplication by 4)
    
    LD   (HL), A             ; Store the new Exponent back to memory
    RET

Z80 Implementation: Division

Division by a power of two is handled identically, but you use the SUB′ or SBC′ (Subtract with Carry) instruction to decrement the exponent.

Example: Dividing by 8 ($2^3$): You subtract 3 from the Exponent byte.

DIVIDE_BY_EIGHT:
    LD   HL, FLOAT_ADDR + EXPONENT_OFFSET
    LD   A, (HL)             ; A ← Current Exponent
    
    SUB  03H                 ; A ← Exponent - 3 (Division by 8)
    
    LD   (HL), A             ; Store the new Exponent
    RET

Error Checking (Overflow/Underflow)

The only required error check is overflow (exponent becomes too large) or underflow (exponent becomes too negative, resulting in zero). The carry flag must be checked after the addition/subtraction to ensure the exponent did not wrap around (overflow/underflow).