fmla

SVE Floating-Point Fused Multiply-Add

FMLA <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T>

Calculates (Zda + Zn * Zm) under predicate.

Pseudocode Operation

for i = 0 to VL/element_size-1:
  if Pg[i] then
    Zda[i] ← Zda[i] + (Zn[i] × Zm[i])
  else
    Zda[i] ← Zda[i]

Example

FMLA z0.s.T, p0/m/M, z1.s.T, z2.s.T

Encoding

Binary Layout
01100101
31:24
size
23:22
1
21
Zm
20:16
0
15
0
14
0
13
Pg
12:10
Zn
9:5
Zda
4:0
 
Format SVE FP Ternary
Opcode 0x65200000
Extension SVE

Operands

  • Zda
    Dest/Addend
  • Pg
    Mask
  • Zn
    First source scalable vector register (SVE)
  • Zm
    Second source scalable vector register (SVE)

Related

Other forms of fmla

  • fmla Vector Floating-Point Multiply-Accumulate
  • fmla Floating-Point Multiply Accumulate (Half-Precision)

Across architectures

Fused Multiply-Add : how x86, ARM, RISC-V, and PowerISA each do this.

More in SVE

Reference

Instruction Forms

Encoding Instruction ISA Bit pattern
0x5F001000 FMLA <Hd>, <Hn>, <Vm>.H[<index>] A64 01 | 0 | 11111 | 00 | L | M | Rm | 0 | 0 | 01 | H | 0 | Rn | Rd
0x5F801000 FMLA <V><d>, <V><n>, <Vm>.<Ts>[<index>] A64 01 | 0 | 111111 | sz | L | M | Rm | 0 | 0 | 01 | H | 0 | Rn | Rd
0x0F001000 FMLA <Vd>.<T>, <Vn>.<T>, <Vm>.H[<index>] A64 0 | Q | 0 | 01111 | 00 | L | M | Rm | 0 | 0 | 01 | H | 0 | Rn | Rd
0x0F801000 FMLA <Vd>.<T>, <Vn>.<T>, <Vm>.<Ts>[<index>] A64 0 | Q | 0 | 011111 | sz | L | M | Rm | 0 | 0 | 01 | H | 0 | Rn | Rd
0x0E400C00 FMLA <Vd>.<T>, <Vn>.<T>, <Vm>.<T> A64 0 | Q | 0 | 01110 | 0 | 10 | Rm | 00 | 001 | 1 | Rn | Rd
0x0E20CC00 FMLA <Vd>.<T>, <Vn>.<T>, <Vm>.<T> A64 0 | Q | 0 | 01110 | 0 | sz | 1 | Rm | 11001 | 1 | Rn | Rd
0x65200000 FMLA <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T> A64 01100101 | size | 1 | Zm | 0 | 0 | 0 | Pg | Zn | Zda
0x64200000 FMLA <Zda>.H, <Zn>.H, <Zm>.H[<imm>] A64 01100100 | 0 | i3h | 1 | i3l | Zm | 0000 | 0 | 0 | Zn | Zda
0x64A00000 FMLA <Zda>.S, <Zn>.S, <Zm>.S[<imm>] A64 01100100 | 1 | 0 | 1 | i2 | Zm | 0000 | 0 | 0 | Zn | Zda
0x64E00000 FMLA <Zda>.D, <Zn>.D, <Zm>.D[<imm>] A64 01100100 | 1 | 1 | 1 | i1 | Zm | 0000 | 0 | 0 | Zn | Zda
0xC1101000 FMLA ZA.H[<Wv>, <offs>{, VGx2}], { <Zn1>.H-<Zn2>.H }, <Zm>.H[<index>] A64 110000010001 | Zm | 0 | Rv | 1 | i3h | Zn | 0 | 0 | i3l | off3
0xC1500000 FMLA ZA.S[<Wv>, <offs>{, VGx2}], { <Zn1>.S-<Zn2>.S }, <Zm>.S[<index>] A64 110000010101 | Zm | 0 | Rv | 0 | i2 | Zn | 0 | 0 | 0 | off3
0xC1D00000 FMLA ZA.D[<Wv>, <offs>{, VGx2}], { <Zn1>.D-<Zn2>.D }, <Zm>.D[<index>] A64 110000011101 | Zm | 0 | Rv | 00 | i1 | Zn | 0 | 0 | 0 | off3
0xC1109000 FMLA ZA.H[<Wv>, <offs>{, VGx4}], { <Zn1>.H-<Zn4>.H }, <Zm>.H[<index>] A64 110000010001 | Zm | 1 | Rv | 1 | i3h | Zn | 0 | 0 | 0 | i3l | off3

Description

Multiply the corresponding active floating-point elements of the first and second source vectors and add to elements of the third source (addend) vector without intermediate rounding. Destructively place the results in the destination and third source (addend) vector. Inactive elements in the destination vector register remain unmodified.

Operation

CheckSVEEnabled();
constant integer VL = CurrentVL;
constant integer PL = VL DIV 8;
constant integer elements = VL DIV esize;
bits(PL) mask = P[g, PL];
bits(VL) operand1 = if AnyActiveElement(mask, esize) then Z[n, VL] else Zeros(VL);
bits(VL) operand2 = if AnyActiveElement(mask, esize) then Z[m, VL] else Zeros(VL);
bits(VL) operand3 = Z[da, VL];
bits(VL) result;

for e = 0 to elements-1
    if ActivePredicateElement(mask, e, esize) then
        bits(esize) element1 = Elem[operand1, e, esize];
        bits(esize) element2 = Elem[operand2, e, esize];
        bits(esize) element3 = Elem[operand3, e, esize];

        if op1_neg then element1 = FPNeg(element1, FPCR);
        if op3_neg then element3 = FPNeg(element3, FPCR);
        Elem[result, e, esize] = FPMulAdd(element3, element1, element2, FPCR);
    else
        Elem[result, e, esize] = Elem[operand3, e, esize];

Z[da, VL] = result;