[clang] 3902ebd - [compiler-rt][builtins] Fix wrong ABI of AVR __mulqi3 & __mulhi3
Ben Shi via cfe-commits
cfe-commits at lists.llvm.org
Fri May 6 06:46:59 PDT 2022
Author: Ben Shi
Date: 2022-05-06T13:46:49Z
New Revision: 3902ebdd5793763431264259dfdca871ef453017
URL: https://github.com/llvm/llvm-project/commit/3902ebdd5793763431264259dfdca871ef453017
DIFF: https://github.com/llvm/llvm-project/commit/3902ebdd5793763431264259dfdca871ef453017.diff
LOG: [compiler-rt][builtins] Fix wrong ABI of AVR __mulqi3 & __mulhi3
Reviewed By: aykevl, dylanmckay
Differential Revision: https://reviews.llvm.org/D125077
Added:
Modified:
clang/lib/Basic/Targets/AVR.cpp
clang/test/Preprocessor/avr-common.c
compiler-rt/lib/builtins/avr/mulhi3.S
compiler-rt/lib/builtins/avr/mulqi3.S
Removed:
################################################################################
diff --git a/clang/lib/Basic/Targets/AVR.cpp b/clang/lib/Basic/Targets/AVR.cpp
index 7be33d4424f4d..67e27ebd58def 100644
--- a/clang/lib/Basic/Targets/AVR.cpp
+++ b/clang/lib/Basic/Targets/AVR.cpp
@@ -380,13 +380,13 @@ void AVRTargetInfo::getTargetDefines(const LangOptions &Opts,
Builder.defineMacro("__AVR__");
Builder.defineMacro("__ELF__");
+ if (ABI == "avrtiny")
+ Builder.defineMacro("__AVR_TINY__", "1");
+
if (!this->CPU.empty()) {
auto It = llvm::find_if(
AVRMcus, [&](const MCUInfo &Info) { return Info.Name == this->CPU; });
- if (It->IsTiny)
- Builder.defineMacro("__AVR_TINY__", "1");
-
if (It != std::end(AVRMcus)) {
Builder.defineMacro(It->DefineName);
if (It->NumFlashBanks >= 1)
diff --git a/clang/test/Preprocessor/avr-common.c b/clang/test/Preprocessor/avr-common.c
index 979dc52e67a10..70daf3fbee23e 100644
--- a/clang/test/Preprocessor/avr-common.c
+++ b/clang/test/Preprocessor/avr-common.c
@@ -1,5 +1,7 @@
// RUN: %clang_cc1 -E -dM -triple avr-unknown-unknown -target-cpu attiny13 /dev/null | FileCheck -match-full-lines --check-prefixes=CHECK,AVR %s
+// RUN: %clang_cc1 -E -dM -triple avr-unknown-unknown -target-cpu avr25 /dev/null | FileCheck -match-full-lines --check-prefixes=CHECK,AVR %s
// RUN: %clang_cc1 -E -dM -triple avr-unknown-unknown -target-cpu attiny4 /dev/null | FileCheck -match-full-lines --check-prefixes=CHECK,TINY %s
+// RUN: %clang_cc1 -E -dM -triple avr-unknown-unknown -target-cpu avrtiny /dev/null | FileCheck -match-full-lines --check-prefixes=CHECK,TINY %s
// CHECK: #define AVR 1
// CHECK: #define __AVR 1
diff --git a/compiler-rt/lib/builtins/avr/mulhi3.S b/compiler-rt/lib/builtins/avr/mulhi3.S
index 97e9bd1a7b56a..d65f52ff27b56 100644
--- a/compiler-rt/lib/builtins/avr/mulhi3.S
+++ b/compiler-rt/lib/builtins/avr/mulhi3.S
@@ -19,40 +19,53 @@
// 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:
- eor r28, r28
- eor r20, r20
- eor r21, r21 ; Initialize the result to 0: `S = 0;`.
+ ; Use Rzero:Rtmp to store the result.
+ clr __tmp_reg__
+ clr __zero_reg__ ; S = 0;
__mulhi3_loop:
- cp r24, r28
- cpc r25, r28 ; `while (A != 0) { ... }`
- breq __mulhi3_end ; End the loop if A is 0.
+ clr r21
+ cp r24, r21
+ cpc r25, r21
+ breq __mulhi3_end ; while (A != 0) {
- mov r29, r24
- andi r29, 1 ; `if (A & 1) { ... }`
- breq __mulhi3_loop_a ; Omit the accumulation (`S += B;`) if A's LSB is 0.
-
- add r20, r22
- adc r21, r23 ; Do the accumulation: `S += B;`.
+ 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
+ lsr r25
+ ror r24 ; A = ((unsigned int) A) >> 1;
+ lsl r22
+ rol r23 ; B <<= 1;
+ rjmp __mulhi3_loop ; }
__mulhi3_end:
- mov r24, r20
- mov r25, r21
- ret
+ ; 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;
diff --git a/compiler-rt/lib/builtins/avr/mulqi3.S b/compiler-rt/lib/builtins/avr/mulqi3.S
index be0fa77ca7add..914735cc6458d 100644
--- a/compiler-rt/lib/builtins/avr/mulqi3.S
+++ b/compiler-rt/lib/builtins/avr/mulqi3.S
@@ -8,24 +8,46 @@
//
// The corresponding C code is something like:
//
-// int __mulqi3(char A, char B) {
-// return __mulhi3((int) A, (int) B);
+// 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:
- mov r25, r24
- lsl r25
- sbc r25, r25 ; Promote A from char to int: `(int) A`.
- mov r23, r22
- lsl r23
- sbc r23, r23 ; Promote B from char to int: `(int) B`.
- rcall __mulhi3 ; `__mulhi3((int) A, (int) B);`.
- ret
+ 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;
More information about the cfe-commits
mailing list