| |||

Home > The A64 instruction set > Data processing instructions > Multiply and divide instructions |

The multiply instructions provided are broadly similar to those in ARMv7-A, but with the ability to perform 64-bit multiplies in a single instruction.

**Table 6.2. Multiplication operations in assembly language**

Opcode | Description |
---|---|

Multiply instructions | |

`MADD` | Multiply add |

`MNEG` | Multiply negate |

`MSUB` | Multiply subtract |

`MUL` | Multiply |

`SMADDL` | Signed multiply-add long |

`SMNEGL` | Signed multiply-negate long |

`SMSUBL` | Signed multiply-subtract long |

`SMULH` | Signed multiply returning high half |

`SMULL` | Signed multiply long |

`UMADDL` | Unsigned multiply-add long |

`UMNEGL` | Unsigned multiply-negate long |

`UMSUBL` | Unsigned multiply-subtract long |

`UMULH` | Unsigned multiply returning high half |

`UMULL` | Unsigned multiply long |

Divide instructions | |

`SDIV` | Signed divide |

`UDIV` | Unsigned divide |

There are multiply instructions that operate on 32-bit or
64-bit values and return a result of the same size as the operands.
For example, two 64-bit registers can be multiplied to produce a 64-bit
result with the `MUL`

instruction.

MUL X0, X1, X2 // X0 = X1 * X2

There is also the ability to add or subtract an accumulator
value in a third source register, using the `MADD`

or `MSUB`

instructions.

The `MNEG`

instruction can be used to negate the
result, for example:

MNEG X0, X1, X2 // X0 = -(X1 * X2)

Additionally, there are a range of multiply instructions that
produce a long result, that is, multiplying two 32-bit numbers and
generating a 64-bit result. There are both signed and unsigned variants
of these long multiplies (`UMULL`

, `SMULL`

).
There are also options to accumulate a value from another register
(`UMADDL`

, `SMADDL`

) or to negate (`UMNEGL`

, `SMNEGL`

).

Including 32-bit and 64-bit multiply with optional accumulation give a result size the same size as the operands:

32 ± (32 × 32) gives a 32-bit result.

64 ± (64 × 64) gives a 64-bit result.

± (32 × 32) gives a 32-bit result.

± (64 × 64) gives a 64-bit result.

Widening multiply, that is signed and unsigned, with accumulation gives a single 64-bit result:

64 ± (32 × 32) gives a 64-bit result.

± (32 × 32) gives a 64-bit result.

A 64 × 64 to 128-bit multiply requires a sequence of two instructions to generate a pair of 64-bit result registers:

± (64 × 64) gives the lower 64 bits of the result [63:0].

(64 × 64) gives the higher 64 bits of the result [127:64].

The list contains no 32 × 64 options. You cannot directly multiply a 32-bit W register by a 64-bit X register.

The ARMv8-A architecture has support for signed and unsigned division of 32-bit and 64-bit sized values. For example:

UDIV W0, W1, W2 // W0 = W1 / W2 (unsigned, 32-bit divide)

SDIV X0, X1, X2 // X0 = X1 / X2 (signed, 64-bit divide)

Overflow and divide-by-zero are not trapped:

Any integer division by zero returns zero.

Overflow can only occur in

`SDIV`

:`INT_MIN / -1`

returns`INT_MIN`

, where`INT_MIN`

is the smallest negative number that can be encoded in the registers used for the operation. The result is always rounded towards zero, as in most C/C++ dialects.