about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/fenv/aarch64/fenv.s67
-rw-r--r--src/internal/aarch64/syscall.s13
-rw-r--r--src/ldso/aarch64/dlsym.s5
-rw-r--r--src/ldso/aarch64/start.s18
-rw-r--r--src/ldso/aarch64/tlsdesc.s92
-rw-r--r--src/math/aarch64/fabs.s6
-rw-r--r--src/math/aarch64/fabsf.s6
-rw-r--r--src/math/aarch64/sqrt.s6
-rw-r--r--src/math/aarch64/sqrtf.s6
-rw-r--r--src/setjmp/aarch64/longjmp.s24
-rw-r--r--src/setjmp/aarch64/setjmp.s24
-rw-r--r--src/signal/aarch64/restore.s8
-rw-r--r--src/signal/aarch64/sigsetjmp.s19
-rw-r--r--src/thread/aarch64/__set_thread_area.s6
-rw-r--r--src/thread/aarch64/__unmapself.s7
-rw-r--r--src/thread/aarch64/clone.s29
-rw-r--r--src/thread/aarch64/syscall_cp.s27
17 files changed, 363 insertions, 0 deletions
diff --git a/src/fenv/aarch64/fenv.s b/src/fenv/aarch64/fenv.s
new file mode 100644
index 00000000..f0db5d9d
--- /dev/null
+++ b/src/fenv/aarch64/fenv.s
@@ -0,0 +1,67 @@
+.global fegetround
+.type fegetround,%function
+fegetround:
+	mrs x0, fpcr
+	and w0, w0, #0xc00000
+	ret
+
+.global __fesetround
+.type __fesetround,%function
+__fesetround:
+	mrs x1, fpcr
+	bic w1, w1, #0xc00000
+	orr w1, w1, w0
+	msr fpcr, x1
+	mov w0, #0
+	ret
+
+.global fetestexcept
+.type fetestexcept,%function
+fetestexcept:
+	and w0, w0, #0x1f
+	mrs x1, fpsr
+	and w0, w0, w1
+	ret
+
+.global feclearexcept
+.type feclearexcept,%function
+feclearexcept:
+	and w0, w0, #0x1f
+	mrs x1, fpsr
+	bic w1, w1, w0
+	msr fpsr, x1
+	mov w0, #0
+	ret
+
+.global feraiseexcept
+.type feraiseexcept,%function
+feraiseexcept:
+	and w0, w0, #0x1f
+	mrs x1, fpsr
+	orr w1, w1, w0
+	msr fpsr, x1
+	mov w0, #0
+	ret
+
+.global fegetenv
+.type fegetenv,%function
+fegetenv:
+	mrs x1, fpcr
+	mrs x2, fpsr
+	stp w1, w2, [x0]
+	mov w0, #0
+	ret
+
+// TODO preserve some bits
+.global fesetenv
+.type fesetenv,%function
+fesetenv:
+	mov x1, #0
+	mov x2, #0
+	cmn x0, #1
+	b.eq 1f
+	ldp w1, w2, [x0]
+1:	msr fpcr, x1
+	msr fpsr, x2
+	mov w0, #0
+	ret
diff --git a/src/internal/aarch64/syscall.s b/src/internal/aarch64/syscall.s
new file mode 100644
index 00000000..48fac924
--- /dev/null
+++ b/src/internal/aarch64/syscall.s
@@ -0,0 +1,13 @@
+.global __syscall
+.type __syscall,%function
+__syscall:
+	uxtw x8,w0
+	mov x0,x1
+	mov x1,x2
+	mov x2,x3
+	mov x3,x4
+	mov x4,x5
+	mov x5,x6
+	mov x6,x7
+	svc 0
+	ret
diff --git a/src/ldso/aarch64/dlsym.s b/src/ldso/aarch64/dlsym.s
new file mode 100644
index 00000000..be2dce52
--- /dev/null
+++ b/src/ldso/aarch64/dlsym.s
@@ -0,0 +1,5 @@
+.global dlsym
+.type dlsym,%function
+dlsym:
+	mov x2,x30
+	b __dlsym
diff --git a/src/ldso/aarch64/start.s b/src/ldso/aarch64/start.s
new file mode 100644
index 00000000..41d1d1e2
--- /dev/null
+++ b/src/ldso/aarch64/start.s
@@ -0,0 +1,18 @@
+.global _dlstart
+_dlstart:
+	ldr x0,[sp]
+	add x1,sp,#8
+	bl __dynlink
+	mov x1,sp
+	ldr x2,[x1],#8
+1:	sub x2,x2,1
+	ldr x3,[x1],#8
+	cmn x3,#1
+	b.eq 1b
+	add x2,x2,1
+	str x3,[x1,#-8]!
+	str x2,[x1,#-8]!
+	mov sp,x1
+	mov x1,x0
+	mov x0,#0
+	blr x1
diff --git a/src/ldso/aarch64/tlsdesc.s b/src/ldso/aarch64/tlsdesc.s
new file mode 100644
index 00000000..32064bd7
--- /dev/null
+++ b/src/ldso/aarch64/tlsdesc.s
@@ -0,0 +1,92 @@
+// long __tlsdesc_static(long *a)
+// {
+// 	return a[1];
+// }
+.global __tlsdesc_static
+.type __tlsdesc_static,@function
+__tlsdesc_static:
+	ldr x0,[x0,#8]
+	ret
+
+// long __tlsdesc_dynamic(long *a)
+// {
+// 	struct {size_t modidx,off;} *p = (void*)a[1];
+// 	size_t *dtv = *(size_t**)(tp + 16 - 8);
+// 	if (p->modidx <= dtv[0])
+// 		return dtv[p->modidx] + p->off - tp;
+// 	return __tls_get_addr(p) - tp;
+// }
+.global __tlsdesc_dynamic
+.type __tlsdesc_dynamic,@function
+__tlsdesc_dynamic:
+	stp x1,x2,[sp,#-32]!
+	stp x3,x4,[sp,#16]
+	mrs x1,tpidr_el0      // tp
+	ldr x0,[x0,#8]        // p
+	ldr x2,[x0]           // p->modidx
+	add x3,x1,#8
+	ldr x3,[x3]           // dtv
+	ldr x4,[x3]           // dtv[0]
+	cmp x2,x4
+	b.hi 1f
+	ldr x2,[x3,x2,lsl #3] // dtv[p->modidx]
+	ldr x0,[x0,#8]        // p->off
+	add x0,x0,x2
+2:	sub x0,x0,x1
+	ldp x3,x4,[sp,#16]
+	ldp x1,x2,[sp],#32
+	ret
+
+	// save all registers __tls_get_addr may clobber
+	// ugly because addr offset must be in [-512,509]
+1:	stp x29,x30,[sp,#-160]!
+	stp x5,x6,[sp,#16]
+	stp x7,x8,[sp,#32]
+	stp x9,x10,[sp,#48]
+	stp x11,x12,[sp,#64]
+	stp x13,x14,[sp,#80]
+	stp x15,x16,[sp,#96]
+	stp x17,x18,[sp,#112]
+	stp q0,q1,[sp,#128]
+	stp q2,q3,[sp,#-480]!
+	stp q4,q5,[sp,#32]
+	stp q6,q7,[sp,#64]
+	stp q8,q9,[sp,#96]
+	stp q10,q11,[sp,#128]
+	stp q12,q13,[sp,#160]
+	stp q14,q15,[sp,#192]
+	stp q16,q17,[sp,#224]
+	stp q18,q19,[sp,#256]
+	stp q20,q21,[sp,#288]
+	stp q22,q23,[sp,#320]
+	stp q24,q25,[sp,#352]
+	stp q26,q27,[sp,#384]
+	stp q28,q29,[sp,#416]
+	stp q30,q31,[sp,#448]
+	bl __tls_get_addr
+	mrs x1,tpidr_el0
+	ldp q4,q5,[sp,#32]
+	ldp q6,q7,[sp,#64]
+	ldp q8,q9,[sp,#96]
+	ldp q10,q11,[sp,#128]
+	ldp q12,q13,[sp,#160]
+	ldp q14,q15,[sp,#192]
+	ldp q16,q17,[sp,#224]
+	ldp q18,q19,[sp,#256]
+	ldp q20,q21,[sp,#288]
+	ldp q22,q23,[sp,#320]
+	ldp q24,q25,[sp,#352]
+	ldp q26,q27,[sp,#384]
+	ldp q28,q29,[sp,#416]
+	ldp q30,q31,[sp,#448]
+	ldp q2,q3,[sp],#480
+	ldp x5,x6,[sp,#16]
+	ldp x7,x8,[sp,#32]
+	ldp x9,x10,[sp,#48]
+	ldp x11,x12,[sp,#64]
+	ldp x13,x14,[sp,#80]
+	ldp x15,x16,[sp,#96]
+	ldp x17,x18,[sp,#112]
+	ldp q0,q1,[sp,#128]
+	ldp x29,x30,[sp],#160
+	b 2b
diff --git a/src/math/aarch64/fabs.s b/src/math/aarch64/fabs.s
new file mode 100644
index 00000000..8c04d091
--- /dev/null
+++ b/src/math/aarch64/fabs.s
@@ -0,0 +1,6 @@
+.text
+.global fabs
+.type   fabs,%function
+fabs:
+	fabs d0, d0
+	ret
diff --git a/src/math/aarch64/fabsf.s b/src/math/aarch64/fabsf.s
new file mode 100644
index 00000000..6e96dd43
--- /dev/null
+++ b/src/math/aarch64/fabsf.s
@@ -0,0 +1,6 @@
+.text
+.global fabsf
+.type   fabsf,%function
+fabsf:
+	fabs s0, s0
+	ret
diff --git a/src/math/aarch64/sqrt.s b/src/math/aarch64/sqrt.s
new file mode 100644
index 00000000..1917e18d
--- /dev/null
+++ b/src/math/aarch64/sqrt.s
@@ -0,0 +1,6 @@
+.text
+.global sqrt
+.type   sqrt,%function
+sqrt:
+	fsqrt d0, d0
+	ret
diff --git a/src/math/aarch64/sqrtf.s b/src/math/aarch64/sqrtf.s
new file mode 100644
index 00000000..1639497b
--- /dev/null
+++ b/src/math/aarch64/sqrtf.s
@@ -0,0 +1,6 @@
+.text
+.global sqrtf
+.type   sqrtf,%function
+sqrtf:
+	fsqrt s0, s0
+	ret
diff --git a/src/setjmp/aarch64/longjmp.s b/src/setjmp/aarch64/longjmp.s
new file mode 100644
index 00000000..7c4655fa
--- /dev/null
+++ b/src/setjmp/aarch64/longjmp.s
@@ -0,0 +1,24 @@
+.global _longjmp
+.global longjmp
+.type _longjmp,%function
+.type longjmp,%function
+_longjmp:
+longjmp:
+	// IHI0055B_aapcs64.pdf 5.1.1, 5.1.2 callee saved registers
+	ldp x19, x20, [x0,#0]
+	ldp x21, x22, [x0,#16]
+	ldp x23, x24, [x0,#32]
+	ldp x25, x26, [x0,#48]
+	ldp x27, x28, [x0,#64]
+	ldp x29, x30, [x0,#80]
+	ldr x2, [x0,#104]
+	mov sp, x2
+	ldp d8 , d9, [x0,#112]
+	ldp d10, d11, [x0,#128]
+	ldp d12, d13, [x0,#144]
+	ldp d14, d15, [x0,#160]
+
+	mov x0, x1
+	cbnz x1, 1f
+	mov x0, #1
+1:	br x30
diff --git a/src/setjmp/aarch64/setjmp.s b/src/setjmp/aarch64/setjmp.s
new file mode 100644
index 00000000..f49288aa
--- /dev/null
+++ b/src/setjmp/aarch64/setjmp.s
@@ -0,0 +1,24 @@
+.global __setjmp
+.global _setjmp
+.global setjmp
+.type __setjmp,@function
+.type _setjmp,@function
+.type setjmp,@function
+__setjmp:
+_setjmp:
+setjmp:
+	// IHI0055B_aapcs64.pdf 5.1.1, 5.1.2 callee saved registers
+	stp x19, x20, [x0,#0]
+	stp x21, x22, [x0,#16]
+	stp x23, x24, [x0,#32]
+	stp x25, x26, [x0,#48]
+	stp x27, x28, [x0,#64]
+	stp x29, x30, [x0,#80]
+	mov x2, sp
+	str x2, [x0,#104]
+	stp  d8,  d9, [x0,#112]
+	stp d10, d11, [x0,#128]
+	stp d12, d13, [x0,#144]
+	stp d14, d15, [x0,#160]
+	mov x0, #0
+	ret
diff --git a/src/signal/aarch64/restore.s b/src/signal/aarch64/restore.s
new file mode 100644
index 00000000..d3d0243d
--- /dev/null
+++ b/src/signal/aarch64/restore.s
@@ -0,0 +1,8 @@
+.global __restore
+.type __restore,%function
+__restore:
+.global __restore_rt
+.type __restore_rt,%function
+__restore_rt:
+	mov x8,#139 // SYS_rt_sigreturn
+	svc 0
diff --git a/src/signal/aarch64/sigsetjmp.s b/src/signal/aarch64/sigsetjmp.s
new file mode 100644
index 00000000..e0f83f06
--- /dev/null
+++ b/src/signal/aarch64/sigsetjmp.s
@@ -0,0 +1,19 @@
+.global sigsetjmp
+.global __sigsetjmp
+.type sigsetjmp,%function
+.type __sigsetjmp,%function
+sigsetjmp:
+__sigsetjmp:
+	str x1,[x0,#176]
+	cbz x1,setjmp
+
+	// TODO errno?
+	// sigprocmask(SIG_SETMASK, 0, (sigset_t*)buf->__ss);
+	stp x0,x30,[sp,#-16]!
+	add x2,x0,#184
+	mov x1,#0
+	mov x0,#2
+	bl sigprocmask
+	ldp x0,x30,[sp],#16
+
+	b setjmp
diff --git a/src/thread/aarch64/__set_thread_area.s b/src/thread/aarch64/__set_thread_area.s
new file mode 100644
index 00000000..97a80acc
--- /dev/null
+++ b/src/thread/aarch64/__set_thread_area.s
@@ -0,0 +1,6 @@
+.global __set_thread_area
+.type   __set_thread_area,@function
+__set_thread_area:
+	msr tpidr_el0,x0
+	mov w0,#0
+	ret
diff --git a/src/thread/aarch64/__unmapself.s b/src/thread/aarch64/__unmapself.s
new file mode 100644
index 00000000..2c5d254f
--- /dev/null
+++ b/src/thread/aarch64/__unmapself.s
@@ -0,0 +1,7 @@
+.global __unmapself
+.type   __unmapself,%function
+__unmapself:
+	mov x8,#215 // SYS_munmap
+	svc 0
+	mov x8,#93 // SYS_exit
+	svc 0
diff --git a/src/thread/aarch64/clone.s b/src/thread/aarch64/clone.s
new file mode 100644
index 00000000..50af913c
--- /dev/null
+++ b/src/thread/aarch64/clone.s
@@ -0,0 +1,29 @@
+// __clone(func, stack, flags, arg, ptid, tls, ctid)
+//         x0,   x1,    w2,    x3,  x4,   x5,  x6
+
+// syscall(SYS_clone, flags, stack, ptid, tls, ctid)
+//         x8,        x0,    x1,    x2,   x3,  x4
+
+.global __clone
+.type   __clone,%function
+__clone:
+	// align stack and save func,arg
+	and x1,x1,#-16
+	stp x0,x3,[x1,#-16]!
+
+	// syscall
+	uxtw x0,w2
+	mov x2,x4
+	mov x3,x5
+	mov x4,x6
+	mov x8,#220 // SYS_clone
+	svc #0
+
+	cbz x0,1f
+	// parent
+	ret
+	// child
+1:	ldp x1,x0,[sp],#16
+	blr x1
+	mov x8,#93 // SYS_exit
+	svc #0
diff --git a/src/thread/aarch64/syscall_cp.s b/src/thread/aarch64/syscall_cp.s
new file mode 100644
index 00000000..6302a0bd
--- /dev/null
+++ b/src/thread/aarch64/syscall_cp.s
@@ -0,0 +1,27 @@
+// __syscall_cp_asm(&self->cancel, nr, u, v, w, x, y, z)
+//                  x0             x1  x2 x3 x4 x5 x6 x7
+
+// syscall(nr, u, v, w, x, y, z)
+//         x8  x0 x1 x2 x3 x4 x5
+
+.global __syscall_cp_asm
+.type __syscall_cp_asm,%function
+__syscall_cp_asm:
+.global __cp_begin
+__cp_begin:
+	ldr w0,[x0]
+	cbnz w0,1f
+	mov x8,x1
+	mov x0,x2
+	mov x1,x3
+	mov x2,x4
+	mov x3,x5
+	mov x4,x6
+	mov x5,x7
+	svc 0
+.global __cp_end
+__cp_end:
+	ret
+
+	// cbnz might not be able to jump far enough
+1:	b __cancel