1    /*
2     * Signed 64-bit integer multiply.
3     *
4     * Consider WXxYZ (r1r0 x r3r2) with a long multiply:
5     *        WX
6     *      x YZ
7     *  --------
8     *     ZW ZX
9     *  YW YX
10     *
11     * The low word of the result holds ZX, the high word holds
12     * (ZW+YX) + (the high overflow from ZX).  YW doesn't matter because
13     * it doesn't fit in the low 64 bits.
14     *
15     * Unlike most ARM math operations, multiply instructions have
16     * restrictions on using the same register more than once (Rd and Rm
17     * cannot be the same).
18     */
19    /* mul-long vAA, vBB, vCC */
20    FETCH r0, 1                         @ r0<- CCBB
21    and     r2, r0, #255                @ r2<- BB
22    mov     r3, r0, lsr #8              @ r3<- CC
23    VREG_INDEX_TO_ADDR r2, r2           @ r2<- &fp[BB]
24    VREG_INDEX_TO_ADDR r3, r3           @ r3<- &fp[CC]
25    ldmia   r2, {r0-r1}                 @ r0/r1<- vBB/vBB+1
26    ldmia   r3, {r2-r3}                 @ r2/r3<- vCC/vCC+1
27    mul     ip, r2, r1                  @ ip<- ZxW
28    umull   r1, lr, r2, r0              @ r1/lr <- ZxX
29    mla     r2, r0, r3, ip              @ r2<- YxX + (ZxW)
30    mov     r0, rINST, lsr #8           @ r0<- AA
31    add     r2, r2, lr                  @ r2<- lr + low(ZxW + (YxX))
32    VREG_INDEX_TO_ADDR r0, r0           @ r0<- &fp[AA]
33    FETCH_ADVANCE_INST 2                @ advance rPC, load rINST
34    GET_INST_OPCODE ip                  @ extract opcode from rINST
35    stmia   r0, {r1-r2 }                @ vAA/vAA+1<- r1/r2
36    GOTO_OPCODE ip                      @ jump to next instruction
37