From 2c1b35dd1757e757da634987634a3acbb93ed7a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vincent=20B=C3=A9ron?= Date: Mon, 18 Oct 2004 21:27:52 +0000 Subject: [PATCH] Add some more Alpha asm code and Alpha-specific parts. --- dlls/ntdll/exception.c | 2 + libs/port/interlocked.c | 14 +-- loader/kthread.c | 16 +++- programs/winedbg/Makefile.in | 1 + programs/winedbg/be_alpha.c | 168 +++++++++++++++++++++++++++++++++++ programs/winedbg/gdbproxy.c | 80 +++++++++++++++-- programs/winedbg/winedbg.c | 4 + tools/winebuild/import.c | 15 ++++ tools/winebuild/spec32.c | 21 +++++ 9 files changed, 306 insertions(+), 15 deletions(-) create mode 100644 programs/winedbg/be_alpha.c diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c index 090795ef0ec..e4822fbe2f3 100644 --- a/dlls/ntdll/exception.c +++ b/dlls/ntdll/exception.c @@ -70,6 +70,8 @@ static CRITICAL_SECTION vectored_handlers_section = { &critsect_debug, -1, 0, 0, # define GET_IP(context) ((LPVOID)(context)->pc) #elif defined(__powerpc__) # define GET_IP(context) ((LPVOID)(context)->Iar) +#elif defined(__ALPHA__) +# define GET_IP(context) ((LPVOID)(context)->Fir) #else # error You must define GET_IP for this CPU #endif diff --git a/libs/port/interlocked.c b/libs/port/interlocked.c index dbcac4f34c2..6223369f300 100644 --- a/libs/port/interlocked.c +++ b/libs/port/interlocked.c @@ -249,11 +249,11 @@ long interlocked_xchg_add( long *dest, long incr ) __ASM_GLOBAL_FUNC(interlocked_cmpxchg, "L0cmpxchg:\n\t" - "ldq_l $0,0($16)\n\t" + "ldl_l $0,0($16)\n\t" "cmpeq $0,$18,$1\n\t" "beq $1,L1cmpxchg\n\t" "mov $17,$0\n\t" - "stq_c $0,0($16)\n\t" + "stl_c $0,0($16)\n\t" "beq $0,L0cmpxchg\n\t" "mov $18,$0\n" "L1cmpxchg:\n\t" @@ -273,9 +273,9 @@ __ASM_GLOBAL_FUNC(interlocked_cmpxchg_ptr, __ASM_GLOBAL_FUNC(interlocked_xchg, "L0xchg:\n\t" - "ldq_l $0,0($16)\n\t" + "ldl_l $0,0($16)\n\t" "mov $17,$1\n\t" - "stq_c $1,0($16)\n\t" + "stl_c $1,0($16)\n\t" "beq $1,L0xchg\n\t" "mb"); @@ -289,9 +289,9 @@ __ASM_GLOBAL_FUNC(interlocked_xchg_ptr, __ASM_GLOBAL_FUNC(interlocked_xchg_add, "L0xchg_add:\n\t" - "ldq_l $0,0($16)\n\t" - "addq $0,$17,$1\n\t" - "stq_c $1,0($16)\n\t" + "ldl_l $0,0($16)\n\t" + "addl $0,$17,$1\n\t" + "stl_c $1,0($16)\n\t" "beq $1,L0xchg_add\n\t" "mb"); diff --git a/loader/kthread.c b/loader/kthread.c index 6fae6be9f63..6fe101ffa8e 100644 --- a/loader/kthread.c +++ b/loader/kthread.c @@ -312,9 +312,11 @@ void wine_pthread_init_current_teb( struct wine_pthread_thread_info *info ) # else __asm__ __volatile__("mr 2, %0" : : "r" (info->teb_base)); # endif -#elif defined(HAVE__LWP_CREATE) - /* On non-i386 Solaris, we use the LWP private pointer */ - _lwp_setprivate( info->teb_base ); +#elif defined(__ALPHA__) + /* FIXME: On Alpha, the current TEB is not accessible to user-space */ +/* __asm__ __volatile__();*/ +#else +# error You must implement wine_pthread_init_current_teb for your platform #endif /* set pid and tid */ @@ -344,6 +346,14 @@ void *wine_pthread_get_current_teb(void) # else __asm__( "mr %0,2" : "=r" (ret) ); # endif +#elif defined(__ALPHA__) + /* 0x00ab is the PAL opcode for rdteb */ + __asm__( "lda $30,8($30)\n\t" + "stq $0,0($30)\n\t" + "call_pal 0x00ab\n\t" + "mov $0,%0\n\t" + "ldq $0,0($30)\n\t" + "lda $30,-8($30)" : "=r" (ret) ); #else # error wine_pthread_get_current_teb not defined for this architecture #endif /* __i386__ */ diff --git a/programs/winedbg/Makefile.in b/programs/winedbg/Makefile.in index 0494338ecc3..a3033465758 100644 --- a/programs/winedbg/Makefile.in +++ b/programs/winedbg/Makefile.in @@ -8,6 +8,7 @@ IMPORTS = dbghelp advapi32 kernel32 ntdll DELAYIMPORTS = user32 C_SRCS = \ + be_alpha.c \ be_i386.c \ be_ppc.c \ break.c \ diff --git a/programs/winedbg/be_alpha.c b/programs/winedbg/be_alpha.c new file mode 100644 index 00000000000..44517293dfc --- /dev/null +++ b/programs/winedbg/be_alpha.c @@ -0,0 +1,168 @@ +/* + * Debugger Alpha specific functions + * + * Copyright 2004 Vincent Béron + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "debugger.h" + +#if defined(__ALPHA__) + +static unsigned be_alpha_get_addr(HANDLE hThread, const CONTEXT* ctx, + enum be_cpu_addr bca, ADDRESS* addr) +{ + dbg_printf("not done\n"); + return FALSE; +} + +static void be_alpha_single_step(CONTEXT* ctx, unsigned enable) +{ + dbg_printf("not done\n"); +} + +static void be_alpha_print_context(HANDLE hThread, const CONTEXT* ctx) +{ + dbg_printf("Context printing for Alpha not done yet\n"); +} + +static void be_alpha_print_segment_info(HANDLE hThread, const CONTEXT* ctx) +{ +} + +static struct dbg_internal_var be_alpha_ctx[] = +{ + {0, NULL, 0, dbg_itype_none} +}; + +static const struct dbg_internal_var* be_alpha_init_registers(CONTEXT* ctx) +{ + dbg_printf("not done\n"); + return be_alpha_ctx; +} + +static unsigned be_alpha_is_step_over_insn(void* insn) +{ + dbg_printf("not done\n"); + return FALSE; +} + +static unsigned be_alpha_is_function_return(void* insn) +{ + dbg_printf("not done\n"); + return FALSE; +} + +static unsigned be_alpha_is_break_insn(void* insn) +{ + dbg_printf("not done\n"); + return FALSE; +} + +static unsigned be_alpha_is_func_call(void* insn, void** insn_callee) +{ + return FALSE; +} + +static void be_alpha_disasm_one_insn(ADDRESS* addr, int display) +{ + dbg_printf("Disasm NIY\n"); +} + +static unsigned be_alpha_insert_Xpoint(HANDLE hProcess, CONTEXT* ctx, + enum be_xpoint_type type, void* addr, + unsigned long* val, unsigned size) +{ + unsigned long xbp; + unsigned long sz; + + switch (type) + { + case be_xpoint_break: + if (!size) return 0; + if (!ReadProcessMemory(hProcess, addr, val, 4, &sz) || sz != 4) return 0; + xbp = 0x7d821008; /* 7d 82 10 08 ... in big endian */ + if (!WriteProcessMemory(hProcess, addr, &xbp, 4, &sz) || sz != 4) return 0; + break; + default: + dbg_printf("Unknown/unsupported bp type %c\n", type); + return 0; + } + return 1; +} + +static unsigned be_alpha_remove_Xpoint(HANDLE hProcess, CONTEXT* ctx, + enum be_xpoint_type type, void* addr, + unsigned long val, unsigned size) +{ + dbg_printf("not done\n"); + return FALSE; +} + +static unsigned be_alpha_is_watchpoint_set(const CONTEXT* ctx, unsigned idx) +{ + dbg_printf("not done\n"); + return FALSE; +} + +static void be_alpha_clear_watchpoint(CONTEXT* ctx, unsigned idx) +{ + dbg_printf("not done\n"); +} + +static int be_alpha_adjust_pc_for_break(CONTEXT* ctx, BOOL way) +{ + dbg_printf("not done\n"); + return 0; +} + +static int be_alpha_fetch_integer(const struct dbg_lvalue* lvalue, unsigned size, + unsigned ext_sign, long long int* ret) +{ + dbg_printf("not done\n"); + return FALSE; +} + +static int be_alpha_fetch_float(const struct dbg_lvalue* lvalue, unsigned size, + long double* ret) +{ + dbg_printf("not done\n"); + return FALSE; +} + +struct backend_cpu be_alpha = +{ + be_cpu_linearize, + be_cpu_build_addr, + be_alpha_get_addr, + be_alpha_single_step, + be_alpha_print_context, + be_alpha_print_segment_info, + be_alpha_init_registers, + be_alpha_is_step_over_insn, + be_alpha_is_function_return, + be_alpha_is_break_insn, + be_alpha_is_func_call, + be_alpha_disasm_one_insn, + be_alpha_insert_Xpoint, + be_alpha_remove_Xpoint, + be_alpha_is_watchpoint_set, + be_alpha_clear_watchpoint, + be_alpha_adjust_pc_for_break, + be_alpha_fetch_integer, + be_alpha_fetch_float, +}; +#endif diff --git a/programs/winedbg/gdbproxy.c b/programs/winedbg/gdbproxy.c index f39861da4ab..018235addb9 100644 --- a/programs/winedbg/gdbproxy.c +++ b/programs/winedbg/gdbproxy.c @@ -177,8 +177,7 @@ static size_t cpu_register_map[] = { FIELD_OFFSET(CONTEXT, SegFs), FIELD_OFFSET(CONTEXT, SegGs), }; -#else -# ifdef __powerpc__ +#elif defined(__powerpc__) static size_t cpu_register_map[] = { FIELD_OFFSET(CONTEXT, Gpr0), FIELD_OFFSET(CONTEXT, Gpr1), @@ -254,9 +253,80 @@ static size_t cpu_register_map[] = { /* FIXME: MQ is missing? FIELD_OFFSET(CONTEXT, Mq), */ /* see gdb/nlm/ppc.c */ }; -# else -# error "Define the registers map for your CPU" -# endif +#elif defined(__ALPHA__) +static size_t cpu_register_map[] = { + FIELD_OFFSET(CONTEXT, IntV0), + FIELD_OFFSET(CONTEXT, IntT0), + FIELD_OFFSET(CONTEXT, IntT1), + FIELD_OFFSET(CONTEXT, IntT2), + FIELD_OFFSET(CONTEXT, IntT3), + FIELD_OFFSET(CONTEXT, IntT4), + FIELD_OFFSET(CONTEXT, IntT5), + FIELD_OFFSET(CONTEXT, IntT6), + FIELD_OFFSET(CONTEXT, IntT7), + FIELD_OFFSET(CONTEXT, IntS0), + FIELD_OFFSET(CONTEXT, IntS1), + FIELD_OFFSET(CONTEXT, IntS2), + FIELD_OFFSET(CONTEXT, IntS3), + FIELD_OFFSET(CONTEXT, IntS4), + FIELD_OFFSET(CONTEXT, IntS5), + FIELD_OFFSET(CONTEXT, IntFp), + FIELD_OFFSET(CONTEXT, IntA0), + FIELD_OFFSET(CONTEXT, IntA1), + FIELD_OFFSET(CONTEXT, IntA2), + FIELD_OFFSET(CONTEXT, IntA3), + FIELD_OFFSET(CONTEXT, IntA4), + FIELD_OFFSET(CONTEXT, IntA5), + FIELD_OFFSET(CONTEXT, IntT8), + FIELD_OFFSET(CONTEXT, IntT9), + FIELD_OFFSET(CONTEXT, IntT10), + FIELD_OFFSET(CONTEXT, IntT11), + FIELD_OFFSET(CONTEXT, IntRa), + FIELD_OFFSET(CONTEXT, IntT12), + FIELD_OFFSET(CONTEXT, IntAt), + FIELD_OFFSET(CONTEXT, IntGp), + FIELD_OFFSET(CONTEXT, IntSp), + FIELD_OFFSET(CONTEXT, IntZero), + FIELD_OFFSET(CONTEXT, FltF0), + FIELD_OFFSET(CONTEXT, FltF1), + FIELD_OFFSET(CONTEXT, FltF2), + FIELD_OFFSET(CONTEXT, FltF3), + FIELD_OFFSET(CONTEXT, FltF4), + FIELD_OFFSET(CONTEXT, FltF5), + FIELD_OFFSET(CONTEXT, FltF6), + FIELD_OFFSET(CONTEXT, FltF7), + FIELD_OFFSET(CONTEXT, FltF8), + FIELD_OFFSET(CONTEXT, FltF9), + FIELD_OFFSET(CONTEXT, FltF10), + FIELD_OFFSET(CONTEXT, FltF11), + FIELD_OFFSET(CONTEXT, FltF12), + FIELD_OFFSET(CONTEXT, FltF13), + FIELD_OFFSET(CONTEXT, FltF14), + FIELD_OFFSET(CONTEXT, FltF15), + FIELD_OFFSET(CONTEXT, FltF16), + FIELD_OFFSET(CONTEXT, FltF17), + FIELD_OFFSET(CONTEXT, FltF18), + FIELD_OFFSET(CONTEXT, FltF19), + FIELD_OFFSET(CONTEXT, FltF20), + FIELD_OFFSET(CONTEXT, FltF21), + FIELD_OFFSET(CONTEXT, FltF22), + FIELD_OFFSET(CONTEXT, FltF23), + FIELD_OFFSET(CONTEXT, FltF24), + FIELD_OFFSET(CONTEXT, FltF25), + FIELD_OFFSET(CONTEXT, FltF26), + FIELD_OFFSET(CONTEXT, FltF27), + FIELD_OFFSET(CONTEXT, FltF28), + FIELD_OFFSET(CONTEXT, FltF29), + FIELD_OFFSET(CONTEXT, FltF30), + FIELD_OFFSET(CONTEXT, FltF31), + + /* FIXME: Didn't look for the right order yet */ + FIELD_OFFSET(CONTEXT, Fir), + FIELD_OFFSET(CONTEXT, Fpcr), + FIELD_OFFSET(CONTEXT, SoftFpcr), +}; +#else +# error Define the registers map for your CPU #endif static const size_t cpu_num_regs = (sizeof(cpu_register_map) / sizeof(cpu_register_map[0])); diff --git a/programs/winedbg/winedbg.c b/programs/winedbg/winedbg.c index 32177ee4c73..3c3f34d6be0 100644 --- a/programs/winedbg/winedbg.c +++ b/programs/winedbg/winedbg.c @@ -1102,6 +1102,8 @@ struct backend_cpu* be_cpu; extern struct backend_cpu be_i386; #elif __powerpc__ extern struct backend_cpu be_ppc; +#elif __ALPHA__ +extern struct backend_cpu be_alpha; #else # error CPU unknown #endif @@ -1115,6 +1117,8 @@ int main(int argc, char** argv) be_cpu = &be_i386; #elif __powerpc__ be_cpu = &be_ppc; +#elif __ALPHA__ + be_cpu = &be_alpha; #else # error CPU unknown #endif diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index f4f43e0331e..1dc91727ea8 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -749,6 +749,10 @@ static int output_immediate_imports( FILE *outfile ) fprintf(outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]); fprintf(outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]); fprintf(outfile, "\t\"\\tbctr\\n"); +#elif defined(__ALPHA__) + fprintf( outfile, "\tlda $0,imports\\n\"\n" ); + fprintf( outfile, "\t\"\\tlda $0,%d($0)\\n\"\n", pos); + fprintf( outfile, "\t\"\\tjmp $31,($0)\\n" ); #else #error You need to define import thunks for your architecture! #endif @@ -952,6 +956,9 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec ) /* branch to ctr register. */ fprintf( outfile, " \"bctr\\n\"\n"); +#elif defined(__ALPHA__) + fprintf( outfile, " \"\\tjsr $26,__wine_delay_load\\n\"\n" ); + fprintf( outfile, " \"\\tjmp $31,($0)\\n\"\n" ); #else #error You need to defined delayed import thunks for your architecture! #endif @@ -997,6 +1004,10 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec ) fprintf( outfile, " \"\\taddic %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]); fprintf( outfile, " \"\\tb " __ASM_NAME("__wine_delay_load_asm") "\\n\"\n"); #endif /* __APPLE__ */ +#elif defined(__ALPHA__) + fprintf( outfile, " \"\\tlda $0,%d($31)\\n\"\n", j); + fprintf( outfile, " \"\\tldah $0,%d($0)\\n\"\n", idx); + fprintf( outfile, " \"\\tjmp $31,__wine_delay_load_asm\\n\"\n" ); #else #error You need to defined delayed import thunks for your architecture! #endif @@ -1064,6 +1075,10 @@ static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec ) fprintf( outfile, "\t\"\\tlwz %s, 0(%s)\\n\"\n", ppc_reg[9], ppc_reg[1]); fprintf( outfile, "\t\"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg[1], ppc_reg[1]); fprintf( outfile, "\t\"\\tbctr\\n\""); +#elif defined(__ALPHA__) + fprintf( outfile, "\t\"lda $0,delay_imports\\n\"\n" ); + fprintf( outfile, "\t\"\\tlda $0,%d($0)\\n\"\n", pos); + fprintf( outfile, "\t\"\\tjmp $31,($0)\\n\"" ); #else #error You need to define delayed import thunks for your architecture! #endif diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c index 1dea09d0ed7..5132975c736 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -468,6 +468,19 @@ void output_dll_init( FILE *outfile, const char *constructor, const char *destru fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" ); } # endif /* __APPLE__ */ +#elif defined(__ALPHA__) + if (constructor) + { + fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" ); + fprintf( outfile, " \"\\tjsr $26," __ASM_NAME("%s") "\\n\"\n", constructor ); + fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" ); + } + if (destructor) + { + fprintf( outfile, "asm(\"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" ); + fprintf( outfile, " \"\\tjsr $26," __ASM_NAME("%s") "\\n\"\n", destructor ); + fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" ); + } #else #error You need to define the DLL constructor for your architecture #endif @@ -757,6 +770,8 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec ) fprintf( outfile, " { 0x%04x,\n", IMAGE_FILE_MACHINE_I386 ); /* Machine */ #elif defined(__powerpc__) fprintf( outfile, " { 0x%04x,\n", IMAGE_FILE_MACHINE_POWERPC ); /* Machine */ +#elif defined(__ALPHA__) + fprintf( outfile, " { 0x%04x,\n", IMAGE_FILE_MACHINE_ALPHA ); /* Machine */ #else fprintf( outfile, " { 0x%04x,\n", IMAGE_FILE_MACHINE_UNKNOWN ); /* Machine */ #endif @@ -965,6 +980,12 @@ void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv ) fprintf( outfile, " \"\\tbl " __ASM_NAME("__wine_dbg_%s_fini") "\\n\"\n", prefix ); fprintf( outfile, " \"\\t.text\\n\");\n" ); # endif +#elif defined(__ALPHA__) + fprintf( outfile, "asm(\"\\t.section\\t\\\".init\\\" ,\\\"ax\\\"\\n\"\n" ); + fprintf( outfile, " \"\\tjsr $26," __ASM_NAME("__wine_dbg_%s_init") "\\n\"\n", prefix ); + fprintf( outfile, " \"\\t.section\\t\\\".fini\\\" ,\\\"ax\\\"\\n\"\n" ); + fprintf( outfile, " \"\\tjsr $26," __ASM_NAME("__wine_dbg_%s_fini") "\\n\"\n", prefix ); + fprintf( outfile, " \"\\t.section\\t\\\".text\\\"\\n\");\n" ); #else #error You need to define the DLL constructor for your architecture #endif