Advanced Topics
Multiply Instructions
In lecture 2, the core arithmetic operations for addition, subtraction, and reverse subtraction (both with and without using the carry bit) were described. The ARM assembly language also has several instructions for multiplication operations. These differ significantly from the other arithmetic operations in that they have restrictions on the operands.
- All source operands and the destination must be given as simple registers.
- Immediate values and shifted registers cannot be used for operand two.
- The destination and operand one must be different registers.
- R15 (the Program Counter) cannot be used as a destination register.
MUL (Multiply) is the simplest multiplication instruction. It multiplies two 32-bit numbers (held in registers) and stores a 32-bit result in a destination register. If the operands are signed, the result will be signed also. Multiplying two 32-bit numbers together gives rise to a 64-bit number. The MUL instruction only stores the lower 32 bits of the product.
MUL takes the form:
MUL | <destination>,<operand1>,<operand2> | |
MUL | r0, r1, r2 | ; r0 := r1 * r2 (bits 31 to 0 only of product) |
MLA (Multiply-Accumulate) can add the product to another register acting as an accumulator. The MLA instruction is useful for calculating running totals.
MLA takes the form:
MLA | <destination>,<operand1>,<operand2>,<accumulator> | |
MLA | r0, r1, r2, r3 | ; r0:= (r1 * r2) + r3 (bits 31 to 0 only of result) |
The ARM also has four instructions for multiplying 32-bit numbers together and retaining all 64 bits of the product. This is accomplished by putting the most significant 32 bits in one register and the least significant 32 bits in a second register.
These instructions adhere to the following format:
UMULL | <low-destination>,<high-destination>,<operand1>,<operand2> | |
UMULL | r0, r1, r2, r3 | ; r1:r0 := r2 * r3 ;(unsigned long multiplication) |
SMULL | <low-destination>,<high-destination>,<operand1>,<operand2> | |
SMULL | r0, r1, r2, r3 | ; r1:r0 := r2 * r3 ;(signed long multiplication) |
UMLAL | <low-destination>,<high-destination>,<operand1>,<operand2> | |
UMLAL | r0, r1, r2, r3 | ; r1:r0 := r2 * r3 + (r1:r0) ; (unsigned multiplication with accumulate) |
SMLAL | <low-destination>,<high-destination>,<operand1>,<operand2> | |
SMLAL | r0, r1, r2, r3 | ; r1:r0 := r2 * r3 + (r1:r0) ; (signed multiplication with accumulate) |
In the UMLAL and SMLAL instructions, the two source operands are multiplied together and the resulting 64-bit product is added to the 64-bit number held by the high and low destination registers. The final total is placed in the high and low destination registers.
In many situations, it will be easier to replace general multiplication operations with sequences of additions, subtractions, and shifted registers.
To multiply by 9:
MOV r1, #9 | ; r1 := 9 |
MUL r0, r2, r1 | ; r0 := r2 * r1 |
Alternatively:
ADD | r0, r2, r2, LSL #3 | ; r0 := r2 + (r2 * 8) = r2 * 9 |