Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
qemu
提交
d8bc1fd0
Q
qemu
项目概览
openeuler
/
qemu
通知
10
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Q
qemu
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
d8bc1fd0
编写于
6月 21, 2003
作者:
B
bellard
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
ring 0 ops
git-svn-id:
svn://svn.savannah.nongnu.org/qemu/trunk@254
c046a42c-6fe2-441c-8c8c-71466251a162
上级
7501267e
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
469 addition
and
51 deletion
+469
-51
exec-i386.h
exec-i386.h
+5
-0
helper-i386.c
helper-i386.c
+168
-16
op-i386.c
op-i386.c
+73
-12
translate-i386.c
translate-i386.c
+223
-23
未找到文件。
exec-i386.h
浏览文件 @
d8bc1fd0
...
...
@@ -123,6 +123,11 @@ typedef struct CCTable {
extern
CCTable
cc_table
[];
void
load_seg
(
int
seg_reg
,
int
selector
,
unsigned
cur_eip
);
void
jmp_seg
(
int
selector
,
unsigned
int
new_eip
);
void
helper_lldt_T0
(
void
);
void
helper_ltr_T0
(
void
);
void
helper_movl_crN_T0
(
int
reg
);
void
helper_movl_drN_T0
(
int
reg
);
void
__hidden
cpu_lock
(
void
);
void
__hidden
cpu_unlock
(
void
);
void
raise_interrupt
(
int
intno
,
int
is_int
,
int
error_code
,
...
...
helper-i386.c
浏览文件 @
d8bc1fd0
...
...
@@ -157,7 +157,7 @@ void raise_interrupt(int intno, int is_int, int error_code,
break;
}
dpl = (e2 >> DESC_DPL_SHIFT) & 3;
cpl = env->segs[R_CS] & 3;
cpl = env->segs[R_CS]
.selector
& 3;
/* check privledge if software int */
if (is_int && dpl < cpl)
raise_exception_err(EXCP0D_GPF, intno * 8 + 2);
...
...
@@ -176,7 +176,7 @@ void raise_interrupt(int intno, int is_int, int error_code,
void
raise_interrupt
(
int
intno
,
int
is_int
,
int
error_code
,
unsigned
int
next_eip
)
{
Segment
DescriptorTabl
e
*
dt
;
Segment
Cach
e
*
dt
;
uint8_t
*
ptr
;
int
dpl
,
cpl
;
uint32_t
e2
;
...
...
@@ -331,21 +331,98 @@ void helper_cpuid(void)
}
}
static
inline
void
load_seg_cache
(
SegmentCache
*
sc
,
uint32_t
e1
,
uint32_t
e2
)
{
sc
->
base
=
(
void
*
)((
e1
>>
16
)
|
((
e2
&
0xff
)
<<
16
)
|
(
e2
&
0xff000000
));
sc
->
limit
=
(
e1
&
0xffff
)
|
(
e2
&
0x000f0000
);
if
(
e2
&
(
1
<<
23
))
sc
->
limit
=
(
sc
->
limit
<<
12
)
|
0xfff
;
sc
->
seg_32bit
=
(
e2
>>
22
)
&
1
;
}
void
helper_lldt_T0
(
void
)
{
int
selector
;
SegmentCache
*
dt
;
uint32_t
e1
,
e2
;
int
index
;
uint8_t
*
ptr
;
selector
=
T0
&
0xffff
;
if
((
selector
&
0xfffc
)
==
0
)
{
/* XXX: NULL selector case: invalid LDT */
env
->
ldt
.
base
=
NULL
;
env
->
ldt
.
limit
=
0
;
}
else
{
if
(
selector
&
0x4
)
raise_exception_err
(
EXCP0D_GPF
,
selector
&
0xfffc
);
dt
=
&
env
->
gdt
;
index
=
selector
&
~
7
;
if
((
index
+
7
)
>
dt
->
limit
)
raise_exception_err
(
EXCP0D_GPF
,
selector
&
0xfffc
);
ptr
=
dt
->
base
+
index
;
e1
=
ldl
(
ptr
);
e2
=
ldl
(
ptr
+
4
);
if
((
e2
&
DESC_S_MASK
)
||
((
e2
>>
DESC_TYPE_SHIFT
)
&
0xf
)
!=
2
)
raise_exception_err
(
EXCP0D_GPF
,
selector
&
0xfffc
);
if
(
!
(
e2
&
DESC_P_MASK
))
raise_exception_err
(
EXCP0B_NOSEG
,
selector
&
0xfffc
);
load_seg_cache
(
&
env
->
ldt
,
e1
,
e2
);
}
env
->
ldt
.
selector
=
selector
;
}
void
helper_ltr_T0
(
void
)
{
int
selector
;
SegmentCache
*
dt
;
uint32_t
e1
,
e2
;
int
index
,
type
;
uint8_t
*
ptr
;
selector
=
T0
&
0xffff
;
if
((
selector
&
0xfffc
)
==
0
)
{
/* XXX: NULL selector case: invalid LDT */
env
->
tr
.
base
=
NULL
;
env
->
tr
.
limit
=
0
;
}
else
{
if
(
selector
&
0x4
)
raise_exception_err
(
EXCP0D_GPF
,
selector
&
0xfffc
);
dt
=
&
env
->
gdt
;
index
=
selector
&
~
7
;
if
((
index
+
7
)
>
dt
->
limit
)
raise_exception_err
(
EXCP0D_GPF
,
selector
&
0xfffc
);
ptr
=
dt
->
base
+
index
;
e1
=
ldl
(
ptr
);
e2
=
ldl
(
ptr
+
4
);
type
=
(
e2
>>
DESC_TYPE_SHIFT
)
&
0xf
;
if
((
e2
&
DESC_S_MASK
)
||
(
type
!=
2
&&
type
!=
9
))
raise_exception_err
(
EXCP0D_GPF
,
selector
&
0xfffc
);
if
(
!
(
e2
&
DESC_P_MASK
))
raise_exception_err
(
EXCP0B_NOSEG
,
selector
&
0xfffc
);
load_seg_cache
(
&
env
->
tr
,
e1
,
e2
);
e2
|=
0x00000200
;
/* set the busy bit */
stl
(
ptr
+
4
,
e2
);
}
env
->
tr
.
selector
=
selector
;
}
/* only works if protected mode and not VM86 */
void
load_seg
(
int
seg_reg
,
int
selector
,
unsigned
cur_eip
)
void
load_seg
(
int
seg_reg
,
int
selector
,
unsigned
int
cur_eip
)
{
SegmentCache
*
sc
;
Segment
DescriptorTabl
e
*
dt
;
Segment
Cach
e
*
dt
;
int
index
;
uint32_t
e1
,
e2
;
uint8_t
*
ptr
;
sc
=
&
env
->
seg
_cache
[
seg_reg
];
sc
=
&
env
->
seg
s
[
seg_reg
];
if
((
selector
&
0xfffc
)
==
0
)
{
/* null selector case */
if
(
seg_reg
==
R_SS
)
{
EIP
=
cur_eip
;
raise_exception_err
(
EXCP0D_GPF
,
selector
&
0xfffc
);
raise_exception_err
(
EXCP0D_GPF
,
0
);
}
else
{
/* XXX: each access should trigger an exception */
sc
->
base
=
NULL
;
...
...
@@ -390,18 +467,93 @@ void load_seg(int seg_reg, int selector, unsigned cur_eip)
else
raise_exception_err
(
EXCP0B_NOSEG
,
selector
&
0xfffc
);
}
sc
->
base
=
(
void
*
)((
e1
>>
16
)
|
((
e2
&
0xff
)
<<
16
)
|
(
e2
&
0xff000000
));
sc
->
limit
=
(
e1
&
0xffff
)
|
(
e2
&
0x000f0000
);
if
(
e2
&
(
1
<<
23
))
sc
->
limit
=
(
sc
->
limit
<<
12
)
|
0xfff
;
sc
->
seg_32bit
=
(
e2
>>
22
)
&
1
;
load_seg_cache
(
sc
,
e1
,
e2
);
#if 0
fprintf(logfile, "load_seg: sel=0x%04x base=0x%08lx limit=0x%08lx seg_32bit=%d\n",
selector, (unsigned long)sc->base, sc->limit, sc->seg_32bit);
#endif
}
env
->
segs
[
seg_reg
]
=
selector
;
sc
->
selector
=
selector
;
}
/* protected mode jump */
void
jmp_seg
(
int
selector
,
unsigned
int
new_eip
)
{
SegmentCache
sc1
;
SegmentCache
*
dt
;
int
index
;
uint32_t
e1
,
e2
,
cpl
,
dpl
,
rpl
;
uint8_t
*
ptr
;
if
((
selector
&
0xfffc
)
==
0
)
{
raise_exception_err
(
EXCP0D_GPF
,
0
);
}
if
(
selector
&
0x4
)
dt
=
&
env
->
ldt
;
else
dt
=
&
env
->
gdt
;
index
=
selector
&
~
7
;
if
((
index
+
7
)
>
dt
->
limit
)
raise_exception_err
(
EXCP0D_GPF
,
selector
&
0xfffc
);
ptr
=
dt
->
base
+
index
;
e1
=
ldl
(
ptr
);
e2
=
ldl
(
ptr
+
4
);
cpl
=
env
->
segs
[
R_CS
].
selector
&
3
;
if
(
e2
&
DESC_S_MASK
)
{
if
(
!
(
e2
&
DESC_CS_MASK
))
raise_exception_err
(
EXCP0D_GPF
,
selector
&
0xfffc
);
dpl
=
(
e2
>>
DESC_DPL_SHIFT
)
&
3
;
if
(
e2
&
DESC_CS_MASK
)
{
/* conforming code segment */
if
(
dpl
>
cpl
)
raise_exception_err
(
EXCP0D_GPF
,
selector
&
0xfffc
);
}
else
{
/* non conforming code segment */
rpl
=
selector
&
3
;
if
(
rpl
>
cpl
)
raise_exception_err
(
EXCP0D_GPF
,
selector
&
0xfffc
);
if
(
dpl
!=
cpl
)
raise_exception_err
(
EXCP0D_GPF
,
selector
&
0xfffc
);
}
if
(
!
(
e2
&
DESC_P_MASK
))
raise_exception_err
(
EXCP0B_NOSEG
,
selector
&
0xfffc
);
load_seg_cache
(
&
sc1
,
e1
,
e2
);
if
(
new_eip
>
sc1
.
limit
)
raise_exception_err
(
EXCP0D_GPF
,
selector
&
0xfffc
);
env
->
segs
[
R_CS
]
=
sc1
;
env
->
segs
[
R_CS
].
selector
=
(
selector
&
0xfffc
)
|
cpl
;
EIP
=
new_eip
;
}
else
{
cpu_abort
(
env
,
"jmp to call/task gate not supported 0x%04x:0x%08x"
,
selector
,
new_eip
);
}
}
/* XXX: do more */
void
helper_movl_crN_T0
(
int
reg
)
{
switch
(
reg
)
{
case
0
:
default:
env
->
cr
[
0
]
=
reg
;
break
;
case
2
:
env
->
cr
[
2
]
=
reg
;
break
;
case
3
:
env
->
cr
[
3
]
=
reg
;
break
;
case
4
:
env
->
cr
[
4
]
=
reg
;
break
;
}
}
/* XXX: do more */
void
helper_movl_drN_T0
(
int
reg
)
{
env
->
dr
[
reg
]
=
T0
;
}
/* rdtsc */
...
...
@@ -425,7 +577,7 @@ void helper_rdtsc(void)
void
helper_lsl
(
void
)
{
unsigned
int
selector
,
limit
;
Segment
DescriptorTabl
e
*
dt
;
Segment
Cach
e
*
dt
;
int
index
;
uint32_t
e1
,
e2
;
uint8_t
*
ptr
;
...
...
@@ -452,7 +604,7 @@ void helper_lsl(void)
void
helper_lar
(
void
)
{
unsigned
int
selector
;
Segment
DescriptorTabl
e
*
dt
;
Segment
Cach
e
*
dt
;
int
index
;
uint32_t
e2
;
uint8_t
*
ptr
;
...
...
op-i386.c
浏览文件 @
d8bc1fd0
...
...
@@ -357,6 +357,11 @@ void OPPROTO op_andl_T0_ffff(void)
T0
=
T0
&
0xffff
;
}
void
OPPROTO
op_andl_T0_im
(
void
)
{
T0
=
T0
&
PARAM1
;
}
void
OPPROTO
op_movl_T0_T1
(
void
)
{
T0
=
T1
;
...
...
@@ -665,7 +670,7 @@ void op_pushl_ss32_T0(void)
{
uint32_t
offset
;
offset
=
ESP
-
4
;
stl
(
env
->
seg
_cache
[
R_SS
].
base
+
offset
,
T0
);
stl
(
env
->
seg
s
[
R_SS
].
base
+
offset
,
T0
);
/* modify ESP after to handle exceptions correctly */
ESP
=
offset
;
}
...
...
@@ -674,7 +679,7 @@ void op_pushw_ss32_T0(void)
{
uint32_t
offset
;
offset
=
ESP
-
2
;
stw
(
env
->
seg
_cache
[
R_SS
].
base
+
offset
,
T0
);
stw
(
env
->
seg
s
[
R_SS
].
base
+
offset
,
T0
);
/* modify ESP after to handle exceptions correctly */
ESP
=
offset
;
}
...
...
@@ -683,7 +688,7 @@ void op_pushl_ss16_T0(void)
{
uint32_t
offset
;
offset
=
(
ESP
-
4
)
&
0xffff
;
stl
(
env
->
seg
_cache
[
R_SS
].
base
+
offset
,
T0
);
stl
(
env
->
seg
s
[
R_SS
].
base
+
offset
,
T0
);
/* modify ESP after to handle exceptions correctly */
ESP
=
(
ESP
&
~
0xffff
)
|
offset
;
}
...
...
@@ -692,7 +697,7 @@ void op_pushw_ss16_T0(void)
{
uint32_t
offset
;
offset
=
(
ESP
-
2
)
&
0xffff
;
stw
(
env
->
seg
_cache
[
R_SS
].
base
+
offset
,
T0
);
stw
(
env
->
seg
s
[
R_SS
].
base
+
offset
,
T0
);
/* modify ESP after to handle exceptions correctly */
ESP
=
(
ESP
&
~
0xffff
)
|
offset
;
}
...
...
@@ -710,22 +715,22 @@ void op_popw_T0(void)
void
op_popl_ss32_T0
(
void
)
{
T0
=
ldl
(
env
->
seg
_cache
[
R_SS
].
base
+
ESP
);
T0
=
ldl
(
env
->
seg
s
[
R_SS
].
base
+
ESP
);
}
void
op_popw_ss32_T0
(
void
)
{
T0
=
lduw
(
env
->
seg
_cache
[
R_SS
].
base
+
ESP
);
T0
=
lduw
(
env
->
seg
s
[
R_SS
].
base
+
ESP
);
}
void
op_popl_ss16_T0
(
void
)
{
T0
=
ldl
(
env
->
seg
_cache
[
R_SS
].
base
+
(
ESP
&
0xffff
));
T0
=
ldl
(
env
->
seg
s
[
R_SS
].
base
+
(
ESP
&
0xffff
));
}
void
op_popw_ss16_T0
(
void
)
{
T0
=
lduw
(
env
->
seg
_cache
[
R_SS
].
base
+
(
ESP
&
0xffff
));
T0
=
lduw
(
env
->
seg
s
[
R_SS
].
base
+
(
ESP
&
0xffff
));
}
void
op_addl_ESP_4
(
void
)
...
...
@@ -909,17 +914,18 @@ void OPPROTO op_movl_seg_T0(void)
void
OPPROTO
op_movl_seg_T0_vm
(
void
)
{
int
selector
;
SegmentCache
*
sc
;
selector
=
T0
&
0xffff
;
/* env->segs[] access */
*
(
uint32_t
*
)((
char
*
)
env
+
PARAM1
)
=
selector
;
/* env->seg_cache[] access */
((
SegmentCache
*
)((
char
*
)
env
+
PARAM2
))
->
base
=
(
void
*
)(
selector
<<
4
);
sc
=
(
SegmentCache
*
)((
char
*
)
env
+
PARAM1
)
;
sc
->
selector
=
selector
;
sc
->
base
=
(
void
*
)(
selector
<<
4
);
}
void
OPPROTO
op_movl_T0_seg
(
void
)
{
T0
=
env
->
segs
[
PARAM1
];
T0
=
env
->
segs
[
PARAM1
]
.
selector
;
}
void
OPPROTO
op_movl_A0_seg
(
void
)
...
...
@@ -942,6 +948,61 @@ void OPPROTO op_lar(void)
helper_lar
();
}
/* T0: segment, T1:eip */
void
OPPROTO
op_ljmp_T0_T1
(
void
)
{
jmp_seg
(
T0
&
0xffff
,
T1
);
}
void
OPPROTO
op_lldt_T0
(
void
)
{
helper_lldt_T0
();
}
void
OPPROTO
op_ltr_T0
(
void
)
{
helper_ltr_T0
();
}
/* CR registers access */
void
OPPROTO
op_movl_crN_T0
(
void
)
{
helper_movl_crN_T0
(
PARAM1
);
}
/* DR registers access */
void
OPPROTO
op_movl_drN_T0
(
void
)
{
helper_movl_drN_T0
(
PARAM1
);
}
void
OPPROTO
op_lmsw_T0
(
void
)
{
/* only 4 lower bits of CR0 are modified */
T0
=
(
env
->
cr
[
0
]
&
~
0xf
)
|
(
T0
&
0xf
);
helper_movl_crN_T0
(
0
);
}
void
OPPROTO
op_movl_T0_env
(
void
)
{
T0
=
*
(
uint32_t
*
)((
char
*
)
env
+
PARAM1
);
}
void
OPPROTO
op_movl_env_T0
(
void
)
{
*
(
uint32_t
*
)((
char
*
)
env
+
PARAM1
)
=
T0
;
}
void
OPPROTO
op_movl_env_T1
(
void
)
{
*
(
uint32_t
*
)((
char
*
)
env
+
PARAM1
)
=
T1
;
}
void
OPPROTO
op_clts
(
void
)
{
env
->
cr
[
0
]
&=
~
CR0_TS_MASK
;
}
/* flags handling */
/* slow jumps cases : in order to avoid calling a function with a
...
...
translate-i386.c
浏览文件 @
d8bc1fd0
...
...
@@ -575,7 +575,7 @@ static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func)
if
(
s
->
addseg
&&
override
<
0
)
override
=
R_DS
;
if
(
override
>=
0
)
{
gen_op_movl_A0_seg
(
offsetof
(
CPUX86State
,
seg
_cache
[
override
].
base
));
gen_op_movl_A0_seg
(
offsetof
(
CPUX86State
,
seg
s
[
override
].
base
));
index
=
3
+
ot
;
}
else
{
index
=
ot
;
...
...
@@ -583,7 +583,7 @@ static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func)
}
else
{
if
(
override
<
0
)
override
=
R_DS
;
gen_op_movl_A0_seg
(
offsetof
(
CPUX86State
,
seg
_cache
[
override
].
base
));
gen_op_movl_A0_seg
(
offsetof
(
CPUX86State
,
seg
s
[
override
].
base
));
/* 16 address, always override */
index
=
6
+
ot
;
}
...
...
@@ -878,7 +878,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
else
override
=
R_DS
;
}
gen_op_addl_A0_seg
(
offsetof
(
CPUX86State
,
seg
_cache
[
override
].
base
));
gen_op_addl_A0_seg
(
offsetof
(
CPUX86State
,
seg
s
[
override
].
base
));
}
}
else
{
switch
(
mod
)
{
...
...
@@ -944,7 +944,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
else
override
=
R_DS
;
}
gen_op_addl_A0_seg
(
offsetof
(
CPUX86State
,
seg
_cache
[
override
].
base
));
gen_op_addl_A0_seg
(
offsetof
(
CPUX86State
,
seg
s
[
override
].
base
));
}
}
...
...
@@ -1146,8 +1146,7 @@ static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip)
if
(
!
s
->
vm86
)
gen_op_movl_seg_T0
(
seg_reg
,
cur_eip
);
else
gen_op_movl_seg_T0_vm
(
offsetof
(
CPUX86State
,
segs
[
seg_reg
]),
offsetof
(
CPUX86State
,
seg_cache
[
seg_reg
].
base
));
gen_op_movl_seg_T0_vm
(
offsetof
(
CPUX86State
,
segs
[
seg_reg
]));
if
(
!
s
->
addseg
&&
seg_reg
<
R_FS
)
s
->
is_jmp
=
2
;
/* abort translation because the register may
have a non zero base */
...
...
@@ -1230,7 +1229,7 @@ static void gen_stack_A0(DisasContext *s)
gen_op_andl_A0_ffff
();
gen_op_movl_T1_A0
();
if
(
s
->
addseg
)
gen_op_addl_A0_seg
(
offsetof
(
CPUX86State
,
seg
_cache
[
R_SS
].
base
));
gen_op_addl_A0_seg
(
offsetof
(
CPUX86State
,
seg
s
[
R_SS
].
base
));
}
/* NOTE: wrap around in 16 bit not fully handled */
...
...
@@ -1243,7 +1242,7 @@ static void gen_pusha(DisasContext *s)
gen_op_andl_A0_ffff
();
gen_op_movl_T1_A0
();
if
(
s
->
addseg
)
gen_op_addl_A0_seg
(
offsetof
(
CPUX86State
,
seg
_cache
[
R_SS
].
base
));
gen_op_addl_A0_seg
(
offsetof
(
CPUX86State
,
seg
s
[
R_SS
].
base
));
for
(
i
=
0
;
i
<
8
;
i
++
)
{
gen_op_mov_TN_reg
[
OT_LONG
][
0
][
7
-
i
]();
gen_op_st_T0_A0
[
OT_WORD
+
s
->
dflag
]();
...
...
@@ -1262,7 +1261,7 @@ static void gen_popa(DisasContext *s)
gen_op_movl_T1_A0
();
gen_op_addl_T1_im
(
16
<<
s
->
dflag
);
if
(
s
->
addseg
)
gen_op_addl_A0_seg
(
offsetof
(
CPUX86State
,
seg
_cache
[
R_SS
].
base
));
gen_op_addl_A0_seg
(
offsetof
(
CPUX86State
,
seg
s
[
R_SS
].
base
));
for
(
i
=
0
;
i
<
8
;
i
++
)
{
/* ESP is not reloaded */
if
(
i
!=
3
)
{
...
...
@@ -1291,7 +1290,7 @@ static void gen_enter(DisasContext *s, int esp_addend, int level)
gen_op_andl_A0_ffff
();
gen_op_movl_T1_A0
();
if
(
s
->
addseg
)
gen_op_addl_A0_seg
(
offsetof
(
CPUX86State
,
seg
_cache
[
R_SS
].
base
));
gen_op_addl_A0_seg
(
offsetof
(
CPUX86State
,
seg
s
[
R_SS
].
base
));
/* push bp */
gen_op_mov_TN_reg
[
OT_LONG
][
0
][
R_EBP
]();
gen_op_st_T0_A0
[
ot
]();
...
...
@@ -1714,9 +1713,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
gen_op_ld_T1_A0
[
ot
]();
gen_op_addl_A0_im
(
1
<<
(
ot
-
OT_WORD
+
1
));
gen_op_lduw_T0_A0
();
gen_movl_seg_T0
(
s
,
R_CS
,
pc_start
-
s
->
cs_base
);
gen_op_movl_T0_T1
();
gen_op_jmp_T0
();
if
(
!
s
->
vm86
)
{
/* we compute EIP to handle the exception case */
gen_op_jmp_im
(
pc_start
-
s
->
cs_base
);
gen_op_ljmp_T0_T1
();
}
else
{
gen_op_movl_seg_T0_vm
(
offsetof
(
CPUX86State
,
segs
[
R_CS
]));
gen_op_movl_T0_T1
();
gen_op_jmp_T0
();
}
s
->
is_jmp
=
1
;
break
;
case
6
:
/* push Ev */
...
...
@@ -2085,7 +2090,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
override
=
R_DS
;
}
if
(
must_add_seg
)
{
gen_op_addl_A0_seg
(
offsetof
(
CPUX86State
,
seg
_cache
[
override
].
base
));
gen_op_addl_A0_seg
(
offsetof
(
CPUX86State
,
seg
s
[
override
].
base
));
}
}
if
((
b
&
2
)
==
0
)
{
...
...
@@ -2113,7 +2118,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
override
=
R_DS
;
}
if
(
must_add_seg
)
{
gen_op_addl_A0_seg
(
offsetof
(
CPUX86State
,
seg
_cache
[
override
].
base
));
gen_op_addl_A0_seg
(
offsetof
(
CPUX86State
,
seg
s
[
override
].
base
));
}
}
gen_op_ldub_T0_A0
();
...
...
@@ -2619,12 +2624,18 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
break
;
case
0x1c
:
switch
(
rm
)
{
case
0
:
/* feni (287 only, just do nop here) */
break
;
case
1
:
/* fdisi (287 only, just do nop here) */
break
;
case
2
:
/* fclex */
gen_op_fclex
();
break
;
case
3
:
/* fninit */
gen_op_fninit
();
break
;
case
4
:
/* fsetpm (287 only, just do nop here) */
break
;
default:
goto
illegal_op
;
}
...
...
@@ -3011,8 +3022,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
/* change cs and pc */
gen_op_movl_T0_im
(
selector
);
gen_movl_seg_T0
(
s
,
R_CS
,
pc_start
-
s
->
cs_base
);
gen_op_jmp_im
((
unsigned
long
)
offset
);
if
(
!
s
->
vm86
)
{
/* we compute EIP to handle the exception case */
gen_op_jmp_im
(
pc_start
-
s
->
cs_base
);
gen_op_movl_T1_im
(
offset
);
gen_op_ljmp_T0_T1
();
}
else
{
gen_op_movl_seg_T0_vm
(
offsetof
(
CPUX86State
,
segs
[
R_CS
]));
gen_op_jmp_im
((
unsigned
long
)
offset
);
}
s
->
is_jmp
=
1
;
}
break
;
...
...
@@ -3343,6 +3361,111 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
/* XXX: if cpl == 0, then should do something else */
gen_exception
(
s
,
EXCP0D_GPF
,
pc_start
-
s
->
cs_base
);
break
;
case
0x100
:
modrm
=
ldub
(
s
->
pc
++
);
mod
=
(
modrm
>>
6
)
&
3
;
op
=
(
modrm
>>
3
)
&
7
;
switch
(
op
)
{
case
0
:
/* sldt */
gen_op_movl_T0_env
(
offsetof
(
CPUX86State
,
ldt
.
selector
));
ot
=
OT_WORD
;
if
(
mod
==
3
)
ot
+=
s
->
dflag
;
gen_ldst_modrm
(
s
,
modrm
,
ot
,
OR_TMP0
,
1
);
break
;
case
2
:
/* lldt */
if
(
s
->
cpl
!=
0
)
{
gen_exception
(
s
,
EXCP0D_GPF
,
pc_start
-
s
->
cs_base
);
}
else
{
gen_ldst_modrm
(
s
,
modrm
,
OT_WORD
,
OR_TMP0
,
0
);
gen_op_jmp_im
(
pc_start
-
s
->
cs_base
);
gen_op_lldt_T0
();
}
break
;
case
1
:
/* str */
gen_op_movl_T0_env
(
offsetof
(
CPUX86State
,
tr
.
selector
));
ot
=
OT_WORD
;
if
(
mod
==
3
)
ot
+=
s
->
dflag
;
gen_ldst_modrm
(
s
,
modrm
,
ot
,
OR_TMP0
,
1
);
break
;
case
3
:
/* ltr */
if
(
s
->
cpl
!=
0
)
{
gen_exception
(
s
,
EXCP0D_GPF
,
pc_start
-
s
->
cs_base
);
}
else
{
gen_ldst_modrm
(
s
,
modrm
,
OT_WORD
,
OR_TMP0
,
0
);
gen_op_jmp_im
(
pc_start
-
s
->
cs_base
);
gen_op_ltr_T0
();
}
break
;
case
4
:
/* verr */
case
5
:
/* verw */
default:
goto
illegal_op
;
}
break
;
case
0x101
:
modrm
=
ldub
(
s
->
pc
++
);
mod
=
(
modrm
>>
6
)
&
3
;
op
=
(
modrm
>>
3
)
&
7
;
switch
(
op
)
{
case
0
:
/* sgdt */
case
1
:
/* sidt */
if
(
mod
==
3
)
goto
illegal_op
;
gen_lea_modrm
(
s
,
modrm
,
&
reg_addr
,
&
offset_addr
);
if
(
op
==
0
)
gen_op_movl_T0_env
(
offsetof
(
CPUX86State
,
gdt
.
limit
));
else
gen_op_movl_T0_env
(
offsetof
(
CPUX86State
,
idt
.
limit
));
gen_op_stw_T0_A0
();
gen_op_addl_A0_im
(
2
);
if
(
op
==
0
)
gen_op_movl_T0_env
(
offsetof
(
CPUX86State
,
gdt
.
base
));
else
gen_op_movl_T0_env
(
offsetof
(
CPUX86State
,
idt
.
base
));
if
(
!
s
->
dflag
)
gen_op_andl_T0_im
(
0xffffff
);
gen_op_stl_T0_A0
();
break
;
case
2
:
/* lgdt */
case
3
:
/* lidt */
if
(
mod
==
3
)
goto
illegal_op
;
if
(
s
->
cpl
!=
0
)
{
gen_exception
(
s
,
EXCP0D_GPF
,
pc_start
-
s
->
cs_base
);
}
else
{
gen_lea_modrm
(
s
,
modrm
,
&
reg_addr
,
&
offset_addr
);
gen_op_lduw_T1_A0
();
gen_op_addl_A0_im
(
2
);
gen_op_ldl_T0_A0
();
if
(
!
s
->
dflag
)
gen_op_andl_T0_im
(
0xffffff
);
if
(
op
==
2
)
{
gen_op_movl_env_T0
(
offsetof
(
CPUX86State
,
gdt
.
base
));
gen_op_movl_env_T1
(
offsetof
(
CPUX86State
,
gdt
.
limit
));
}
else
{
gen_op_movl_env_T0
(
offsetof
(
CPUX86State
,
idt
.
base
));
gen_op_movl_env_T1
(
offsetof
(
CPUX86State
,
idt
.
limit
));
}
}
break
;
case
4
:
/* smsw */
gen_op_movl_T0_env
(
offsetof
(
CPUX86State
,
cr
[
0
]));
gen_ldst_modrm
(
s
,
modrm
,
OT_WORD
,
OR_TMP0
,
1
);
break
;
case
6
:
/* lmsw */
if
(
s
->
cpl
!=
0
)
{
gen_exception
(
s
,
EXCP0D_GPF
,
pc_start
-
s
->
cs_base
);
}
else
{
gen_ldst_modrm
(
s
,
modrm
,
OT_WORD
,
OR_TMP0
,
0
);
gen_op_lmsw_T0
();
}
break
;
default:
goto
illegal_op
;
}
break
;
case
0x102
:
/* lar */
case
0x103
:
/* lsl */
if
(
s
->
vm86
)
...
...
@@ -3361,6 +3484,83 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
s
->
cc_op
=
CC_OP_EFLAGS
;
gen_op_mov_reg_T1
[
ot
][
reg
]();
break
;
case
0x118
:
modrm
=
ldub
(
s
->
pc
++
);
mod
=
(
modrm
>>
6
)
&
3
;
op
=
(
modrm
>>
3
)
&
7
;
switch
(
op
)
{
case
0
:
/* prefetchnta */
case
1
:
/* prefetchnt0 */
case
2
:
/* prefetchnt0 */
case
3
:
/* prefetchnt0 */
if
(
mod
==
3
)
goto
illegal_op
;
gen_lea_modrm
(
s
,
modrm
,
&
reg_addr
,
&
offset_addr
);
/* nothing more to do */
break
;
default:
goto
illegal_op
;
}
break
;
case
0x120
:
/* mov reg, crN */
case
0x122
:
/* mov crN, reg */
if
(
s
->
cpl
!=
0
)
{
gen_exception
(
s
,
EXCP0D_GPF
,
pc_start
-
s
->
cs_base
);
}
else
{
modrm
=
ldub
(
s
->
pc
++
);
if
((
modrm
&
0xc0
)
!=
0xc0
)
goto
illegal_op
;
rm
=
modrm
&
7
;
reg
=
(
modrm
>>
3
)
&
7
;
switch
(
reg
)
{
case
0
:
case
2
:
case
3
:
case
4
:
if
(
b
&
2
)
{
gen_op_mov_TN_reg
[
OT_LONG
][
0
][
rm
]();
gen_op_movl_crN_T0
(
reg
);
s
->
is_jmp
=
2
;
}
else
{
gen_op_movl_T0_env
(
offsetof
(
CPUX86State
,
cr
[
reg
]));
gen_op_mov_reg_T0
[
OT_LONG
][
rm
]();
}
break
;
default:
goto
illegal_op
;
}
}
break
;
case
0x121
:
/* mov reg, drN */
case
0x123
:
/* mov drN, reg */
if
(
s
->
cpl
!=
0
)
{
gen_exception
(
s
,
EXCP0D_GPF
,
pc_start
-
s
->
cs_base
);
}
else
{
modrm
=
ldub
(
s
->
pc
++
);
if
((
modrm
&
0xc0
)
!=
0xc0
)
goto
illegal_op
;
rm
=
modrm
&
7
;
reg
=
(
modrm
>>
3
)
&
7
;
/* XXX: do it dynamically with CR4.DE bit */
if
(
reg
==
4
||
reg
==
5
)
goto
illegal_op
;
if
(
b
&
2
)
{
gen_op_mov_TN_reg
[
OT_LONG
][
0
][
rm
]();
gen_op_movl_drN_T0
(
reg
);
s
->
is_jmp
=
2
;
}
else
{
gen_op_movl_T0_env
(
offsetof
(
CPUX86State
,
dr
[
reg
]));
gen_op_mov_reg_T0
[
OT_LONG
][
rm
]();
}
}
break
;
case
0x106
:
/* clts */
if
(
s
->
cpl
!=
0
)
{
gen_exception
(
s
,
EXCP0D_GPF
,
pc_start
-
s
->
cs_base
);
}
else
{
gen_op_clts
();
}
break
;
default:
goto
illegal_op
;
}
...
...
@@ -3859,12 +4059,12 @@ void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
eflags
&
CC_P
?
'P'
:
'-'
,
eflags
&
CC_C
?
'C'
:
'-'
);
fprintf
(
f
,
"CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x
\n
"
,
env
->
segs
[
R_CS
],
env
->
segs
[
R_SS
],
env
->
segs
[
R_DS
],
env
->
segs
[
R_ES
],
env
->
segs
[
R_FS
],
env
->
segs
[
R_GS
]);
env
->
segs
[
R_CS
]
.
selector
,
env
->
segs
[
R_SS
]
.
selector
,
env
->
segs
[
R_DS
]
.
selector
,
env
->
segs
[
R_ES
]
.
selector
,
env
->
segs
[
R_FS
]
.
selector
,
env
->
segs
[
R_GS
]
.
selector
);
if
(
flags
&
X86_DUMP_CCOP
)
{
if
((
unsigned
)
env
->
cc_op
<
CC_OP_NB
)
strcpy
(
cc_op_name
,
cc_op_str
[
env
->
cc_op
]);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录