Instruction Syntax
Mnemonic | Format | Flags |
fmsub | frD,frA,frC,frB | Rc = 0 |
fmsub. | frD,frA,frC,frB | Rc = 1 |
Instruction Encoding
Field | Bits | Description |
Primary Opcode | 0-5 | 111111 (0x3F) |
frD | 6-10 | Destination floating-point register |
frA | 11-15 | Source floating-point register A (multiplicand) |
frB | 16-20 | Source floating-point register B (subtrahend) |
frC | 21-25 | Source floating-point register C (multiplier) |
XO | 26-30 | 11100 (28) |
Rc | 31 | Record Condition Register |
Operation
frD ← (frA × frC) - frB
The contents of floating-point register frA are multiplied by the contents of floating-point register frC. The contents of floating-point register frB are then subtracted from this intermediate product. The result is placed into floating-point register frD.
Note: This is a fused multiply-subtract operation. The intermediate product (frA × frC) is computed to infinite precision and is not rounded before subtracting frB. Only one rounding operation occurs, at the end, which provides higher accuracy than separate multiply and subtract operations. This instruction is essential for high-performance computing and numerical algorithms.
Affected Registers
Condition Register (CR1 field)
(if Rc = 1)
- Reflects floating-point exception summary and status
Floating-Point Status and Control Register (FPSCR)
Affected fields:
- FPRF (Floating-Point Result Flags)
- FX (Floating-Point Exception Summary)
- OX (Overflow Exception)
- UX (Underflow Exception)
- XX (Inexact Exception)
- VXISI (Invalid Operation Exception for ∞ - ∞)
- VXIMZ (Invalid Operation Exception for 0 × ∞)
- FR (Fraction Rounded)
- FI (Fraction Inexact)
For more information on floating-point status see Section 2.1.4, "Floating-Point Status and Control Register (FPSCR)," in the PowerPC Microprocessor Family: The Programming Environments manual.
Examples
Basic Multiply-Subtract Operation
lfd f1, multiplicand(r0) # Load multiplicand (A) lfd f2, subtrahend(r0) # Load subtrahend (B) lfd f3, multiplier(r0) # Load multiplier (C) fmsub f4, f1, f3, f2 # f4 = (f1 × f3) - f2 stfd f4, result(r0) # Store result
Digital Signal Processing: Biquad Filter
# Biquad filter coefficient application with subtraction # y[n] = b₀×x[n] + state - a₁×y[n-1] lfd f1, b0_coeff(r0) # Load b₀ coefficient lfd f2, input_sample(r0) # Load input x[n] lfd f3, filter_state(r0) # Load filter state lfd f4, a1_coeff(r0) # Load a₁ coefficient lfd f5, prev_output(r0) # Load y[n-1] fmsub f6, f1, f2, f0 # f6 = b₀ × x[n] - 0 = b₀ × x[n] fadd f6, f6, f3 # f6 = b₀×x[n] + state fmsub f7, f4, f5, f6 # f7 = f6 - a₁×y[n-1] stfd f7, output_sample(r0) # Store y[n]
3D Graphics: Distance Calculation
# Calculate squared distance with optimization: d² = (x₁-x₂)² + (y₁-y₂)² + (z₁-z₂)² # Using fmsub for: d² = x₁² - 2×x₁×x₂ + x₂² (part of distance formula) lfd f1, point1_x(r0) # Load x₁ lfd f2, point1_y(r0) # Load y₁ lfd f3, point1_z(r0) # Load z₁ lfd f4, point2_x(r0) # Load x₂ lfd f5, point2_y(r0) # Load y₂ lfd f6, point2_z(r0) # Load z₂ lfd f7, two_constant(r0) # Load 2.0 fmul f8, f1, f1 # f8 = x₁² fmul f9, f4, f4 # f9 = x₂² fmsub f10, f7, f1, f8 # f10 = f8 - 2×x₁ (partial calculation) # Continue with complete distance calculation...
Physics: Force Calculation
# Calculate net force: F_net = ma - friction # F_net = mass × acceleration - friction_coefficient × normal_force lfd f1, mass(r0) # Load mass lfd f2, acceleration(r0) # Load acceleration lfd f3, friction_coeff(r0) # Load friction coefficient lfd f4, normal_force(r0) # Load normal force fmsub f5, f1, f2, f0 # f5 = mass × acceleration - 0 fmsub f6, f3, f4, f5 # f6 = f5 - friction_coeff × normal_force stfd f6, net_force(r0) # Store net force
Financial Calculation: Loan Payment
# Calculate remaining balance: new_balance = old_balance × (1 + rate) - payment lfd f1, old_balance(r0) # Load current balance lfd f2, interest_rate(r0) # Load interest rate lfd f3, payment(r0) # Load payment amount lfd f4, one_constant(r0) # Load 1.0 fadd f5, f4, f2 # f5 = 1 + rate fmsub f6, f1, f5, f3 # f6 = old_balance × (1 + rate) - payment stfd f6, new_balance(r0) # Store new balance
Game Physics: Projectile Motion
# Calculate projectile position: y = v₀t - ½gt² # Rearranged as: y = v₀ × t - (½g) × t² lfd f1, initial_velocity(r0) # Load initial velocity lfd f2, time(r0) # Load time lfd f3, gravity_half(r0) # Load ½g (half gravity) lfd f4, time_squared(r0) # Load t² (precomputed) fmsub f5, f1, f2, f0 # f5 = v₀ × t - 0 fmsub f6, f3, f4, f5 # f6 = f5 - (½g) × t² = v₀t - ½gt² stfd f6, position_y(r0) # Store Y position
Audio Processing: Echo/Delay Effect
# Echo effect: output = input × gain - delayed_signal × feedback lfd f1, input_signal(r0) # Load input signal lfd f2, gain_factor(r0) # Load gain factor lfd f3, delayed_signal(r0) # Load delayed signal lfd f4, feedback_coeff(r0) # Load feedback coefficient fmsub f5, f1, f2, f0 # f5 = input × gain - 0 fmsub f6, f3, f4, f5 # f6 = f5 - delayed × feedback stfd f6, output_signal(r0) # Store output signal
Machine Learning: Gradient Descent
# Weight update: new_weight = old_weight - learning_rate × gradient # Using fmsub: new_weight = old_weight × 1 - learning_rate × gradient lfd f1, old_weight(r0) # Load current weight lfd f2, learning_rate(r0) # Load learning rate lfd f3, gradient(r0) # Load gradient lfd f4, one_constant(r0) # Load 1.0 fmsub f5, f1, f4, f0 # f5 = old_weight × 1 - 0 = old_weight fmsub f6, f2, f3, f5 # f6 = f5 - learning_rate × gradient stfd f6, new_weight(r0) # Store updated weight
Scientific Computing: Error Calculation
# Calculate relative error: error = computed_value × scale - reference_value lfd f1, computed_value(r0) # Load computed result lfd f2, scale_factor(r0) # Load scaling factor lfd f3, reference_value(r0) # Load reference value fmsub f4, f1, f2, f3 # f4 = computed × scale - reference stfd f4, error_value(r0) # Store error
Graphics: Color Blending
# Alpha blending: result = src_color × alpha - dst_color × (1-alpha) # Simplified version using fmsub for one component lfd f1, src_color(r0) # Load source color lfd f2, alpha(r0) # Load alpha value lfd f3, dst_color(r0) # Load destination color lfd f4, one_minus_alpha(r0) # Load (1-alpha) fmsub f5, f1, f2, f0 # f5 = src × alpha - 0 fmsub f6, f3, f4, f5 # f6 = f5 - dst × (1-alpha) (for subtract blend mode) stfd f6, blended_color(r0) # Store blended color
Numerical Analysis: Finite Difference
# Calculate finite difference: df/dx ≈ (f(x+h) - f(x)) / h # Rearranged: df/dx = f(x+h) × (1/h) - f(x) × (1/h) lfd f1, f_x_plus_h(r0) # Load f(x+h) lfd f2, f_x(r0) # Load f(x) lfd f3, inv_h(r0) # Load 1/h fmsub f4, f1, f3, f0 # f4 = f(x+h) × (1/h) - 0 fmsub f5, f2, f3, f4 # f5 = f4 - f(x) × (1/h) = derivative approximation stfd f5, derivative(r0) # Store derivative