Search
lxdream.org :: lxdream/src/xlat/x86/ia32abi.h
lxdream 0.9.1
released Jun 29
Download Now
filename src/xlat/x86/ia32abi.h
changeset 1067:d3c00ffccfcd
prevsrc/sh4/ia32abi.h@947:aa80962d6439
prevsrc/sh4/ia32abi.h@1065:bc1cc0c54917
next1112: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)
view annotate diff log raw
     1 /**
     2  * $Id$
     3  * 
     4  * Provides the implementation for the ia32 ABI variant 
     5  * (eg prologue, epilogue, and calling conventions). Stack frame is
     6  * aligned on 16-byte boundaries for the benefit of OS X (which 
     7  * requires it).
     8  * 
     9  * Note: These should only be included from x86op.h
    10  *
    11  * Copyright (c) 2007 Nathan Keynes.
    12  *
    13  * This program is free software; you can redistribute it and/or modify
    14  * it under the terms of the GNU General Public License as published by
    15  * the Free Software Foundation; either version 2 of the License, or
    16  * (at your option) any later version.
    17  *
    18  * This program is distributed in the hope that it will be useful,
    19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    21  * GNU General Public License for more details.
    22  */
    24 #define REG_ARG1 REG_EAX
    25 #define REG_ARG2 REG_EDX
    26 #define REG_RESULT1 REG_EAX
    27 #define MAX_REG_ARG 2
    29 static inline void decode_address( uintptr_t base, int addr_reg )
    30 {
    31     MOVL_r32_r32( addr_reg, REG_ECX );
    32     SHRL_imm_r32( 12, REG_ECX ); 
    33     MOVP_sib_rptr( 2, REG_ECX, -1, base, REG_ECX );
    34 }
    36 /**
    37  * Note: clobbers ECX to make the indirect call - this isn't usually
    38  * a problem since the callee will generally clobber it anyway.
    39  */
    40 static inline void CALL_ptr( void *ptr )
    41 {
    42     MOVP_immptr_rptr( (uintptr_t)ptr, REG_ECX );
    43     CALL_r32(REG_ECX);
    44 }
    46 #ifdef HAVE_FASTCALL
    47 static inline void CALL1_ptr_r32( void *ptr, int arg1 )
    48 {
    49     if( arg1 != REG_ARG1 ) {
    50         MOVL_r32_r32( arg1, REG_ARG1 );
    51     }
    52     CALL_ptr(ptr);
    53 }
    55 static inline void CALL1_r32disp_r32( int preg, uint32_t disp, int arg1 )
    56 {
    57     if( arg1 != REG_ARG1 ) {
    58         MOVL_r32_r32( arg1, REG_ARG1 );
    59     }
    60     CALL_r32disp(preg, disp);
    61 }
    63 static inline void CALL2_ptr_r32_r32( void *ptr, int arg1, int arg2 )
    64 {
    65     if( arg2 != REG_ARG2 ) {
    66         MOVL_r32_r32( arg2, REG_ARG2 );
    67     }
    68     if( arg1 != REG_ARG1 ) {
    69         MOVL_r32_r32( arg1, REG_ARG1 );
    70     }
    71     CALL_ptr(ptr);
    72 }
    74 static inline void CALL2_r32disp_r32_r32( int preg, uint32_t disp, int arg1, int arg2 )
    75 {
    76     if( arg2 != REG_ARG2 ) {
    77         MOVL_r32_r32( arg2, REG_ARG2 );
    78     }
    79     if( arg1 != REG_ARG1 ) {
    80         MOVL_r32_r32( arg1, REG_ARG1 );
    81     }
    82     CALL_r32disp(preg, disp);
    83 }
    85 #define CALL3_r32disp_r32_r32_r32(preg,disp,arg1,arg2,arg3) CALL2_r32disp_r32_r32(preg,disp,arg1,arg2)
    87 #else
    88 static inline void CALL1_ptr( void *ptr, int arg1 )
    89 {
    90     SUBL_imms_r32( 12, REG_ESP );
    91     PUSH_r32(arg1);
    92     CALL_ptr(ptr);
    93     ADDL_imms_r32( 16, REG_ESP );
    94 }
    96 static inline void CALL1_r32disp_r32( int preg, uint32_t disp, int arg1 )
    97 {
    98     SUBL_imms_r32( 12, REG_ESP );
    99     PUSH_r32(arg1);
   100     CALL_r32disp(preg, disp);
   101     ADDL_imms_r32( 16, REG_ESP );
   102 }
   104 static inline void CALL2_ptr_r32_r32( void *ptr, int arg1, int arg2 )
   105 {
   106     SUBL_imms_r32( 8, REG_ESP );
   107     PUSH_r32(arg2);
   108     PUSH_r32(arg1);
   109     CALL_ptr(ptr);
   110     ADDL_imms_r32( 16, REG_ESP );
   111 }
   113 static inline void CALL2_r32disp_r32_r32( int preg, uint32_t disp, int arg1, int arg2 )
   114 {
   115     SUBL_imms_r32( 8, REG_ESP );
   116     PUSH_r32(arg2);
   117     PUSH_r32(arg1);
   118     CALL_r32disp(preg, disp);
   119     ADDL_imms_r32( 16, REG_ESP );
   120 }
   122 static inline void CALL3_r32disp_r32_r32_r32( int preg, uint32_t disp, int arg1, int arg2, int arg3 )
   123 {
   124     SUBL_imms_r32( 8, REG_ESP );
   125     PUSH_r32(arg2);
   126     PUSH_r32(arg1);
   127     MOVL_rspdisp_r32( 16, REG_EAX );
   128     MOVL_r32_rspdisp( R_EAX, 8 );
   129     CALL_r32disp(preg,disp);
   130     ADDL_imms_r32( 16, REG_ESP );
   131 }
   133 #endif
   135 /**
   136  * Emit the 'start of block' assembly. Sets up the stack frame and save
   137  * SI/DI as required
   138  * Allocates 8 bytes for local variables, which also has the convenient
   139  * side-effect of aligning the stack.
   140  */
   141 static inline void enter_block( ) 
   142 {
   143     PUSH_r32(REG_EBP);
   144     SUBL_imms_r32( 8, REG_ESP ); 
   145 }
   147 static inline void exit_block( )
   148 {
   149     ADDL_imms_r32( 8, REG_ESP );
   150     POP_r32(REG_EBP);
   151     RET();
   152 }
.