- moved the remaining of int21 calls to dlls/winedos
[wine] / server / context_powerpc.c
1 /*
2  * PowerPC register context support
3  *
4  * Copyright (C) 2002 Marcus Meissner, SuSE Linux AG.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "config.h"
22
23 #ifdef __powerpc__
24
25 #include <assert.h>
26 #include <errno.h>
27 #include <sys/types.h>
28 #ifdef HAVE_SYS_REG_H
29 # include <sys/reg.h>
30 #endif
31 #include <stdarg.h>
32 #include <unistd.h>
33 #ifdef HAVE_SYS_PTRACE_H
34 # include <sys/ptrace.h>
35 #endif
36
37 #ifndef PTRACE_PEEKUSER
38 # ifdef PT_READ_D
39 #  define PTRACE_PEEKUSER PT_READ_D
40 # endif
41 #endif /* PTRACE_PEEKUSER */
42
43 #ifndef PTRACE_POKEUSER
44 # ifdef PT_WRITE_D
45 #  define PTRACE_POKEUSER PT_WRITE_D
46 # endif
47 #endif /* PTRACE_POKEUSER */
48
49 #include "windef.h"
50 #include "winbase.h"
51
52 #include "file.h"
53 #include "thread.h"
54 #include "request.h"
55
56 /* retrieve a thread context */
57 static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
58 {
59     int pid = get_ptrace_pid(thread);
60     if (flags & CONTEXT_FULL)
61     {
62         if (flags & CONTEXT_INTEGER)
63         {
64 #define XREG(x,y) if (ptrace( PTRACE_PEEKUSER, pid, (void*)(x<<2), &context->y) == -1) goto error;
65 #define IREG(x) if (ptrace( PTRACE_PEEKUSER, pid, (void*)(x<<2), &context->Gpr##x) == -1) goto error;
66             IREG(0); IREG(1); IREG(2); IREG(3); IREG(4); IREG(5); IREG(6);
67             IREG(7); IREG(8); IREG(9); IREG(10); IREG(11); IREG(12); IREG(13);
68             IREG(14); IREG(15); IREG(16); IREG(17); IREG(18); IREG(19);
69             IREG(20); IREG(21); IREG(22); IREG(23); IREG(24); IREG(25);
70             IREG(26); IREG(27); IREG(28); IREG(29); IREG(30); IREG(31);
71 #undef IREG
72             XREG(37,Xer);
73             XREG(38,Cr);
74         }
75         if (flags & CONTEXT_CONTROL)
76         {
77             XREG(32,Iar);
78             XREG(33,Msr);
79             XREG(35,Ctr);
80             XREG(36,Lr); /* 36 is LNK ... probably Lr ? */
81         }
82     }
83     if (flags & CONTEXT_FLOATING_POINT)
84     {
85 #define FREG(x) if (ptrace( PTRACE_PEEKUSER, pid, (void*)((48+x*2)<<2), &context->Fpr##x) == -1) goto error;
86         FREG(0);
87         FREG(1);
88         FREG(2);
89         FREG(3);
90         FREG(4);
91         FREG(5);
92         FREG(6);
93         FREG(7);
94         FREG(8);
95         FREG(9);
96         FREG(10);
97         FREG(11);
98         FREG(12);
99         FREG(13);
100         FREG(14);
101         FREG(15);
102         FREG(16);
103         FREG(17);
104         FREG(18);
105         FREG(19);
106         FREG(20);
107         FREG(21);
108         FREG(22);
109         FREG(23);
110         FREG(24);
111         FREG(25);
112         FREG(26);
113         FREG(27);
114         FREG(28);
115         FREG(29);
116         FREG(30);
117         FREG(31);
118         XREG((48+32*2),Fpscr);
119     }
120     return;
121  error:
122     file_set_error();
123 }
124 #undef XREG
125 #undef IREG
126 #undef FREG
127
128 #define XREG(x,y) if (ptrace( PTRACE_POKEUSER, pid, (void*)(x<<2), &context->y) == -1) goto error;
129 #define IREG(x) if (ptrace( PTRACE_POKEUSER, pid, (void*)(x<<2), &context->Gpr##x) == -1) goto error;
130 #define FREG(x) if (ptrace( PTRACE_POKEUSER, pid, (void*)((48+x*2)<<2), &context->Fpr##x) == -1) goto error;
131 /* set a thread context */
132 static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
133 {
134     int pid = get_ptrace_pid(thread);
135     if (flags & CONTEXT_FULL)
136     {
137         if (flags & CONTEXT_INTEGER)
138         {
139             IREG(0); IREG(1); IREG(2); IREG(3); IREG(4); IREG(5); IREG(6);
140             IREG(7); IREG(8); IREG(9); IREG(10); IREG(11); IREG(12); IREG(13);
141             IREG(14); IREG(15); IREG(16); IREG(17); IREG(18); IREG(19);
142             IREG(20); IREG(21); IREG(22); IREG(23); IREG(24); IREG(25);
143             IREG(26); IREG(27); IREG(28); IREG(29); IREG(30); IREG(31);
144             XREG(37,Xer);
145             XREG(38,Cr);
146
147         }
148         if (flags & CONTEXT_CONTROL)
149         {
150             XREG(32,Iar);
151             XREG(33,Msr);
152             XREG(35,Ctr);
153             XREG(36,Lr);
154         }
155     }
156     if (flags & CONTEXT_FLOATING_POINT)
157     {
158         FREG(0);
159         FREG(1);
160         FREG(2);
161         FREG(3);
162         FREG(4);
163         FREG(5);
164         FREG(6);
165         FREG(7);
166         FREG(8);
167         FREG(9);
168         FREG(10);
169         FREG(11);
170         FREG(12);
171         FREG(13);
172         FREG(14);
173         FREG(15);
174         FREG(16);
175         FREG(17);
176         FREG(18);
177         FREG(19);
178         FREG(20);
179         FREG(21);
180         FREG(22);
181         FREG(23);
182         FREG(24);
183         FREG(25);
184         FREG(26);
185         FREG(27);
186         FREG(28);
187         FREG(29);
188         FREG(30);
189         FREG(31);
190 #undef FREG
191         XREG((48+32*2),Fpscr);
192     }
193     return;
194  error:
195     file_set_error();
196 }
197 #undef XREG
198 #undef IREG
199 #undef FREG
200
201 #define IREG(x) to->Gpr##x = from->Gpr##x;
202 #define FREG(x) to->Fpr##x = from->Fpr##x;
203 #define CREG(x) to->x = from->x;
204 /* copy a context structure according to the flags */
205 static void copy_context( CONTEXT *to, const CONTEXT *from, int flags )
206 {
207     if (flags & CONTEXT_CONTROL)
208     {
209         CREG(Msr);
210         CREG(Ctr);
211         CREG(Iar);
212     }
213     if (flags & CONTEXT_INTEGER)
214     {
215         IREG(0); IREG(1); IREG(2); IREG(3); IREG(4); IREG(5); IREG(6);
216         IREG(7); IREG(8); IREG(9); IREG(10); IREG(11); IREG(12); IREG(13);
217         IREG(14); IREG(15); IREG(16); IREG(17); IREG(18); IREG(19);
218         IREG(20); IREG(21); IREG(22); IREG(23); IREG(24); IREG(25);
219         IREG(26); IREG(27); IREG(28); IREG(29); IREG(30); IREG(31);
220         CREG(Xer);
221         CREG(Cr);
222     }
223     if (flags & CONTEXT_FLOATING_POINT)
224     {
225         FREG(0);
226         FREG(1);
227         FREG(2);
228         FREG(3);
229         FREG(4);
230         FREG(5);
231         FREG(6);
232         FREG(7);
233         FREG(8);
234         FREG(9);
235         FREG(10);
236         FREG(11);
237         FREG(12);
238         FREG(13);
239         FREG(14);
240         FREG(15);
241         FREG(16);
242         FREG(17);
243         FREG(18);
244         FREG(19);
245         FREG(20);
246         FREG(21);
247         FREG(22);
248         FREG(23);
249         FREG(24);
250         FREG(25);
251         FREG(26);
252         FREG(27);
253         FREG(28);
254         FREG(29);
255         FREG(30);
256         FREG(31);
257         CREG(Fpscr);
258     }
259 }
260
261 /* retrieve the current instruction pointer of a thread */
262 void *get_thread_ip( struct thread *thread )
263 {
264     CONTEXT context;
265     context.Iar = 0;
266     if (suspend_for_ptrace( thread ))
267     {
268         get_thread_context( thread, CONTEXT_CONTROL, &context );
269         resume_after_ptrace( thread );
270     }
271     return (void *)context.Iar;
272 }
273
274 /* determine if we should continue the thread in single-step mode */
275 int get_thread_single_step( struct thread *thread )
276 {
277     CONTEXT context;
278     if (thread->context) return 0;
279     get_thread_context( thread, CONTEXT_CONTROL, &context );
280 #ifndef MSR_SE
281 # define MSR_SE (1<<10)
282 #endif
283     return (context.Msr & MSR_SE) != 0;
284 }
285
286 /* send a signal to a specific thread */
287 int tkill( int pid, int sig )
288 {
289     /* FIXME: should do something here */
290     errno = ENOSYS;
291     return -1;
292 }
293
294 /* retrieve the current context of a thread */
295 DECL_HANDLER(get_thread_context)
296 {
297     struct thread *thread;
298     void *data;
299     int flags = req->flags;
300
301     if (get_reply_max_size() < sizeof(CONTEXT))
302     {
303         set_error( STATUS_INVALID_PARAMETER );
304         return;
305     }
306     if (!(thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT ))) return;
307
308     if ((data = set_reply_data_size( sizeof(CONTEXT) )))
309     {
310         if (thread->context)  /* thread is inside an exception event */
311         {
312             copy_context( data, thread->context, flags );
313             flags = 0;
314         }
315         if (flags && suspend_for_ptrace( thread ))
316         {
317             get_thread_context( thread, flags, data );
318             resume_after_ptrace( thread );
319         }
320     }
321     release_object( thread );
322 }
323
324
325 /* set the current context of a thread */
326 DECL_HANDLER(set_thread_context)
327 {
328     struct thread *thread;
329     int flags = req->flags;
330
331     if (get_req_data_size() < sizeof(CONTEXT))
332     {
333         set_error( STATUS_INVALID_PARAMETER );
334         return;
335     }
336     if ((thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT )))
337     {
338         if (thread->context)  /* thread is inside an exception event */
339         {
340             copy_context( thread->context, get_req_data(), flags );
341             flags = 0;
342         }
343         if (flags && suspend_for_ptrace( thread ))
344         {
345             set_thread_context( thread, flags, get_req_data() );
346             resume_after_ptrace( thread );
347         }
348         release_object( thread );
349     }
350 }
351
352 #endif  /* __powerpc__ */