1 /////////////////////////////////////////////////////////////////////////
2 // $Id: flag_ctrl.cc,v 1.40 2008/07/13 14:01:09 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
5 // Copyright (C) 2002 MandrakeSoft S.A.
9 // 75002 Paris - France
10 // http://www.linux-mandrake.com/
11 // http://www.mandrakesoft.com/
13 // This library is free software; you can redistribute it and/or
14 // modify it under the terms of the GNU Lesser General Public
15 // License as published by the Free Software Foundation; either
16 // version 2 of the License, or (at your option) any later version.
18 // This library 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 GNU
21 // Lesser General Public License for more details.
23 // You should have received a copy of the GNU Lesser General Public
24 // License along with this library; if not, write to the Free Software
25 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 /////////////////////////////////////////////////////////////////////////
28 #define NEED_CPU_REG_SHORTCUTS 1
31 #define LOG_THIS BX_CPU_THIS_PTR
33 // Make code more tidy with a few macros.
34 #if BX_SUPPORT_X86_64==0
38 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SAHF(bxInstruction_c
*i
)
40 set_SF((AH
& 0x80) >> 7);
41 set_ZF((AH
& 0x40) >> 6);
42 set_AF((AH
& 0x10) >> 4);
44 set_PF((AH
& 0x04) >> 2);
47 void BX_CPP_AttrRegparmN(1) BX_CPU_C::LAHF(bxInstruction_c
*i
)
49 AH
= read_eflags() & 0xFF;
52 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CLC(bxInstruction_c
*i
)
57 void BX_CPP_AttrRegparmN(1) BX_CPU_C::STC(bxInstruction_c
*i
)
62 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CLI(bxInstruction_c
*i
)
64 Bit32u IOPL
= BX_CPU_THIS_PTR
get_IOPL();
69 if (BX_CPU_THIS_PTR cr4
.get_PVI() && (CPL
== 3))
72 BX_CPU_THIS_PTR
clear_VIF();
80 BX_DEBUG(("CLI: IOPL < CPL in protected mode"));
81 exception(BX_GP_EXCEPTION
, 0, 0);
85 else if (v8086_mode())
89 if (CR4_VME_ENABLED
) {
90 BX_CPU_THIS_PTR
clear_VIF();
94 BX_DEBUG(("CLI: IOPL != 3 in v8086 mode"));
95 exception(BX_GP_EXCEPTION
, 0, 0);
99 BX_CPU_THIS_PTR
clear_IF();
102 void BX_CPP_AttrRegparmN(1) BX_CPU_C::STI(bxInstruction_c
*i
)
104 Bit32u IOPL
= BX_CPU_THIS_PTR
get_IOPL();
106 if (protected_mode())
109 if (BX_CPU_THIS_PTR cr4
.get_PVI())
111 if (CPL
== 3 && IOPL
< 3) {
112 if (! BX_CPU_THIS_PTR
get_VIP())
114 BX_CPU_THIS_PTR
assert_VIF();
118 BX_DEBUG(("STI: #GP(0) in VME mode"));
119 exception(BX_GP_EXCEPTION
, 0, 0);
124 BX_DEBUG(("STI: CPL > IOPL in protected mode"));
125 exception(BX_GP_EXCEPTION
, 0, 0);
128 else if (v8086_mode())
132 if (CR4_VME_ENABLED
&& BX_CPU_THIS_PTR
get_VIP() == 0)
134 BX_CPU_THIS_PTR
assert_VIF();
138 BX_DEBUG(("STI: IOPL != 3 in v8086 mode"));
139 exception(BX_GP_EXCEPTION
, 0, 0);
143 if (!BX_CPU_THIS_PTR
get_IF()) {
144 BX_CPU_THIS_PTR
assert_IF();
145 BX_CPU_THIS_PTR inhibit_mask
|= BX_INHIBIT_INTERRUPTS
;
146 BX_CPU_THIS_PTR async_event
= 1;
150 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CLD(bxInstruction_c
*i
)
152 BX_CPU_THIS_PTR
clear_DF();
155 void BX_CPP_AttrRegparmN(1) BX_CPU_C::STD(bxInstruction_c
*i
)
157 BX_CPU_THIS_PTR
assert_DF();
160 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CMC(bxInstruction_c
*i
)
165 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSHF_Fw(bxInstruction_c
*i
)
167 Bit16u flags
= (Bit16u
) read_eflags();
170 if ((BX_CPU_THIS_PTR
get_IOPL() < 3) && (CR4_VME_ENABLED
== 0)) {
171 BX_DEBUG(("PUSHFW: #GP(0) in v8086 (no VME) mode"));
172 exception(BX_GP_EXCEPTION
, 0, 0);
175 if (CR4_VME_ENABLED
&& BX_CPU_THIS_PTR
get_IOPL() < 3) {
176 flags
|= EFlagsIOPLMask
;
177 if (BX_CPU_THIS_PTR
get_VIF())
178 flags
|= EFlagsIFMask
;
180 flags
&= ~EFlagsIFMask
;
188 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POPF_Fw(bxInstruction_c
*i
)
190 // Build a mask of the following bits:
191 // x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF
192 Bit32u changeMask
= EFlagsOSZAPCMask
| EFlagsTFMask
| EFlagsDFMask
;
193 #if BX_CPU_LEVEL >= 3
194 changeMask
|= EFlagsNTMask
; // NT could be modified
198 if (protected_mode()) {
201 changeMask
|= EFlagsIOPLMask
;
202 if (CPL
<= BX_CPU_THIS_PTR
get_IOPL())
203 changeMask
|= EFlagsIFMask
;
205 else if (v8086_mode()) {
206 if ((BX_CPU_THIS_PTR
get_IOPL() < 3) && (CR4_VME_ENABLED
== 0)) {
207 BX_DEBUG(("POPFW: #GP(0) in v8086 (no VME) mode"));
208 exception(BX_GP_EXCEPTION
, 0, 0);
210 BX_CPU_THIS_PTR speculative_rsp
= 1;
211 BX_CPU_THIS_PTR prev_rsp
= RSP
;
215 if (CR4_VME_ENABLED
&& BX_CPU_THIS_PTR
get_IOPL() < 3) {
216 if (((flags16
& EFlagsIFMask
) && BX_CPU_THIS_PTR
get_VIP()) ||
217 (flags16
& EFlagsTFMask
))
219 BX_DEBUG(("POPFW: #GP(0) in VME mode"));
220 exception(BX_GP_EXCEPTION
, 0, 0);
223 // IF, IOPL unchanged, EFLAGS.VIF = TMP_FLAGS.IF
224 changeMask
|= EFlagsVIFMask
;
225 Bit32u flags32
= (Bit32u
) flags16
;
226 if (BX_CPU_THIS_PTR
get_IF()) flags32
|= EFlagsVIFMask
;
227 writeEFlags(flags32
, changeMask
);
231 changeMask
|= EFlagsIFMask
;
233 BX_CPU_THIS_PTR speculative_rsp
= 0;
237 // All non-reserved flags can be modified
238 changeMask
|= (EFlagsIOPLMask
| EFlagsIFMask
);
241 writeEFlags((Bit32u
) flags16
, changeMask
);
244 #if BX_CPU_LEVEL >= 3
246 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSHF_Fd(bxInstruction_c
*i
)
248 if (v8086_mode() && (BX_CPU_THIS_PTR
get_IOPL()<3)) {
249 BX_DEBUG(("PUSHFD: #GP(0) in v8086 mode"));
250 exception(BX_GP_EXCEPTION
, 0, 0);
253 // VM & RF flags cleared in image stored on the stack
254 push_32(read_eflags() & 0x00fcffff);
257 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POPF_Fd(bxInstruction_c
*i
)
259 // Build a mask of the following bits:
260 // ID,VIP,VIF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF
261 Bit32u changeMask
= EFlagsOSZAPCMask
| EFlagsTFMask
|
262 EFlagsDFMask
| EFlagsNTMask
| EFlagsRFMask
;
263 #if BX_CPU_LEVEL >= 4
264 changeMask
|= (EFlagsIDMask
| EFlagsACMask
); // ID/AC
268 if (protected_mode()) {
270 // IOPL changed only if (CPL == 0),
271 // IF changed only if (CPL <= EFLAGS.IOPL),
272 // VIF, VIP, VM are unaffected
274 changeMask
|= EFlagsIOPLMask
;
275 if (CPL
<= BX_CPU_THIS_PTR
get_IOPL())
276 changeMask
|= EFlagsIFMask
;
278 else if (v8086_mode()) {
279 if (BX_CPU_THIS_PTR
get_IOPL() < 3) {
280 BX_DEBUG(("POPFD: #GP(0) in v8086 mode"));
281 exception(BX_GP_EXCEPTION
, 0, 0);
284 // v8086-mode: VM, IOPL, VIP, VIF are unaffected
285 changeMask
|= EFlagsIFMask
;
289 // VIF, VIP, VM are unaffected
290 changeMask
|= (EFlagsIOPLMask
| EFlagsIFMask
);
293 writeEFlags(flags32
, changeMask
);
296 #if BX_SUPPORT_X86_64
297 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSHF_Fq(bxInstruction_c
*i
)
299 // VM & RF flags cleared in image stored on the stack
300 push_64(read_eflags() & 0x00fcffff);
303 void BX_CPP_AttrRegparmN(1) BX_CPU_C::POPF_Fq(bxInstruction_c
*i
)
305 // Build a mask of the following bits:
306 // ID,VIP,VIF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF
307 Bit32u changeMask
= EFlagsOSZAPCMask
| EFlagsTFMask
| EFlagsDFMask
308 | EFlagsNTMask
| EFlagsRFMask
| EFlagsACMask
311 BX_ASSERT (protected_mode());
313 Bit32u eflags32
= (Bit32u
) pop_64();
316 changeMask
|= EFlagsIOPLMask
;
317 if (CPL
<= BX_CPU_THIS_PTR
get_IOPL())
318 changeMask
|= EFlagsIFMask
;
320 // VIF, VIP, VM are unaffected
321 writeEFlags(eflags32
, changeMask
);
325 #endif // BX_CPU_LEVEL >= 3
327 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SALC(bxInstruction_c
*i
)