forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
xtensa: add helpers for division, remainder and shifts
Don't rely on libgcc presence, build own versions of the helpers with correct ABI. Signed-off-by: Max Filippov <[email protected]>
- Loading branch information
Showing
10 changed files
with
539 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0 */ | ||
#include <linux/linkage.h> | ||
#include <asm/asmmacro.h> | ||
#include <asm/core.h> | ||
|
||
#ifdef __XTENSA_EB__ | ||
#define uh a2 | ||
#define ul a3 | ||
#else | ||
#define uh a3 | ||
#define ul a2 | ||
#endif /* __XTENSA_EB__ */ | ||
|
||
ENTRY(__ashldi3) | ||
|
||
abi_entry_default | ||
ssl a4 | ||
bgei a4, 32, .Llow_only | ||
src uh, uh, ul | ||
sll ul, ul | ||
abi_ret_default | ||
|
||
.Llow_only: | ||
sll uh, ul | ||
movi ul, 0 | ||
abi_ret_default | ||
|
||
ENDPROC(__ashldi3) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0 */ | ||
#include <linux/linkage.h> | ||
#include <asm/asmmacro.h> | ||
#include <asm/core.h> | ||
|
||
#ifdef __XTENSA_EB__ | ||
#define uh a2 | ||
#define ul a3 | ||
#else | ||
#define uh a3 | ||
#define ul a2 | ||
#endif /* __XTENSA_EB__ */ | ||
|
||
ENTRY(__ashrdi3) | ||
|
||
abi_entry_default | ||
ssr a4 | ||
bgei a4, 32, .Lhigh_only | ||
src ul, uh, ul | ||
sra uh, uh | ||
abi_ret_default | ||
|
||
.Lhigh_only: | ||
sra ul, uh | ||
srai uh, uh, 31 | ||
abi_ret_default | ||
|
||
ENDPROC(__ashrdi3) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0 */ | ||
#include <linux/linkage.h> | ||
#include <asm/asmmacro.h> | ||
#include <asm/core.h> | ||
|
||
ENTRY(__divsi3) | ||
|
||
abi_entry_default | ||
#if XCHAL_HAVE_DIV32 | ||
quos a2, a2, a3 | ||
#else | ||
xor a7, a2, a3 /* sign = dividend ^ divisor */ | ||
do_abs a6, a2, a4 /* udividend = abs (dividend) */ | ||
do_abs a3, a3, a4 /* udivisor = abs (divisor) */ | ||
bltui a3, 2, .Lle_one /* check if udivisor <= 1 */ | ||
do_nsau a5, a6, a2, a8 /* udividend_shift = nsau (udividend) */ | ||
do_nsau a4, a3, a2, a8 /* udivisor_shift = nsau (udivisor) */ | ||
bgeu a5, a4, .Lspecial | ||
|
||
sub a4, a4, a5 /* count = udivisor_shift - udividend_shift */ | ||
ssl a4 | ||
sll a3, a3 /* udivisor <<= count */ | ||
movi a2, 0 /* quotient = 0 */ | ||
|
||
/* test-subtract-and-shift loop; one quotient bit on each iteration */ | ||
#if XCHAL_HAVE_LOOPS | ||
loopnez a4, .Lloopend | ||
#endif /* XCHAL_HAVE_LOOPS */ | ||
.Lloop: | ||
bltu a6, a3, .Lzerobit | ||
sub a6, a6, a3 | ||
addi a2, a2, 1 | ||
.Lzerobit: | ||
slli a2, a2, 1 | ||
srli a3, a3, 1 | ||
#if !XCHAL_HAVE_LOOPS | ||
addi a4, a4, -1 | ||
bnez a4, .Lloop | ||
#endif /* !XCHAL_HAVE_LOOPS */ | ||
.Lloopend: | ||
|
||
bltu a6, a3, .Lreturn | ||
addi a2, a2, 1 /* increment if udividend >= udivisor */ | ||
.Lreturn: | ||
neg a5, a2 | ||
movltz a2, a5, a7 /* return (sign < 0) ? -quotient : quotient */ | ||
abi_ret_default | ||
|
||
.Lle_one: | ||
beqz a3, .Lerror | ||
neg a2, a6 /* if udivisor == 1, then return... */ | ||
movgez a2, a6, a7 /* (sign < 0) ? -udividend : udividend */ | ||
abi_ret_default | ||
|
||
.Lspecial: | ||
bltu a6, a3, .Lreturn0 /* if dividend < divisor, return 0 */ | ||
movi a2, 1 | ||
movi a4, -1 | ||
movltz a2, a4, a7 /* else return (sign < 0) ? -1 : 1 */ | ||
abi_ret_default | ||
|
||
.Lerror: | ||
/* Divide by zero: Use an illegal instruction to force an exception. | ||
The subsequent "DIV0" string can be recognized by the exception | ||
handler to identify the real cause of the exception. */ | ||
ill | ||
.ascii "DIV0" | ||
|
||
.Lreturn0: | ||
movi a2, 0 | ||
#endif /* XCHAL_HAVE_DIV32 */ | ||
abi_ret_default | ||
|
||
ENDPROC(__divsi3) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0 */ | ||
#include <linux/linkage.h> | ||
#include <asm/asmmacro.h> | ||
#include <asm/core.h> | ||
|
||
#ifdef __XTENSA_EB__ | ||
#define uh a2 | ||
#define ul a3 | ||
#else | ||
#define uh a3 | ||
#define ul a2 | ||
#endif /* __XTENSA_EB__ */ | ||
|
||
ENTRY(__lshrdi3) | ||
|
||
abi_entry_default | ||
ssr a4 | ||
bgei a4, 32, .Lhigh_only | ||
src ul, uh, ul | ||
srl uh, uh | ||
abi_ret_default | ||
|
||
.Lhigh_only: | ||
srl ul, uh | ||
movi uh, 0 | ||
abi_ret_default | ||
|
||
ENDPROC(__lshrdi3) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
/* SPDX-License-Identifier: GPL-2.0-or-later WITH GCC-exception-2.0 */ | ||
#include <linux/linkage.h> | ||
#include <asm/asmmacro.h> | ||
#include <asm/core.h> | ||
|
||
ENTRY(__modsi3) | ||
|
||
abi_entry_default | ||
#if XCHAL_HAVE_DIV32 | ||
rems a2, a2, a3 | ||
#else | ||
mov a7, a2 /* save original (signed) dividend */ | ||
do_abs a2, a2, a4 /* udividend = abs (dividend) */ | ||
do_abs a3, a3, a4 /* udivisor = abs (divisor) */ | ||
bltui a3, 2, .Lle_one /* check if udivisor <= 1 */ | ||
do_nsau a5, a2, a6, a8 /* udividend_shift = nsau (udividend) */ | ||
do_nsau a4, a3, a6, a8 /* udivisor_shift = nsau (udivisor) */ | ||
bgeu a5, a4, .Lspecial | ||
|
||
sub a4, a4, a5 /* count = udivisor_shift - udividend_shift */ | ||
ssl a4 | ||
sll a3, a3 /* udivisor <<= count */ | ||
|
||
/* test-subtract-and-shift loop */ | ||
#if XCHAL_HAVE_LOOPS | ||
loopnez a4, .Lloopend | ||
#endif /* XCHAL_HAVE_LOOPS */ | ||
.Lloop: | ||
bltu a2, a3, .Lzerobit | ||
sub a2, a2, a3 | ||
.Lzerobit: | ||
srli a3, a3, 1 | ||
#if !XCHAL_HAVE_LOOPS | ||
addi a4, a4, -1 | ||
bnez a4, .Lloop | ||
#endif /* !XCHAL_HAVE_LOOPS */ | ||
.Lloopend: | ||
|
||
.Lspecial: | ||
bltu a2, a3, .Lreturn | ||
sub a2, a2, a3 /* subtract again if udividend >= udivisor */ | ||
.Lreturn: | ||
bgez a7, .Lpositive | ||
neg a2, a2 /* if (dividend < 0), return -udividend */ | ||
.Lpositive: | ||
abi_ret_default | ||
|
||
.Lle_one: | ||
bnez a3, .Lreturn0 | ||
|
||
/* Divide by zero: Use an illegal instruction to force an exception. | ||
The subsequent "DIV0" string can be recognized by the exception | ||
handler to identify the real cause of the exception. */ | ||
ill | ||
.ascii "DIV0" | ||
|
||
.Lreturn0: | ||
movi a2, 0 | ||
#endif /* XCHAL_HAVE_DIV32 */ | ||
abi_ret_default | ||
|
||
ENDPROC(__modsi3) | ||
|
||
#if !XCHAL_HAVE_NSA | ||
.section .rodata | ||
.align 4 | ||
.global __nsau_data | ||
.type __nsau_data, @object | ||
__nsau_data: | ||
.byte 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4 | ||
.byte 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 | ||
.byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 | ||
.byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 | ||
.byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 | ||
.byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 | ||
.byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 | ||
.byte 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 | ||
.byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
.byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
.byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
.byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
.byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
.byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
.byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
.byte 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 | ||
.size __nsau_data, . - __nsau_data | ||
#endif /* !XCHAL_HAVE_NSA */ |
Oops, something went wrong.