aboutsummaryrefslogtreecommitdiff
path: root/op-i386.c
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-03-30 21:01:16 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-03-30 21:01:16 +0000
commitf631ef9bd262796779dd2b18741cf924831dab54 (patch)
tree84de5132f935b7a0f9c9a41238e5519f2f00a6d3 /op-i386.c
parentf7341ff4006dd90ffc6560bb9db761b9d2950aaf (diff)
better vm86 support - added iret - fixed push/pop fs/gs
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@68 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'op-i386.c')
-rw-r--r--op-i386.c99
1 files changed, 96 insertions, 3 deletions
diff --git a/op-i386.c b/op-i386.c
index dbf70bb590..43303784da 100644
--- a/op-i386.c
+++ b/op-i386.c
@@ -611,6 +611,35 @@ void OPPROTO op_into(void)
}
}
+/* XXX: add IOPL/CPL tests */
+void OPPROTO op_cli(void)
+{
+ raise_exception(EXCP0D_GPF);
+}
+
+/* XXX: add IOPL/CPL tests */
+void OPPROTO op_sti(void)
+{
+ raise_exception(EXCP0D_GPF);
+}
+
+/* vm86plus instructions */
+
+void OPPROTO op_cli_vm(void)
+{
+ env->eflags &= ~VIF_MASK;
+}
+
+void OPPROTO op_sti_vm(void)
+{
+ env->eflags |= VIF_MASK;
+ if (env->eflags & VIP_MASK) {
+ EIP = PARAM1;
+ raise_exception(EXCP0D_GPF);
+ }
+ FORCE_RET();
+}
+
void OPPROTO op_boundw(void)
{
int low, high, v;
@@ -1234,7 +1263,8 @@ void OPPROTO op_set_cc_op(void)
CC_OP = PARAM1;
}
-#define FL_UPDATE_MASK (TF_MASK | AC_MASK | ID_MASK)
+#define FL_UPDATE_MASK32 (TF_MASK | AC_MASK | ID_MASK)
+#define FL_UPDATE_MASK16 (TF_MASK)
void OPPROTO op_movl_eflags_T0(void)
{
@@ -1243,7 +1273,56 @@ void OPPROTO op_movl_eflags_T0(void)
CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
DF = 1 - (2 * ((eflags >> 10) & 1));
/* we also update some system flags as in user mode */
- env->eflags = (env->eflags & ~FL_UPDATE_MASK) | (eflags & FL_UPDATE_MASK);
+ env->eflags = (env->eflags & ~FL_UPDATE_MASK32) | (eflags & FL_UPDATE_MASK32);
+}
+
+void OPPROTO op_movw_eflags_T0(void)
+{
+ int eflags;
+ eflags = T0;
+ CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
+ DF = 1 - (2 * ((eflags >> 10) & 1));
+ /* we also update some system flags as in user mode */
+ env->eflags = (env->eflags & ~FL_UPDATE_MASK16) | (eflags & FL_UPDATE_MASK16);
+}
+
+/* vm86 version */
+void OPPROTO op_movw_eflags_T0_vm(void)
+{
+ int eflags;
+ eflags = T0;
+ CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
+ DF = 1 - (2 * ((eflags >> 10) & 1));
+ /* we also update some system flags as in user mode */
+ env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) |
+ (eflags & FL_UPDATE_MASK16);
+ if (eflags & IF_MASK) {
+ env->eflags |= VIF_MASK;
+ if (env->eflags & VIP_MASK) {
+ EIP = PARAM1;
+ raise_exception(EXCP0D_GPF);
+ }
+ }
+ FORCE_RET();
+}
+
+void OPPROTO op_movl_eflags_T0_vm(void)
+{
+ int eflags;
+ eflags = T0;
+ CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
+ DF = 1 - (2 * ((eflags >> 10) & 1));
+ /* we also update some system flags as in user mode */
+ env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) |
+ (eflags & FL_UPDATE_MASK32);
+ if (eflags & IF_MASK) {
+ env->eflags |= VIF_MASK;
+ if (env->eflags & VIP_MASK) {
+ EIP = PARAM1;
+ raise_exception(EXCP0D_GPF);
+ }
+ }
+ FORCE_RET();
}
/* XXX: compute only O flag */
@@ -1263,6 +1342,18 @@ void OPPROTO op_movl_T0_eflags(void)
T0 = eflags;
}
+/* vm86 version */
+void OPPROTO op_movl_T0_eflags_vm(void)
+{
+ int eflags;
+ eflags = cc_table[CC_OP].compute_all();
+ eflags |= (DF & DF_MASK);
+ eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK);
+ if (env->eflags & VIF_MASK)
+ eflags |= IF_MASK;
+ T0 = eflags;
+}
+
void OPPROTO op_cld(void)
{
DF = 1;
@@ -1377,7 +1468,9 @@ CCTable cc_table[CC_OP_NB] = {
[CC_OP_SARL] = { compute_all_sarl, compute_c_shll },
};
-/* floating point support */
+/* floating point support. Some of the code for complicated x87
+ functions comes from the LGPL'ed x86 emulator found in the Willows
+ TWIN windows emulator. */
#ifdef USE_X86LDOUBLE
/* use long double functions */