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 995:eb9d43e8aa08
prev992:7c15f8a71995
next1004:eae001858134
author nkeynes
date Thu Mar 05 21:42:35 2009 +0000 (13 years ago)
permissions -rw-r--r--
last change Cleanup ABI headers - most of the content made consistent between versions, and moved into sh4x86.in proper
file annotate diff log raw
nkeynes@539
     1
/**
nkeynes@586
     2
 * $Id$
nkeynes@539
     3
 * 
nkeynes@926
     4
 * Provides the implementation for the ia32 ABI variant 
nkeynes@926
     5
 * (eg prologue, epilogue, and calling conventions). Stack frame is
nkeynes@926
     6
 * aligned on 16-byte boundaries for the benefit of OS X (which 
nkeynes@926
     7
 * requires it).
nkeynes@995
     8
 * 
nkeynes@995
     9
 * Note: These should only be included from x86op.h
nkeynes@539
    10
 *
nkeynes@539
    11
 * Copyright (c) 2007 Nathan Keynes.
nkeynes@539
    12
 *
nkeynes@539
    13
 * This program is free software; you can redistribute it and/or modify
nkeynes@539
    14
 * it under the terms of the GNU General Public License as published by
nkeynes@539
    15
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@539
    16
 * (at your option) any later version.
nkeynes@539
    17
 *
nkeynes@539
    18
 * This program is distributed in the hope that it will be useful,
nkeynes@539
    19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@539
    20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@539
    21
 * GNU General Public License for more details.
nkeynes@539
    22
 */
nkeynes@539
    23
nkeynes@995
    24
#define REG_ARG1 REG_EAX
nkeynes@995
    25
#define REG_ARG2 REG_EDX
nkeynes@995
    26
#define REG_RESULT1 REG_EAX
nkeynes@995
    27
#define MAX_REG_ARG 2
nkeynes@539
    28
nkeynes@968
    29
static inline void decode_address( int addr_reg )
nkeynes@953
    30
{
nkeynes@953
    31
    uintptr_t base = (sh4r.xlat_sh4_mode&SR_MD) ? (uintptr_t)sh4_address_space : (uintptr_t)sh4_user_address_space;
nkeynes@995
    32
    MOVL_r32_r32( addr_reg, REG_ECX );
nkeynes@991
    33
    SHRL_imm_r32( 12, REG_ECX ); 
nkeynes@991
    34
    MOVP_sib_rptr( 2, REG_ECX, -1, base, REG_ECX );
nkeynes@953
    35
}
nkeynes@953
    36
nkeynes@539
    37
/**
nkeynes@995
    38
 * Note: clobbers ECX to make the indirect call - this isn't usually
nkeynes@995
    39
 * a problem since the callee will generally clobber it anyway.
nkeynes@539
    40
 */
nkeynes@995
    41
static inline void CALL_ptr( void *ptr )
nkeynes@539
    42
{
nkeynes@995
    43
    MOVP_immptr_rptr( (uintptr_t)ptr, REG_ECX );
nkeynes@991
    44
    CALL_r32(REG_ECX);
nkeynes@539
    45
}
nkeynes@539
    46
nkeynes@905
    47
#ifdef HAVE_FASTCALL
nkeynes@995
    48
static inline void CALL1_ptr_r32( void *ptr, int arg1 )
nkeynes@905
    49
{
nkeynes@995
    50
    if( arg1 != REG_ARG1 ) {
nkeynes@995
    51
        MOVL_r32_r32( arg1, REG_ARG1 );
nkeynes@905
    52
    }
nkeynes@995
    53
    CALL_ptr(ptr);
nkeynes@953
    54
}
nkeynes@953
    55
nkeynes@995
    56
static inline void CALL1_r32disp_r32( int preg, uint32_t disp, int arg1 )
nkeynes@953
    57
{
nkeynes@995
    58
    if( arg1 != REG_ARG1 ) {
nkeynes@995
    59
        MOVL_r32_r32( arg1, REG_ARG1 );
nkeynes@953
    60
    }
nkeynes@995
    61
    CALL_r32disp(preg, disp);
nkeynes@953
    62
}
nkeynes@953
    63
nkeynes@995
    64
static inline void CALL2_ptr_r32_r32( void *ptr, int arg1, int arg2 )
nkeynes@953
    65
{
nkeynes@995
    66
    if( arg2 != REG_ARG2 ) {
nkeynes@995
    67
        MOVL_r32_r32( arg2, REG_ARG2 );
nkeynes@953
    68
    }
nkeynes@995
    69
    if( arg1 != REG_ARG1 ) {
nkeynes@995
    70
        MOVL_r32_r32( arg1, REG_ARG1 );
nkeynes@995
    71
    }
nkeynes@995
    72
    CALL_ptr(ptr);
nkeynes@953
    73
}
nkeynes@953
    74
nkeynes@995
    75
static inline void CALL2_r32disp_r32_r32( int preg, uint32_t disp, int arg1, int arg2 )
nkeynes@953
    76
{
nkeynes@995
    77
    if( arg2 != REG_ARG2 ) {
nkeynes@995
    78
        MOVL_r32_r32( arg2, REG_ARG2 );
nkeynes@953
    79
    }
nkeynes@995
    80
    if( arg1 != REG_ARG1 ) {
nkeynes@995
    81
        MOVL_r32_r32( arg1, REG_ARG1 );
nkeynes@995
    82
    }
nkeynes@995
    83
    CALL_r32disp(preg, disp);
nkeynes@905
    84
}
nkeynes@905
    85
nkeynes@995
    86
#define CALL3_r32disp_r32_r32_r32(preg,disp,arg1,arg2,arg3) CALL2_r32disp_r32_r32(preg,disp,arg1,arg2)
nkeynes@927
    87
nkeynes@905
    88
#else
nkeynes@995
    89
static inline void CALL1_ptr( void *ptr, int arg1 )
nkeynes@539
    90
{
nkeynes@991
    91
    SUBL_imms_r32( 12, REG_ESP );
nkeynes@539
    92
    PUSH_r32(arg1);
nkeynes@995
    93
    CALL_ptr(ptr);
nkeynes@991
    94
    ADDL_imms_r32( 16, REG_ESP );
nkeynes@539
    95
}
nkeynes@539
    96
nkeynes@995
    97
static inline void CALL1_r32disp_r32( int preg, uint32_t disp, int arg1 )
nkeynes@995
    98
{
nkeynes@995
    99
    SUBL_imms_r32( 12, REG_ESP );
nkeynes@995
   100
    PUSH_r32(arg1);
nkeynes@995
   101
    CALL_r32disp(preg, disp);
nkeynes@995
   102
    ADDL_imms_r32( 16, REG_ESP );
nkeynes@995
   103
}
nkeynes@995
   104
nkeynes@995
   105
static inline void CALL2_ptr_r32_r32( void *ptr, int arg1, int arg2 )
nkeynes@539
   106
{
nkeynes@991
   107
    SUBL_imms_r32( 8, REG_ESP );
nkeynes@539
   108
    PUSH_r32(arg2);
nkeynes@539
   109
    PUSH_r32(arg1);
nkeynes@995
   110
    CALL_ptr(ptr);
nkeynes@995
   111
    ADDL_imms_r32( 16, REG_ESP );
nkeynes@995
   112
}
nkeynes@995
   113
nkeynes@995
   114
static inline void CALL2_r32disp_r32_r32( int preg, uint32_t disp, int arg1, int arg2 )
nkeynes@995
   115
{
nkeynes@995
   116
    SUBL_imms_r32( 8, REG_ESP );
nkeynes@995
   117
    PUSH_r32(arg2);
nkeynes@995
   118
    PUSH_r32(arg1);
nkeynes@995
   119
    CALL_r32disp(preg, disp);
nkeynes@995
   120
    ADDL_imms_r32( 16, REG_ESP );
nkeynes@995
   121
}
nkeynes@995
   122
nkeynes@995
   123
static inline void CALL3_r32disp_r32_r32_r32( int preg, uint32_t disp, int arg1, int arg2, int arg3 )
nkeynes@995
   124
{
nkeynes@995
   125
    SUBL_imms_r32( 8, REG_ESP );
nkeynes@995
   126
    PUSH_r32(arg2);
nkeynes@995
   127
    PUSH_r32(arg1);
nkeynes@995
   128
    MOVL_rspdisp_r32( 16, REG_EAX );
nkeynes@995
   129
    MOVL_r32_rspdisp( R_EAX, 8 );
nkeynes@995
   130
    CALL_r32disp(preg,disp);
nkeynes@991
   131
    ADDL_imms_r32( 16, REG_ESP );
nkeynes@539
   132
}
nkeynes@926
   133
nkeynes@905
   134
#endif
nkeynes@539
   135
nkeynes@539
   136
/**
nkeynes@539
   137
 * Emit the 'start of block' assembly. Sets up the stack frame and save
nkeynes@539
   138
 * SI/DI as required
nkeynes@926
   139
 * Allocates 8 bytes for local variables, which also has the convenient
nkeynes@926
   140
 * side-effect of aligning the stack.
nkeynes@539
   141
 */
nkeynes@995
   142
static inline void enter_block( ) 
nkeynes@539
   143
{
nkeynes@991
   144
    PUSH_r32(REG_EBP);
nkeynes@995
   145
    MOVP_immptr_rptr( ((uint8_t *)&sh4r) + 128, REG_EBP );
nkeynes@991
   146
    SUBL_imms_r32( 8, REG_ESP ); 
nkeynes@926
   147
}
nkeynes@736
   148
nkeynes@926
   149
static inline void exit_block( )
nkeynes@926
   150
{
nkeynes@991
   151
    ADDL_imms_r32( 8, REG_ESP );
nkeynes@991
   152
    POP_r32(REG_EBP);
nkeynes@926
   153
    RET();
nkeynes@539
   154
}
.