summaryrefslogtreecommitdiff
path: root/target-i386
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2005-04-17 19:50:21 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2005-04-17 19:50:21 +0000
commit5516d670f69dafc77c936a02ff9916a9fba9fcd0 (patch)
treea8813cd3afae0c753dd52838d133f74b42b6a837 /target-i386
parentcc6f538bf6768cec1383c72e864f547ad9f04e30 (diff)
downloadqemu-5516d670f69dafc77c936a02ff9916a9fba9fcd0.tar.gz
make lsl, lar verr and verw exception safe
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1369 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-i386')
-rw-r--r--target-i386/helper.c78
1 files changed, 45 insertions, 33 deletions
diff --git a/target-i386/helper.c b/target-i386/helper.c
index b358c2ecfe..2c852090aa 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -2335,13 +2335,13 @@ void helper_rdmsr(void)
void helper_lsl(void)
{
unsigned int selector, limit;
- uint32_t e1, e2;
+ uint32_t e1, e2, eflags;
int rpl, dpl, cpl, type;
- CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
+ eflags = cc_table[CC_OP].compute_all();
selector = T0 & 0xffff;
if (load_segment(&e1, &e2, selector) != 0)
- return;
+ goto fail;
rpl = selector & 3;
dpl = (e2 >> DESC_DPL_SHIFT) & 3;
cpl = env->hflags & HF_CPL_MASK;
@@ -2350,7 +2350,7 @@ void helper_lsl(void)
/* conforming */
} else {
if (dpl < cpl || dpl < rpl)
- return;
+ goto fail;
}
} else {
type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
@@ -2362,28 +2362,31 @@ void helper_lsl(void)
case 11:
break;
default:
- return;
+ goto fail;
}
- if (dpl < cpl || dpl < rpl)
+ if (dpl < cpl || dpl < rpl) {
+ fail:
+ CC_SRC = eflags & ~CC_Z;
return;
+ }
}
limit = get_seg_limit(e1, e2);
T1 = limit;
- CC_SRC |= CC_Z;
+ CC_SRC = eflags | CC_Z;
}
void helper_lar(void)
{
unsigned int selector;
- uint32_t e1, e2;
+ uint32_t e1, e2, eflags;
int rpl, dpl, cpl, type;
- CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
+ eflags = cc_table[CC_OP].compute_all();
selector = T0 & 0xffff;
if ((selector & 0xfffc) == 0)
- return;
+ goto fail;
if (load_segment(&e1, &e2, selector) != 0)
- return;
+ goto fail;
rpl = selector & 3;
dpl = (e2 >> DESC_DPL_SHIFT) & 3;
cpl = env->hflags & HF_CPL_MASK;
@@ -2392,7 +2395,7 @@ void helper_lar(void)
/* conforming */
} else {
if (dpl < cpl || dpl < rpl)
- return;
+ goto fail;
}
} else {
type = (e2 >> DESC_TYPE_SHIFT) & 0xf;
@@ -2407,72 +2410,81 @@ void helper_lar(void)
case 12:
break;
default:
- return;
+ goto fail;
}
- if (dpl < cpl || dpl < rpl)
+ if (dpl < cpl || dpl < rpl) {
+ fail:
+ CC_SRC = eflags & ~CC_Z;
return;
+ }
}
T1 = e2 & 0x00f0ff00;
- CC_SRC |= CC_Z;
+ CC_SRC = eflags | CC_Z;
}
void helper_verr(void)
{
unsigned int selector;
- uint32_t e1, e2;
+ uint32_t e1, e2, eflags;
int rpl, dpl, cpl;
- CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
+ eflags = cc_table[CC_OP].compute_all();
selector = T0 & 0xffff;
if ((selector & 0xfffc) == 0)
- return;
+ goto fail;
if (load_segment(&e1, &e2, selector) != 0)
- return;
+ goto fail;
if (!(e2 & DESC_S_MASK))
- return;
+ goto fail;
rpl = selector & 3;
dpl = (e2 >> DESC_DPL_SHIFT) & 3;
cpl = env->hflags & HF_CPL_MASK;
if (e2 & DESC_CS_MASK) {
if (!(e2 & DESC_R_MASK))
- return;
+ goto fail;
if (!(e2 & DESC_C_MASK)) {
if (dpl < cpl || dpl < rpl)
- return;
+ goto fail;
}
} else {
- if (dpl < cpl || dpl < rpl)
+ if (dpl < cpl || dpl < rpl) {
+ fail:
+ CC_SRC = eflags & ~CC_Z;
return;
+ }
}
- CC_SRC |= CC_Z;
+ CC_SRC = eflags | CC_Z;
}
void helper_verw(void)
{
unsigned int selector;
- uint32_t e1, e2;
+ uint32_t e1, e2, eflags;
int rpl, dpl, cpl;
- CC_SRC = cc_table[CC_OP].compute_all() & ~CC_Z;
+ eflags = cc_table[CC_OP].compute_all();
selector = T0 & 0xffff;
if ((selector & 0xfffc) == 0)
- return;
+ goto fail;
if (load_segment(&e1, &e2, selector) != 0)
- return;
+ goto fail;
if (!(e2 & DESC_S_MASK))
- return;
+ goto fail;
rpl = selector & 3;
dpl = (e2 >> DESC_DPL_SHIFT) & 3;
cpl = env->hflags & HF_CPL_MASK;
if (e2 & DESC_CS_MASK) {
- return;
+ goto fail;
} else {
if (dpl < cpl || dpl < rpl)
+ goto fail;
+ if (!(e2 & DESC_W_MASK)) {
+ fail:
+ CC_SRC = eflags & ~CC_Z;
return;
- if (!(e2 & DESC_W_MASK))
- return;
+ }
}
- CC_SRC |= CC_Z;
+ CC_SRC = eflags | CC_Z;
}
/* FPU helpers */