Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
1c73ef66
Commit
1c73ef66
authored
Nov 01, 2007
by
Avi Kivity
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
KVM: x86 emulator: Hoist modrm and abs decoding into separate functions
Signed-off-by:
Avi Kivity
<
avi@qumranet.com
>
parent
3b6fff19
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
177 additions
and
160 deletions
+177
-160
drivers/kvm/x86_emulate.c
drivers/kvm/x86_emulate.c
+177
-160
No files found.
drivers/kvm/x86_emulate.c
View file @
1c73ef66
...
...
@@ -548,122 +548,20 @@ static void decode_register_operand(struct operand *op,
op
->
orig_val
=
op
->
val
;
}
int
x86_decode_insn
(
struct
x86_emulate_ctxt
*
ctxt
,
struct
x86_emulate_ops
*
ops
)
static
int
decode_modrm
(
struct
x86_emulate_ctxt
*
ctxt
,
struct
x86_emulate_ops
*
ops
)
{
struct
decode_cache
*
c
=
&
ctxt
->
decode
;
u8
sib
;
int
rc
=
0
;
int
mode
=
ctxt
->
mode
;
int
index_reg
=
0
,
base_reg
=
0
,
scale
,
rip_relative
=
0
;
int
rc
=
0
;
/* Shadow copy of register state. Committed on successful emulation. */
memset
(
c
,
0
,
sizeof
(
struct
decode_cache
));
c
->
eip
=
ctxt
->
vcpu
->
rip
;
memcpy
(
c
->
regs
,
ctxt
->
vcpu
->
regs
,
sizeof
c
->
regs
);
switch
(
mode
)
{
case
X86EMUL_MODE_REAL
:
case
X86EMUL_MODE_PROT16
:
c
->
op_bytes
=
c
->
ad_bytes
=
2
;
break
;
case
X86EMUL_MODE_PROT32
:
c
->
op_bytes
=
c
->
ad_bytes
=
4
;
break
;
#ifdef CONFIG_X86_64
case
X86EMUL_MODE_PROT64
:
c
->
op_bytes
=
4
;
c
->
ad_bytes
=
8
;
break
;
#endif
default:
return
-
1
;
}
/* Legacy prefixes. */
for
(;;)
{
switch
(
c
->
b
=
insn_fetch
(
u8
,
1
,
c
->
eip
))
{
case
0x66
:
/* operand-size override */
c
->
op_bytes
^=
6
;
/* switch between 2/4 bytes */
break
;
case
0x67
:
/* address-size override */
if
(
mode
==
X86EMUL_MODE_PROT64
)
/* switch between 4/8 bytes */
c
->
ad_bytes
^=
12
;
else
/* switch between 2/4 bytes */
c
->
ad_bytes
^=
6
;
break
;
case
0x2e
:
/* CS override */
c
->
override_base
=
&
ctxt
->
cs_base
;
break
;
case
0x3e
:
/* DS override */
c
->
override_base
=
&
ctxt
->
ds_base
;
break
;
case
0x26
:
/* ES override */
c
->
override_base
=
&
ctxt
->
es_base
;
break
;
case
0x64
:
/* FS override */
c
->
override_base
=
&
ctxt
->
fs_base
;
break
;
case
0x65
:
/* GS override */
c
->
override_base
=
&
ctxt
->
gs_base
;
break
;
case
0x36
:
/* SS override */
c
->
override_base
=
&
ctxt
->
ss_base
;
break
;
case
0x40
...
0x4f
:
/* REX */
if
(
mode
!=
X86EMUL_MODE_PROT64
)
goto
done_prefixes
;
c
->
rex_prefix
=
c
->
b
;
continue
;
case
0xf0
:
/* LOCK */
c
->
lock_prefix
=
1
;
break
;
case
0xf2
:
/* REPNE/REPNZ */
case
0xf3
:
/* REP/REPE/REPZ */
c
->
rep_prefix
=
1
;
break
;
default:
goto
done_prefixes
;
}
/* Any legacy prefix after a REX prefix nullifies its effect. */
c
->
rex_prefix
=
0
;
}
done_prefixes:
/* REX prefix. */
if
(
c
->
rex_prefix
)
{
if
(
c
->
rex_prefix
&
8
)
c
->
op_bytes
=
8
;
/* REX.W */
c
->
modrm_reg
=
(
c
->
rex_prefix
&
4
)
<<
1
;
/* REX.R */
index_reg
=
(
c
->
rex_prefix
&
2
)
<<
2
;
/* REX.X */
c
->
modrm_rm
=
base_reg
=
(
c
->
rex_prefix
&
1
)
<<
3
;
/* REG.B */
}
/* Opcode byte(s). */
c
->
d
=
opcode_table
[
c
->
b
];
if
(
c
->
d
==
0
)
{
/* Two-byte opcode? */
if
(
c
->
b
==
0x0f
)
{
c
->
twobyte
=
1
;
c
->
b
=
insn_fetch
(
u8
,
1
,
c
->
eip
);
c
->
d
=
twobyte_table
[
c
->
b
];
}
/* Unrecognised? */
if
(
c
->
d
==
0
)
{
DPRINTF
(
"Cannot emulate %02x
\n
"
,
c
->
b
);
return
-
1
;
}
}
/* ModRM and SIB bytes. */
if
(
c
->
d
&
ModRM
)
{
c
->
modrm
=
insn_fetch
(
u8
,
1
,
c
->
eip
);
c
->
modrm_mod
|=
(
c
->
modrm
&
0xc0
)
>>
6
;
c
->
modrm_reg
|=
(
c
->
modrm
&
0x38
)
>>
3
;
...
...
@@ -674,7 +572,7 @@ done_prefixes:
if
(
c
->
modrm_mod
==
3
)
{
c
->
modrm_val
=
*
(
unsigned
long
*
)
decode_register
(
c
->
modrm_rm
,
c
->
regs
,
c
->
d
&
ByteOp
);
goto
modrm_done
;
return
rc
;
}
if
(
c
->
ad_bytes
==
2
)
{
...
...
@@ -687,8 +585,7 @@ done_prefixes:
switch
(
c
->
modrm_mod
)
{
case
0
:
if
(
c
->
modrm_rm
==
6
)
c
->
modrm_ea
+=
insn_fetch
(
u16
,
2
,
c
->
eip
);
c
->
modrm_ea
+=
insn_fetch
(
u16
,
2
,
c
->
eip
);
break
;
case
1
:
c
->
modrm_ea
+=
insn_fetch
(
s8
,
1
,
c
->
eip
);
...
...
@@ -742,8 +639,7 @@ done_prefixes:
switch
(
base_reg
)
{
case
5
:
if
(
c
->
modrm_mod
!=
0
)
c
->
modrm_ea
+=
c
->
regs
[
base_reg
];
c
->
modrm_ea
+=
c
->
regs
[
base_reg
];
else
c
->
modrm_ea
+=
insn_fetch
(
s32
,
4
,
c
->
eip
);
...
...
@@ -755,15 +651,13 @@ done_prefixes:
case
4
:
break
;
default:
c
->
modrm_ea
+=
c
->
regs
[
index_reg
]
<<
scale
;
c
->
modrm_ea
+=
c
->
regs
[
index_reg
]
<<
scale
;
}
break
;
case
5
:
if
(
c
->
modrm_mod
!=
0
)
c
->
modrm_ea
+=
c
->
regs
[
c
->
modrm_rm
];
else
if
(
mode
==
X86EMUL_MODE_PROT64
)
else
if
(
ctxt
->
mode
==
X86EMUL_MODE_PROT64
)
rip_relative
=
1
;
break
;
default:
...
...
@@ -773,8 +667,7 @@ done_prefixes:
switch
(
c
->
modrm_mod
)
{
case
0
:
if
(
c
->
modrm_rm
==
5
)
c
->
modrm_ea
+=
insn_fetch
(
s32
,
4
,
c
->
eip
);
c
->
modrm_ea
+=
insn_fetch
(
s32
,
4
,
c
->
eip
);
break
;
case
1
:
c
->
modrm_ea
+=
insn_fetch
(
s8
,
1
,
c
->
eip
);
...
...
@@ -800,9 +693,16 @@ done_prefixes:
c
->
modrm_ea
+=
c
->
op_bytes
;
}
}
modrm_done:
;
}
else
if
(
c
->
d
&
MemAbs
)
{
done:
return
rc
;
}
static
int
decode_abs
(
struct
x86_emulate_ctxt
*
ctxt
,
struct
x86_emulate_ops
*
ops
)
{
struct
decode_cache
*
c
=
&
ctxt
->
decode
;
int
rc
=
0
;
switch
(
c
->
ad_bytes
)
{
case
2
:
c
->
modrm_ea
=
insn_fetch
(
u16
,
2
,
c
->
eip
);
...
...
@@ -814,9 +714,126 @@ modrm_done:
c
->
modrm_ea
=
insn_fetch
(
u64
,
8
,
c
->
eip
);
break
;
}
done:
return
rc
;
}
int
x86_decode_insn
(
struct
x86_emulate_ctxt
*
ctxt
,
struct
x86_emulate_ops
*
ops
)
{
struct
decode_cache
*
c
=
&
ctxt
->
decode
;
int
rc
=
0
;
int
mode
=
ctxt
->
mode
;
/* Shadow copy of register state. Committed on successful emulation. */
memset
(
c
,
0
,
sizeof
(
struct
decode_cache
));
c
->
eip
=
ctxt
->
vcpu
->
rip
;
memcpy
(
c
->
regs
,
ctxt
->
vcpu
->
regs
,
sizeof
c
->
regs
);
switch
(
mode
)
{
case
X86EMUL_MODE_REAL
:
case
X86EMUL_MODE_PROT16
:
c
->
op_bytes
=
c
->
ad_bytes
=
2
;
break
;
case
X86EMUL_MODE_PROT32
:
c
->
op_bytes
=
c
->
ad_bytes
=
4
;
break
;
#ifdef CONFIG_X86_64
case
X86EMUL_MODE_PROT64
:
c
->
op_bytes
=
4
;
c
->
ad_bytes
=
8
;
break
;
#endif
default:
return
-
1
;
}
/* Legacy prefixes. */
for
(;;)
{
switch
(
c
->
b
=
insn_fetch
(
u8
,
1
,
c
->
eip
))
{
case
0x66
:
/* operand-size override */
c
->
op_bytes
^=
6
;
/* switch between 2/4 bytes */
break
;
case
0x67
:
/* address-size override */
if
(
mode
==
X86EMUL_MODE_PROT64
)
/* switch between 4/8 bytes */
c
->
ad_bytes
^=
12
;
else
/* switch between 2/4 bytes */
c
->
ad_bytes
^=
6
;
break
;
case
0x2e
:
/* CS override */
c
->
override_base
=
&
ctxt
->
cs_base
;
break
;
case
0x3e
:
/* DS override */
c
->
override_base
=
&
ctxt
->
ds_base
;
break
;
case
0x26
:
/* ES override */
c
->
override_base
=
&
ctxt
->
es_base
;
break
;
case
0x64
:
/* FS override */
c
->
override_base
=
&
ctxt
->
fs_base
;
break
;
case
0x65
:
/* GS override */
c
->
override_base
=
&
ctxt
->
gs_base
;
break
;
case
0x36
:
/* SS override */
c
->
override_base
=
&
ctxt
->
ss_base
;
break
;
case
0x40
...
0x4f
:
/* REX */
if
(
mode
!=
X86EMUL_MODE_PROT64
)
goto
done_prefixes
;
c
->
rex_prefix
=
c
->
b
;
continue
;
case
0xf0
:
/* LOCK */
c
->
lock_prefix
=
1
;
break
;
case
0xf2
:
/* REPNE/REPNZ */
case
0xf3
:
/* REP/REPE/REPZ */
c
->
rep_prefix
=
1
;
break
;
default:
goto
done_prefixes
;
}
/* Any legacy prefix after a REX prefix nullifies its effect. */
c
->
rex_prefix
=
0
;
}
done_prefixes:
/* REX prefix. */
if
(
c
->
rex_prefix
)
if
(
c
->
rex_prefix
&
8
)
c
->
op_bytes
=
8
;
/* REX.W */
/* Opcode byte(s). */
c
->
d
=
opcode_table
[
c
->
b
];
if
(
c
->
d
==
0
)
{
/* Two-byte opcode? */
if
(
c
->
b
==
0x0f
)
{
c
->
twobyte
=
1
;
c
->
b
=
insn_fetch
(
u8
,
1
,
c
->
eip
);
c
->
d
=
twobyte_table
[
c
->
b
];
}
/* Unrecognised? */
if
(
c
->
d
==
0
)
{
DPRINTF
(
"Cannot emulate %02x
\n
"
,
c
->
b
);
return
-
1
;
}
}
/* ModRM and SIB bytes. */
if
(
c
->
d
&
ModRM
)
rc
=
decode_modrm
(
ctxt
,
ops
);
else
if
(
c
->
d
&
MemAbs
)
rc
=
decode_abs
(
ctxt
,
ops
);
if
(
rc
)
goto
done
;
if
(
!
c
->
override_base
)
c
->
override_base
=
&
ctxt
->
ds_base
;
if
(
mode
==
X86EMUL_MODE_PROT64
&&
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment