/[pcsx2_0.9.7]/trunk/common/src/x86emitter/groups.cpp
ViewVC logotype

Contents of /trunk/common/src/x86emitter/groups.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 10 - (show annotations) (download)
Mon Sep 6 11:40:06 2010 UTC (9 years, 5 months ago) by william
File size: 11173 byte(s)
exported r3113 from ./upstream/trunk
1 /* PCSX2 - PS2 Emulator for PCs
2 * Copyright (C) 2002-2010 PCSX2 Dev Team
3 *
4 * PCSX2 is free software: you can redistribute it and/or modify it under the terms
5 * of the GNU Lesser General Public License as published by the Free Software Found-
6 * ation, either version 3 of the License, or (at your option) any later version.
7 *
8 * PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
9 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
10 * PURPOSE. See the GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License along with PCSX2.
13 * If not, see <http://www.gnu.org/licenses/>.
14 */
15
16 /*
17 * ix86 core v0.9.1
18 *
19 * Original Authors (v0.6.2 and prior):
20 * linuzappz <linuzappz@pcsx.net>
21 * alexey silinov
22 * goldfinger
23 * zerofrog(@gmail.com)
24 *
25 * Authors of v0.9.1:
26 * Jake.Stine(@gmail.com)
27 * cottonvibes(@gmail.com)
28 * sudonim(1@gmail.com)
29 */
30
31 #include "PrecompiledHeader.h"
32 #include "internal.h"
33 #include "implement/helpers.h"
34
35 namespace x86Emitter {
36
37 // =====================================================================================================
38 // Group 1 Instructions - ADD, SUB, ADC, etc.
39 // =====================================================================================================
40
41 // Note on "[Indirect],Imm" forms : use int as the source operand since it's "reasonably inert" from a
42 // compiler perspective. (using uint tends to make the compiler try and fail to match signed immediates
43 // with one of the other overloads).
44 static void _g1_IndirectImm( G1Type InstType, const ModSib32orLess& sibdest, int imm )
45 {
46 if( sibdest.Is8BitOp() )
47 {
48 xWrite8( 0x80 );
49 EmitSibMagic( InstType, sibdest );
50 xWrite<s8>( imm );
51 }
52 else
53 {
54 sibdest.prefix16();
55 xWrite8( is_s8( imm ) ? 0x83 : 0x81 );
56 EmitSibMagic( InstType, sibdest );
57 if( is_s8( imm ) )
58 xWrite<s8>( imm );
59 else
60 sibdest.xWriteImm( imm );
61 }
62 }
63
64 void _g1_EmitOp( G1Type InstType, const xRegisterInt& to, const xRegisterInt& from )
65 {
66 pxAssert( to.GetOperandSize() == from.GetOperandSize() );
67 to.prefix16();
68 xWrite8( (to.Is8BitOp() ? 0 : 1) | (InstType<<3) );
69 EmitSibMagic( from, to );
70 }
71
72 static void _g1_EmitOp( G1Type InstType, const ModSibBase& sibdest, const xRegisterInt& from )
73 {
74 from.prefix16();
75 xWrite8( (from.Is8BitOp() ? 0 : 1) | (InstType<<3) );
76 EmitSibMagic( from, sibdest );
77 }
78
79 static void _g1_EmitOp( G1Type InstType, const xRegisterInt& to, const ModSibBase& sibsrc )
80 {
81 to.prefix16();
82 xWrite8( (to.Is8BitOp() ? 2 : 3) | (InstType<<3) );
83 EmitSibMagic( to, sibsrc );
84 }
85
86 static void _g1_EmitOp( G1Type InstType, const xRegisterInt& to, int imm )
87 {
88 to.prefix16();
89 if( !to.Is8BitOp() && is_s8( imm ) )
90 {
91 xWrite8( 0x83 );
92 EmitSibMagic( InstType, to );
93 xWrite<s8>( imm );
94 }
95 else
96 {
97 if( to.IsAccumulator() )
98 xWrite8( (to.Is8BitOp() ? 4 : 5) | (InstType<<3) );
99 else
100 {
101 xWrite8( to.Is8BitOp() ? 0x80 : 0x81 );
102 EmitSibMagic( InstType, to );
103 }
104 to.xWriteImm( imm );
105 }
106 }
107
108 #define ImplementGroup1( g1type, insttype ) \
109 void g1type::operator()( const xRegister8& to, const xRegister8& from ) const { _g1_EmitOp( insttype, to, from ); } \
110 void g1type::operator()( const xRegister16& to, const xRegister16& from ) const { _g1_EmitOp( insttype, to, from ); } \
111 void g1type::operator()( const xRegister32& to, const xRegister32& from ) const { _g1_EmitOp( insttype, to, from ); } \
112 void g1type::operator()( const ModSibBase& to, const xRegisterInt& from ) const { _g1_EmitOp( insttype, to, from ); } \
113 void g1type::operator()( const xRegisterInt& to, const ModSibBase& from ) const { _g1_EmitOp( insttype, to, from ); } \
114 void g1type::operator()( const xRegisterInt& to, int imm ) const { _g1_EmitOp( insttype, to, imm ); } \
115 void g1type::operator()( const ModSib32orLess& sibdest, int imm ) const { _g1_IndirectImm( insttype, sibdest, imm ); }
116
117 ImplementGroup1( xImpl_Group1, InstType )
118 ImplementGroup1( xImpl_G1Logic, InstType )
119 ImplementGroup1( xImpl_G1Arith, InstType )
120 ImplementGroup1( xImpl_G1Compare, G1Type_CMP )
121
122 const xImpl_G1Logic xAND = { G1Type_AND, { 0x00, 0x54 }, { 0x66, 0x54 } };
123 const xImpl_G1Logic xOR = { G1Type_OR, { 0x00, 0x56 }, { 0x66, 0x56 } };
124 const xImpl_G1Logic xXOR = { G1Type_XOR, { 0x00, 0x57 }, { 0x66, 0x57 } };
125
126 const xImpl_G1Arith xADD = { G1Type_ADD, { 0x00, 0x58 }, { 0x66, 0x58 }, { 0xf3, 0x58 }, { 0xf2, 0x58 } };
127 const xImpl_G1Arith xSUB = { G1Type_SUB, { 0x00, 0x5c }, { 0x66, 0x5c }, { 0xf3, 0x5c }, { 0xf2, 0x5c } };
128 const xImpl_G1Compare xCMP = { { 0x00, 0xc2 }, { 0x66, 0xc2 }, { 0xf3, 0xc2 }, { 0xf2, 0xc2 } };
129
130 const xImpl_Group1 xADC = { G1Type_ADC };
131 const xImpl_Group1 xSBB = { G1Type_SBB };
132
133 // =====================================================================================================
134 // Group 2 Instructions - SHR, SHL, etc.
135 // =====================================================================================================
136
137 void xImpl_Group2::operator()( const xRegisterInt& to, const xRegisterCL& /* from */ ) const
138 {
139 to.prefix16();
140 xWrite8( to.Is8BitOp() ? 0xd2 : 0xd3 );
141 EmitSibMagic( InstType, to );
142 }
143
144 void xImpl_Group2::operator()(const xRegisterInt& to, u8 imm ) const
145 {
146 if( imm == 0 ) return;
147
148 to.prefix16();
149 if( imm == 1 )
150 {
151 // special encoding of 1's
152 xWrite8( to.Is8BitOp() ? 0xd0 : 0xd1 );
153 EmitSibMagic( InstType, to );
154 }
155 else
156 {
157 xWrite8( to.Is8BitOp() ? 0xc0 : 0xc1 );
158 EmitSibMagic( InstType, to );
159 xWrite8( imm );
160 }
161 }
162
163 void xImpl_Group2::operator()( const ModSib32orLess& sibdest, const xRegisterCL& /* from */ ) const
164 {
165 sibdest.prefix16();
166 xWrite8( sibdest.Is8BitOp() ? 0xd2 : 0xd3 );
167 EmitSibMagic( InstType, sibdest );
168 }
169
170 void xImpl_Group2::operator()( const ModSib32orLess& sibdest, u8 imm ) const
171 {
172 if( imm == 0 ) return;
173
174 sibdest.prefix16();
175 if( imm == 1 )
176 {
177 // special encoding of 1's
178 xWrite8( sibdest.Is8BitOp() ? 0xd0 : 0xd1 );
179 EmitSibMagic( InstType, sibdest );
180 }
181 else
182 {
183 xWrite8( sibdest.Is8BitOp() ? 0xc0 : 0xc1 );
184 EmitSibMagic( InstType, sibdest );
185 xWrite8( imm );
186 }
187 }
188
189 const xImpl_Group2 xROL = { G2Type_ROL };
190 const xImpl_Group2 xROR = { G2Type_ROR };
191 const xImpl_Group2 xRCL = { G2Type_RCL };
192 const xImpl_Group2 xRCR = { G2Type_RCR };
193 const xImpl_Group2 xSHL = { G2Type_SHL };
194 const xImpl_Group2 xSHR = { G2Type_SHR };
195 const xImpl_Group2 xSAR = { G2Type_SAR };
196
197
198 // =====================================================================================================
199 // Group 3 Instructions - NOT, NEG, MUL, DIV
200 // =====================================================================================================
201
202 static void _g3_EmitOp( G3Type InstType, const xRegisterInt& from )
203 {
204 from.prefix16();
205 xWrite8(from.Is8BitOp() ? 0xf6 : 0xf7 );
206 EmitSibMagic( InstType, from );
207 }
208
209 static void _g3_EmitOp( G3Type InstType, const ModSib32orLess& from )
210 {
211 from.prefix16();
212 xWrite8( from.Is8BitOp() ? 0xf6 : 0xf7 );
213 EmitSibMagic( InstType, from );
214 }
215
216 void xImpl_Group3::operator()( const xRegisterInt& from ) const { _g3_EmitOp( InstType, from ); }
217 void xImpl_Group3::operator()( const ModSib32orLess& from ) const { _g3_EmitOp( InstType, from ); }
218
219 void xImpl_iDiv::operator()( const xRegisterInt& from ) const { _g3_EmitOp( G3Type_iDIV, from ); }
220 void xImpl_iDiv::operator()( const ModSib32orLess& from ) const { _g3_EmitOp( G3Type_iDIV, from ); }
221
222 template< typename SrcType >
223 static void _imul_ImmStyle( const xRegisterInt& param1, const SrcType& param2, int imm )
224 {
225 // for iMul OpSize is allowed to be 16 or 32 bit only.
226 const uint OpSize = param1.GetOperandSize();
227
228 pxAssert( OpSize == param2.GetOperandSize() );
229 pxAssert( OpSize > 1 );
230
231 xOpWrite0F( (OpSize == 2) ? 0x66 : 0, is_s8( imm ) ? 0x6b : 0x69, param1, param2 );
232
233 if( is_s8( imm ) )
234 xWrite8( (u8)imm );
235 else
236 param1.xWriteImm( imm );
237 }
238
239 void xImpl_iMul::operator()( const xRegisterInt& from ) const { _g3_EmitOp( G3Type_iMUL, from ); }
240 void xImpl_iMul::operator()( const ModSib32orLess& from ) const { _g3_EmitOp( G3Type_iMUL, from ); }
241
242 void xImpl_iMul::operator()( const xRegister32& to, const xRegister32& from ) const { xOpWrite0F( 0xaf, to, from ); }
243 void xImpl_iMul::operator()( const xRegister32& to, const ModSibBase& src ) const { xOpWrite0F( 0xaf, to, src ); }
244 void xImpl_iMul::operator()( const xRegister16& to, const xRegister16& from ) const { xOpWrite0F( 0x66, 0xaf, to, from ); }
245 void xImpl_iMul::operator()( const xRegister16& to, const ModSibBase& src ) const { xOpWrite0F( 0x66, 0xaf, to, src ); }
246
247 void xImpl_iMul::operator()( const xRegister32& to, const xRegister32& from, s32 imm ) const{ _imul_ImmStyle( to, from, imm ); }
248 void xImpl_iMul::operator()( const xRegister32& to, const ModSibBase& from, s32 imm ) const { _imul_ImmStyle( to, from, imm ); }
249 void xImpl_iMul::operator()( const xRegister16& to, const xRegister16& from, s16 imm ) const{ _imul_ImmStyle( to, from, imm ); }
250 void xImpl_iMul::operator()( const xRegister16& to, const ModSibBase& from, s16 imm ) const { _imul_ImmStyle( to, from, imm ); }
251
252 const xImpl_Group3 xNOT = { G3Type_NOT };
253 const xImpl_Group3 xNEG = { G3Type_NEG };
254 const xImpl_Group3 xUMUL = { G3Type_MUL };
255 const xImpl_Group3 xUDIV = { G3Type_DIV };
256
257 const xImpl_iDiv xDIV = { { 0x00, 0x5e }, { 0x66, 0x5e }, { 0xf3, 0x5e }, { 0xf2, 0x5e } };
258 const xImpl_iMul xMUL = { { 0x00, 0x59 }, { 0x66, 0x59 }, { 0xf3, 0x59 }, { 0xf2, 0x59 } };
259
260 // =====================================================================================================
261 // Group 8 Instructions
262 // =====================================================================================================
263
264 void xImpl_Group8::operator()( const xRegister32& bitbase, const xRegister32& bitoffset ) const { xOpWrite0F( 0xa3 | (InstType << 3), bitbase, bitoffset ); }
265 void xImpl_Group8::operator()( const xRegister16& bitbase, const xRegister16& bitoffset ) const { xOpWrite0F( 0x66, 0xa3 | (InstType << 3), bitbase, bitoffset ); }
266 void xImpl_Group8::operator()( const ModSib32& bitbase, u8 bitoffset ) const { xOpWrite0F( 0xba, InstType, bitbase, bitoffset ); }
267 void xImpl_Group8::operator()( const ModSib16& bitbase, u8 bitoffset ) const { xOpWrite0F( 0x66, 0xba, InstType, bitbase, bitoffset ); }
268
269 void xImpl_Group8::operator()( const xRegister16or32& bitbase, u8 bitoffset ) const
270 {
271 xOpWrite0F( (bitbase->GetOperandSize() == 2) ? 0x66 : 0x00, 0xba, InstType, bitbase, bitoffset );
272 }
273
274 void xImpl_Group8::operator()( const ModSibBase& bitbase, const xRegister16or32& bitoffset ) const
275 {
276 xOpWrite0F( (bitoffset->GetOperandSize() == 2) ? 0x66 : 0x00, 0xa3 | (InstType << 3), bitoffset, bitbase );
277 }
278
279 const xImpl_Group8 xBT = { G8Type_BT };
280 const xImpl_Group8 xBTR = { G8Type_BTR };
281 const xImpl_Group8 xBTS = { G8Type_BTS };
282 const xImpl_Group8 xBTC = { G8Type_BTC };
283
284
285
286 } // End namespace x86Emitter
287

  ViewVC Help
Powered by ViewVC 1.1.22