- compilation fixes for MSVC toolkit 2003
[bochs-mirror.git] / cpu / flag_ctrl.cc
blobbb4dbf18fddb67d2b617c26af5056b6d25d91794
1 /////////////////////////////////////////////////////////////////////////
2 // $Id: flag_ctrl.cc,v 1.40 2008/07/13 14:01:09 sshwarts Exp $
3 /////////////////////////////////////////////////////////////////////////
4 //
5 // Copyright (C) 2002 MandrakeSoft S.A.
6 //
7 // MandrakeSoft S.A.
8 // 43, rue d'Aboukir
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
29 #include "bochs.h"
30 #include "cpu.h"
31 #define LOG_THIS BX_CPU_THIS_PTR
33 // Make code more tidy with a few macros.
34 #if BX_SUPPORT_X86_64==0
35 #define RSP ESP
36 #endif
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);
43 set_CF (AH & 0x01);
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)
54 clear_CF();
57 void BX_CPP_AttrRegparmN(1) BX_CPU_C::STC(bxInstruction_c *i)
59 assert_CF();
62 void BX_CPP_AttrRegparmN(1) BX_CPU_C::CLI(bxInstruction_c *i)
64 Bit32u IOPL = BX_CPU_THIS_PTR get_IOPL();
66 if (protected_mode())
68 #if BX_SUPPORT_VME
69 if (BX_CPU_THIS_PTR cr4.get_PVI() && (CPL == 3))
71 if (IOPL < 3) {
72 BX_CPU_THIS_PTR clear_VIF();
73 return;
76 else
77 #endif
79 if (IOPL < CPL) {
80 BX_DEBUG(("CLI: IOPL < CPL in protected mode"));
81 exception(BX_GP_EXCEPTION, 0, 0);
85 else if (v8086_mode())
87 if (IOPL != 3) {
88 #if BX_SUPPORT_VME
89 if (CR4_VME_ENABLED) {
90 BX_CPU_THIS_PTR clear_VIF();
91 return;
93 #endif
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())
108 #if BX_SUPPORT_VME
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();
115 return;
118 BX_DEBUG(("STI: #GP(0) in VME mode"));
119 exception(BX_GP_EXCEPTION, 0, 0);
122 #endif
123 if (CPL > IOPL) {
124 BX_DEBUG(("STI: CPL > IOPL in protected mode"));
125 exception(BX_GP_EXCEPTION, 0, 0);
128 else if (v8086_mode())
130 if (IOPL != 3) {
131 #if BX_SUPPORT_VME
132 if (CR4_VME_ENABLED && BX_CPU_THIS_PTR get_VIP() == 0)
134 BX_CPU_THIS_PTR assert_VIF();
135 return;
137 #endif
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)
162 set_CF(! get_CF());
165 void BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSHF_Fw(bxInstruction_c *i)
167 Bit16u flags = (Bit16u) read_eflags();
169 if (v8086_mode()) {
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);
174 #if BX_SUPPORT_VME
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;
179 else
180 flags &= ~EFlagsIFMask;
182 #endif
185 push_16(flags);
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
195 #endif
196 Bit16u flags16;
198 if (protected_mode()) {
199 flags16 = pop_16();
200 if (CPL==0)
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;
213 flags16 = pop_16();
214 #if BX_SUPPORT_VME
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);
228 return;
230 #endif
231 changeMask |= EFlagsIFMask;
233 BX_CPU_THIS_PTR speculative_rsp = 0;
235 else {
236 flags16 = pop_16();
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
265 #endif
266 Bit32u flags32;
268 if (protected_mode()) {
269 flags32 = pop_32();
270 // IOPL changed only if (CPL == 0),
271 // IF changed only if (CPL <= EFLAGS.IOPL),
272 // VIF, VIP, VM are unaffected
273 if (CPL==0)
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);
283 flags32 = pop_32();
284 // v8086-mode: VM, IOPL, VIP, VIF are unaffected
285 changeMask |= EFlagsIFMask;
287 else { // Real-mode
288 flags32 = pop_32();
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
309 | EFlagsIDMask;
311 BX_ASSERT (protected_mode());
313 Bit32u eflags32 = (Bit32u) pop_64();
315 if (CPL==0)
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);
323 #endif
325 #endif // BX_CPU_LEVEL >= 3
327 void BX_CPP_AttrRegparmN(1) BX_CPU_C::SALC(bxInstruction_c *i)
329 if (get_CF()) {
330 AL = 0xff;
332 else {
333 AL = 0x00;