filename | src/sh4/ia32mac.h |
changeset | 905:4c17ebd9ef5e |
prev | 901:32c5cf5e206f |
next | 906:268ea359f884 |
author | nkeynes |
date | Wed Oct 29 23:51:58 2008 +0000 (13 years ago) |
permissions | -rw-r--r-- |
last change | Use regparam calling conventions for all functions called from translated code, along with a few other high-use functions. Can probably extend this to all functions, but as it is this is a nice performance boost |
file | annotate | diff | log | raw |
1.1 --- a/src/sh4/ia32mac.h Sun Oct 26 02:28:29 2008 +00001.2 +++ b/src/sh4/ia32mac.h Wed Oct 29 23:51:58 2008 +00001.3 @@ -32,12 +32,73 @@1.4 {1.5 int adj = (-sh4_x86.stack_posn)&0x0F;1.6 SUB_imm8s_r32( adj, R_ESP );1.7 - load_imm32(R_EAX, (uint32_t)ptr);1.8 - CALL_r32(R_EAX);1.9 + load_imm32(R_ECX, (uint32_t)ptr);1.10 + CALL_r32(R_ECX);1.11 ADD_imm8s_r32( adj, R_ESP );1.12 }1.14 -#define CALL_FUNC1_SIZE 141.15 +#ifdef HAVE_FASTCALL1.16 +static inline void call_func1( void *ptr, int arg1 )1.17 +{1.18 + int adj = (-sh4_x86.stack_posn)&0x0F;1.19 + SUB_imm8s_r32( adj, R_ESP );1.20 + if( arg1 != R_EAX ) {1.21 + MOV_r32_r32( arg1, R_EAX );1.22 + }1.23 + load_imm32(R_ECX, (uint32_t)ptr);1.24 + CALL_r32(R_ECX);1.25 + ADD_imm8s_r32( adj, R_ESP );1.26 +}1.27 +1.28 +static inline void call_func2( void *ptr, int arg1, int arg2 )1.29 +{1.30 + int adj = (-sh4_x86.stack_posn)&0x0F;1.31 + SUB_imm8s_r32( adj, R_ESP );1.32 + if( arg2 != R_EDX ) {1.33 + MOV_r32_r32( arg2, R_EDX );1.34 + }1.35 + if( arg1 != R_EAX ) {1.36 + MOV_r32_r32( arg1, R_EAX );1.37 + }1.38 + load_imm32(R_ECX, (uint32_t)ptr);1.39 + CALL_r32(R_ECX);1.40 + ADD_imm8s_r32( adj, R_ESP );1.41 +}1.42 +1.43 +/**1.44 + * Write a double (64-bit) value into memory, with the first word in arg2a, and1.45 + * the second in arg2b1.46 + */1.47 +static inline void MEM_WRITE_DOUBLE( int addr, int arg2a, int arg2b )1.48 +{1.49 + PUSH_r32(arg2b);1.50 + PUSH_r32(addr);1.51 + call_func2(sh4_write_long, addr, arg2a);1.52 + POP_r32(R_EAX);1.53 + POP_r32(R_EDX);1.54 + ADD_imm8s_r32(4, R_EAX);1.55 + call_func0(sh4_write_long);1.56 +}1.57 +1.58 +/**1.59 + * Read a double (64-bit) value from memory, writing the first word into arg2a1.60 + * and the second into arg2b. The addr must not be in EAX1.61 + */1.62 +static inline void MEM_READ_DOUBLE( int addr, int arg2a, int arg2b )1.63 +{1.64 + PUSH_r32(addr);1.65 + call_func1(sh4_read_long, addr);1.66 + POP_r32(R_ECX);1.67 + PUSH_r32(R_EAX);1.68 + MOV_r32_r32(R_ECX, R_EAX);1.69 + ADD_imm8s_r32(4, R_EAX);1.70 + call_func0(sh4_read_long);1.71 + if( arg2b != R_EAX ) {1.72 + MOV_r32_r32(R_EAX, arg2b);1.73 + }1.74 + POP_r32(arg2a);1.75 +}1.76 +#else1.77 static inline void call_func1( void *ptr, int arg1 )1.78 {1.79 int adj = (-4-sh4_x86.stack_posn)&0x0F;1.80 @@ -65,9 +126,7 @@1.81 /**1.82 * Write a double (64-bit) value into memory, with the first word in arg2a, and1.83 * the second in arg2b1.84 - * NB: 30 bytes1.85 */1.86 -#define MEM_WRITE_DOUBLE_SIZE 361.87 static inline void MEM_WRITE_DOUBLE( int addr, int arg2a, int arg2b )1.88 {1.89 int adj = (-8-sh4_x86.stack_posn)&0x0F;1.90 @@ -91,9 +150,7 @@1.91 /**1.92 * Read a double (64-bit) value from memory, writing the first word into arg2a1.93 * and the second into arg2b. The addr must not be in EAX1.94 - * NB: 27 bytes1.95 */1.96 -#define MEM_READ_DOUBLE_SIZE 361.97 static inline void MEM_READ_DOUBLE( int addr, int arg2a, int arg2b )1.98 {1.99 int adj = (-4-sh4_x86.stack_posn)&0x0F;1.100 @@ -116,6 +173,8 @@1.101 sh4_x86.stack_posn -= 4;1.102 }1.104 +#endif1.105 +1.106 /**1.107 * Emit the 'start of block' assembly. Sets up the stack frame and save1.108 * SI/DI as required1.109 @@ -164,9 +223,6 @@1.110 }1.113 -#define EXIT_BLOCK_SIZE(pc) (24 + (IS_IN_ICACHE(pc)?5:CALL_FUNC1_SIZE))1.114 -1.115 -1.116 /**1.117 * Exit the block to an absolute PC1.118 */1.119 @@ -188,8 +244,6 @@1.120 RET();1.121 }1.123 -#define EXIT_BLOCK_REL_SIZE(pc) (27 + (IS_IN_ICACHE(pc)?5:CALL_FUNC1_SIZE))1.124 -1.125 /**1.126 * Exit the block to a relative PC1.127 */1.128 @@ -280,6 +334,47 @@1.129 }1.130 }1.132 +1.133 +/**1.134 + * The unwind methods only work if we compiled with DWARF2 frame information1.135 + * (ie -fexceptions), otherwise we have to use the direct frame scan.1.136 + */1.137 +#ifdef HAVE_EXCEPTIONS1.138 +#include <unwind.h>1.139 +1.140 +struct UnwindInfo {1.141 + int have_result;1.142 + void *pc;1.143 +};1.144 +1.145 +_Unwind_Reason_Code xlat_check_frame( struct _Unwind_Context *context, void *arg )1.146 +{1.147 + void *ebp = (void *)_Unwind_GetGR(context, 5);1.148 + void *expect = (((uint8_t *)&sh4r) + 128 );1.149 + struct UnwindInfo *info = arg;1.150 + if( ebp == expect ) {1.151 + info->have_result = 1;1.152 + info->pc = (void *)_Unwind_GetIP(context);1.153 + } else if( info->have_result ) {1.154 + return _URC_NORMAL_STOP;1.155 + }1.156 +1.157 + return _URC_NO_REASON;1.158 +}1.159 +1.160 +void *xlat_get_native_pc()1.161 +{1.162 + struct _Unwind_Exception exc;1.163 + struct UnwindInfo info;1.164 +1.165 + info.have_result = 0;1.166 + void *result = NULL;1.167 + _Unwind_Backtrace( xlat_check_frame, &info );1.168 + if( info.have_result )1.169 + return info.pc;1.170 + return NULL;1.171 +}1.172 +#else1.173 void *xlat_get_native_pc()1.174 {1.175 void *result = NULL;1.176 @@ -302,7 +397,7 @@1.177 : "eax", "ecx", "edx" );1.178 return result;1.179 }1.180 -1.181 +#endif1.183 #endif /* !lxdream_ia32mac.h */
.