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
Hide 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,14 +548,182 @@ static void decode_register_operand(struct operand *op,
op
->
orig_val
=
op
->
val
;
}
static
int
decode_modrm
(
struct
x86_emulate_ctxt
*
ctxt
,
struct
x86_emulate_ops
*
ops
)
{
struct
decode_cache
*
c
=
&
ctxt
->
decode
;
u8
sib
;
int
index_reg
=
0
,
base_reg
=
0
,
scale
,
rip_relative
=
0
;
int
rc
=
0
;
if
(
c
->
rex_prefix
)
{
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 */
}
c
->
modrm
=
insn_fetch
(
u8
,
1
,
c
->
eip
);
c
->
modrm_mod
|=
(
c
->
modrm
&
0xc0
)
>>
6
;
c
->
modrm_reg
|=
(
c
->
modrm
&
0x38
)
>>
3
;
c
->
modrm_rm
|=
(
c
->
modrm
&
0x07
);
c
->
modrm_ea
=
0
;
c
->
use_modrm_ea
=
1
;
if
(
c
->
modrm_mod
==
3
)
{
c
->
modrm_val
=
*
(
unsigned
long
*
)
decode_register
(
c
->
modrm_rm
,
c
->
regs
,
c
->
d
&
ByteOp
);
return
rc
;
}
if
(
c
->
ad_bytes
==
2
)
{
unsigned
bx
=
c
->
regs
[
VCPU_REGS_RBX
];
unsigned
bp
=
c
->
regs
[
VCPU_REGS_RBP
];
unsigned
si
=
c
->
regs
[
VCPU_REGS_RSI
];
unsigned
di
=
c
->
regs
[
VCPU_REGS_RDI
];
/* 16-bit ModR/M decode. */
switch
(
c
->
modrm_mod
)
{
case
0
:
if
(
c
->
modrm_rm
==
6
)
c
->
modrm_ea
+=
insn_fetch
(
u16
,
2
,
c
->
eip
);
break
;
case
1
:
c
->
modrm_ea
+=
insn_fetch
(
s8
,
1
,
c
->
eip
);
break
;
case
2
:
c
->
modrm_ea
+=
insn_fetch
(
u16
,
2
,
c
->
eip
);
break
;
}
switch
(
c
->
modrm_rm
)
{
case
0
:
c
->
modrm_ea
+=
bx
+
si
;
break
;
case
1
:
c
->
modrm_ea
+=
bx
+
di
;
break
;
case
2
:
c
->
modrm_ea
+=
bp
+
si
;
break
;
case
3
:
c
->
modrm_ea
+=
bp
+
di
;
break
;
case
4
:
c
->
modrm_ea
+=
si
;
break
;
case
5
:
c
->
modrm_ea
+=
di
;
break
;
case
6
:
if
(
c
->
modrm_mod
!=
0
)
c
->
modrm_ea
+=
bp
;
break
;
case
7
:
c
->
modrm_ea
+=
bx
;
break
;
}
if
(
c
->
modrm_rm
==
2
||
c
->
modrm_rm
==
3
||
(
c
->
modrm_rm
==
6
&&
c
->
modrm_mod
!=
0
))
if
(
!
c
->
override_base
)
c
->
override_base
=
&
ctxt
->
ss_base
;
c
->
modrm_ea
=
(
u16
)
c
->
modrm_ea
;
}
else
{
/* 32/64-bit ModR/M decode. */
switch
(
c
->
modrm_rm
)
{
case
4
:
case
12
:
sib
=
insn_fetch
(
u8
,
1
,
c
->
eip
);
index_reg
|=
(
sib
>>
3
)
&
7
;
base_reg
|=
sib
&
7
;
scale
=
sib
>>
6
;
switch
(
base_reg
)
{
case
5
:
if
(
c
->
modrm_mod
!=
0
)
c
->
modrm_ea
+=
c
->
regs
[
base_reg
];
else
c
->
modrm_ea
+=
insn_fetch
(
s32
,
4
,
c
->
eip
);
break
;
default:
c
->
modrm_ea
+=
c
->
regs
[
base_reg
];
}
switch
(
index_reg
)
{
case
4
:
break
;
default:
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
(
ctxt
->
mode
==
X86EMUL_MODE_PROT64
)
rip_relative
=
1
;
break
;
default:
c
->
modrm_ea
+=
c
->
regs
[
c
->
modrm_rm
];
break
;
}
switch
(
c
->
modrm_mod
)
{
case
0
:
if
(
c
->
modrm_rm
==
5
)
c
->
modrm_ea
+=
insn_fetch
(
s32
,
4
,
c
->
eip
);
break
;
case
1
:
c
->
modrm_ea
+=
insn_fetch
(
s8
,
1
,
c
->
eip
);
break
;
case
2
:
c
->
modrm_ea
+=
insn_fetch
(
s32
,
4
,
c
->
eip
);
break
;
}
}
if
(
rip_relative
)
{
c
->
modrm_ea
+=
c
->
eip
;
switch
(
c
->
d
&
SrcMask
)
{
case
SrcImmByte
:
c
->
modrm_ea
+=
1
;
break
;
case
SrcImm
:
if
(
c
->
d
&
ByteOp
)
c
->
modrm_ea
+=
1
;
else
if
(
c
->
op_bytes
==
8
)
c
->
modrm_ea
+=
4
;
else
c
->
modrm_ea
+=
c
->
op_bytes
;
}
}
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
);
break
;
case
4
:
c
->
modrm_ea
=
insn_fetch
(
u32
,
4
,
c
->
eip
);
break
;
case
8
:
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
;
u8
sib
;
int
rc
=
0
;
int
mode
=
ctxt
->
mode
;
int
index_reg
=
0
,
base_reg
=
0
,
scale
,
rip_relative
=
0
;
/* Shadow copy of register state. Committed on successful emulation. */
...
...
@@ -637,13 +805,9 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
done_prefixes:
/* REX prefix. */
if
(
c
->
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
];
...
...
@@ -663,159 +827,12 @@ done_prefixes:
}
/* 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
;
c
->
modrm_rm
|=
(
c
->
modrm
&
0x07
);
c
->
modrm_ea
=
0
;
c
->
use_modrm_ea
=
1
;
if
(
c
->
modrm_mod
==
3
)
{
c
->
modrm_val
=
*
(
unsigned
long
*
)
decode_register
(
c
->
modrm_rm
,
c
->
regs
,
c
->
d
&
ByteOp
);
goto
modrm_done
;
}
if
(
c
->
ad_bytes
==
2
)
{
unsigned
bx
=
c
->
regs
[
VCPU_REGS_RBX
];
unsigned
bp
=
c
->
regs
[
VCPU_REGS_RBP
];
unsigned
si
=
c
->
regs
[
VCPU_REGS_RSI
];
unsigned
di
=
c
->
regs
[
VCPU_REGS_RDI
];
/* 16-bit ModR/M decode. */
switch
(
c
->
modrm_mod
)
{
case
0
:
if
(
c
->
modrm_rm
==
6
)
c
->
modrm_ea
+=
insn_fetch
(
u16
,
2
,
c
->
eip
);
break
;
case
1
:
c
->
modrm_ea
+=
insn_fetch
(
s8
,
1
,
c
->
eip
);
break
;
case
2
:
c
->
modrm_ea
+=
insn_fetch
(
u16
,
2
,
c
->
eip
);
break
;
}
switch
(
c
->
modrm_rm
)
{
case
0
:
c
->
modrm_ea
+=
bx
+
si
;
break
;
case
1
:
c
->
modrm_ea
+=
bx
+
di
;
break
;
case
2
:
c
->
modrm_ea
+=
bp
+
si
;
break
;
case
3
:
c
->
modrm_ea
+=
bp
+
di
;
break
;
case
4
:
c
->
modrm_ea
+=
si
;
break
;
case
5
:
c
->
modrm_ea
+=
di
;
break
;
case
6
:
if
(
c
->
modrm_mod
!=
0
)
c
->
modrm_ea
+=
bp
;
break
;
case
7
:
c
->
modrm_ea
+=
bx
;
break
;
}
if
(
c
->
modrm_rm
==
2
||
c
->
modrm_rm
==
3
||
(
c
->
modrm_rm
==
6
&&
c
->
modrm_mod
!=
0
))
if
(
!
c
->
override_base
)
c
->
override_base
=
&
ctxt
->
ss_base
;
c
->
modrm_ea
=
(
u16
)
c
->
modrm_ea
;
}
else
{
/* 32/64-bit ModR/M decode. */
switch
(
c
->
modrm_rm
)
{
case
4
:
case
12
:
sib
=
insn_fetch
(
u8
,
1
,
c
->
eip
);
index_reg
|=
(
sib
>>
3
)
&
7
;
base_reg
|=
sib
&
7
;
scale
=
sib
>>
6
;
switch
(
base_reg
)
{
case
5
:
if
(
c
->
modrm_mod
!=
0
)
c
->
modrm_ea
+=
c
->
regs
[
base_reg
];
else
c
->
modrm_ea
+=
insn_fetch
(
s32
,
4
,
c
->
eip
);
break
;
default:
c
->
modrm_ea
+=
c
->
regs
[
base_reg
];
}
switch
(
index_reg
)
{
case
4
:
break
;
default:
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
)
rip_relative
=
1
;
break
;
default:
c
->
modrm_ea
+=
c
->
regs
[
c
->
modrm_rm
];
break
;
}
switch
(
c
->
modrm_mod
)
{
case
0
:
if
(
c
->
modrm_rm
==
5
)
c
->
modrm_ea
+=
insn_fetch
(
s32
,
4
,
c
->
eip
);
break
;
case
1
:
c
->
modrm_ea
+=
insn_fetch
(
s8
,
1
,
c
->
eip
);
break
;
case
2
:
c
->
modrm_ea
+=
insn_fetch
(
s32
,
4
,
c
->
eip
);
break
;
}
}
if
(
rip_relative
)
{
c
->
modrm_ea
+=
c
->
eip
;
switch
(
c
->
d
&
SrcMask
)
{
case
SrcImmByte
:
c
->
modrm_ea
+=
1
;
break
;
case
SrcImm
:
if
(
c
->
d
&
ByteOp
)
c
->
modrm_ea
+=
1
;
else
if
(
c
->
op_bytes
==
8
)
c
->
modrm_ea
+=
4
;
else
c
->
modrm_ea
+=
c
->
op_bytes
;
}
}
modrm_done:
;
}
else
if
(
c
->
d
&
MemAbs
)
{
switch
(
c
->
ad_bytes
)
{
case
2
:
c
->
modrm_ea
=
insn_fetch
(
u16
,
2
,
c
->
eip
);
break
;
case
4
:
c
->
modrm_ea
=
insn_fetch
(
u32
,
4
,
c
->
eip
);
break
;
case
8
:
c
->
modrm_ea
=
insn_fetch
(
u64
,
8
,
c
->
eip
);
break
;
}
}
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
;
...
...
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