1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
|
/*
* plex86: run multiple x86 operating systems concurrently
* Copyright (C) 1999-2001 Kevin P. Lawton
*
* flag.c: x86 eflags oriented instructions
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "plex86.h"
#include "monitor.h"
void
POPF_Fv(vm_t *vm)
{
Bit32u eflags, change_mask;
unsigned prevIF;
prevIF = G_GetIF(vm);
if (V8086Mode(vm)) {
if (G_GetIOPL(vm) < 3) {
exception(vm, ExceptionGP, 0);
}
if (vm->i.os_32) {
monpanic(vm, "popf_fv: os_32\n");
exception(vm, ExceptionGP, 0);
}
}
if (vm->i.os_32) {
pop32(vm, &eflags);
change_mask = 0x00244dd5;
if (!RealMode(vm)) {
if (G_CPL(vm)==0) change_mask |= 0x00003000; /* IOPL */
if (G_CPL(vm)<=G_GetIOPL(vm)) change_mask |= 0x00000200; /* IF */
}
else { /* real mode */
change_mask |= 0x00003200; /* IOPL,IF */
}
/* VM,RF are not changed */
}
else { /* 16 bit opsize */
Bit16u flags;
pop16(vm, &flags);
eflags = flags;
change_mask = 0x00004dd5;
if (!RealMode(vm)) {
if (G_CPL(vm)==0) change_mask |= 0x00003000; /* IOPL */
if (G_CPL(vm)<=G_GetIOPL(vm)) change_mask |= 0x00000200; /* IF */
}
else {
change_mask |= 0x00003200; /* IOPL,IF */
}
}
write_eflags(vm, eflags, change_mask);
/* +++ does POPF do this? */
if (!prevIF && G_GetIF(vm)) {
vm->guest_cpu.inhibit_mask |= INHIBIT_INTERRUPTS;
vm->guest_cpu.async_event = 1;
}
/*monprint(vm, "POPF: image=0x%x, IF=%u\n", eflags, G_GetIF(vm)); */
/* +++ does this inhibit ints like STI does? */
}
void
PUSHF_Fv(vm_t *vm)
{
if (V8086Mode(vm) && (G_GetIOPL(vm)<3)) {
exception(vm, ExceptionGP, 0);
}
if (vm->i.os_32) {
push32(vm, read_eflags(vm) & 0x00fcffff);
}
else {
push16(vm, (Bit16u) read_eflags(vm));
}
}
void
LAHF(vm_t *vm)
{
G_AH(vm) = (Bit8u) read_eflags(vm);
}
void
SAHF(vm_t *vm)
{
Bit32u eflags;
eflags = G_AH(vm);
SetSZAPC(vm, eflags);
}
void
CMC(vm_t *vm)
{
G_SetCF(vm, !G_GetCF(vm) );
}
void
SALC(vm_t *vm)
{
if ( G_GetCF(vm) ) {
G_AL(vm) = 0xff;
}
else {
G_AL(vm) = 0x00;
}
}
|