summaryrefslogtreecommitdiff
path: root/gnu/llvm/compiler-rt/lib/builtins/avr/mulqi3.S
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/llvm/compiler-rt/lib/builtins/avr/mulqi3.S')
-rw-r--r--gnu/llvm/compiler-rt/lib/builtins/avr/mulqi3.S53
1 files changed, 53 insertions, 0 deletions
diff --git a/gnu/llvm/compiler-rt/lib/builtins/avr/mulqi3.S b/gnu/llvm/compiler-rt/lib/builtins/avr/mulqi3.S
new file mode 100644
index 00000000000..914735cc645
--- /dev/null
+++ b/gnu/llvm/compiler-rt/lib/builtins/avr/mulqi3.S
@@ -0,0 +1,53 @@
+//===------------ mulhi3.S - int8 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:
+//
+// char __mulqi3(char A, char B) {
+// int S = 0;
+// while (A != 0) {
+// if (A & 1)
+// S += B;
+// B <<= 1;
+// A = ((unsigned char) A) >> 1;
+// }
+// return S;
+// }
+//
+// __mulqi3 has special ABI, as the implementation of libgcc, the result is
+// returned via R24, while Rtmp and R22 are clobbered.
+//
+//===----------------------------------------------------------------------===//
+
+ .text
+ .align 2
+
+#ifdef __AVR_TINY__
+ .set __tmp_reg__, 16
+#else
+ .set __tmp_reg__, 0
+#endif
+
+ .globl __mulqi3
+ .type __mulqi3, @function
+
+__mulqi3:
+ clr __tmp_reg__ ; S = 0;
+
+__mulqi3_loop:
+ cpi r24, 0
+ breq __mulqi3_end ; while (A != 0) {
+ sbrc r24, 0 ; if (A & 1)
+ add __tmp_reg__, r22 ; S += B;
+ add r22, r22 ; B <<= 1;
+ lsr r24 ; A = ((unsigned char) A) >> 1;
+ rjmp __mulqi3_loop ; }
+
+__mulqi3_end:
+ mov r24, __tmp_reg__
+ ret ; return S;