From 1c8eb8bad791fe9d01d0d4ab77882db634fa933d Mon Sep 17 00:00:00 2001 From: rofl0r Date: Fri, 9 Nov 2012 23:36:55 +0100 Subject: PPC port cleaned up, static linking works well now. --- src/internal/powerpc/syscall.s | 18 ++++++++ src/internal/ppc/syscall.S | 24 ---------- src/ldso/powerpc/dlsym.s | 8 ++++ src/ldso/powerpc/start.s | 23 ++++++++++ src/ldso/ppc/dlsym.S | 9 ---- src/ldso/ppc/start.S | 22 --------- src/setjmp/powerpc/longjmp.s | 47 +++++++++++++++++++ src/setjmp/powerpc/setjmp.s | 40 ++++++++++++++++ src/setjmp/ppc/longjmp.S | 17 ------- src/setjmp/ppc/setjmp.S | 18 -------- src/signal/powerpc/restore.s | 11 +++++ src/signal/powerpc/sigsetjmp.s | 34 ++++++++++++++ src/signal/ppc/restore.S | 13 ------ src/signal/ppc/sigsetjmp.S | 12 ----- src/thread/powerpc/__set_thread_area.s | 11 +++++ src/thread/powerpc/__unmapself.s | 9 ++++ src/thread/powerpc/clone.s | 83 ++++++++++++++++++++++++++++++++++ src/thread/powerpc/syscall_cp.s | 51 +++++++++++++++++++++ src/thread/ppc/__unmapself.S | 11 ----- 19 files changed, 335 insertions(+), 126 deletions(-) create mode 100644 src/internal/powerpc/syscall.s delete mode 100644 src/internal/ppc/syscall.S create mode 100644 src/ldso/powerpc/dlsym.s create mode 100644 src/ldso/powerpc/start.s delete mode 100644 src/ldso/ppc/dlsym.S delete mode 100644 src/ldso/ppc/start.S create mode 100644 src/setjmp/powerpc/longjmp.s create mode 100644 src/setjmp/powerpc/setjmp.s delete mode 100644 src/setjmp/ppc/longjmp.S delete mode 100644 src/setjmp/ppc/setjmp.S create mode 100644 src/signal/powerpc/restore.s create mode 100644 src/signal/powerpc/sigsetjmp.s delete mode 100644 src/signal/ppc/restore.S delete mode 100644 src/signal/ppc/sigsetjmp.S create mode 100644 src/thread/powerpc/__set_thread_area.s create mode 100644 src/thread/powerpc/__unmapself.s create mode 100644 src/thread/powerpc/clone.s create mode 100644 src/thread/powerpc/syscall_cp.s delete mode 100644 src/thread/ppc/__unmapself.S (limited to 'src') 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 - .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/powerpc/dlsym.s b/src/ldso/powerpc/dlsym.s new file mode 100644 index 00000000..20796176 --- /dev/null +++ b/src/ldso/powerpc/dlsym.s @@ -0,0 +1,8 @@ + .text + .global dlsym + .type dlsym,@function +dlsym: + 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/dlsym.S b/src/ldso/ppc/dlsym.S deleted file mode 100644 index e36de10b..00000000 --- a/src/ldso/ppc/dlsym.S +++ /dev/null @@ -1,9 +0,0 @@ -#include - .text - .global dlsym - .type dlsym,@function -dlsym: - mflr r5 // The return address is arg3. - b __dlsym - .end dlsym - .size dlsym, .-dlsym 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 - .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 - .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 - .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 -#include - .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 - .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/powerpc/__unmapself.s b/src/thread/powerpc/__unmapself.s new file mode 100644 index 00000000..bb3724e3 --- /dev/null +++ b/src/thread/powerpc/__unmapself.s @@ -0,0 +1,9 @@ + .text + .global __unmapself + .type __unmapself,%function +__unmapself: + li 0, 91 # __NR_munmap + sc + 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 diff --git a/src/thread/ppc/__unmapself.S b/src/thread/ppc/__unmapself.S deleted file mode 100644 index e14663e7..00000000 --- a/src/thread/ppc/__unmapself.S +++ /dev/null @@ -1,11 +0,0 @@ -#include -#include - .text - .global __unmapself - .type __unmapself,%function -__unmapself: - li r0, __NR_munmap - sc - li r0, __NR_exit - sc - blr -- cgit v1.2.1