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