1.0.39.4: fix build on non-darwin and ppc/darwin platforms
[sbcl.git] / src / runtime / ppc-linux-os.c
1 /*
2  * This is the IBM/Motorola/Apple/whoever Linux incarnation of
3  * arch-dependent OS-dependent routines. See also "linux-os.c".  */
4
5 /*
6  * This software is part of the SBCL system. See the README file for
7  * more information.
8  *
9  * This software is derived from the CMU CL system, which was
10  * written at Carnegie Mellon University and released into the
11  * public domain. The software is in the public domain and is
12  * provided with absolutely no warranty. See the COPYING and CREDITS
13  * files for more information.
14  */
15
16 /* These header files were lifted wholesale from linux-os.c, some may
17  * be redundant. -- Dan Barlow ca. 2001-05-01 */
18 #include <stdio.h>
19 #include <sys/param.h>
20 #include <sys/file.h>
21 #include "sbcl.h"
22 #include "./signal.h"
23 #include "os.h"
24 #include "arch.h"
25 #include "globals.h"
26 #include "interrupt.h"
27 #include "interr.h"
28 #include "lispregs.h"
29 #include <sys/socket.h>
30 #include <sys/utsname.h>
31
32 #include <sys/types.h>
33 #include <signal.h>
34 #include <sys/time.h>
35 #include <sys/stat.h>
36 #include <unistd.h>
37 #include <sys/prctl.h>
38
39 #include "validate.h"
40 #include "ppc-linux-mcontext.h"
41
42 size_t os_vm_page_size;
43
44 int arch_os_thread_init(struct thread *thread) {
45     /* For some reason, PPC Linux appears to default to not generating
46      * floating point exceptions.  PR_SET_FPEXC is a PPC-specific
47      * option new in kernel 2.4.21 and 2.5.32 that allows us to
48      * configure this.  Should we need to run on an older kenel, the
49      * equivalent trick is to get into a signal-handling context and
50      * modify the saved machine state register.
51      *
52      * PR_FP_EXC_PRECISE may be more accurate than we need,
53      * particularly if we move to the x86oid trick of inserting
54      * explicit synchronization for floating-point exception
55      * delivery.  If we wish to move to such a model, the other two
56      * exception delivery modes that we could use are PR_FP_EXC_ASYNC
57      * and PR_FP_EXC_NONRECOV, and exception delivery can be forced
58      * by any access to the FPSCR.  -- AB, 2010-May-23 */
59     prctl(PR_SET_FPEXC, PR_FP_EXC_PRECISE, 0, 0);
60
61     return 1;                   /* success */
62 }
63 int arch_os_thread_cleanup(struct thread *thread) {
64     return 1;                   /* success */
65 }
66
67 os_context_register_t   *
68 os_context_register_addr(os_context_t *context, int offset)
69 {
70 #if defined(GLIBC231_STYLE_UCONTEXT)
71     return &((context->uc_mcontext.regs)->gpr[offset]);
72 #elif defined(GLIBC232_STYLE_UCONTEXT)
73     return &((context->uc_mcontext.uc_regs->gregs)[offset]);
74 #endif
75 }
76
77 os_context_register_t *
78 os_context_pc_addr(os_context_t *context)
79 {
80 #if defined(GLIBC231_STYLE_UCONTEXT)
81     return &((context->uc_mcontext.regs)->nip);
82 #elif defined(GLIBC232_STYLE_UCONTEXT)
83     return &((context->uc_mcontext.uc_regs->gregs)[PT_NIP]);
84 #endif
85 }
86
87 os_context_register_t *
88 os_context_lr_addr(os_context_t *context)
89 {
90 #if defined(GLIBC231_STYLE_UCONTEXT)
91     return &((context->uc_mcontext.regs)->link);
92 #elif defined(GLIBC232_STYLE_UCONTEXT)
93     return &((context->uc_mcontext.uc_regs->gregs)[PT_LNK]);
94 #endif
95 }
96
97 sigset_t *
98 os_context_sigmask_addr(os_context_t *context)
99 {
100 #if defined(GLIBC231_STYLE_UCONTEXT)
101     return &context->uc_sigmask;
102 #elif defined(GLIBC232_STYLE_UCONTEXT)
103     return &context->uc_sigmask;
104 #endif
105 }
106
107 unsigned long
108 os_context_fp_control(os_context_t *context)
109 {
110     /* So this may look like nice, well behaved code. However, closer
111        inspection reveals that gpr is simply the general purpose
112        registers, and PT_FPSCR is an offset that is larger than 32
113        (the number of ppc registers), but that happens to get the
114        right answer. -- CSR, 2002-07-11 */
115 #if defined(GLIBC231_STYLE_UCONTEXT)
116     return context->uc_mcontext.regs->gpr[PT_FPSCR];
117 #elif defined(GLIBC232_STYLE_UCONTEXT)
118     return context->uc_mcontext.uc_regs->gregs[PT_FPSCR];
119 #endif
120 }
121
122 void
123 os_restore_fp_control(os_context_t *context)
124 {
125     /* KLUDGE: mtfsf has to be run against a float register, so we
126      * construct the float we need to use as an integer, then cast
127      * a pointer to its storage to a double and load that.  For
128      * this to work, control must be the same width as a double,
129      * 64 bits.  And why aren't we using a union here, anyway? */
130     unsigned long long control;
131     double d;
132
133     /* FIXME: We are only preserving enabled traps and rounding
134      * mode here.  Do we also want to preserve "fast mode"? */
135     control = os_context_fp_control(context) &
136         (FLOAT_TRAPS_BYTE_MASK | FLOAT_ROUNDING_MODE_MASK);
137
138     d = *((double *) &control);
139     asm volatile ("mtfsf 0xff,%0" : : "f" (d));
140 }
141
142 void
143 os_flush_icache(os_vm_address_t address, os_vm_size_t length)
144 {
145     /* see ppc-arch.c */
146     ppc_flush_icache(address,length);
147 }
148