Implementations of some libroot functions for x86_64.
These are the functions required by the kernel. These are all full implementations except for system_time(), which will be implemented later.
This commit is contained in:
@@ -1,12 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2005-2010 Haiku Inc. All Rights Reserved.
|
* Copyright 2005-2012 Haiku Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef _ARCH_SETJMP_H_
|
#ifndef _ARCH_SETJMP_H_
|
||||||
#define _ARCH_SETJMP_H_
|
#define _ARCH_SETJMP_H_
|
||||||
|
|
||||||
|
|
||||||
/* TODO: A jmp_buf size of 12 might not be large enough. Increase to a large size if needed. */
|
typedef int __jmp_buf[8];
|
||||||
typedef int __jmp_buf[12];
|
|
||||||
|
|
||||||
#endif /* _ARCH_SETJMP_H_ */
|
#endif /* _ARCH_SETJMP_H_ */
|
||||||
|
|||||||
@@ -0,0 +1,128 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <asm_defs.h>
|
||||||
|
|
||||||
|
|
||||||
|
.text
|
||||||
|
|
||||||
|
/* int32 atomic_set(vint32 *value, int32 newValue) */
|
||||||
|
FUNCTION(atomic_set):
|
||||||
|
movl %esi, %eax
|
||||||
|
lock
|
||||||
|
xchgl %eax, (%rdi)
|
||||||
|
ret
|
||||||
|
FUNCTION_END(atomic_set)
|
||||||
|
|
||||||
|
/* int32 atomic_test_and_set(vint32 *value, int32 newValue, int32 testAgainst) */
|
||||||
|
FUNCTION(atomic_test_and_set):
|
||||||
|
movl %edx, %eax
|
||||||
|
lock
|
||||||
|
cmpxchgl %esi, (%rdi)
|
||||||
|
ret
|
||||||
|
FUNCTION_END(atomic_test_and_set)
|
||||||
|
|
||||||
|
/* int32 atomic_add(vint32 *value, int32 addValue) */
|
||||||
|
FUNCTION(atomic_add):
|
||||||
|
movl %esi, %eax
|
||||||
|
lock
|
||||||
|
xaddl %eax, (%rdi)
|
||||||
|
ret
|
||||||
|
FUNCTION_END(atomic_add)
|
||||||
|
|
||||||
|
/* int32 atomic_and(vint32 *value, int32 andValue) */
|
||||||
|
FUNCTION(atomic_and):
|
||||||
|
movl (%rdi), %eax
|
||||||
|
1: movl %eax, %edx
|
||||||
|
movl %eax, %ecx
|
||||||
|
andl %esi, %edx
|
||||||
|
lock
|
||||||
|
cmpxchgl %edx, (%rdi)
|
||||||
|
jnz 1b
|
||||||
|
movl %ecx, %eax
|
||||||
|
ret
|
||||||
|
FUNCTION_END(atomic_and)
|
||||||
|
|
||||||
|
/* int32 atomic_or(vint32 *value, int32 orValue) */
|
||||||
|
FUNCTION(atomic_or):
|
||||||
|
movl (%rdi), %eax
|
||||||
|
1: movl %eax, %edx
|
||||||
|
movl %eax, %ecx
|
||||||
|
orl %esi, %edx
|
||||||
|
lock
|
||||||
|
cmpxchgl %edx, (%rdi)
|
||||||
|
jnz 1b
|
||||||
|
movl %ecx, %eax
|
||||||
|
ret
|
||||||
|
FUNCTION_END(atomic_or)
|
||||||
|
|
||||||
|
/* int32 atomic_get(vint32 *value) */
|
||||||
|
FUNCTION(atomic_get):
|
||||||
|
movl (%rdi), %eax
|
||||||
|
1: lock
|
||||||
|
cmpxchgl %eax, (%rdi)
|
||||||
|
jnz 1b
|
||||||
|
ret
|
||||||
|
FUNCTION_END(atomic_get)
|
||||||
|
|
||||||
|
/* int64 atomic_set64(vint64 *value, int64 newValue) */
|
||||||
|
FUNCTION(atomic_set64):
|
||||||
|
movq %rsi, %rax
|
||||||
|
lock
|
||||||
|
xchgq %rax, (%rdi)
|
||||||
|
ret
|
||||||
|
FUNCTION_END(atomic_set64)
|
||||||
|
|
||||||
|
/* int64 atomic_test_and_set64(vint64 *value, int64 newValue, int64 testAgainst) */
|
||||||
|
FUNCTION(atomic_test_and_set64):
|
||||||
|
movq %rdx, %rax
|
||||||
|
lock
|
||||||
|
cmpxchgq %rsi, (%rdi)
|
||||||
|
ret
|
||||||
|
FUNCTION_END(atomic_test_and_set64)
|
||||||
|
|
||||||
|
/* int64 atomic_add64(vint64 *value, int64 addValue) */
|
||||||
|
FUNCTION(atomic_add64):
|
||||||
|
movq %rsi, %rax
|
||||||
|
lock
|
||||||
|
xaddq %rax, (%rdi)
|
||||||
|
ret
|
||||||
|
FUNCTION_END(atomic_add64)
|
||||||
|
|
||||||
|
/* int64 atomic_and64(vint64 *value, int64 andValue) */
|
||||||
|
FUNCTION(atomic_and64):
|
||||||
|
movq (%rdi), %rax
|
||||||
|
1: movq %rax, %rdx
|
||||||
|
movq %rax, %rcx
|
||||||
|
andq %rsi, %rdx
|
||||||
|
lock
|
||||||
|
cmpxchgq %rdx, (%rdi)
|
||||||
|
jnz 1b
|
||||||
|
movq %rcx, %rax
|
||||||
|
ret
|
||||||
|
FUNCTION_END(atomic_and64)
|
||||||
|
|
||||||
|
/* int64 atomic_or64(vint64 *value, int64 orValue) */
|
||||||
|
FUNCTION(atomic_or64):
|
||||||
|
movq (%rdi), %rax
|
||||||
|
1: movq %rax, %rdx
|
||||||
|
movq %rax, %rcx
|
||||||
|
orq %rsi, %rdx
|
||||||
|
lock
|
||||||
|
cmpxchgq %rdx, (%rdi)
|
||||||
|
jnz 1b
|
||||||
|
movq %rcx, %rax
|
||||||
|
ret
|
||||||
|
FUNCTION_END(atomic_or64)
|
||||||
|
|
||||||
|
/* int64 atomic_get64(vint64 *value) */
|
||||||
|
FUNCTION(atomic_get64):
|
||||||
|
movq (%rdi), %rax
|
||||||
|
1: lock
|
||||||
|
cmpxchgq %rax, (%rdi)
|
||||||
|
jnz 1b
|
||||||
|
ret
|
||||||
|
FUNCTION_END(atomic_get64)
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <asm_defs.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* uint16 __swap_int16(uint16 value) */
|
||||||
|
FUNCTION(__swap_int16):
|
||||||
|
movl %edi, %eax
|
||||||
|
bswap %eax
|
||||||
|
shr $16, %eax
|
||||||
|
ret
|
||||||
|
FUNCTION_END(__swap_int16)
|
||||||
|
|
||||||
|
/* uint32 __swap_int32(uint32 value) */
|
||||||
|
FUNCTION(__swap_int32):
|
||||||
|
movl %edi, %eax
|
||||||
|
bswap %eax
|
||||||
|
ret
|
||||||
|
FUNCTION_END(__swap_int32)
|
||||||
|
|
||||||
|
/* uint64 __swap_int64(uint64 value) */
|
||||||
|
FUNCTION(__swap_int64):
|
||||||
|
movq %rdi, %rax
|
||||||
|
bswap %rax
|
||||||
|
ret
|
||||||
|
FUNCTION_END(__swap_int64)
|
||||||
|
|
||||||
|
/* float __swap_float(float value) */
|
||||||
|
FUNCTION(__swap_float):
|
||||||
|
sub $8, %rsp
|
||||||
|
movss %xmm0, (%rsp)
|
||||||
|
movl (%rsp), %eax
|
||||||
|
bswap %eax
|
||||||
|
movl %eax, (%rsp)
|
||||||
|
movss (%rsp), %xmm0
|
||||||
|
add $8, %rsp
|
||||||
|
ret
|
||||||
|
FUNCTION_END(__swap_float)
|
||||||
|
|
||||||
|
/* double __swap_double(double value) */
|
||||||
|
FUNCTION(__swap_double):
|
||||||
|
sub $8, %rsp
|
||||||
|
movsd %xmm0, (%rsp)
|
||||||
|
movq (%rsp), %rax
|
||||||
|
bswap %rax
|
||||||
|
movq %rax, (%rsp)
|
||||||
|
movsd (%rsp), %xmm0
|
||||||
|
add $8, %rsp
|
||||||
|
ret
|
||||||
|
FUNCTION_END(__swap_double)
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
/*
|
||||||
|
Just a dummy to avoid a special case in the build system. system_time()
|
||||||
|
is implemented in system_time_asm.S.
|
||||||
|
*/
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
|
||||||
|
* Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*
|
||||||
|
* Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||||
|
* Distributed under the terms of the NewOS License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <asm_defs.h>
|
||||||
|
|
||||||
|
FUNCTION(__x86_setup_system_time):
|
||||||
|
ret
|
||||||
|
FUNCTION_END(__x86_setup_system_time)
|
||||||
|
|
||||||
|
// TODO: Implement these.
|
||||||
|
|
||||||
|
/* int64 system_time(); */
|
||||||
|
FUNCTION(system_time):
|
||||||
|
ud2a
|
||||||
|
ret
|
||||||
|
FUNCTION_END(system_time)
|
||||||
|
|
||||||
|
|
||||||
|
/* int64 system_time_nsecs(); */
|
||||||
|
FUNCTION(system_time_nsecs):
|
||||||
|
ud2a
|
||||||
|
ret
|
||||||
|
FUNCTION_END(system_time_nsecs)
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
/* saves the conversion factor needed for system_time */
|
||||||
|
.lcomm cv_factor 4
|
||||||
|
.lcomm cv_factor_nsecs 4
|
||||||
|
.lcomm cv_factor_nsecs_shift 1
|
||||||
|
|
||||||
|
|
||||||
|
.text
|
||||||
|
|
||||||
|
|
||||||
|
FUNCTION(__x86_setup_system_time):
|
||||||
|
movl 4(%esp), %eax
|
||||||
|
movl %eax, cv_factor
|
||||||
|
movl 8(%esp), %eax
|
||||||
|
movl %eax, cv_factor_nsecs
|
||||||
|
movb 12(%esp), %al
|
||||||
|
movb %al, cv_factor_nsecs_shift
|
||||||
|
ret
|
||||||
|
FUNCTION_END(__x86_setup_system_time)
|
||||||
|
|
||||||
|
|
||||||
|
/* int64 system_time(); */
|
||||||
|
FUNCTION(system_time):
|
||||||
|
pushl %ebx
|
||||||
|
pushl %ecx
|
||||||
|
movl cv_factor, %ebx
|
||||||
|
|
||||||
|
/* load 64-bit factor into %eax (low), %edx (high) */
|
||||||
|
rdtsc /* time in %edx,%eax */
|
||||||
|
|
||||||
|
movl %edx, %ecx /* save high half */
|
||||||
|
mull %ebx /* truncate %eax, but keep %edx */
|
||||||
|
movl %ecx, %eax
|
||||||
|
movl %edx, %ecx /* save high half of low */
|
||||||
|
mull %ebx /*, %eax*/
|
||||||
|
/* now compute [%edx, %eax] + [%ecx], propagating carry */
|
||||||
|
subl %ebx, %ebx /* need zero to propagate carry */
|
||||||
|
addl %ecx, %eax
|
||||||
|
adc %ebx, %edx
|
||||||
|
popl %ecx
|
||||||
|
popl %ebx
|
||||||
|
ret
|
||||||
|
FUNCTION_END(system_time)
|
||||||
|
|
||||||
|
|
||||||
|
/* int64 system_time_nsecs(); */
|
||||||
|
FUNCTION(system_time_nsecs):
|
||||||
|
testb $0, cv_factor_nsecs_shift
|
||||||
|
jne 1f
|
||||||
|
|
||||||
|
/* same algorithm as system_time(), just with a different factor */
|
||||||
|
|
||||||
|
pushl %ebx
|
||||||
|
pushl %ecx
|
||||||
|
movl cv_factor_nsecs, %ebx
|
||||||
|
|
||||||
|
/* load 64-bit factor into %eax (low), %edx (high) */
|
||||||
|
rdtsc /* time in %edx,%eax */
|
||||||
|
|
||||||
|
movl %edx, %ecx /* save high half */
|
||||||
|
mull %ebx /* truncate %eax, but keep %edx */
|
||||||
|
movl %ecx, %eax
|
||||||
|
movl %edx, %ecx /* save high half of low */
|
||||||
|
mull %ebx /*, %eax*/
|
||||||
|
/* now compute [%edx, %eax] + [%ecx], propagating carry */
|
||||||
|
subl %ebx, %ebx /* need zero to propagate carry */
|
||||||
|
addl %ecx, %eax
|
||||||
|
adc %ebx, %edx
|
||||||
|
popl %ecx
|
||||||
|
popl %ebx
|
||||||
|
ret
|
||||||
|
|
||||||
|
1:
|
||||||
|
/* TSC frequency is less than 1 GHz -- we shift everything up 16 bit */
|
||||||
|
|
||||||
|
pushl %ebx
|
||||||
|
pushl %ecx
|
||||||
|
pushl %esi
|
||||||
|
movl cv_factor_nsecs, %ebx
|
||||||
|
|
||||||
|
/* load 64-bit factor into %eax (low), %edx (high) */
|
||||||
|
rdtsc /* time in %edx,%eax */
|
||||||
|
|
||||||
|
/* save high half */
|
||||||
|
movl %edx, %ecx
|
||||||
|
|
||||||
|
/* multiply low half by conversion factor */
|
||||||
|
mull %ebx
|
||||||
|
|
||||||
|
/* save result */
|
||||||
|
movl %eax, %esi /* low half -> %esi */
|
||||||
|
movl %ecx, %eax
|
||||||
|
movl %edx, %ecx /* high half -> %ecx */
|
||||||
|
|
||||||
|
/* multiply high half by conversion factor */
|
||||||
|
mull %ebx
|
||||||
|
|
||||||
|
/* now compute [%edx, %eax] + [%ecx], propagating carry */
|
||||||
|
xorl %ebx, %ebx /* need zero to propagate carry */
|
||||||
|
addl %ecx, %eax
|
||||||
|
adc %ebx, %edx
|
||||||
|
|
||||||
|
/* shift the result left 16 bit */
|
||||||
|
shl $16, %edx
|
||||||
|
movl %eax, %ebx
|
||||||
|
shr $16, %ebx
|
||||||
|
orw %bx, %dx
|
||||||
|
shl $16, %eax
|
||||||
|
|
||||||
|
/* add the high 16 bit of the low half of the low product */
|
||||||
|
shr $16, %esi
|
||||||
|
orw %si, %ax
|
||||||
|
|
||||||
|
popl %esi
|
||||||
|
popl %ecx
|
||||||
|
popl %ebx
|
||||||
|
ret
|
||||||
|
FUNCTION_END(system_time_nsecs)
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Alex Smith, [email protected].
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef SETJMP_INTERNAL_H
|
||||||
|
#define SETJMP_INTERNAL_H
|
||||||
|
|
||||||
|
|
||||||
|
#define JMP_REGS_IP 0
|
||||||
|
#define JMP_REGS_SP 8
|
||||||
|
#define JMP_REGS_BP 16
|
||||||
|
#define JMP_REGS_BX 24
|
||||||
|
#define JMP_REGS_R12 32
|
||||||
|
#define JMP_REGS_R13 40
|
||||||
|
#define JMP_REGS_R14 48
|
||||||
|
#define JMP_REGS_R15 56
|
||||||
|
|
||||||
|
#include <asm_defs.h>
|
||||||
|
|
||||||
|
#endif /* SETJMP_INTERNAL_H */
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "setjmp_internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* int __siglongjmp(jmp_buf buffer, int value) */
|
||||||
|
FUNCTION(siglongjmp):
|
||||||
|
FUNCTION(longjmp):
|
||||||
|
FUNCTION(_longjmp):
|
||||||
|
// Restore new callee-save registers.
|
||||||
|
movq JMP_REGS_R15(%rdi), %r15
|
||||||
|
movq JMP_REGS_R14(%rdi), %r14
|
||||||
|
movq JMP_REGS_R13(%rdi), %r13
|
||||||
|
movq JMP_REGS_R12(%rdi), %r12
|
||||||
|
movq JMP_REGS_BX(%rdi), %rbx
|
||||||
|
movq JMP_REGS_BP(%rdi), %rbp
|
||||||
|
|
||||||
|
// Restore new stack pointer and push return address.
|
||||||
|
movq JMP_REGS_SP(%rdi), %rsp
|
||||||
|
movq JMP_REGS_IP(%rdi), %rax
|
||||||
|
push %rax
|
||||||
|
|
||||||
|
// __longjmp_return restores the signal mask and sets the return value.
|
||||||
|
call __longjmp_return
|
||||||
|
ret
|
||||||
|
FUNCTION_END(siglongjmp)
|
||||||
|
|
||||||
|
|
||||||
|
#pragma weak longjmp=siglongjmp
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2012, Alex Smith, alex@alex-smith.me.uk.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "setjmp_internal.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* int sigsetjmp(jmp_buf buffer, int saveMask) */
|
||||||
|
FUNCTION(__sigsetjmp):
|
||||||
|
FUNCTION(sigsetjmp):
|
||||||
|
// Save instruction/stack pointers.
|
||||||
|
movq (%rsp), %rax
|
||||||
|
movq %rax, JMP_REGS_IP(%rdi)
|
||||||
|
leaq 8(%rsp), %rax
|
||||||
|
movq %rax, JMP_REGS_SP(%rdi)
|
||||||
|
|
||||||
|
// Save callee-save registers.
|
||||||
|
movq %rbp, JMP_REGS_BP(%rdi)
|
||||||
|
movq %rbx, JMP_REGS_BX(%rdi)
|
||||||
|
movq %r12, JMP_REGS_R12(%rdi)
|
||||||
|
movq %r13, JMP_REGS_R13(%rdi)
|
||||||
|
movq %r14, JMP_REGS_R14(%rdi)
|
||||||
|
movq %r15, JMP_REGS_R15(%rdi)
|
||||||
|
|
||||||
|
// __setjmp_save_sigs handles signal mask and return value.
|
||||||
|
jmp __setjmp_save_sigs
|
||||||
|
FUNCTION_END(setjmp)
|
||||||
|
|
||||||
|
|
||||||
|
/* int setjmp(jmp_buf buffer) */
|
||||||
|
FUNCTION(setjmp):
|
||||||
|
// Jump to sigsetjmp with a zero saveMask.
|
||||||
|
xorl %edi, %edi
|
||||||
|
jmp sigsetjmp
|
||||||
|
FUNCTION_END(setjmp)
|
||||||
|
|
||||||
|
|
||||||
|
#pragma weak _setjmp=setjmp
|
||||||
Reference in New Issue
Block a user