fmla

SVE Floating-Point Fused Multiply-Add

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

Calculates (Zda + Zn * Zm) under predicate.

Details

SVE floating-point fused multiply-add instruction that computes Zda + (Zn × Zm) for each element under predicate control, with a single rounding step at the end. Inactive elements (where the predicate is false) are left unchanged in the destination. This instruction performs true fusedoperation with only one rounding error, unlike separate multiply and add instructions. NZCV flags are not affected.

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
size
1
Zm
0
0
0
Pg
Zn
Zda
 
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)

Reference (Arm A64 ISA)

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;