OpenCores
URL https://opencores.org/ocsvn/ao486/ao486/trunk

Subversion Repositories ao486

[/] [ao486/] [trunk/] [bochs486/] [cpu/] [flag_ctrl.cc] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 alfik
/////////////////////////////////////////////////////////////////////////
2
// $Id: flag_ctrl.cc 11480 2012-10-03 20:24:29Z sshwarts $
3
/////////////////////////////////////////////////////////////////////////
4
//
5
//  Copyright (C) 2002-2012  The Bochs Project
6
//
7
//  This library is free software; you can redistribute it and/or
8
//  modify it under the terms of the GNU Lesser General Public
9
//  License as published by the Free Software Foundation; either
10
//  version 2 of the License, or (at your option) any later version.
11
//
12
//  This library is distributed in the hope that it will be useful,
13
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
//  Lesser General Public License for more details.
16
//
17
//  You should have received a copy of the GNU Lesser General Public
18
//  License along with this library; if not, write to the Free Software
19
//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
20
/////////////////////////////////////////////////////////////////////////
21
 
22
#define NEED_CPU_REG_SHORTCUTS 1
23
#include "bochs.h"
24
#include "cpu.h"
25
#define LOG_THIS BX_CPU_THIS_PTR
26
 
27
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SAHF(bxInstruction_c *i)
28
{
29
  set_SF((AH & 0x80) >> 7);
30
  set_ZF((AH & 0x40) >> 6);
31
  set_AF((AH & 0x10) >> 4);
32
  set_CF (AH & 0x01);
33
  set_PF((AH & 0x04) >> 2);
34
 
35
  BX_NEXT_INSTR(i);
36
}
37
 
38
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::LAHF(bxInstruction_c *i)
39
{
40
  AH = read_eflags() & 0xFF;
41
 
42
  BX_NEXT_INSTR(i);
43
}
44
 
45
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CLC(bxInstruction_c *i)
46
{
47
  clear_CF();
48
 
49
  BX_NEXT_INSTR(i);
50
}
51
 
52
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::STC(bxInstruction_c *i)
53
{
54
  assert_CF();
55
 
56
  BX_NEXT_INSTR(i);
57
}
58
 
59
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CLI(bxInstruction_c *i)
60
{
61
  Bit32u IOPL = BX_CPU_THIS_PTR get_IOPL();
62
 
63
  if (protected_mode())
64
  {
65
#if BX_CPU_LEVEL >= 5
66
    if (BX_CPU_THIS_PTR cr4.get_PVI() && (CPL == 3))
67
    {
68
      if (IOPL < 3) {
69
        BX_CPU_THIS_PTR clear_VIF();
70
        BX_NEXT_INSTR(i);
71
      }
72
    }
73
    else
74
#endif
75
    {
76
      if (IOPL < CPL) {
77
        BX_DEBUG(("CLI: IOPL < CPL in protected mode"));
78
        exception(BX_GP_EXCEPTION, 0);
79
      }
80
    }
81
  }
82
  else if (v8086_mode())
83
  {
84
    if (IOPL != 3) {
85
#if BX_CPU_LEVEL >= 5
86
      if (BX_CPU_THIS_PTR cr4.get_VME()) {
87
        BX_CPU_THIS_PTR clear_VIF();
88
        BX_NEXT_INSTR(i);
89
      }
90
#endif
91
      BX_DEBUG(("CLI: IOPL != 3 in v8086 mode"));
92
      exception(BX_GP_EXCEPTION, 0);
93
    }
94
  }
95
 
96
  BX_CPU_THIS_PTR clear_IF();
97
 
98
  BX_NEXT_INSTR(i);
99
}
100
 
101
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::STI(bxInstruction_c *i)
102
{
103
  Bit32u IOPL = BX_CPU_THIS_PTR get_IOPL();
104
 
105
  if (protected_mode())
106
  {
107
#if BX_CPU_LEVEL >= 5
108
    if (BX_CPU_THIS_PTR cr4.get_PVI())
109
    {
110
      if (CPL == 3 && IOPL < 3) {
111
        if (! BX_CPU_THIS_PTR get_VIP())
112
        {
113
          BX_CPU_THIS_PTR assert_VIF();
114
          BX_NEXT_INSTR(i);
115
        }
116
 
117
        BX_DEBUG(("STI: #GP(0) in VME mode"));
118
        exception(BX_GP_EXCEPTION, 0);
119
      }
120
    }
121
#endif
122
    if (CPL > IOPL) {
123
      BX_DEBUG(("STI: CPL > IOPL in protected mode"));
124
      exception(BX_GP_EXCEPTION, 0);
125
    }
126
  }
127
  else if (v8086_mode())
128
  {
129
    if (IOPL != 3) {
130
#if BX_CPU_LEVEL >= 5
131
      if (BX_CPU_THIS_PTR cr4.get_VME() && BX_CPU_THIS_PTR get_VIP() == 0)
132
      {
133
        BX_CPU_THIS_PTR assert_VIF();
134
        BX_NEXT_INSTR(i);
135
      }
136
#endif
137
      BX_DEBUG(("STI: IOPL != 3 in v8086 mode"));
138
      exception(BX_GP_EXCEPTION, 0);
139
    }
140
  }
141
 
142
  if (! BX_CPU_THIS_PTR get_IF()) {
143
    BX_CPU_THIS_PTR assert_IF();
144
    inhibit_interrupts(BX_INHIBIT_INTERRUPTS);
145
  }
146
 
147
  BX_NEXT_INSTR(i);
148
}
149
 
150
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CLD(bxInstruction_c *i)
151
{
152
  BX_CPU_THIS_PTR clear_DF();
153
 
154
  BX_NEXT_INSTR(i);
155
}
156
 
157
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::STD(bxInstruction_c *i)
158
{
159
  BX_CPU_THIS_PTR assert_DF();
160
 
161
  BX_NEXT_INSTR(i);
162
}
163
 
164
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CMC(bxInstruction_c *i)
165
{
166
  set_CF(! get_CF());
167
 
168
  BX_NEXT_INSTR(i);
169
}
170
 
171
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSHF_Fw(bxInstruction_c *i)
172
{
173
#if BX_SUPPORT_SVM
174
  if (BX_CPU_THIS_PTR in_svm_guest) {
175
    if (SVM_INTERCEPT(SVM_INTERCEPT0_PUSHF)) Svm_Vmexit(SVM_VMEXIT_PUSHF);
176
  }
177
#endif
178
 
179
  Bit16u flags = (Bit16u) read_eflags();
180
 
181
  if (v8086_mode()) {
182
    if (BX_CPU_THIS_PTR get_IOPL() < 3) {
183
#if BX_CPU_LEVEL >= 5
184
      if (BX_CPU_THIS_PTR cr4.get_VME()) {
185
        flags |= EFlagsIOPLMask;
186
        if (BX_CPU_THIS_PTR get_VIF())
187
          flags |=  EFlagsIFMask;
188
        else
189
          flags &= ~EFlagsIFMask;
190
      }
191
      else
192
#endif
193
      {
194
        BX_DEBUG(("PUSHFW: #GP(0) in v8086 (no VME) mode"));
195
        exception(BX_GP_EXCEPTION, 0);
196
      }
197
    }
198
  }
199
 
200
  push_16(flags);
201
 
202
  BX_NEXT_INSTR(i);
203
}
204
 
205
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POPF_Fw(bxInstruction_c *i)
206
{
207
#if BX_SUPPORT_SVM
208
  if (BX_CPU_THIS_PTR in_svm_guest) {
209
    if (SVM_INTERCEPT(SVM_INTERCEPT0_POPF)) Svm_Vmexit(SVM_VMEXIT_POPF);
210
  }
211
#endif
212
 
213
  // Build a mask of the following bits:
214
  // x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF
215
  Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask | EFlagsDFMask | EFlagsNTMask;
216
 
217
  RSP_SPECULATIVE;
218
 
219
  Bit16u flags16 = pop_16();
220
 
221
  if (protected_mode()) {
222
    if (CPL==0)
223
      changeMask |= EFlagsIOPLMask;
224
    if (CPL <= BX_CPU_THIS_PTR get_IOPL())
225
      changeMask |= EFlagsIFMask;
226
  }
227
  else if (v8086_mode()) {
228
    if (BX_CPU_THIS_PTR get_IOPL() < 3) {
229
#if BX_CPU_LEVEL >= 5
230
      if (BX_CPU_THIS_PTR cr4.get_VME()) {
231
 
232
        if (((flags16 & EFlagsIFMask) && BX_CPU_THIS_PTR get_VIP()) ||
233
             (flags16 & EFlagsTFMask))
234
        {
235
          BX_ERROR(("POPFW: #GP(0) in VME mode"));
236
          exception(BX_GP_EXCEPTION, 0);
237
        }
238
 
239
        // IF, IOPL unchanged, EFLAGS.VIF = TMP_FLAGS.IF
240
        changeMask |= EFlagsVIFMask;
241
        Bit32u flags32 = (Bit32u) flags16;
242
        if (flags32 & EFlagsIFMask) flags32 |= EFlagsVIFMask;
243
        writeEFlags(flags32, changeMask);
244
        RSP_COMMIT;
245
 
246
        BX_NEXT_INSTR(i);
247
      }
248
#endif
249
      BX_DEBUG(("POPFW: #GP(0) in v8086 (no VME) mode"));
250
      exception(BX_GP_EXCEPTION, 0);
251
    }
252
 
253
    changeMask |= EFlagsIFMask;
254
  }
255
  else {
256
    // All non-reserved flags can be modified
257
    changeMask |= (EFlagsIOPLMask | EFlagsIFMask);
258
  }
259
 
260
  writeEFlags((Bit32u) flags16, changeMask);
261
 
262
  RSP_COMMIT;
263
 
264
  BX_NEXT_INSTR(i);
265
}
266
 
267
#if BX_CPU_LEVEL >= 3
268
 
269
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSHF_Fd(bxInstruction_c *i)
270
{
271
#if BX_SUPPORT_SVM
272
  if (BX_CPU_THIS_PTR in_svm_guest) {
273
    if (SVM_INTERCEPT(SVM_INTERCEPT0_PUSHF)) Svm_Vmexit(SVM_VMEXIT_PUSHF);
274
  }
275
#endif
276
 
277
  if (v8086_mode() && (BX_CPU_THIS_PTR get_IOPL()<3)) {
278
    BX_DEBUG(("PUSHFD: #GP(0) in v8086 mode"));
279
    exception(BX_GP_EXCEPTION, 0);
280
  }
281
 
282
  // VM & RF flags cleared in image stored on the stack
283
  push_32(read_eflags() & 0x00fcffff);
284
 
285
  BX_NEXT_INSTR(i);
286
}
287
 
288
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POPF_Fd(bxInstruction_c *i)
289
{
290
#if BX_SUPPORT_SVM
291
  if (BX_CPU_THIS_PTR in_svm_guest) {
292
    if (SVM_INTERCEPT(SVM_INTERCEPT0_POPF)) Svm_Vmexit(SVM_VMEXIT_POPF);
293
  }
294
#endif
295
 
296
  // Build a mask of the following bits:
297
  // ID,VIP,VIF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF
298
  Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask |
299
                          EFlagsDFMask | EFlagsNTMask | EFlagsRFMask;
300
#if BX_CPU_LEVEL >= 4
301
  changeMask |= (EFlagsIDMask | EFlagsACMask);  // ID/AC
302
#endif
303
 
304
  RSP_SPECULATIVE;
305
 
306
  Bit32u flags32 = pop_32();
307
 
308
  if (protected_mode()) {
309
    // IOPL changed only if (CPL == 0),
310
    // IF changed only if (CPL <= EFLAGS.IOPL),
311
    // VIF, VIP, VM are unaffected
312
    if (CPL==0)
313
      changeMask |= EFlagsIOPLMask;
314
    if (CPL <= BX_CPU_THIS_PTR get_IOPL())
315
      changeMask |= EFlagsIFMask;
316
  }
317
  else if (v8086_mode()) {
318
    if (BX_CPU_THIS_PTR get_IOPL() < 3) {
319
      BX_ERROR(("POPFD: #GP(0) in v8086 mode"));
320
      exception(BX_GP_EXCEPTION, 0);
321
    }
322
    // v8086-mode: VM, IOPL, VIP, VIF are unaffected
323
    changeMask |= EFlagsIFMask;
324
  }
325
  else { // Real-mode
326
    // VIF, VIP, VM are unaffected
327
    changeMask |= (EFlagsIOPLMask | EFlagsIFMask);
328
  }
329
 
330
  writeEFlags(flags32, changeMask);
331
 
332
  RSP_COMMIT;
333
 
334
  BX_NEXT_INSTR(i);
335
}
336
 
337
#if BX_SUPPORT_X86_64
338
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::PUSHF_Fq(bxInstruction_c *i)
339
{
340
#if BX_SUPPORT_SVM
341
  if (BX_CPU_THIS_PTR in_svm_guest) {
342
    if (SVM_INTERCEPT(SVM_INTERCEPT0_PUSHF)) Svm_Vmexit(SVM_VMEXIT_PUSHF);
343
  }
344
#endif
345
 
346
  // VM & RF flags cleared in image stored on the stack
347
  push_64(read_eflags() & 0x00fcffff);
348
 
349
  BX_NEXT_INSTR(i);
350
}
351
 
352
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::POPF_Fq(bxInstruction_c *i)
353
{
354
#if BX_SUPPORT_SVM
355
  if (BX_CPU_THIS_PTR in_svm_guest) {
356
    if (SVM_INTERCEPT(SVM_INTERCEPT0_POPF)) Svm_Vmexit(SVM_VMEXIT_POPF);
357
  }
358
#endif
359
 
360
  // Build a mask of the following bits:
361
  // ID,VIP,VIF,AC,VM,RF,x,NT,IOPL,OF,DF,IF,TF,SF,ZF,x,AF,x,PF,x,CF
362
  Bit32u changeMask = EFlagsOSZAPCMask | EFlagsTFMask | EFlagsDFMask
363
                        | EFlagsNTMask | EFlagsRFMask | EFlagsACMask
364
                        | EFlagsIDMask;
365
 
366
  BX_ASSERT (protected_mode());
367
 
368
  Bit32u eflags32 = (Bit32u) pop_64();
369
 
370
  if (CPL==0)
371
    changeMask |= EFlagsIOPLMask;
372
  if (CPL <= BX_CPU_THIS_PTR get_IOPL())
373
    changeMask |= EFlagsIFMask;
374
 
375
  // VIF, VIP, VM are unaffected
376
  writeEFlags(eflags32, changeMask);
377
 
378
  BX_NEXT_INSTR(i);
379
}
380
#endif
381
 
382
#endif  // BX_CPU_LEVEL >= 3
383
 
384
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::SALC(bxInstruction_c *i)
385
{
386
  if (get_CF()) {
387
    AL = 0xff;
388
  }
389
  else {
390
    AL = 0x00;
391
  }
392
 
393
  BX_NEXT_INSTR(i);
394
}
395
 
396
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::STAC(bxInstruction_c *i)
397
{
398
  if (CPL != 0) {
399
    BX_ERROR(("STAC is not recognized when CPL != 0"));
400
    exception(BX_UD_EXCEPTION, 0);
401
  }
402
 
403
  assert_AC();
404
 
405
  BX_NEXT_INSTR(i);
406
}
407
 
408
BX_INSF_TYPE BX_CPP_AttrRegparmN(1) BX_CPU_C::CLAC(bxInstruction_c *i)
409
{
410
  if (CPL != 0) {
411
    BX_ERROR(("CLAC is not recognized when CPL != 0"));
412
    exception(BX_UD_EXCEPTION, 0);
413
  }
414
 
415
  clear_AC();
416
 
417
  BX_NEXT_INSTR(i);
418
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.