cosmopolitan/libc/sysv/systemfive.S

315 lines
12 KiB
ArmAsm
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
This program is free software; you can redistribute it and/or modify │
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. │
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of │
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software │
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/dce.h"
#include "libc/macros.h"
.source __FILE__
/*
besiyata
dishmaya
cosmopolitan § bell system five » system call support
*/
/ Performs System Five System Call.
/
/ Cosmopolitan is designed to delegate all function calls into the
/ Linux, FreeBSD, OpenBSD, and XNU kernels through this function,
/ with few exceptions. This function is intended to be called via
/ generated thunks in the libc/sysv/syscalls/ directory.
/
/ It's safe to call this function on Windows, where it'll always
/ return -1 w/ errno == ENOSYS. Further note that -1 is the only
/ return value that means error, a common anti-pattern is to check
/ for values less than 0 (which is more problematic on 32-bit).
/
/ It's important to consider that system calls are an order of a
/ magnitude more expensive than normal function calls. For example
/ getpid() on Linux usually takes 500ns, and cached i/o calls will
/ take 1µs or more.
/
/ @param %rax function ordinal supplied by jump slot
/ @param %rdi,%rsi,%rdx,%rcx,%r8,%r9 and rest on stack
/ @return %rax:%rdx is result, or -1 w/ errno on error
/ @clob %rcx,%r10,%r11
/ @see syscalls.sh
.initbss 300,_init_systemfive
__hostos:
.quad 0
.endobj __hostos,globl,hidden
__systemfive:
.quad 0
.endobj __systemfive,globl,hidden
.previous
.Lanchorpoint:
systemfive.linux:
movswl %ax,%eax
test %eax,%eax
js systemfive.enosys
mov %rcx,%r10
push %rbp
mov %rsp,%rbp
syscall
pop %rbp
cmp $-4095,%rax
jae systemfive.error
ret
.endfn systemfive.linux,globl,hidden
systemfive.error:
neg %eax
/ 𝑠𝑙𝑖𝑑𝑒
.endfn systemfive.error,globl,hidden
systemfive.errno:
mov %eax,errno(%rip)
push $-1
pop %rax
stc
ret
.endfn systemfive.errno,globl,hidden
systemfive.enosys:
mov ENOSYS(%rip),%eax
jmp systemfive.errno
.endfn systemfive.enosys,globl,hidden
systemfive.openbsd:
shr $48,%rax
jmp systemfive.bsd
.endfn systemfive.openbsd,globl,hidden
systemfive.freebsd:
shr $32,%rax
movzwl %ax,%eax
/ 𝑠𝑙𝑖𝑑𝑒
.endfn systemfive.freebsd,globl,hidden
systemfive.bsd:
cmp $0xfff,%ax
jae systemfive.enosys
mov %rcx,%r10
push %rbp
mov %rsp,%rbp
syscall
pop %rbp
jc systemfive.errno
ret
.endfn systemfive.bsd
systemfive.xnu:
/ do this to rax
/ 0x????????2153????
/
/
/ 0x0000000002000153
mov %eax,%r11d
shr $4*7,%r11d
shl $4*6,%r11d
shl $4*1,%eax
shr $4*5,%eax
or %r11d,%eax
jmp systemfive.bsd
.endfn systemfive.xnu,globl,hidden
.previous
/ Initializes System Five system call support.
/
/ (1) Extracts parameters passed by kernel,
/ (2) Detects O/S without issuing system calls,
/ (3) Unpacks numbers.
/
/ @param %r15 is auxv
/ @note OpenBSD devs: let us know if you start using auxv
.init.start 300,_init_systemfive
push %rbx
push %rsi
testb $METAL,(%rdi) # @see ape/ape.S
jnz systemfive.init.metal
testb $XNU,(%rdi) # @see libc/crt/crt.S
jnz systemfive.init.xnu
testb $FREEBSD,(%rdi) # @see libc/crt/crt.S
jnz systemfive.init.freebsd
testb $WINDOWS,(%rdi) # @see libc/runtime/winmain.c
jnz systemfive.init.windows
cmpq $0,(%r15) # OpenBSD doesn't have auxv
je systemfive.init.openbsd
/ default state is safe state
/ 𝑠𝑙𝑖𝑑𝑒
systemfive.init.linux:
pushb systemfive.linux-.Lanchorpoint
push $LINUX
ezlea syscon.linux,si
jmp systemfive.init.os
systemfive.init.metal:
pushb systemfive.linux-.Lanchorpoint
push $METAL
ezlea syscon.linux,si
jmp systemfive.init.os
systemfive.init.windows:
pushb systemfive.enosys-.Lanchorpoint
push $WINDOWS
ezlea syscon.windows,si
jmp systemfive.init.os
systemfive.init.freebsd:
pushb systemfive.freebsd-.Lanchorpoint
push $FREEBSD
ezlea syscon.freebsd,si
jmp systemfive.init.os
systemfive.init.openbsd:
pushb systemfive.openbsd-.Lanchorpoint
push $OPENBSD
ezlea syscon.openbsd,si
jmp systemfive.init.os
systemfive.init.xnu:
pushb systemfive.xnu-.Lanchorpoint
push $XNU
ezlea syscon.xnu,si
/ 𝑠𝑙𝑖𝑑𝑒
systemfive.init.os:
ezlea .Lanchorpoint,cx
pop %rax
stosq # __hostos
pop %rax
add %rcx,%rax
stosq # __systemfive
push %rdi
ezlea syscon.start,di
ezlea syscon.end,bx
call systemfive.sleb128unpacker
pop %rdi
/ 𝑠𝑙𝑖𝑑𝑒
systemfive.init.done:
pop %rsi
pop %rbx
.init.end 300,_init_systemfive,globl,hidden
.text.startup
systemfive.sleb128unpacker:
.leafprologue
or $-1,%r9
2: cmp %rbx,%rdi
jnb 5f
xor %ecx,%ecx
xor %edx,%edx
3: lodsb
mov %rax,%r8
and $127,%r8d
sal %cl,%r8
add $7,%ecx
or %r8,%rdx
test %al,%al
js 3b
test $64,%al
je 4f
mov %r9,%rax
sal %cl,%rax
or %rax,%rdx
4: mov %rdx,%rax
cmpq $0,(%rdi) # don't change consts already set
cmovne (%rdi),%rax # @see WinMain() for example
stosq
jmp 2b
5: .leafepilogue
.previous
/ Sections for varint encoded numbers.
/
/ These sections are all ordered by (group_name, constant_name).
/ They're populated by modules simply referencing the symbols.
/
/ @see libc/sysv/consts.sh
/ @see libc/sysv/consts/syscon.h
.section .piro.bss.sort.syscon.1,"aw",@nobits
.align 8
syscon.start:/*
...decentralized quadwords...
*/.previous
.section .piro.bss.sort.syscon.3,"aw",@nobits
syscon.end:
.previous
.section .sort.rodata.syscon.linux.1,"a",@progbits
.align 1
syscon.linux:/*
...decentralized leb128...
*/.previous
.section .sort.rodata.syscon.xnu.1,"a",@progbits
.align 1
syscon.xnu:/*
...decentralized leb128...
*/.previous
.section .sort.rodata.syscon.freebsd.1,"a",@progbits
.align 1
syscon.freebsd:/*
...decentralized leb128...
*/.previous
.section .sort.rodata.syscon.openbsd.1,"a",@progbits
.align 1
syscon.openbsd:/*
...decentralized leb128...
*/.previous
.section .sort.rodata.syscon.windows.1,"a",@progbits
.align 1
syscon.windows:/*
...decentralized leb128...
*/.previous
.type syscon.start,@object
.type syscon.end,@object
.type syscon.linux,@object
.type syscon.xnu,@object
.type syscon.freebsd,@object
.type syscon.openbsd,@object
.type syscon.windows,@object
.globl syscon.start
.globl syscon.end
.globl syscon.linux
.globl syscon.xnu
.globl syscon.freebsd
.globl syscon.openbsd
.globl syscon.windows