filename | src/xlat/x86/ia32abi.h |
changeset | 1067:d3c00ffccfcd |
prev | 947:aa80962d6439 |
prev | 1065:bc1cc0c54917 |
next | 1112:4cac5e474d4c |
author | nkeynes |
date | Sun Jul 05 13:54:48 2009 +1000 (14 years ago) |
permissions | -rw-r--r-- |
last change | No-op merge lxdream-mem to tip to remove head (Long since merged in actuality) |
file | annotate | diff | log | raw |
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +00001.2 +++ b/src/xlat/x86/ia32abi.h Sun Jul 05 13:54:48 2009 +10001.3 @@ -0,0 +1,152 @@1.4 +/**1.5 + * $Id$1.6 + *1.7 + * Provides the implementation for the ia32 ABI variant1.8 + * (eg prologue, epilogue, and calling conventions). Stack frame is1.9 + * aligned on 16-byte boundaries for the benefit of OS X (which1.10 + * requires it).1.11 + *1.12 + * Note: These should only be included from x86op.h1.13 + *1.14 + * Copyright (c) 2007 Nathan Keynes.1.15 + *1.16 + * This program is free software; you can redistribute it and/or modify1.17 + * it under the terms of the GNU General Public License as published by1.18 + * the Free Software Foundation; either version 2 of the License, or1.19 + * (at your option) any later version.1.20 + *1.21 + * This program is distributed in the hope that it will be useful,1.22 + * but WITHOUT ANY WARRANTY; without even the implied warranty of1.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1.24 + * GNU General Public License for more details.1.25 + */1.26 +1.27 +#define REG_ARG1 REG_EAX1.28 +#define REG_ARG2 REG_EDX1.29 +#define REG_RESULT1 REG_EAX1.30 +#define MAX_REG_ARG 21.31 +1.32 +static inline void decode_address( uintptr_t base, int addr_reg )1.33 +{1.34 + MOVL_r32_r32( addr_reg, REG_ECX );1.35 + SHRL_imm_r32( 12, REG_ECX );1.36 + MOVP_sib_rptr( 2, REG_ECX, -1, base, REG_ECX );1.37 +}1.38 +1.39 +/**1.40 + * Note: clobbers ECX to make the indirect call - this isn't usually1.41 + * a problem since the callee will generally clobber it anyway.1.42 + */1.43 +static inline void CALL_ptr( void *ptr )1.44 +{1.45 + MOVP_immptr_rptr( (uintptr_t)ptr, REG_ECX );1.46 + CALL_r32(REG_ECX);1.47 +}1.48 +1.49 +#ifdef HAVE_FASTCALL1.50 +static inline void CALL1_ptr_r32( void *ptr, int arg1 )1.51 +{1.52 + if( arg1 != REG_ARG1 ) {1.53 + MOVL_r32_r32( arg1, REG_ARG1 );1.54 + }1.55 + CALL_ptr(ptr);1.56 +}1.57 +1.58 +static inline void CALL1_r32disp_r32( int preg, uint32_t disp, int arg1 )1.59 +{1.60 + if( arg1 != REG_ARG1 ) {1.61 + MOVL_r32_r32( arg1, REG_ARG1 );1.62 + }1.63 + CALL_r32disp(preg, disp);1.64 +}1.65 +1.66 +static inline void CALL2_ptr_r32_r32( void *ptr, int arg1, int arg2 )1.67 +{1.68 + if( arg2 != REG_ARG2 ) {1.69 + MOVL_r32_r32( arg2, REG_ARG2 );1.70 + }1.71 + if( arg1 != REG_ARG1 ) {1.72 + MOVL_r32_r32( arg1, REG_ARG1 );1.73 + }1.74 + CALL_ptr(ptr);1.75 +}1.76 +1.77 +static inline void CALL2_r32disp_r32_r32( int preg, uint32_t disp, int arg1, int arg2 )1.78 +{1.79 + if( arg2 != REG_ARG2 ) {1.80 + MOVL_r32_r32( arg2, REG_ARG2 );1.81 + }1.82 + if( arg1 != REG_ARG1 ) {1.83 + MOVL_r32_r32( arg1, REG_ARG1 );1.84 + }1.85 + CALL_r32disp(preg, disp);1.86 +}1.87 +1.88 +#define CALL3_r32disp_r32_r32_r32(preg,disp,arg1,arg2,arg3) CALL2_r32disp_r32_r32(preg,disp,arg1,arg2)1.89 +1.90 +#else1.91 +static inline void CALL1_ptr( void *ptr, int arg1 )1.92 +{1.93 + SUBL_imms_r32( 12, REG_ESP );1.94 + PUSH_r32(arg1);1.95 + CALL_ptr(ptr);1.96 + ADDL_imms_r32( 16, REG_ESP );1.97 +}1.98 +1.99 +static inline void CALL1_r32disp_r32( int preg, uint32_t disp, int arg1 )1.100 +{1.101 + SUBL_imms_r32( 12, REG_ESP );1.102 + PUSH_r32(arg1);1.103 + CALL_r32disp(preg, disp);1.104 + ADDL_imms_r32( 16, REG_ESP );1.105 +}1.106 +1.107 +static inline void CALL2_ptr_r32_r32( void *ptr, int arg1, int arg2 )1.108 +{1.109 + SUBL_imms_r32( 8, REG_ESP );1.110 + PUSH_r32(arg2);1.111 + PUSH_r32(arg1);1.112 + CALL_ptr(ptr);1.113 + ADDL_imms_r32( 16, REG_ESP );1.114 +}1.115 +1.116 +static inline void CALL2_r32disp_r32_r32( int preg, uint32_t disp, int arg1, int arg2 )1.117 +{1.118 + SUBL_imms_r32( 8, REG_ESP );1.119 + PUSH_r32(arg2);1.120 + PUSH_r32(arg1);1.121 + CALL_r32disp(preg, disp);1.122 + ADDL_imms_r32( 16, REG_ESP );1.123 +}1.124 +1.125 +static inline void CALL3_r32disp_r32_r32_r32( int preg, uint32_t disp, int arg1, int arg2, int arg3 )1.126 +{1.127 + SUBL_imms_r32( 8, REG_ESP );1.128 + PUSH_r32(arg2);1.129 + PUSH_r32(arg1);1.130 + MOVL_rspdisp_r32( 16, REG_EAX );1.131 + MOVL_r32_rspdisp( R_EAX, 8 );1.132 + CALL_r32disp(preg,disp);1.133 + ADDL_imms_r32( 16, REG_ESP );1.134 +}1.135 +1.136 +#endif1.137 +1.138 +/**1.139 + * Emit the 'start of block' assembly. Sets up the stack frame and save1.140 + * SI/DI as required1.141 + * Allocates 8 bytes for local variables, which also has the convenient1.142 + * side-effect of aligning the stack.1.143 + */1.144 +static inline void enter_block( )1.145 +{1.146 + PUSH_r32(REG_EBP);1.147 + SUBL_imms_r32( 8, REG_ESP );1.148 +}1.149 +1.150 +static inline void exit_block( )1.151 +{1.152 + ADDL_imms_r32( 8, REG_ESP );1.153 + POP_r32(REG_EBP);1.154 + RET();1.155 +}
.