Skip to content

Commit

Permalink
Add loongarch64 support (#53)
Browse files Browse the repository at this point in the history
  • Loading branch information
k0tran authored Aug 20, 2024
1 parent e7e6353 commit 21faac7
Show file tree
Hide file tree
Showing 7 changed files with 989 additions and 2 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ jobs:
- armv5te-unknown-linux-gnueabi
- armv7-linux-androideabi
- armv7-unknown-linux-gnueabi
# Does not work on cross-rs v0.2.5 release, waiting for the next one
# - loongarch64-unknown-linux-gnu
- thumbv7neon-linux-androideabi
- thumbv7neon-unknown-linux-gnueabihf
- aarch64-unknown-linux-gnu
Expand Down Expand Up @@ -93,6 +95,8 @@ jobs:
- armv5te-unknown-linux-gnueabi
- armv7-linux-androideabi
- armv7-unknown-linux-gnueabi
# Does not work on cross-rs v0.2.5 release, waiting for the next one
# - loongarch64-unknown-linux-gnu
- thumbv7neon-linux-androideabi
- thumbv7neon-unknown-linux-gnueabihf
#- mips-unknown-linux-gnu
Expand Down
5 changes: 3 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@ std = []

# Includes the syscall tables for all architectures.
all = [
"aarch64", "arm", "mips", "mips64", "powerpc", "powerpc64", "riscv32",
"riscv64", "s390x", "sparc", "sparc64", "x86", "x86_64"
"aarch64", "arm", "loongarch64", "mips", "mips64", "powerpc", "powerpc64",
"riscv32", "riscv64", "s390x", "sparc", "sparc64", "x86", "x86_64"
]

# Enable syscall tables for individual architectures.
aarch64 = []
arm = []
loongarch64 = []
mips = []
mips64 = []
powerpc = []
Expand Down
683 changes: 683 additions & 0 deletions src/arch/loongarch64.rs

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions src/arch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ mod macros;
pub mod aarch64;
#[cfg(any(target_arch = "arm", feature = "arm"))]
pub mod arm;
#[cfg(any(target_arch = "loongarch64", feature = "loongarch64"))]
pub mod loongarch64;
#[cfg(any(target_arch = "mips", feature = "mips"))]
pub mod mips;
#[cfg(any(target_arch = "mips64", feature = "mips64"))]
Expand Down Expand Up @@ -34,6 +36,9 @@ pub use aarch64::*;
#[cfg(target_arch = "arm")]
pub use arm::*;

#[cfg(target_arch = "loongarch64")]
pub use loongarch64::*;

#[cfg(target_arch = "mips")]
pub use mips::*;

Expand Down
280 changes: 280 additions & 0 deletions src/syscall/loongarch64.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,280 @@
// LoongArch has the following registers:
//
// | General-purpose Register Convension |
// | ============================================================================== |
// | Symbolic Name | Number | Usage |
// | ============== | =============== | =========================================== |
// | zero | 0 | Constant 0 |
// | ra | 1 | Return address |
// | tp | 2 | Thread pointer |
// | sp | 3 | Stack pointer |
// | a0 - a1 | 4 - 5 | Argument registers / return value registers |
// | a2 - a7 | 6 - 11 | Argument registers |
// | t0 - t8 | 12 - 20 | Tempotaty registers |
// | u0 | 21 | Reserved |
// | fp | 22 | Frame pointer / Static register |
// | s0 - s8 | 23 - 31 | Static registers |
//
// | Floating-point Register Convention |
// | ============================================================================= |
// | Symbolic Name | Number | Usage |
// | ============= | =============== | =========================================== |
// | fa0 - fa1 | 0 - 1 | Argument registers / return value registers |
// | fa2 - fa7 | 2 - 7 | Argument registers |
// | ft0 - ft15 | 8 - 23 | Temporary registers |
// | fs0 - fs7 | 24 - 31 | Static registers |
//
// Note that v0, v1, fv0, fv1 are just old aliases to a0, a1, fa0, fa1 (not recommended to use)
//
// The following registers are used for args 1-7:
//
// arg1: %a0
// arg2: %a1
// arg3: %a2
// arg4: %a3
// arg5: %a4
// arg6: %a5
// arg7: %a6
//
// %a7 is the syscall number
// %a0, %a1 is the return value
// registers t0 - t8 should be clobbered

use core::arch::asm;

/// Issues a raw system call with 0 arguments.
///
/// # Safety
///
/// Running a system call is inherently unsafe. It is the caller's
/// responsibility to ensure safety.
#[inline]
pub unsafe fn syscall0(n: usize) -> usize {
let mut ret: usize;
asm!(
"syscall 0",
in("$a7") n,
lateout("$a0") ret,
// All temporary registers are always clobbered
lateout("$t0") _,
lateout("$t1") _,
lateout("$t2") _,
lateout("$t3") _,
lateout("$t4") _,
lateout("$t5") _,
lateout("$t6") _,
lateout("$t7") _,
lateout("$t8") _,
options(nostack, preserves_flags)
);
ret
}

/// Issues a raw system call with 1 argument.
///
/// # Safety
///
/// Running a system call is inherently unsafe. It is the caller's
/// responsibility to ensure safety.
#[inline]
pub unsafe fn syscall1(n: usize, arg1: usize) -> usize {
let mut ret: usize;
asm!(
"syscall 0",
in("$a7") n,
inlateout("$a0") arg1 => ret,
// All temporary registers are always clobbered
lateout("$t0") _,
lateout("$t1") _,
lateout("$t2") _,
lateout("$t3") _,
lateout("$t4") _,
lateout("$t5") _,
lateout("$t6") _,
lateout("$t7") _,
lateout("$t8") _,
options(nostack, preserves_flags)
);
ret
}

/// Issues a raw system call with 2 arguments.
///
/// # Safety
///
/// Running a system call is inherently unsafe. It is the caller's
/// responsibility to ensure safety.
#[inline]
pub unsafe fn syscall2(n: usize, arg1: usize, arg2: usize) -> usize {
let mut ret: usize;
asm!(
"syscall 0",
in("$a7") n,
inlateout("$a0") arg1 => ret,
in("$a1") arg2,
// All temporary registers are always clobbered
lateout("$t0") _,
lateout("$t1") _,
lateout("$t2") _,
lateout("$t3") _,
lateout("$t4") _,
lateout("$t5") _,
lateout("$t6") _,
lateout("$t7") _,
lateout("$t8") _,
options(nostack, preserves_flags)
);
ret
}

/// Issues a raw system call with 3 arguments.
///
/// # Safety
///
/// Running a system call is inherently unsafe. It is the caller's
/// responsibility to ensure safety.
#[inline]
pub unsafe fn syscall3(
n: usize,
arg1: usize,
arg2: usize,
arg3: usize,
) -> usize {
let mut ret: usize;
asm!(
"syscall 0",
in("$a7") n,
inlateout("$a0") arg1 => ret,
in("$a1") arg2,
in("$a2") arg3,
// All temporary registers are always clobbered
lateout("$t0") _,
lateout("$t1") _,
lateout("$t2") _,
lateout("$t3") _,
lateout("$t4") _,
lateout("$t5") _,
lateout("$t6") _,
lateout("$t7") _,
lateout("$t8") _,
options(nostack, preserves_flags)
);
ret
}

/// Issues a raw system call with 4 arguments.
///
/// # Safety
///
/// Running a system call is inherently unsafe. It is the caller's
/// responsibility to ensure safety.
#[inline]
pub unsafe fn syscall4(
n: usize,
arg1: usize,
arg2: usize,
arg3: usize,
arg4: usize,
) -> usize {
let mut ret: usize;
asm!(
"syscall 0",
in("$a7") n,
inlateout("$a0") arg1 => ret,
in("$a1") arg2,
in("$a2") arg3,
in("$a3") arg4,
// All temporary registers are always clobbered
lateout("$t0") _,
lateout("$t1") _,
lateout("$t2") _,
lateout("$t3") _,
lateout("$t4") _,
lateout("$t5") _,
lateout("$t6") _,
lateout("$t7") _,
lateout("$t8") _,
options(nostack, preserves_flags)
);
ret
}

/// Issues a raw system call with 5 arguments.
///
/// # Safety
///
/// Running a system call is inherently unsafe. It is the caller's
/// responsibility to ensure safety.
#[inline]
pub unsafe fn syscall5(
n: usize,
arg1: usize,
arg2: usize,
arg3: usize,
arg4: usize,
arg5: usize,
) -> usize {
let mut ret: usize;
asm!(
"syscall 0",
in("$a7") n,
inlateout("$a0") arg1 => ret,
in("$a1") arg2,
in("$a2") arg3,
in("$a3") arg4,
in("$a4") arg5,
// All temporary registers are always clobbered
lateout("$t0") _,
lateout("$t1") _,
lateout("$t2") _,
lateout("$t3") _,
lateout("$t4") _,
lateout("$t5") _,
lateout("$t6") _,
lateout("$t7") _,
lateout("$t8") _,
options(nostack, preserves_flags)
);
ret
}

/// Issues a raw system call with 6 arguments.
///
/// # Safety
///
/// Running a system call is inherently unsafe. It is the caller's
/// responsibility to ensure safety.
#[inline]
pub unsafe fn syscall6(
n: usize,
arg1: usize,
arg2: usize,
arg3: usize,
arg4: usize,
arg5: usize,
arg6: usize,
) -> usize {
let mut ret: usize;
asm!(
"syscall 0",
in("$a7") n,
inlateout("$a0") arg1 => ret,
in("$a1") arg2,
in("$a2") arg3,
in("$a3") arg4,
in("$a4") arg5,
in("$a5") arg6,
// All temporary registers are always clobbered
lateout("$t0") _,
lateout("$t1") _,
lateout("$t2") _,
lateout("$t3") _,
lateout("$t4") _,
lateout("$t5") _,
lateout("$t6") _,
lateout("$t7") _,
lateout("$t8") _,
options(nostack, preserves_flags)
);
ret
}
5 changes: 5 additions & 0 deletions src/syscall/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ mod aarch64;
mod arm;
#[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))]
mod arm_thumb;
#[cfg(target_arch = "loongarch64")]
mod loongarch64;
#[cfg(target_arch = "mips")]
mod mips;
#[cfg(target_arch = "mips64")]
Expand Down Expand Up @@ -36,6 +38,9 @@ pub use arm::*;
#[cfg(all(target_arch = "arm", target_feature = "thumb-mode"))]
pub use arm_thumb::*;

#[cfg(target_arch = "loongarch64")]
pub use loongarch64::*;

#[cfg(target_arch = "mips")]
pub use mips::*;

Expand Down
9 changes: 9 additions & 0 deletions syscalls-gen/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,15 @@ lazy_static! {
],
blocklist: &["sync_file_range"],
}),
// For loongarch64, see aarch64's explanation.
Source::Header(Header {
arch: "loongarch64",
headers: &[
"include/uapi/asm-generic/unistd.h",
"arch/loongarch/include/uapi/asm/unistd.h",
],
blocklist: &["sync_file_range"],
}),
];
}

Expand Down

0 comments on commit 21faac7

Please sign in to comment.