The parts of klibc specific to the ppc architecture. Signed-off-by: H. Peter Anvin <hpa at zytor.com> --- commit a82c9b6e9b3428bae592241d1ac276054bc46fc5 tree 70852f39dd495c9bffc307d38f6da673d91ab08a parent 078d6614054391efe17093f8d70340e2c0644ffb author H. Peter Anvin <hpa at zytor.com> Sun, 25 Jun 2006 16:58:37 -0700 committer H. Peter Anvin <hpa at zytor.com> Sun, 25 Jun 2006 16:58:37 -0700 usr/include/arch/ppc/klibc/archconfig.h | 14 +++++++ usr/include/arch/ppc/klibc/archsetjmp.h | 36 ++++++++++++++++++ usr/include/arch/ppc/klibc/archsignal.h | 14 +++++++ usr/include/arch/ppc/klibc/archstat.h | 30 +++++++++++++++ usr/include/arch/ppc/klibc/archsys.h | 61 +++++++++++++++++++++++++++++++ usr/klibc/arch/ppc/MCONFIG | 29 +++++++++++++++ usr/klibc/arch/ppc/Makefile.inc | 22 +++++++++++ usr/klibc/arch/ppc/crt0.S | 23 ++++++++++++ usr/klibc/arch/ppc/setjmp.S | 34 +++++++++++++++++ usr/klibc/arch/ppc/syscall.S | 16 ++++++++ usr/klibc/arch/ppc/sysstub.ph | 25 +++++++++++++ 11 files changed, 304 insertions(+), 0 deletions(-) diff --git a/usr/include/arch/ppc/klibc/archconfig.h b/usr/include/arch/ppc/klibc/archconfig.h new file mode 100644 index 0000000..ce04eee --- /dev/null +++ b/usr/include/arch/ppc/klibc/archconfig.h @@ -0,0 +1,14 @@ +/* + * include/arch/ppc/klibc/archconfig.h + * + * See include/klibc/sysconfig.h for the options that can be set in + * this file. + * + */ + +#ifndef _KLIBC_ARCHCONFIG_H +#define _KLIBC_ARCHCONFIG_H + +/* All defaults */ + +#endif /* _KLIBC_ARCHCONFIG_H */ diff --git a/usr/include/arch/ppc/klibc/archsetjmp.h b/usr/include/arch/ppc/klibc/archsetjmp.h new file mode 100644 index 0000000..4be9ed6 --- /dev/null +++ b/usr/include/arch/ppc/klibc/archsetjmp.h @@ -0,0 +1,36 @@ +/* + * arch/ppc/include/klibc/archsetjmp.h + */ + +#ifndef _KLIBC_ARCHSETJMP_H +#define _KLIBC_ARCHSETJMP_H + +struct __jmp_buf { + unsigned long __r2; + unsigned long __sp; + unsigned long __lr; + unsigned long __cr; + unsigned long __r13; + unsigned long __r14; + unsigned long __r15; + unsigned long __r16; + unsigned long __r17; + unsigned long __r18; + unsigned long __r19; + unsigned long __r20; + unsigned long __r21; + unsigned long __r22; + unsigned long __r23; + unsigned long __r24; + unsigned long __r25; + unsigned long __r26; + unsigned long __r27; + unsigned long __r28; + unsigned long __r29; + unsigned long __r30; + unsigned long __r31; +}; + +typedef struct __jmp_buf jmp_buf[1]; + +#endif /* _SETJMP_H */ diff --git a/usr/include/arch/ppc/klibc/archsignal.h b/usr/include/arch/ppc/klibc/archsignal.h new file mode 100644 index 0000000..9c3ac92 --- /dev/null +++ b/usr/include/arch/ppc/klibc/archsignal.h @@ -0,0 +1,14 @@ +/* + * arch/ppc/include/klibc/archsignal.h + * + * Architecture-specific signal definitions + * + */ + +#ifndef _KLIBC_ARCHSIGNAL_H +#define _KLIBC_ARCHSIGNAL_H + +#include <asm/signal.h> +/* No special stuff for this architecture */ + +#endif diff --git a/usr/include/arch/ppc/klibc/archstat.h b/usr/include/arch/ppc/klibc/archstat.h new file mode 100644 index 0000000..9e31f4a --- /dev/null +++ b/usr/include/arch/ppc/klibc/archstat.h @@ -0,0 +1,30 @@ +#ifndef _KLIBC_ARCHSTAT_H +#define _KLIBC_ARCHSTAT_H + +#include <klibc/stathelp.h> + +#define _STATBUF_ST_NSEC + +/* This matches struct stat64 in glibc2.1. + */ +struct stat { + __stdev64 (st_dev); /* Device. */ + unsigned long long st_ino; /* File serial number. */ + unsigned int st_mode; /* File mode. */ + unsigned int st_nlink; /* Link count. */ + unsigned int st_uid; /* User ID of the file's owner. */ + unsigned int st_gid; /* Group ID of the file's group. */ + __stdev64 (st_rdev); /* Device number, if device. */ + unsigned short int __pad2; + long long st_size; /* Size of file, in bytes. */ + long st_blksize; /* Optimal block size for I/O. */ + + long long st_blocks; /* Number 512-byte blocks allocated. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ + unsigned long int __unused4; + unsigned long int __unused5; +}; + +#endif diff --git a/usr/include/arch/ppc/klibc/archsys.h b/usr/include/arch/ppc/klibc/archsys.h new file mode 100644 index 0000000..24752da --- /dev/null +++ b/usr/include/arch/ppc/klibc/archsys.h @@ -0,0 +1,61 @@ +/* + * arch/ppc/include/klibc/archsys.h + * + * Architecture-specific syscall definitions + */ + +#ifndef _KLIBC_ARCHSYS_H +#define _KLIBC_ARCHSYS_H + +/* PowerPC seems to lack _syscall6() in its headers */ +/* This seems to work on both 32- and 64-bit ppc */ + +#ifndef _syscall6 + +#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \ + type5,arg5,type6,arg6) \ +type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5,type6 arg6) \ +{ \ + unsigned long __sc_ret, __sc_err; \ + { \ + register unsigned long __sc_0 __asm__ ("r0"); \ + register unsigned long __sc_3 __asm__ ("r3"); \ + register unsigned long __sc_4 __asm__ ("r4"); \ + register unsigned long __sc_5 __asm__ ("r5"); \ + register unsigned long __sc_6 __asm__ ("r6"); \ + register unsigned long __sc_7 __asm__ ("r7"); \ + register unsigned long __sc_8 __asm__ ("r8"); \ + \ + __sc_3 = (unsigned long) (arg1); \ + __sc_4 = (unsigned long) (arg2); \ + __sc_5 = (unsigned long) (arg3); \ + __sc_6 = (unsigned long) (arg4); \ + __sc_7 = (unsigned long) (arg5); \ + __sc_8 = (unsigned long) (arg6); \ + __sc_0 = __NR_##name; \ + __asm__ __volatile__ \ + ("sc \n\t" \ + "mfcr %1 " \ + : "+r" (__sc_3), \ + "+r" (__sc_0), \ + "+r" (__sc_4), \ + "+r" (__sc_5), \ + "+r" (__sc_6), \ + "+r" (__sc_7), \ + "+r" (__sc_8) \ + : : "cr0", "ctr", "memory", \ + "r9", "r10", "r11", "r12"); \ + __sc_ret = __sc_3; \ + __sc_err = __sc_0; \ + } \ + if (__sc_err & 0x10000000) \ + { \ + errno = (int)__sc_ret; \ + __sc_ret = -1; \ + } \ + return (type)__sc_ret; \ +} + +#endif /* _syscall6() missing */ + +#endif /* _KLIBC_ARCHSYS_H */ diff --git a/usr/klibc/arch/ppc/MCONFIG b/usr/klibc/arch/ppc/MCONFIG new file mode 100644 index 0000000..5410933 --- /dev/null +++ b/usr/klibc/arch/ppc/MCONFIG @@ -0,0 +1,29 @@ +# -*- makefile -*- +# +# arch/ppc/MCONFIG +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +gcc_m32_option := $(call cc-option, -m32, ) + +KLIBCOPTFLAGS = -Os +KLIBCLDFLAGS = -m elf32ppclinux +KLIBCARCHREQFLAGS += $(gcc_m32_option) + +KLIBCBITSIZE = 32 + +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +# 256-16 MB - normal binaries start at 256 MB, and jumps are limited +# to +/- 16 MB +KLIBCSHAREDFLAGS = -Ttext 0x0f800200 + +# The kernel so far has both asm-ppc* and asm-powerpc. +KLIBCARCHINCFLAGS = -I$(KLIBCKERNELOBJ)arch/$(KLIBCARCH)/include + +# The asm include files live in asm-powerpc +KLIBCASMARCH = powerpc diff --git a/usr/klibc/arch/ppc/Makefile.inc b/usr/klibc/arch/ppc/Makefile.inc new file mode 100644 index 0000000..53d99c4 --- /dev/null +++ b/usr/klibc/arch/ppc/Makefile.inc @@ -0,0 +1,22 @@ +# -*- makefile -*- +# +# arch/ppc/Makefile.inc +# +# Special rules for this architecture. Note that this is actually +# included from the main Makefile, and that pathnames should be +# accordingly. +# + +KLIBCARCHOBJS = \ + arch/$(KLIBCARCH)/setjmp.o \ + arch/$(KLIBCARCH)/syscall.o \ + libgcc/__divdi3.o \ + libgcc/__moddi3.o \ + libgcc/__udivdi3.o \ + libgcc/__umoddi3.o \ + libgcc/__udivmoddi4.o + + +KLIBCARCHSOOBJS = $(patsubst %.o,%.lo,$(KLIBCARCHOBJS)) + +archclean: diff --git a/usr/klibc/arch/ppc/crt0.S b/usr/klibc/arch/ppc/crt0.S new file mode 100644 index 0000000..85b6dca --- /dev/null +++ b/usr/klibc/arch/ppc/crt0.S @@ -0,0 +1,23 @@ +# +# arch/ppc/crt0.S +# + + .text + .align 4 + .type _start, at function + .globl _start +_start: + stwu 1,-16(1) + addi 3,1,16 + /* + * the SVR4abippc.pdf specifies r7 as a pointer to + * a termination function point + * However, Section 8.4.1 of the LSB API docs say that + * The value to be placed into register r7, the termination + * function pointer, is not passed to the process. + * So we stub it out, instead. + */ + li 4,0 + bl __libc_init + + .size _start,.-_start diff --git a/usr/klibc/arch/ppc/setjmp.S b/usr/klibc/arch/ppc/setjmp.S new file mode 100644 index 0000000..e02b7da --- /dev/null +++ b/usr/klibc/arch/ppc/setjmp.S @@ -0,0 +1,34 @@ +# +# arch/ppc/setjmp.S +# +# Basic setjmp/longjmp implementation +# This file was derived from the equivalent file in NetBSD +# + + .text + .align 4 + .type setjmp, at function + .globl setjmp +setjmp: + mflr %r11 /* save return address */ + mfcr %r12 /* save condition register */ + mr %r10,%r1 /* save stack pointer */ + mr %r9,%r2 /* save GPR2 (not needed) */ + stmw %r9,0(%r3) /* save r9..r31 */ + li %r3,0 /* indicate success */ + blr /* return */ + + .size setjmp,.-setjmp + + .type longjmp, at function + .globl longjmp +longjmp: + lmw %r9,0(%r3) /* save r9..r31 */ + mtlr %r11 /* restore LR */ + mtcr %r12 /* restore CR */ + mr %r2,%r9 /* restore GPR2 (not needed) */ + mr %r1,%r10 /* restore stack */ + mr %r3,%r4 /* get return value */ + blr /* return */ + + .size longjmp,.-longjmp diff --git a/usr/klibc/arch/ppc/syscall.S b/usr/klibc/arch/ppc/syscall.S new file mode 100644 index 0000000..0a7c37c --- /dev/null +++ b/usr/klibc/arch/ppc/syscall.S @@ -0,0 +1,16 @@ +/* + * arch/ppc/syscall.S + * + * Common error-handling path for system calls. + */ + + .text + .align 2 + .globl __syscall_error + .type __syscall_error, at function +__syscall_error: + lis 9,errno at ha + stw 3,errno at l(9) + li 3,-1 + blr + .size __syscall_error,.-__syscall_error diff --git a/usr/klibc/arch/ppc/sysstub.ph b/usr/klibc/arch/ppc/sysstub.ph new file mode 100644 index 0000000..3b3916c --- /dev/null +++ b/usr/klibc/arch/ppc/sysstub.ph @@ -0,0 +1,25 @@ +# -*- perl -*- +# +# arch/ppc/sysstub.ph +# +# Script to generate system call stubs +# + +sub make_sysstub($$$$$@) { + my($outputdir, $fname, $type, $sname, $stype, @args) = @_; + + open(OUT, '>', "${outputdir}/${fname}.S"); + print OUT "#include <asm/unistd.h>\n"; + print OUT "\n"; + print OUT "\t.type ${fname},\@function\n"; + print OUT "\t.globl ${fname}\n"; + print OUT "${fname}:\n"; + print OUT "\tli 0,__NR_${sname}\n"; + print OUT "\tsc\n"; + print OUT "\tbnslr\n"; + print OUT "\tb __syscall_error\n"; + print OUT "\t.size ${fname},.-${fname}\n"; + close(OUT); +} + +1;