fmls

SVE Floating-Point Fused Multiply-Subtract

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

Calculates (Zda - Zn * Zm) under predicate.

Details

SVE floating-point fused multiply-subtract 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 fused operation with only one rounding error, unlike separate multiply and subtract 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

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

Encoding

Binary Layout
01100101
size
1
Zm
0
0
1
Pg
Zn
Zda
 
Format SVE FP Ternary
Opcode 0x65202000
Extension SVE

Operands

  • Zda
    Dest/Minuend
  • 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
0x5F005000 FMLS <Hd>, <Hn>, <Vm>.H[<index>] A64 01 | 0 | 11111 | 00 | L | M | Rm | 0 | 1 | 01 | H | 0 | Rn | Rd
0x5F805000 FMLS <V><d>, <V><n>, <Vm>.<Ts>[<index>] A64 01 | 0 | 111111 | sz | L | M | Rm | 0 | 1 | 01 | H | 0 | Rn | Rd
0x0F005000 FMLS <Vd>.<T>, <Vn>.<T>, <Vm>.H[<index>] A64 0 | Q | 0 | 01111 | 00 | L | M | Rm | 0 | 1 | 01 | H | 0 | Rn | Rd
0x0F805000 FMLS <Vd>.<T>, <Vn>.<T>, <Vm>.<Ts>[<index>] A64 0 | Q | 0 | 011111 | sz | L | M | Rm | 0 | 1 | 01 | H | 0 | Rn | Rd
0x0EC00C00 FMLS <Vd>.<T>, <Vn>.<T>, <Vm>.<T> A64 0 | Q | 0 | 01110 | 1 | 10 | Rm | 00 | 001 | 1 | Rn | Rd
0x0EA0CC00 FMLS <Vd>.<T>, <Vn>.<T>, <Vm>.<T> A64 0 | Q | 0 | 01110 | 1 | sz | 1 | Rm | 11001 | 1 | Rn | Rd
0x65202000 FMLS <Zda>.<T>, <Pg>/M, <Zn>.<T>, <Zm>.<T> A64 01100101 | size | 1 | Zm | 0 | 0 | 1 | Pg | Zn | Zda
0x64200400 FMLS <Zda>.H, <Zn>.H, <Zm>.H[<imm>] A64 01100100 | 0 | i3h | 1 | i3l | Zm | 0000 | 0 | 1 | Zn | Zda
0x64A00400 FMLS <Zda>.S, <Zn>.S, <Zm>.S[<imm>] A64 01100100 | 1 | 0 | 1 | i2 | Zm | 0000 | 0 | 1 | Zn | Zda
0x64E00400 FMLS <Zda>.D, <Zn>.D, <Zm>.D[<imm>] A64 01100100 | 1 | 1 | 1 | i1 | Zm | 0000 | 0 | 1 | Zn | Zda
0xC1101010 FMLS ZA.H[<Wv>, <offs>{, VGx2}], { <Zn1>.H-<Zn2>.H }, <Zm>.H[<index>] A64 110000010001 | Zm | 0 | Rv | 1 | i3h | Zn | 0 | 1 | i3l | off3
0xC1500010 FMLS ZA.S[<Wv>, <offs>{, VGx2}], { <Zn1>.S-<Zn2>.S }, <Zm>.S[<index>] A64 110000010101 | Zm | 0 | Rv | 0 | i2 | Zn | 0 | 1 | 0 | off3
0xC1D00010 FMLS ZA.D[<Wv>, <offs>{, VGx2}], { <Zn1>.D-<Zn2>.D }, <Zm>.D[<index>] A64 110000011101 | Zm | 0 | Rv | 00 | i1 | Zn | 0 | 1 | 0 | off3
0xC1109010 FMLS ZA.H[<Wv>, <offs>{, VGx4}], { <Zn1>.H-<Zn4>.H }, <Zm>.H[<index>] A64 110000010001 | Zm | 1 | Rv | 1 | i3h | Zn | 0 | 0 | 1 | i3l | off3

Description

Multiply the corresponding active floating-point elements of the first and second source vectors and subtract from 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;