1 | //===------------ mulhi3.S - int16 multiplication -------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // The corresponding C code is something like: |
10 | // |
11 | // int __mulhi3(int A, int B) { |
12 | // int S = 0; |
13 | // while (A != 0) { |
14 | // if (A & 1) |
15 | // S += B; |
16 | // A = ((unsigned int) A) >> 1; |
17 | // B <<= 1; |
18 | // } |
19 | // return S; |
20 | // } |
21 | // |
22 | // __mulhi3 has special ABI, as the implementation of libgcc, R25:R24 is used |
23 | // to return result, while Rtmp/R21/R22/R23 are clobbered. |
24 | // |
25 | //===----------------------------------------------------------------------===// |
26 | |
27 | .text |
28 | .align 2 |
29 | |
30 | #ifdef __AVR_TINY__ |
31 | .set __tmp_reg__, 16 |
32 | .set __zero_reg__, 17 |
33 | #else |
34 | .set __tmp_reg__, 0 |
35 | .set __zero_reg__, 1 |
36 | #endif |
37 | |
38 | .globl __mulhi3 |
39 | .type __mulhi3, @function |
40 | |
41 | __mulhi3: |
42 | ; Use Rzero:Rtmp to store the result. |
43 | clr __tmp_reg__ |
44 | clr __zero_reg__ ; S = 0; |
45 | |
46 | __mulhi3_loop: |
47 | clr r21 |
48 | cp r24, r21 |
49 | cpc r25, r21 |
50 | breq __mulhi3_end ; while (A != 0) { |
51 | |
52 | mov r21, r24 |
53 | andi r21, 1 |
54 | breq __mulhi3_loop_a ; if (A & 1) |
55 | add __tmp_reg__, r22 |
56 | adc __zero_reg__, r23 ; S += B; |
57 | |
58 | __mulhi3_loop_a: |
59 | lsr r25 |
60 | ror r24 ; A = ((unsigned int) A) >> 1; |
61 | lsl r22 |
62 | rol r23 ; B <<= 1; |
63 | rjmp __mulhi3_loop ; } |
64 | |
65 | __mulhi3_end: |
66 | ; Return the result via R25:R24. |
67 | mov r24, __tmp_reg__ |
68 | mov r25, __zero_reg__ |
69 | ; Restore __zero_reg__ to 0. |
70 | clr __zero_reg__ |
71 | ret ; return S; |
72 | |