filename | src/xlat/x86/ia32abi.h |
changeset | 1146:76c5d1064262 |
prev | 1125:9dd5dee45db9 |
next | 1292:799fdd4f704a |
author | nkeynes |
date | Tue Feb 28 18:22:52 2012 +1000 (12 years ago) |
permissions | -rw-r--r-- |
last change | Add a GL-only video driver for android usage (since the Java code is responsible for creating the context) |
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 #define CALL1_PTR_MIN_SIZE 7
49 static inline void CALL1_ptr_r32( void *ptr, int arg1 )
50 {
51 if( arg1 != REG_ARG1 ) {
52 MOVL_r32_r32( arg1, REG_ARG1 );
53 }
54 CALL_ptr(ptr);
55 }
57 static inline void CALL1_r32disp_r32( int preg, uint32_t disp, int arg1 )
58 {
59 if( arg1 != REG_ARG1 ) {
60 MOVL_r32_r32( arg1, REG_ARG1 );
61 }
62 CALL_r32disp(preg, disp);
63 }
65 static inline void CALL2_ptr_r32_r32( void *ptr, int arg1, int arg2 )
66 {
67 if( arg2 != REG_ARG2 ) {
68 MOVL_r32_r32( arg2, REG_ARG2 );
69 }
70 if( arg1 != REG_ARG1 ) {
71 MOVL_r32_r32( arg1, REG_ARG1 );
72 }
73 CALL_ptr(ptr);
74 }
76 static inline void CALL2_r32disp_r32_r32( int preg, uint32_t disp, int arg1, int arg2 )
77 {
78 if( arg2 != REG_ARG2 ) {
79 MOVL_r32_r32( arg2, REG_ARG2 );
80 }
81 if( arg1 != REG_ARG1 ) {
82 MOVL_r32_r32( arg1, REG_ARG1 );
83 }
84 CALL_r32disp(preg, disp);
85 }
87 #define CALL3_r32disp_r32_r32_r32(preg,disp,arg1,arg2,arg3) CALL2_r32disp_r32_r32(preg,disp,arg1,arg2)
89 #else
91 #define CALL1_PTR_MIN_SIZE (3+1+7+3)
93 static inline void CALL1_ptr_r32( void *ptr, int arg1 )
94 {
95 SUBL_imms_r32( 12, REG_ESP );
96 PUSH_r32(arg1);
97 CALL_ptr(ptr);
98 ADDL_imms_r32( 16, REG_ESP );
99 }
101 static inline void CALL1_r32disp_r32( int preg, uint32_t disp, int arg1 )
102 {
103 SUBL_imms_r32( 12, REG_ESP );
104 PUSH_r32(arg1);
105 CALL_r32disp(preg, disp);
106 ADDL_imms_r32( 16, REG_ESP );
107 }
109 static inline void CALL2_ptr_r32_r32( void *ptr, int arg1, int arg2 )
110 {
111 SUBL_imms_r32( 8, REG_ESP );
112 PUSH_r32(arg2);
113 PUSH_r32(arg1);
114 CALL_ptr(ptr);
115 ADDL_imms_r32( 16, REG_ESP );
116 }
118 static inline void CALL2_r32disp_r32_r32( int preg, uint32_t disp, int arg1, int arg2 )
119 {
120 SUBL_imms_r32( 8, REG_ESP );
121 PUSH_r32(arg2);
122 PUSH_r32(arg1);
123 CALL_r32disp(preg, disp);
124 ADDL_imms_r32( 16, REG_ESP );
125 }
127 static inline void CALL3_r32disp_r32_r32_r32( int preg, uint32_t disp, int arg1, int arg2, int arg3 )
128 {
129 SUBL_imms_r32( 8, REG_ESP );
130 PUSH_r32(arg2);
131 PUSH_r32(arg1);
132 MOVL_rspdisp_r32( 16, REG_EAX );
133 MOVL_r32_rspdisp( REG_EAX, 8 );
134 CALL_r32disp(preg,disp);
135 ADDL_imms_r32( 16, REG_ESP );
136 }
138 #endif
140 #define PROLOGUE_SIZE 9
142 /**
143 * Emit the 'start of block' assembly. Sets up the stack frame and save
144 * SI/DI as required
145 * Allocates 8 bytes for local variables, which also has the convenient
146 * side-effect of aligning the stack.
147 */
148 static inline void emit_prologue( )
149 {
150 PUSH_r32(REG_EBP);
151 SUBL_imms_r32( 8, REG_ESP );
152 MOVP_immptr_rptr( ((uint8_t *)&sh4r) + 128, REG_EBP );
153 }
155 static inline void emit_epilogue( )
156 {
157 ADDL_imms_r32( 8, REG_ESP );
158 POP_r32(REG_EBP);
159 }
.