mirror of
https://github.com/intel/llvm.git
synced 2026-01-15 20:54:40 +08:00
[compiler-rt][builtins] Fix wrong ABI of AVR __mulqi3 & __mulhi3
Reviewed By: aykevl, dylanmckay Differential Revision: https://reviews.llvm.org/D125077
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user