Search
lxdream.org :: lxdream/src/xlat/x86/ia32abi.h :: diff
lxdream 0.9.1
released Jun 29
Download Now
filename src/xlat/x86/ia32abi.h
changeset 1065:bc1cc0c54917
prev577:a181aeacd6e8
prev1004:eae001858134
next1067:d3c00ffccfcd
author nkeynes
date Sun Jul 05 13:52:50 2009 +1000 (12 years ago)
permissions -rw-r--r--
last change No-op merge lxdream-mmu to remove head (actually merged long ago)
file annotate diff log raw
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/xlat/x86/ia32abi.h Sun Jul 05 13:52:50 2009 +1000
1.3 @@ -0,0 +1,152 @@
1.4 +/**
1.5 + * $Id$
1.6 + *
1.7 + * Provides the implementation for the ia32 ABI variant
1.8 + * (eg prologue, epilogue, and calling conventions). Stack frame is
1.9 + * aligned on 16-byte boundaries for the benefit of OS X (which
1.10 + * requires it).
1.11 + *
1.12 + * Note: These should only be included from x86op.h
1.13 + *
1.14 + * Copyright (c) 2007 Nathan Keynes.
1.15 + *
1.16 + * This program is free software; you can redistribute it and/or modify
1.17 + * it under the terms of the GNU General Public License as published by
1.18 + * the Free Software Foundation; either version 2 of the License, or
1.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 of
1.23 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.24 + * GNU General Public License for more details.
1.25 + */
1.26 +
1.27 +#define REG_ARG1 REG_EAX
1.28 +#define REG_ARG2 REG_EDX
1.29 +#define REG_RESULT1 REG_EAX
1.30 +#define MAX_REG_ARG 2
1.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 usually
1.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_FASTCALL
1.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 +#else
1.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 +#endif
1.137 +
1.138 +/**
1.139 + * Emit the 'start of block' assembly. Sets up the stack frame and save
1.140 + * SI/DI as required
1.141 + * Allocates 8 bytes for local variables, which also has the convenient
1.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 +}
.