| //===------------ mulhi3.S - int16 multiplication -------------------------===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // The corresponding C code is something like: |
| // |
| // int __mulhi3(int A, int B) { |
| // int S = 0; |
| // while (A != 0) { |
| // if (A & 1) |
| // S += B; |
| // A = ((unsigned int) A) >> 1; |
| // B <<= 1; |
| // } |
| // return S; |
| // } |
| // |
| // __mulhi3 has special ABI, as the implementation of libgcc, R25:R24 is used |
| // to return result, while Rtmp/R21/R22/R23 are clobbered. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| .text |
| .align 2 |
| |
| #ifdef __AVR_TINY__ |
| .set __tmp_reg__, 16 |
| .set __zero_reg__, 17 |
| #else |
| .set __tmp_reg__, 0 |
| .set __zero_reg__, 1 |
| #endif |
| |
| .globl __mulhi3 |
| .type __mulhi3, @function |
| |
| __mulhi3: |
| ; Use Rzero:Rtmp to store the result. |
| clr __tmp_reg__ |
| clr __zero_reg__ ; S = 0; |
| |
| __mulhi3_loop: |
| clr r21 |
| cp r24, r21 |
| cpc r25, r21 |
| breq __mulhi3_end ; while (A != 0) { |
| |
| mov r21, r24 |
| andi r21, 1 |
| breq __mulhi3_loop_a ; if (A & 1) |
| add __tmp_reg__, r22 |
| adc __zero_reg__, r23 ; S += B; |
| |
| __mulhi3_loop_a: |
| lsr r25 |
| ror r24 ; A = ((unsigned int) A) >> 1; |
| lsl r22 |
| rol r23 ; B <<= 1; |
| rjmp __mulhi3_loop ; } |
| |
| __mulhi3_end: |
| ; Return the result via R25:R24. |
| mov r24, __tmp_reg__ |
| mov r25, __zero_reg__ |
| ; Restore __zero_reg__ to 0. |
| clr __zero_reg__ |
| ret ; return S; |