[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