/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
/*
* SPARC ( 32 bit and 64 bit ) specific definitions for NOLIBC
* Copyright ( C ) 2025 Thomas Wei ß schuh < linux @ weissschuh . net >
*/
#ifndef _NOLIBC_ARCH_SPARC_H
#define _NOLIBC_ARCH_SPARC_H
#include <linux/unistd.h>
#include "compiler.h"
#include "crt.h"
/*
* Syscalls for SPARC :
* - registers are native word size
* - syscall number is passed in g1
* - arguments are in o0 - o5
* - the system call is performed by calling a trap instruction
* - syscall return value is in o0
* - syscall error flag is in the carry bit of the processor status register
*/
#ifdef __arch64__
#define _NOLIBC_SYSCALL "t 0x6d\n" \
"bcs,a %%xcc, 1f\n" \
"sub %%g0, %%o0, %%o0\n" \
"1:\n"
#else
#define _NOLIBC_SYSCALL "t 0x10\n" \
"bcs,a 1f\n" \
"sub %%g0, %%o0, %%o0\n" \
"1:\n"
#endif /* __arch64__ */
#define my_syscall0(num) \
({ \
register long _num __asm__ ("g1" ) = (num); \
register long _arg1 __asm__ ("o0" ); \
\
__asm__ volatile ( \
_NOLIBC_SYSCALL \
: "+r" (_arg1) \
: "r" (_num) \
: "memory" , "cc" \
); \
_arg1; \
})
#define my_syscall1(num, arg1) \
({ \
register long _num __asm__ ("g1" ) = (num); \
register long _arg1 __asm__ ("o0" ) = (long )(arg1); \
\
__asm__ volatile ( \
_NOLIBC_SYSCALL \
: "+r" (_arg1) \
: "r" (_num) \
: "memory" , "cc" \
); \
_arg1; \
})
#define my_syscall2(num, arg1, arg2) \
({ \
register long _num __asm__ ("g1" ) = (num); \
register long _arg1 __asm__ ("o0" ) = (long )(arg1); \
register long _arg2 __asm__ ("o1" ) = (long )(arg2); \
\
__asm__ volatile ( \
_NOLIBC_SYSCALL \
: "+r" (_arg1) \
: "r" (_arg2), "r" (_num) \
: "memory" , "cc" \
); \
_arg1; \
})
#define my_syscall3(num, arg1, arg2, arg3) \
({ \
register long _num __asm__ ("g1" ) = (num); \
register long _arg1 __asm__ ("o0" ) = (long )(arg1); \
register long _arg2 __asm__ ("o1" ) = (long )(arg2); \
register long _arg3 __asm__ ("o2" ) = (long )(arg3); \
\
__asm__ volatile ( \
_NOLIBC_SYSCALL \
: "+r" (_arg1) \
: "r" (_arg2), "r" (_arg3), "r" (_num) \
: "memory" , "cc" \
); \
_arg1; \
})
#define my_syscall4(num, arg1, arg2, arg3, arg4) \
({ \
register long _num __asm__ ("g1" ) = (num); \
register long _arg1 __asm__ ("o0" ) = (long )(arg1); \
register long _arg2 __asm__ ("o1" ) = (long )(arg2); \
register long _arg3 __asm__ ("o2" ) = (long )(arg3); \
register long _arg4 __asm__ ("o3" ) = (long )(arg4); \
\
__asm__ volatile ( \
_NOLIBC_SYSCALL \
: "+r" (_arg1) \
: "r" (_arg2), "r" (_arg3), "r" (_arg4), "r" (_num) \
: "memory" , "cc" \
); \
_arg1; \
})
#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
({ \
register long _num __asm__ ("g1" ) = (num); \
register long _arg1 __asm__ ("o0" ) = (long )(arg1); \
register long _arg2 __asm__ ("o1" ) = (long )(arg2); \
register long _arg3 __asm__ ("o2" ) = (long )(arg3); \
register long _arg4 __asm__ ("o3" ) = (long )(arg4); \
register long _arg5 __asm__ ("o4" ) = (long )(arg5); \
\
__asm__ volatile ( \
_NOLIBC_SYSCALL \
: "+r" (_arg1) \
: "r" (_arg2), "r" (_arg3), "r" (_arg4), "r" (_arg5), "r" (_num) \
: "memory" , "cc" \
); \
_arg1; \
})
#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
({ \
register long _num __asm__ ("g1" ) = (num); \
register long _arg1 __asm__ ("o0" ) = (long )(arg1); \
register long _arg2 __asm__ ("o1" ) = (long )(arg2); \
register long _arg3 __asm__ ("o2" ) = (long )(arg3); \
register long _arg4 __asm__ ("o3" ) = (long )(arg4); \
register long _arg5 __asm__ ("o4" ) = (long )(arg5); \
register long _arg6 __asm__ ("o5" ) = (long )(arg6); \
\
__asm__ volatile ( \
_NOLIBC_SYSCALL \
: "+r" (_arg1) \
: "r" (_arg2), "r" (_arg3), "r" (_arg4), "r" (_arg5), "r" (_arg6), \
"r" (_num) \
: "memory" , "cc" \
); \
_arg1; \
})
/* startup code */
void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void )
{
__asm__ volatile (
/*
* Save argc pointer to o0 , as arg1 of _ start_c .
* Account for the window save area , which is 16 registers wide .
*/
#ifdef __arch64__
"add %sp, 128 + 2047, %o0\n" /* on sparc64 / v9 the stack is offset by 2047 */
#else
"add %sp, 64, %o0\n"
#endif
"b,a _start_c\n" /* transfer to c runtime */
);
__nolibc_entrypoint_epilogue();
}
static pid_t getpid(void );
static __attribute__((unused))
pid_t sys_fork(void )
{
pid_t parent, ret;
parent = getpid();
ret = my_syscall0(__NR_fork);
/* The syscall returns the parent pid in the child instead of 0 */
if (ret == parent)
return 0 ;
else
return ret;
}
#define sys_fork sys_fork
static __attribute__((unused))
pid_t sys_vfork(void )
{
pid_t parent, ret;
parent = getpid();
ret = my_syscall0(__NR_vfork);
/* The syscall returns the parent pid in the child instead of 0 */
if (ret == parent)
return 0 ;
else
return ret;
}
#define sys_vfork sys_vfork
#endif /* _NOLIBC_ARCH_SPARC_H */
Messung V0.5 in Prozent C=95 H=100 G=97
¤ Dauer der Verarbeitung: 0.23 Sekunden
(vorverarbeitet am 2026-09-28)
¤
*© Formatika GbR, Deutschland