| //===------------ 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; |