about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorrofl0r <retnyg@gmx.net>2012-11-09 23:36:55 +0100
committerrofl0r <retnyg@gmx.net>2012-11-13 19:12:25 +0100
commit1c8eb8bad791fe9d01d0d4ab77882db634fa933d (patch)
treed3faf83663c1383f7ea16a0e6c68b3e2f4cc968a /src
parent7669d1e334e6b96455eece78da43bf830b93d697 (diff)
downloadmusl-1c8eb8bad791fe9d01d0d4ab77882db634fa933d.tar.gz
musl-1c8eb8bad791fe9d01d0d4ab77882db634fa933d.tar.xz
musl-1c8eb8bad791fe9d01d0d4ab77882db634fa933d.zip
PPC port cleaned up, static linking works well now.
Diffstat (limited to 'src')
-rw-r--r--src/internal/powerpc/syscall.s18
-rw-r--r--src/internal/ppc/syscall.S24
-rw-r--r--src/ldso/powerpc/dlsym.s (renamed from src/ldso/ppc/dlsym.S)3
-rw-r--r--src/ldso/powerpc/start.s23
-rw-r--r--src/ldso/ppc/start.S22
-rw-r--r--src/setjmp/powerpc/longjmp.s47
-rw-r--r--src/setjmp/powerpc/setjmp.s40
-rw-r--r--src/setjmp/ppc/longjmp.S17
-rw-r--r--src/setjmp/ppc/setjmp.S18
-rw-r--r--src/signal/powerpc/restore.s11
-rw-r--r--src/signal/powerpc/sigsetjmp.s34
-rw-r--r--src/signal/ppc/restore.S13
-rw-r--r--src/signal/ppc/sigsetjmp.S12
-rw-r--r--src/thread/powerpc/__set_thread_area.s11
-rw-r--r--src/thread/powerpc/__unmapself.s (renamed from src/thread/ppc/__unmapself.S)6
-rw-r--r--src/thread/powerpc/clone.s83
-rw-r--r--src/thread/powerpc/syscall_cp.s51
17 files changed, 321 insertions, 112 deletions
diff --git a/src/internal/powerpc/syscall.s b/src/internal/powerpc/syscall.s
new file mode 100644
index 00000000..bca620db
--- /dev/null
+++ b/src/internal/powerpc/syscall.s
@@ -0,0 +1,18 @@
+	.global __syscall
+	.type   __syscall,@function
+__syscall:
+	mr      0, 3                  # Save the system call number
+	mr      3, 4                  # Shift the arguments: arg1
+	mr      4, 5                  # arg2
+	mr      5, 6                  # arg3
+	mr      6, 7                  # arg4
+	mr      7, 8                  # arg5
+	mr      8, 9                  # arg6
+	sc
+	bnslr+ # return if not summary overflow
+	#else error:
+	# return negated value.
+	neg 3, 3
+	blr
+	.end    __syscall
+	.size   __syscall, .-__syscall
diff --git a/src/internal/ppc/syscall.S b/src/internal/ppc/syscall.S
deleted file mode 100644
index e56abc6f..00000000
--- a/src/internal/ppc/syscall.S
+++ /dev/null
@@ -1,24 +0,0 @@
-#include <bits/asm.h>
-        .global __syscall
-        .type   __syscall,@function
-__syscall:
-        mflr    r0
-        stw     r0, -4(r1)              // Save the return address.
-        mr      r0, r3                  // Save the system call number
-        mr      r3, r4                  // Shift the arguments: arg1
-        mr      r4, r5                  // arg2
-        mr      r5, r6                  // arg3
-        mr      r6, r7                  // arg4
-        mr      r7, r8                  // arg5
-        mr      r8, r9                  // arg6
-        sc
-        mfcr    r0                      // Check for an error
-        rlwinm  r4, r0, r0, 3, 3        // by checking for bit 28.
-        cmplwi  r0, r4, 0               // It is an error if non-zero.
-        beq     r0, 1f                  // Jump if not an error.
-        neg     r3, r3                  // Negate the error number.
-1:      lwz     r0, -4(r1)              // Restore the return address.
-        mtlr    r0
-	blr
-        .end    __syscall
-        .size   __syscall, .-__syscall
diff --git a/src/ldso/ppc/dlsym.S b/src/ldso/powerpc/dlsym.s
index e36de10b..20796176 100644
--- a/src/ldso/ppc/dlsym.S
+++ b/src/ldso/powerpc/dlsym.s
@@ -1,9 +1,8 @@
-#include <bits/asm.h>
         .text
         .global dlsym
         .type   dlsym,@function
 dlsym:
-        mflr    r5                      // The return address is arg3.
+        mflr    5                      # The return address is arg3.
         b       __dlsym
         .end    dlsym
         .size   dlsym, .-dlsym
diff --git a/src/ldso/powerpc/start.s b/src/ldso/powerpc/start.s
new file mode 100644
index 00000000..d2060e3d
--- /dev/null
+++ b/src/ldso/powerpc/start.s
@@ -0,0 +1,23 @@
+# FIXME : does not work, the small data array needs to be relocated.
+# see elfspec_ppc.pdf, page 76-84
+        .global _start
+        .type   _start,@function
+_start:
+        mr      9, 1                  # Save the original stack pointer.
+        clrrwi  1, 1, 4               # Align the stack to 16 bytes.
+        lis     13, _SDA_BASE_@ha      # r13 points to the small data area.
+        addi    13, 13, _SDA_BASE_@l
+        li      0, 0                   # Zero the frame pointer.
+        lwz     3, 0(9)               # and argc...
+        addi    4, 9, 4               # and argv ...
+        mtlr    0                      # Clear the link register.
+        # Go to the musl dynamic linker entry point.
+        bl      __dynlink
+        cmpi    4, 0, 3, 1            # Check for a 1.
+        bne     4, .                   # Stay here
+        mtlr    3                      # Set the link address...
+        li      3, 0
+        blr                             # and go.
+        .end    _start
+        .size   _start, .-_start
+
diff --git a/src/ldso/ppc/start.S b/src/ldso/ppc/start.S
deleted file mode 100644
index f3419824..00000000
--- a/src/ldso/ppc/start.S
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <bits/asm.h>
-        .global _start
-        .type   _start,@function
-_start:
-        mr      r9, r1                  // Save the original stack pointer.
-        clrrwi  r1, r1, 4               // Align the stack to 16 bytes.
-        lis     r13, _SDA_BASE_@ha      // r13 points to the small data area.
-        addi    r13, r13, _SDA_BASE_@l  //
-        li      r0, 0                   // Zero the frame pointer.
-        lwz     r3, 0(r9)               // and argc...
-        addi    r4, r9, 4               // and argv ...
-        mtlr    r0                      // Clear the link register.
-        // Go to the musl dynamic linker entry point.
-        bl      __dynlink
-        cmpi    r4, 0, r3, 1            // Check for a 1.
-        bne     r4, .                   // Stay here
-        mtlr    r3                      // Set the link address...
-        li      r3, 0
-        blr                             // and go.
-        .end    _start
-        .size   _start, .-_start
-
diff --git a/src/setjmp/powerpc/longjmp.s b/src/setjmp/powerpc/longjmp.s
new file mode 100644
index 00000000..e3740901
--- /dev/null
+++ b/src/setjmp/powerpc/longjmp.s
@@ -0,0 +1,47 @@
+        .global _longjmp
+        .global longjmp
+        .type   _longjmp,@function
+        .type   longjmp,@function
+_longjmp:
+longjmp:
+# void longjmp(jmp_buf env, int val);
+# put val into return register and restore the env saved in setjmp
+# if val(r4) is 0, put 1 there.
+	# 0) move old return address into r0
+	lwz 0, 0(3)
+	# 1) put it into link reg
+	mtlr 0
+	#2 ) restore stack ptr
+	lwz 1, 4(3)
+	#3) restore control reg
+	lwz 0, 8(3)
+	mtcr 0
+	#4) restore r14-r31
+	lwz 14, 12(3)
+	lwz 15, 16(3)
+	lwz 16, 20(3)
+	lwz 17, 24(3)
+	lwz 18, 28(3)
+	lwz 19, 32(3)
+	lwz 20, 36(3)
+	lwz 21, 40(3)
+	lwz 22, 44(3)
+	lwz 23, 48(3)
+	lwz 24, 52(3)
+	lwz 25, 56(3)
+	lwz 26, 60(3)
+	lwz 27, 64(3)
+	lwz 28, 68(3)
+	lwz 29, 72(3)
+	lwz 30, 76(3)
+	lwz 31, 80(3)
+	#5) put val into return reg r3
+	mr 3, 4
+
+	#6) check if return value is 0, make it 1 in that case
+	cmpwi cr7, 4, 0
+	bne cr7, 1f
+	li 3, 1
+1:
+	blr
+
diff --git a/src/setjmp/powerpc/setjmp.s b/src/setjmp/powerpc/setjmp.s
new file mode 100644
index 00000000..27c975e4
--- /dev/null
+++ b/src/setjmp/powerpc/setjmp.s
@@ -0,0 +1,40 @@
+        .global __setjmp
+        .global _setjmp
+        .global setjmp
+        .type   __setjmp,@function
+        .type   _setjmp,@function
+        .type   setjmp,@function
+__setjmp:
+_setjmp:
+setjmp:
+	# 0) store IP int 0, then into the jmpbuf pointed to by r3 (first arg)
+	mflr 0
+	stw 0, 0(3)
+	# 1) store reg1 (SP)
+	stw 1, 4(3)
+	# 2) store cr
+	mfcr 0
+	stw 0, 8(3)
+	# 3) store r14-31
+	stw 14, 12(3)
+	stw 15, 16(3)
+	stw 16, 20(3)
+	stw 17, 24(3)
+	stw 18, 28(3)
+	stw 19, 32(3)
+	stw 20, 36(3)
+	stw 21, 40(3)
+	stw 22, 44(3)
+	stw 23, 48(3)
+	stw 24, 52(3)
+	stw 25, 56(3)
+	stw 26, 60(3)
+	stw 27, 64(3)
+	stw 28, 68(3)
+	stw 29, 72(3)
+	stw 30, 76(3)
+	stw 31, 80(3)
+	# 4) set return value to 0
+	li 3, 0
+	# 5) return
+	blr
diff --git a/src/setjmp/ppc/longjmp.S b/src/setjmp/ppc/longjmp.S
deleted file mode 100644
index df13c7b1..00000000
--- a/src/setjmp/ppc/longjmp.S
+++ /dev/null
@@ -1,17 +0,0 @@
-#include <bits/asm.h>
-        .global _longjmp
-        .global longjmp
-        .type   _longjmp,@function
-        .type   longjmp,@function
-_longjmp:
-longjmp:
-        cmpi    7, 0, r3, 0
-        bne     7, 1f
-        addi    r3, r3, 1
-1:      lmw     r8, 4(r3)               // load r8-r31
-        mr      r6, r4
-        mtlr    r11
-        mtcr    r12
-        mr      r2, r9
-        mr      r1, r10
-        blr 
diff --git a/src/setjmp/ppc/setjmp.S b/src/setjmp/ppc/setjmp.S
deleted file mode 100644
index 7d0b9ac5..00000000
--- a/src/setjmp/ppc/setjmp.S
+++ /dev/null
@@ -1,18 +0,0 @@
-#include <bits/asm.h>
-        .global __setjmp
-        .global _setjmp
-        .global setjmp
-        .type   __setjmp,@function
-        .type   _setjmp,@function
-        .type   setjmp,@function
-__setjmp:
-_setjmp:
-setjmp:
-        mflr    r11
-        mfcr    r12
-        mr      r10, r1
-        mr      r9, r2
-        stmw    r8, 0(r3)               // save r8-r31
-        li      r3,0
-        blr
-
diff --git a/src/signal/powerpc/restore.s b/src/signal/powerpc/restore.s
new file mode 100644
index 00000000..fd7bcba5
--- /dev/null
+++ b/src/signal/powerpc/restore.s
@@ -0,0 +1,11 @@
+        .global __restore
+        .type __restore,%function
+__restore:
+        li      0, 119 #__NR_sigreturn
+        sc
+
+        .global __restore_rt
+        .type __restore_rt,%function
+__restore_rt:
+        li      0, 172 # __NR_rt_sigreturn
+        sc
diff --git a/src/signal/powerpc/sigsetjmp.s b/src/signal/powerpc/sigsetjmp.s
new file mode 100644
index 00000000..0b79dcce
--- /dev/null
+++ b/src/signal/powerpc/sigsetjmp.s
@@ -0,0 +1,34 @@
+        .global sigsetjmp
+        .type sigsetjmp,%function
+sigsetjmp:
+	#int sigsetjmp(sigjmp_buf buf, int save)
+	#		r3		r4
+	#0) store save into buf->__fl
+	stw 4, 256(3)
+	#1) compare save with 0
+	cmpwi cr7, 4, 0
+	#2) if its 0, goto setjmp code
+	beq- cr7, 1f
+	#3) else: we must call pthread_sigmask(SIG_SETMASK, 0, (sigset_t *)buf->__ss);
+	# thus store r3 on the stack, to restore it later
+	stw 3, -4(1)
+	# store old link reg
+	mflr 0
+	stw 0, -8(1)
+	# increase stack frame by 16
+	subi 1, 1, 16
+	# put pointer to ss buf into r5 (3rd arg)
+	addi 5, 3, 260
+	# put "2" i.e. SIG_SETMASK in r3
+	li 3, 2
+	li 4, 0
+	bl pthread_sigmask
+	#restore sp
+	addi 1, 1, 16
+	#restore r3
+	lwz 3, -4(1)
+	#restore link reg
+	lwz 0, -8(1)
+	mtlr 0
+1:
+	b setjmp
diff --git a/src/signal/ppc/restore.S b/src/signal/ppc/restore.S
deleted file mode 100644
index 50887e91..00000000
--- a/src/signal/ppc/restore.S
+++ /dev/null
@@ -1,13 +0,0 @@
-#include <bits/asm.h>
-#include <bits/syscall.h>
-        .global __restore
-        .type __restore,@function
-__restore:
-        li      r0, __NR_sigreturn
-        sc
-
-        .global __restore_rt
-        .type __restore_rt,@function
-__restore_rt:
-        li      r0, __NR_rt_sigreturn
-        sc
diff --git a/src/signal/ppc/sigsetjmp.S b/src/signal/ppc/sigsetjmp.S
deleted file mode 100644
index 527ef8e4..00000000
--- a/src/signal/ppc/sigsetjmp.S
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <bits/asm.h>
-        .global sigsetjmp
-        .type sigsetjmp,@function
-sigsetjmp:
-        lwz     r4, 64*4-2*4(r3)        // Second last long.
-        cmpi    r4, 0, r4, 0
-        bne     r4, 1f
-        addi    r5, r3, 64*4-1*4        // Address of last long.
-        li      r4, 0
-        li      r3, 2
-        bl      sigprocmask
-1:      b       setjmp
diff --git a/src/thread/powerpc/__set_thread_area.s b/src/thread/powerpc/__set_thread_area.s
new file mode 100644
index 00000000..c1a34c1f
--- /dev/null
+++ b/src/thread/powerpc/__set_thread_area.s
@@ -0,0 +1,11 @@
+.text
+.global __set_thread_area
+.type   __set_thread_area, %function
+__set_thread_area:
+	# mov pointer in reg3 into r2
+	mr 2, 3
+	# put 0 into return reg
+	li 3, 0
+	# return
+	blr
+
diff --git a/src/thread/ppc/__unmapself.S b/src/thread/powerpc/__unmapself.s
index e14663e7..bb3724e3 100644
--- a/src/thread/ppc/__unmapself.S
+++ b/src/thread/powerpc/__unmapself.s
@@ -1,11 +1,9 @@
-#include <bits/asm.h>
-#include <bits/syscall.h>
         .text
         .global __unmapself
         .type   __unmapself,%function
 __unmapself:
-        li      r0, __NR_munmap
+        li      0, 91 # __NR_munmap
         sc
-        li      r0, __NR_exit
+        li      0, 1 #__NR_exit
         sc
         blr
diff --git a/src/thread/powerpc/clone.s b/src/thread/powerpc/clone.s
new file mode 100644
index 00000000..cea69e99
--- /dev/null
+++ b/src/thread/powerpc/clone.s
@@ -0,0 +1,83 @@
+.text
+.global __clone
+.type __clone, %function
+__clone:
+# int clone(fn, stack, flags, arg, ptid, tls, ctid)
+#            a  b       c     d     e    f    g
+#            3  4       5     6     7    8    9
+# pseudo C code:
+# tid = syscall(SYS_clone,c,b,e,f,g);
+# if (!tid) syscall(SYS_exit, a(d));
+# return tid;
+
+# SYS_clone = 120
+# SYS_exit = 1
+
+# in order that the child can find the start func and its arg, we need to store it into
+# non-volative regs. to do so, we have to store those 2 regs into our stackframe, so
+# we can restore them later.
+stw 30, -4(1)
+stw 31, -8(1)
+subi 1, 1, 16 
+
+# save r3 (func) into r30, and r6(arg) into r31
+mr 30, 3
+mr 31, 6
+
+#move c into first arg
+mr 3, 5
+#mr 4, 4
+mr 5, 7
+mr 6, 8
+mr 7, 9
+
+# move syscall number into r0    
+li 0, 120
+
+sc
+
+# check for syscall error
+#this code should be more efficient, but it borks
+#bns+ 1f # jump to label 1 if no summary overflow.
+#else
+#neg 3, 3 #negate the result (errno)
+#b 2f # jump to epilogue
+
+# this error check code at least does not spoil the clone call.
+#mfcr    0                      # Check for an error
+#rlwinm  4, 0, 0, 3, 3        # by checking for bit 28.
+#cmplwi  0, 4, 0               # It is an error if non-zero.
+#beq     0, 1f                  # Jump if not an error.
+#neg     3, 3                  # Negate the error number.
+#b       2f # jump to epilogue
+1:
+# compare sc result with 0
+cmpwi cr7, 3, 0
+
+# if not 0, jump to end
+bne cr7, 2f
+
+#else: we're the child
+#call funcptr
+# move arg (d) into r3
+mr 3, 31
+#move r30 (funcptr) into CTR reg
+mtctr 30
+# call CTR reg
+bctrl
+# mov SYS_exit into r0 (the exit param is already in r3)
+li 0, 1
+sc
+
+2:
+
+# restore stack
+addi 1, 1, 16
+lwz 30, -4(1)
+lwz 31, -8(1)
+
+blr
+
+
+
+
diff --git a/src/thread/powerpc/syscall_cp.s b/src/thread/powerpc/syscall_cp.s
new file mode 100644
index 00000000..2c97ca04
--- /dev/null
+++ b/src/thread/powerpc/syscall_cp.s
@@ -0,0 +1,51 @@
+#r0: volatile. may be modified during linkage.
+#r1: stack frame: 16 byte alignment.
+#r2: tls/thread pointer on pp32
+#r3,r4: return values, first args
+#r5-r10: args
+#r11-r12: volatile. may be modified during linkage
+#r13: "small data area" pointer
+#r14 - r30: local vars
+#r31: local or environment pointer
+
+#r1, r14-31: belong to the caller, must be saved and restored
+#r0, r3-r12, ctr, xer: volatile, not preserved
+#r0,r11,r12: may be altered by cross-module call, 
+#"a func cannot depend on that these regs have the values placed by the caller"
+
+#the fields CR2,CR2,CR4 of the cond reg must be preserved
+#LR (link reg) shall contain the funcs return address
+	.text
+	.global __syscall_cp_asm
+	.type   __syscall_cp_asm,%function
+__syscall_cp_asm:
+	# at enter: r3 = pointer to self->cancel, r4: syscall no, r5: first arg, r6: 2nd, r7: 3rd, r8: 4th, r9: 5th, r10: 6th
+	.global __cp_begin
+__cp_begin:
+	# r3 holds first argument, its a pointer to self->cancel. 
+	# we must compare the dereferenced value with 0 and jump to __cancel if its not
+	
+	lwz 0, 0(3) #deref pointer into r0
+	
+	cmpwi cr7, 0, 0 #compare r0 with 0, store result in cr7. 
+	beq+ cr7, 1f #jump to label 1 if r0 was 0
+	
+	b __cancel #else call cancel 
+	# (the return address is not needed, since __cancel never returns)
+1:
+	#ok, the cancel flag was not set
+	# syscall: number goes to r0, the rest 3-8
+	mr      0, 4                  # put the system call number into r0
+	mr      3, 5                  # Shift the arguments: arg1
+	mr      4, 6                  # arg2
+	mr      5, 7                  # arg3
+	mr      6, 8                  # arg4
+	mr      7, 9                  # arg5
+	mr      8, 10                  # arg6
+	sc
+	.global __cp_end
+__cp_end:
+	bnslr+ # return if no summary overflow. 
+	#else negate result.
+	neg 3, 3
+	blr