brintos

brintos / linux-shallow public Read only

0
0
Text · 8.8 KiB · ff5afc3 Raw
181 lines · c
1/* SPDX-License-Identifier: LGPL-2.1 OR MIT */2/*3 * i386 specific definitions for NOLIBC4 * Copyright (C) 2017-2022 Willy Tarreau <w@1wt.eu>5 */6 7#ifndef _NOLIBC_ARCH_I386_H8#define _NOLIBC_ARCH_I386_H9 10#include "compiler.h"11#include "crt.h"12 13/* Syscalls for i386 :14 *   - mostly similar to x86_6415 *   - registers are 32-bit16 *   - syscall number is passed in eax17 *   - arguments are in ebx, ecx, edx, esi, edi, ebp respectively18 *   - all registers are preserved (except eax of course)19 *   - the system call is performed by calling int $0x8020 *   - syscall return comes in eax21 *   - the arguments are cast to long and assigned into the target registers22 *     which are then simply passed as registers to the asm code, so that we23 *     don't have to experience issues with register constraints.24 *   - the syscall number is always specified last in order to allow to force25 *     some registers before (gcc refuses a %-register at the last position).26 *27 * Also, i386 supports the old_select syscall if newselect is not available28 */29#define __ARCH_WANT_SYS_OLD_SELECT30 31#define my_syscall0(num)                                                      \32({                                                                            \33	long _ret;                                                            \34	register long _num __asm__ ("eax") = (num);                           \35									      \36	__asm__ volatile (                                                    \37		"int $0x80\n"                                                 \38		: "=a" (_ret)                                                 \39		: "0"(_num)                                                   \40		: "memory", "cc"                                              \41	);                                                                    \42	_ret;                                                                 \43})44 45#define my_syscall1(num, arg1)                                                \46({                                                                            \47	long _ret;                                                            \48	register long _num __asm__ ("eax") = (num);                           \49	register long _arg1 __asm__ ("ebx") = (long)(arg1);                   \50									      \51	__asm__ volatile (                                                    \52		"int $0x80\n"                                                 \53		: "=a" (_ret)                                                 \54		: "r"(_arg1),                                                 \55		  "0"(_num)                                                   \56		: "memory", "cc"                                              \57	);                                                                    \58	_ret;                                                                 \59})60 61#define my_syscall2(num, arg1, arg2)                                          \62({                                                                            \63	long _ret;                                                            \64	register long _num __asm__ ("eax") = (num);                           \65	register long _arg1 __asm__ ("ebx") = (long)(arg1);                   \66	register long _arg2 __asm__ ("ecx") = (long)(arg2);                   \67									      \68	__asm__ volatile (                                                    \69		"int $0x80\n"                                                 \70		: "=a" (_ret)                                                 \71		: "r"(_arg1), "r"(_arg2),                                     \72		  "0"(_num)                                                   \73		: "memory", "cc"                                              \74	);                                                                    \75	_ret;                                                                 \76})77 78#define my_syscall3(num, arg1, arg2, arg3)                                    \79({                                                                            \80	long _ret;                                                            \81	register long _num __asm__ ("eax") = (num);                           \82	register long _arg1 __asm__ ("ebx") = (long)(arg1);                   \83	register long _arg2 __asm__ ("ecx") = (long)(arg2);                   \84	register long _arg3 __asm__ ("edx") = (long)(arg3);                   \85									      \86	__asm__ volatile (                                                    \87		"int $0x80\n"                                                 \88		: "=a" (_ret)                                                 \89		: "r"(_arg1), "r"(_arg2), "r"(_arg3),                         \90		  "0"(_num)                                                   \91		: "memory", "cc"                                              \92	);                                                                    \93	_ret;                                                                 \94})95 96#define my_syscall4(num, arg1, arg2, arg3, arg4)                              \97({                                                                            \98	long _ret;                                                            \99	register long _num __asm__ ("eax") = (num);                           \100	register long _arg1 __asm__ ("ebx") = (long)(arg1);                   \101	register long _arg2 __asm__ ("ecx") = (long)(arg2);                   \102	register long _arg3 __asm__ ("edx") = (long)(arg3);                   \103	register long _arg4 __asm__ ("esi") = (long)(arg4);                   \104									      \105	__asm__ volatile (                                                    \106		"int $0x80\n"                                                 \107		: "=a" (_ret)                                                 \108		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4),             \109		  "0"(_num)                                                   \110		: "memory", "cc"                                              \111	);                                                                    \112	_ret;                                                                 \113})114 115#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5)                        \116({                                                                            \117	long _ret;                                                            \118	register long _num __asm__ ("eax") = (num);                           \119	register long _arg1 __asm__ ("ebx") = (long)(arg1);                   \120	register long _arg2 __asm__ ("ecx") = (long)(arg2);                   \121	register long _arg3 __asm__ ("edx") = (long)(arg3);                   \122	register long _arg4 __asm__ ("esi") = (long)(arg4);                   \123	register long _arg5 __asm__ ("edi") = (long)(arg5);                   \124									      \125	__asm__ volatile (                                                    \126		"int $0x80\n"                                                 \127		: "=a" (_ret)                                                 \128		: "r"(_arg1), "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \129		  "0"(_num)                                                   \130		: "memory", "cc"                                              \131	);                                                                    \132	_ret;                                                                 \133})134 135#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6)	\136({								\137	long _eax  = (long)(num);				\138	long _arg6 = (long)(arg6); /* Always in memory */	\139	__asm__ volatile (					\140		"pushl	%[_arg6]\n\t"				\141		"pushl	%%ebp\n\t"				\142		"movl	4(%%esp),%%ebp\n\t"			\143		"int	$0x80\n\t"				\144		"popl	%%ebp\n\t"				\145		"addl	$4,%%esp\n\t"				\146		: "+a"(_eax)		/* %eax */		\147		: "b"(arg1),		/* %ebx */		\148		  "c"(arg2),		/* %ecx */		\149		  "d"(arg3),		/* %edx */		\150		  "S"(arg4),		/* %esi */		\151		  "D"(arg5),		/* %edi */		\152		  [_arg6]"m"(_arg6)	/* memory */		\153		: "memory", "cc"				\154	);							\155	_eax;							\156})157 158/* startup code */159/*160 * i386 System V ABI mandates:161 * 1) last pushed argument must be 16-byte aligned.162 * 2) The deepest stack frame should be set to zero163 *164 */165void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void)166{167	__asm__ volatile (168		"xor  %ebp, %ebp\n"       /* zero the stack frame                                */169		"mov  %esp, %eax\n"       /* save stack pointer to %eax, as arg1 of _start_c     */170		"add  $12, %esp\n"        /* avoid over-estimating after the 'and' & 'sub' below */171		"and  $-16, %esp\n"       /* the %esp must be 16-byte aligned on 'call'          */172		"sub  $12, %esp\n"        /* sub 12 to keep it aligned after the push %eax       */173		"push %eax\n"             /* push arg1 on stack to support plain stack modes too */174		"call _start_c\n"         /* transfer to c runtime                               */175		"hlt\n"                   /* ensure it does not return                           */176	);177	__nolibc_entrypoint_epilogue();178}179 180#endif /* _NOLIBC_ARCH_I386_H */181