diff --git a/dlls/ntdll/signal_sparc.c b/dlls/ntdll/signal_sparc.c index 8fd61fd7036..d64b5c06bc7 100644 --- a/dlls/ntdll/signal_sparc.c +++ b/dlls/ntdll/signal_sparc.c @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -348,4 +349,20 @@ BOOL SIGNAL_Init(void) return FALSE; } +/********************************************************************** + * DbgBreakPoint (NTDLL) + */ +void WINAPI DbgBreakPoint(void) +{ + /* FIXME */ +} + +/********************************************************************** + * DbgUserBreakPoint (NTDLL) + */ +void WINAPI DbgUserBreakPoint(void) +{ + /* FIXME */ +} + #endif /* __sparc__ */ diff --git a/memory/selector.c b/memory/selector.c index 0f0b99f6742..c12b6205eed 100644 --- a/memory/selector.c +++ b/memory/selector.c @@ -663,7 +663,7 @@ BOOL WINAPI GetThreadSelectorEntry( HANDLE hthread, DWORD sel, LPLDT_ENTRY ldten if (!(req->flags & LDT_FLAGS_READONLY)) ldtent->HighWord.Bits.Type |= 0x2; return TRUE; #else - SetLastError( ERROR_NOT_IMPLEMENTED ); + SetLastError( ERROR_CALL_NOT_IMPLEMENTED ); return FALSE; #endif } diff --git a/scheduler/critsection.c b/scheduler/critsection.c index 4437d0e794d..a68be298acc 100644 --- a/scheduler/critsection.c +++ b/scheduler/critsection.c @@ -222,6 +222,80 @@ __ASM_GLOBAL_FUNC(InterlockedDecrement, "decl %eax\n\t" "ret $4"); -#else /* __i386__ */ +#elif defined(__sparc__) && defined(__sun__) + +/* + * As the earlier Sparc processors lack necessary atomic instructions, + * I'm simply falling back to the library-provided _lwp_mutex routines + * to ensure mutual exclusion in a way appropriate for the current + * architecture. + * + * FIXME: If we have the compare-and-swap instruction (Sparc v9 and above) + * we could use this to speed up the Interlocked operations ... + */ + +#include +static lwp_mutex_t interlocked_mutex = DEFAULTMUTEX; + +PVOID WINAPI InterlockedCompareExchange( PVOID *dest, PVOID xchg, PVOID compare ) +{ + _lwp_mutex_lock( &interlocked_mutex ); + + if ( *dest == compare ) + *dest = xchg; + else + compare = *dest; + + _lwp_mutex_unlock( &interlocked_mutex ); + return compare; +} + +LONG WINAPI InterlockedExchange( PLONG dest, LONG val ) +{ + LONG retv; + _lwp_mutex_lock( &interlocked_mutex ); + + retv = *dest; + *dest = val; + + _lwp_mutex_unlock( &interlocked_mutex ); + return retv; +} + +LONG WINAPI InterlockedExchangeAdd( PLONG dest, LONG incr ) +{ + LONG retv; + _lwp_mutex_lock( &interlocked_mutex ); + + retv = *dest; + *dest += incr; + + _lwp_mutex_unlock( &interlocked_mutex ); + return retv; +} + +LONG WINAPI InterlockedIncrement( PLONG dest ) +{ + LONG retv; + _lwp_mutex_lock( &interlocked_mutex ); + + retv = ++*dest; + + _lwp_mutex_unlock( &interlocked_mutex ); + return retv; +} + +LONG WINAPI InterlockedDecrement( PLONG dest ) +{ + LONG retv; + _lwp_mutex_lock( &interlocked_mutex ); + + retv = --*dest; + + _lwp_mutex_unlock( &interlocked_mutex ); + return retv; +} + +#else #error You must implement the Interlocked* functions for your CPU -#endif /* __i386__ */ +#endif diff --git a/server/Makefile.in b/server/Makefile.in index 2416736cb39..05c18d8b255 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -10,6 +10,7 @@ C_SRCS = \ change.c \ console.c \ context_i386.c \ + context_sparc.c \ debugger.c \ device.c \ event.c \ diff --git a/server/context_sparc.c b/server/context_sparc.c new file mode 100644 index 00000000000..23351201c5d --- /dev/null +++ b/server/context_sparc.c @@ -0,0 +1,201 @@ +/* + * Sparc register context support + * + * Copyright (C) 2000 Ulrich Weigand + */ + +#include "config.h" + +#ifdef __sparc__ + +#include +#include +#include +#ifdef HAVE_SYS_REG_H +#include +#endif +#include +#include +#include + +#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) ®s ) == -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, 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, 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; +} + +/* retrieve the current context of a thread */ +DECL_HANDLER(get_thread_context) +{ + struct thread *thread; + int flags = req->flags & ~CONTEXT_SPARC; /* get rid of CPU id */ + + if ((thread = get_thread_from_handle( req->handle, THREAD_GET_CONTEXT ))) + { + if (thread->context) /* thread is inside an exception event */ + { + copy_context( &req->context, thread->context, flags ); + flags = 0; + } + if (flags && suspend_for_ptrace( thread )) + { + get_thread_context( thread, flags, &req->context ); + 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 ((thread = get_thread_from_handle( req->handle, THREAD_SET_CONTEXT ))) + { + if (thread->context) /* thread is inside an exception event */ + { + copy_context( thread->context, &req->context, flags ); + flags = 0; + } + if (flags && suspend_for_ptrace( thread )) + { + set_thread_context( thread, flags, &req->context ); + resume_thread( thread ); + } + release_object( thread ); + } +} + +#endif /* __sparc__ */