tools/include/nolibc/arch-mips.h

Source file repositories/reference/linux-study-clean/tools/include/nolibc/arch-mips.h

File Facts

System
Linux kernel
Corpus path
tools/include/nolibc/arch-mips.h
Extension
.h
Size
14806 bytes
Lines
298
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

#ifndef _NOLIBC_ARCH_MIPS_H
#define _NOLIBC_ARCH_MIPS_H

#include <linux/unistd.h>

#include "compiler.h"
#include "crt.h"
#include "std.h"

#if !defined(_ABIO32) && !defined(_ABIN32) && !defined(_ABI64)
#error Unsupported MIPS ABI
#endif

/* Syscalls for MIPS ABI O32 :
 *   - WARNING! there's always a delayed slot!
 *   - WARNING again, the syntax is different, registers take a '$' and numbers
 *     do not.
 *   - registers are 32-bit
 *   - stack is 8-byte aligned
 *   - syscall number is passed in v0 (starts at 0xfa0).
 *   - arguments are in a0, a1, a2, a3, then the stack. The caller needs to
 *     leave some room in the stack for the callee to save a0..a3 if needed.
 *   - Many registers are clobbered, in fact only a0..a2 and s0..s8 are
 *     preserved. See: https://www.linux-mips.org/wiki/Syscall as well as
 *     scall32-o32.S in the kernel sources.
 *   - the system call is performed by calling "syscall"
 *   - syscall return comes in v0, and register a3 needs to be checked to know
 *     if an error occurred, in which case errno is in v0.
 *   - the arguments are cast to long and assigned into the target registers
 *     which are then simply passed as registers to the asm code, so that we
 *     don't have to experience issues with register constraints.
 *
 * Syscalls for MIPS ABI N32, same as ABI O32 with the following differences :
 *   - arguments are in a0, a1, a2, a3, t0, t1, t2, t3.
 *     t0..t3 are also known as a4..a7.
 *   - stack is 16-byte aligned
 */

#if !defined(__mips_isa_rev) || __mips_isa_rev < 6
#define _NOLIBC_SYSCALL_CLOBBER_HI_LO "hi", "lo"
#else
#define _NOLIBC_SYSCALL_CLOBBER_HI_LO "$0"
#endif

#if defined(_ABIO32)

#define _NOLIBC_SYSCALL_CLOBBERLIST \
	"memory", "cc", "at", "v1", \
	"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", \
	_NOLIBC_SYSCALL_CLOBBER_HI_LO

#define _NOLIBC_SYSCALL_STACK_RESERVE "addiu $sp, $sp, -32\n"
#define _NOLIBC_SYSCALL_STACK_UNRESERVE "addiu $sp, $sp, 32\n"

#define _NOLIBC_SYSCALL_REG register long

#else /* _ABIN32 || _ABI64 */

/* binutils, GCC and clang disagree about register aliases, use numbers instead. */
#define _NOLIBC_SYSCALL_CLOBBERLIST \
	"memory", "cc", "at", "v1", \
	"10", "11", "12", "13", "14", "15", "24", "25", \
	_NOLIBC_SYSCALL_CLOBBER_HI_LO

#define _NOLIBC_SYSCALL_STACK_RESERVE
#define _NOLIBC_SYSCALL_STACK_UNRESERVE

#define _NOLIBC_SYSCALL_REG register long long

#endif /* _ABIO32 */

#define __nolibc_syscall0(num)                                                \
({                                                                            \
	_NOLIBC_SYSCALL_REG _num __asm__ ("v0")  = (num);                     \
	_NOLIBC_SYSCALL_REG _arg4 __asm__ ("a3");                             \
									      \
	__asm__ volatile (                                                    \
		_NOLIBC_SYSCALL_STACK_RESERVE                                 \
		"syscall\n"                                                   \
		_NOLIBC_SYSCALL_STACK_UNRESERVE                               \
		: "=r"(_num), "=r"(_arg4)                                     \
		: "r"(_num)                                                   \
		: _NOLIBC_SYSCALL_CLOBBERLIST                                 \
	);                                                                    \
	_arg4 ? -_num : _num;                                                 \
})

#define __nolibc_syscall1(num, arg1)                                          \
({                                                                            \
	_NOLIBC_SYSCALL_REG _num __asm__ ("v0")  = (num);                     \

Annotation

Implementation Notes