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
9 * Note: These should only be included from x86op.h
11 * Copyright (c) 2007 Nathan Keynes.
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.
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.
24 #define REG_ARG1 REG_EAX
25 #define REG_ARG2 REG_EDX
26 #define REG_RESULT1 REG_EAX
29 static inline void decode_address( uintptr_t base, int addr_reg )
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 );
37 * Note: clobbers ECX to make the indirect call - this isn't usually
38 * a problem since the callee will generally clobber it anyway.
40 static inline void CALL_ptr( void *ptr )
42 MOVP_immptr_rptr( (uintptr_t)ptr, REG_ECX );
47 static inline void CALL1_ptr_r32( void *ptr, int arg1 )
49 if( arg1 != REG_ARG1 ) {
50 MOVL_r32_r32( arg1, REG_ARG1 );
55 static inline void CALL1_r32disp_r32( int preg, uint32_t disp, int arg1 )
57 if( arg1 != REG_ARG1 ) {
58 MOVL_r32_r32( arg1, REG_ARG1 );
60 CALL_r32disp(preg, disp);
63 static inline void CALL2_ptr_r32_r32( void *ptr, int arg1, int arg2 )
65 if( arg2 != REG_ARG2 ) {
66 MOVL_r32_r32( arg2, REG_ARG2 );
68 if( arg1 != REG_ARG1 ) {
69 MOVL_r32_r32( arg1, REG_ARG1 );
74 static inline void CALL2_r32disp_r32_r32( int preg, uint32_t disp, int arg1, int arg2 )
76 if( arg2 != REG_ARG2 ) {
77 MOVL_r32_r32( arg2, REG_ARG2 );
79 if( arg1 != REG_ARG1 ) {
80 MOVL_r32_r32( arg1, REG_ARG1 );
82 CALL_r32disp(preg, disp);
85 #define CALL3_r32disp_r32_r32_r32(preg,disp,arg1,arg2,arg3) CALL2_r32disp_r32_r32(preg,disp,arg1,arg2)
88 static inline void CALL1_ptr( void *ptr, int arg1 )
90 SUBL_imms_r32( 12, REG_ESP );
93 ADDL_imms_r32( 16, REG_ESP );
96 static inline void CALL1_r32disp_r32( int preg, uint32_t disp, int arg1 )
98 SUBL_imms_r32( 12, REG_ESP );
100 CALL_r32disp(preg, disp);
101 ADDL_imms_r32( 16, REG_ESP );
104 static inline void CALL2_ptr_r32_r32( void *ptr, int arg1, int arg2 )
106 SUBL_imms_r32( 8, REG_ESP );
110 ADDL_imms_r32( 16, REG_ESP );
113 static inline void CALL2_r32disp_r32_r32( int preg, uint32_t disp, int arg1, int arg2 )
115 SUBL_imms_r32( 8, REG_ESP );
118 CALL_r32disp(preg, disp);
119 ADDL_imms_r32( 16, REG_ESP );
122 static inline void CALL3_r32disp_r32_r32_r32( int preg, uint32_t disp, int arg1, int arg2, int arg3 )
124 SUBL_imms_r32( 8, REG_ESP );
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 );
136 * Emit the 'start of block' assembly. Sets up the stack frame and save
138 * Allocates 8 bytes for local variables, which also has the convenient
139 * side-effect of aligning the stack.
141 static inline void enter_block( )
144 SUBL_imms_r32( 8, REG_ESP );
147 static inline void exit_block( )
149 ADDL_imms_r32( 8, REG_ESP );
.