wine/server/context_sparc.c
Alexandre Julliard 9caa71eef4 Redesign of the server communication protocol to allow arbitrary sized
data to be exchanged.
Split request and reply structures to make backwards compatibility
easier.
Moved many console functions to dlls/kernel, added code page support,
changed a few requests to behave properly with the new protocol.
2001-11-30 18:46:42 +00:00

222 lines
5.4 KiB
C

/*
* Sparc register context support
*
* Copyright (C) 2000 Ulrich Weigand
*/
#include "config.h"
#ifdef __sparc__
#include <assert.h>
#include <errno.h>
#include <sys/types.h>
#ifdef HAVE_SYS_REG_H
# include <sys/reg.h>
#endif
#include <unistd.h>
#ifdef HAVE_SYS_PTRACE_H
# include <sys/ptrace.h>
#endif
#include "winbase.h"
#include "thread.h"
#include "request.h"
#if defined(__sun) || defined(__sun__)
/* retrieve a thread context */
static void get_thread_context( struct thread *thread, unsigned int flags, CONTEXT *context )
{
int pid = thread->unix_pid;
if (flags & CONTEXT_FULL)
{
struct regs regs;
if (ptrace( PTRACE_GETREGS, pid, 0, (int) &regs ) == -1) goto error;
if (flags & CONTEXT_INTEGER)
{
context->g0 = 0;
context->g1 = regs.r_g1;
context->g2 = regs.r_g2;
context->g3 = regs.r_g3;
context->g4 = regs.r_g4;
context->g5 = regs.r_g5;
context->g6 = regs.r_g6;
context->g7 = regs.r_g7;
context->o0 = regs.r_o0;
context->o1 = regs.r_o1;
context->o2 = regs.r_o2;
context->o3 = regs.r_o3;
context->o4 = regs.r_o4;
context->o5 = regs.r_o5;
context->o6 = regs.r_o6;
context->o7 = regs.r_o7;
/* FIXME: local and in registers */
}
if (flags & CONTEXT_CONTROL)
{
context->psr = regs.r_psr;
context->pc = regs.r_pc;
context->npc = regs.r_npc;
context->y = regs.r_y;
context->wim = 0; /* FIXME */
context->tbr = 0; /* FIXME */
}
}
if (flags & CONTEXT_FLOATING_POINT)
{
/* FIXME */
}
return;
error:
file_set_error();
}
/* set a thread context */
static void set_thread_context( struct thread *thread, unsigned int flags, const CONTEXT *context )
{
/* FIXME */
}
#else /* __sun__ */
#error You must implement get/set_thread_context for your platform
#endif /* __sun__ */
/* copy a context structure according to the flags */
static void copy_context( CONTEXT *to, const CONTEXT *from, int flags )
{
if (flags & CONTEXT_CONTROL)
{
to->psr = from->psr;
to->pc = from->pc;
to->npc = from->npc;
to->y = from->y;
to->wim = from->wim;
to->tbr = from->tbr;
}
if (flags & CONTEXT_INTEGER)
{
to->g0 = from->g0;
to->g1 = from->g1;
to->g2 = from->g2;
to->g3 = from->g3;
to->g4 = from->g4;
to->g5 = from->g5;
to->g6 = from->g6;
to->g7 = from->g7;
to->o0 = from->o0;
to->o1 = from->o1;
to->o2 = from->o2;
to->o3 = from->o3;
to->o4 = from->o4;
to->o5 = from->o5;
to->o6 = from->o6;
to->o7 = from->o7;
to->l0 = from->l0;
to->l1 = from->l1;
to->l2 = from->l2;
to->l3 = from->l3;
to->l4 = from->l4;
to->l5 = from->l5;
to->l6 = from->l6;
to->l7 = from->l7;
to->i0 = from->i0;
to->i1 = from->i1;
to->i2 = from->i2;
to->i3 = from->i3;
to->i4 = from->i4;
to->i5 = from->i5;
to->i6 = from->i6;
to->i7 = from->i7;
}
if (flags & CONTEXT_FLOATING_POINT)
{
/* FIXME */
}
}
/* retrieve the current instruction pointer of a thread */
void *get_thread_ip( struct thread *thread )
{
CONTEXT context;
context.pc = 0;
if (suspend_for_ptrace( thread ))
{
get_thread_context( thread, CONTEXT_CONTROL, &context );
resume_thread( thread );
}
return (void *)context.pc;
}
/* determine if we should continue the thread in single-step mode */
int get_thread_single_step( struct thread *thread )
{
return 0; /* FIXME */
}
/* retrieve the current context of a thread */
DECL_HANDLER(get_thread_context)
{
struct thread *thread;
void *data;
int flags = req->flags & ~CONTEXT_SPARC; /* get rid of CPU id */
if (get_reply_max_size() < sizeof(CONTEXT))
{
set_error( STATUS_INVALID_PARAMETER );
return;
}
if (!(thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT ))) return;
if ((data = set_reply_data_size( sizeof(CONTEXT) )))
{
if (thread->context) /* thread is inside an exception event */
{
copy_context( data, thread->context, flags );
flags = 0;
}
if (flags && suspend_for_ptrace( thread ))
{
get_thread_context( thread, flags, data );
resume_thread( thread );
}
}
release_object( thread );
}
/* set the current context of a thread */
DECL_HANDLER(set_thread_context)
{
struct thread *thread;
int flags = req->flags & ~CONTEXT_SPARC; /* get rid of CPU id */
if (get_req_data_size() < sizeof(CONTEXT))
{
set_error( STATUS_INVALID_PARAMETER );
return;
}
if ((thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT )))
{
if (thread->context) /* thread is inside an exception event */
{
copy_context( thread->context, get_req_data(), flags );
flags = 0;
}
if (flags && suspend_for_ptrace( thread ))
{
set_thread_context( thread, flags, get_req_data() );
resume_thread( thread );
}
release_object( thread );
}
}
#endif /* __sparc__ */