Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
recolic-hust
hust-x86-simulator
Commits
211e6d2c
Commit
211e6d2c
authored
Dec 27, 2019
by
Recolic Keghart
Browse files
Merge branch 'reconstruct-helpers' into 'pa2'
Reconstruct helpers See merge request
!1
parents
3949ce4c
f6760515
Changes
15
Hide whitespace changes
Inline
Side-by-side
nemu/include/cpu/decode.h
View file @
211e6d2c
...
...
@@ -75,47 +75,48 @@ extern DecodeInfo decoding;
#define id_src2 (&decoding.src2)
#define id_dest (&decoding.dest)
#define make_DHelper_funcname(name) concat(decode_, name)
#define make_DHelper(name) void make_DHelper_funcname(name) (vaddr_t *eip)
#define make_DHelper(name) void name (vaddr_t *eip)
typedef
void
(
*
DHelper
)
(
vaddr_t
*
);
make_DHelper
(
I2E
);
make_DHelper
(
I2a
);
make_DHelper
(
I2r
);
make_DHelper
(
SI2E
);
make_DHelper
(
SI_E2G
);
make_DHelper
(
I_E2G
);
make_DHelper
(
I_G2E
);
make_DHelper
(
I
);
make_DHelper
(
r
);
make_DHelper
(
E
);
make_DHelper
(
setcc_E
);
make_DHelper
(
gp7_E
);
make_DHelper
(
test_I
);
make_DHelper
(
SI
);
make_DHelper
(
G2E
);
make_DHelper
(
E2G
);
make_DHelper
(
mov_I2r
);
make_DHelper
(
mov_I2E
);
make_DHelper
(
mov_G2E
);
make_DHelper
(
mov_E2G
);
make_DHelper
(
lea_M2G
);
make_DHelper
(
gp2_1_E
);
make_DHelper
(
gp2_cl2E
);
make_DHelper
(
gp2_Ib2E
);
make_DHelper
(
O2a
);
make_DHelper
(
a2O
);
make_DHelper
(
J
);
make_DHelper
(
push_SI
);
make_DHelper
(
in_I2a
);
make_DHelper
(
in_dx2a
);
make_DHelper
(
out_a2I
);
make_DHelper
(
out_a2dx
);
namespace
DHelperImpl
{
make_DHelper
(
I2E
);
make_DHelper
(
I2a
);
make_DHelper
(
I2r
);
make_DHelper
(
SI2E
);
make_DHelper
(
SI_E2G
);
make_DHelper
(
I_E2G
);
make_DHelper
(
I_G2E
);
make_DHelper
(
I
);
make_DHelper
(
r
);
make_DHelper
(
E
);
make_DHelper
(
setcc_E
);
make_DHelper
(
gp7_E
);
make_DHelper
(
test_I
);
make_DHelper
(
SI
);
make_DHelper
(
G2E
);
make_DHelper
(
E2G
);
make_DHelper
(
mov_I2r
);
make_DHelper
(
mov_I2E
);
make_DHelper
(
mov_G2E
);
make_DHelper
(
mov_E2G
);
make_DHelper
(
lea_M2G
);
make_DHelper
(
gp2_1_E
);
make_DHelper
(
gp2_cl2E
);
make_DHelper
(
gp2_Ib2E
);
make_DHelper
(
O2a
);
make_DHelper
(
a2O
);
make_DHelper
(
J
);
make_DHelper
(
push_SI
);
make_DHelper
(
in_I2a
);
make_DHelper
(
in_dx2a
);
make_DHelper
(
out_a2I
);
make_DHelper
(
out_a2dx
);
}
#endif
nemu/include/cpu/exec.h
View file @
211e6d2c
...
...
@@ -3,8 +3,7 @@
#include
"nemu.h"
#define make_EHelper_funcname(name) concat(exec_, name)
#define make_EHelper(name) void make_EHelper_funcname(name) (vaddr_t *eip)
#define make_EHelper(name) void name(vaddr_t *eip)
typedef
void
(
*
EHelper
)
(
vaddr_t
*
);
#include
"cpu/decode.h"
...
...
nemu/include/cpu/rtl.h
View file @
211e6d2c
...
...
@@ -217,7 +217,7 @@ static inline void rtl_update_ZF(const rtlreg_t* result, int width) {
// eflags.ZF <- is_zero(result[width * 8 - 1 .. 0])
RLIB_MACRO_DEBUG_ASSERT
((
unsigned
)
width
<
5
);
static
const
uint32_t
niddles
[
5
]
{
0
,
0x000000ff
,
0x0000ffff
,
0x00ffffff
,
0xffffffff
};
cpu_eflags
::
get
<
cpu_eflags
::
ZF
>
()
=
(
*
result
&
niddles
[
width
]);
cpu_eflags
::
get
<
cpu_eflags
::
ZF
>
()
=
!
(
*
result
&
niddles
[
width
]);
}
static
inline
void
rtl_update_SF
(
const
rtlreg_t
*
result
,
int
width
)
{
...
...
nemu/src/cpu/decode/decode.cc
View file @
211e6d2c
...
...
@@ -9,320 +9,327 @@ void decoding_set_jmp(bool is_jmp) {
decoding
.
is_jmp
=
is_jmp
;
}
#define make_DopHelper_funcname(name) concat(decode_op_, name)
#define make_DopHelper(name) void make_DopHelper_funcname(name) (vaddr_t *eip, Operand *op, bool load_val)
/* Refer to Appendix A in i386 manual for the explanations of these abbreviations */
/* Ib, Iv */
static
inline
make_DopHelper
(
I
)
{
/* eip here is pointing to the immediate */
op
->
type
=
OP_TYPE_IMM
;
op
->
imm
=
instr_fetch
(
eip
,
op
->
width
);
rtl_li
(
&
op
->
val
,
op
->
imm
);
#ifdef DEBUG
snprintf
(
op
->
str
,
OP_STR_SIZE
,
"$0x%x"
,
op
->
imm
);
#endif
}
/* I386 manual does not contain this abbreviation, but it is different from
* the one above from the view of implementation. So we use another helper
* function to decode it.
*/
/* sign immediate */
static
inline
make_DopHelper
(
SI
)
{
assert
(
op
->
width
==
1
||
op
->
width
==
4
);
op
->
type
=
OP_TYPE_IMM
;
/* TODO: Use instr_fetch() to read `op->width' bytes of memory
* pointed by `eip'. Interpret the result as a signed immediate,
* and assign it to op->simm.
*
op->simm = ???
#define make_DopHelper_funcname(name) DopHelperImpl::name
#define make_DopHelper(name) void name (vaddr_t *eip, Operand *op, bool load_val)
namespace
DopHelperImpl
{
/* Refer to Appendix A in i386 manual for the explanations of these abbreviations */
/* Ib, Iv */
static
inline
make_DopHelper
(
I
)
{
/* eip here is pointing to the immediate */
op
->
type
=
OP_TYPE_IMM
;
op
->
imm
=
instr_fetch
(
eip
,
op
->
width
);
rtl_li
(
&
op
->
val
,
op
->
imm
);
#ifdef DEBUG
snprintf
(
op
->
str
,
OP_STR_SIZE
,
"$0x%x"
,
op
->
imm
);
#endif
}
/* I386 manual does not contain this abbreviation, but it is different from
* the one above from the view of implementation. So we use another helper
* function to decode it.
*/
op
->
simm
=
instr_fetch
(
eip
,
op
->
width
);
rtl_li
(
&
op
->
val
,
op
->
simm
);
#ifdef DEBUG
snprintf
(
op
->
str
,
OP_STR_SIZE
,
"$0x%x"
,
op
->
simm
);
#endif
}
/* I386 manual does not contain this abbreviation.
* It is convenient to merge them into a single helper function.
*/
/* AL/eAX */
static
inline
make_DopHelper
(
a
)
{
op
->
type
=
OP_TYPE_REG
;
op
->
reg
=
R_EAX
;
if
(
load_val
)
{
rtl_lr
(
&
op
->
val
,
R_EAX
,
op
->
width
);
/* sign immediate */
static
inline
make_DopHelper
(
SI
)
{
assert
(
op
->
width
==
1
||
op
->
width
==
4
);
op
->
type
=
OP_TYPE_IMM
;
/* TODO: Use instr_fetch() to read `op->width' bytes of memory
* pointed by `eip'. Interpret the result as a signed immediate,
* and assign it to op->simm.
*
op->simm = ???
*/
op
->
simm
=
instr_fetch
(
eip
,
op
->
width
);
rtl_li
(
&
op
->
val
,
op
->
simm
);
#ifdef DEBUG
snprintf
(
op
->
str
,
OP_STR_SIZE
,
"$0x%x"
,
op
->
simm
);
#endif
}
#ifdef DEBUG
snprintf
(
op
->
str
,
OP_STR_SIZE
,
"%%%s"
,
reg_name
(
R_EAX
,
op
->
width
));
#endif
}
/* This helper function is use to decode register encoded in the opcode. */
/* XX: AL, AH, BL, BH, CL, CH, DL, DH
* eXX: eAX, eCX, eDX, eBX, eSP, eBP, eSI, eDI
*/
static
inline
make_DopHelper
(
r
)
{
op
->
type
=
OP_TYPE_REG
;
op
->
reg
=
decoding
.
opcode
&
0x7
;
if
(
load_val
)
{
rtl_lr
(
&
op
->
val
,
op
->
reg
,
op
->
width
);
/* I386 manual does not contain this abbreviation.
* It is convenient to merge them into a single helper function.
*/
/* AL/eAX */
static
inline
make_DopHelper
(
a
)
{
op
->
type
=
OP_TYPE_REG
;
op
->
reg
=
R_EAX
;
if
(
load_val
)
{
rtl_lr
(
&
op
->
val
,
R_EAX
,
op
->
width
);
}
#ifdef DEBUG
snprintf
(
op
->
str
,
OP_STR_SIZE
,
"%%%s"
,
reg_name
(
R_EAX
,
op
->
width
));
#endif
}
#ifdef DEBUG
snprintf
(
op
->
str
,
OP_STR_SIZE
,
"%%%s"
,
reg_name
(
op
->
reg
,
op
->
width
));
#endif
}
/* I386 manual does not contain this abbreviation.
* We decode everything of modR/M byte by one time.
*/
/* Eb, Ew, Ev
* Gb, Gv
* Cd,
* M
* Rd
* Sw
*/
static
inline
void
make_DopHelper_funcname
(
rm
)(
vaddr_t
*
eip
,
Operand
*
rm
,
bool
load_rm_val
,
Operand
*
reg
,
bool
load_reg_val
)
{
read_ModR_M
(
eip
,
rm
,
load_rm_val
,
reg
,
load_reg_val
);
}
/* Ob, Ov */
static
inline
make_DopHelper
(
O
)
{
op
->
type
=
OP_TYPE_MEM
;
rtl_li
(
&
op
->
addr
,
instr_fetch
(
eip
,
4
));
if
(
load_val
)
{
rtl_lm
(
&
op
->
val
,
&
op
->
addr
,
op
->
width
);
/* This helper function is use to decode register encoded in the opcode. */
/* XX: AL, AH, BL, BH, CL, CH, DL, DH
* eXX: eAX, eCX, eDX, eBX, eSP, eBP, eSI, eDI
*/
static
inline
make_DopHelper
(
r
)
{
op
->
type
=
OP_TYPE_REG
;
op
->
reg
=
decoding
.
opcode
&
0x7
;
if
(
load_val
)
{
rtl_lr
(
&
op
->
val
,
op
->
reg
,
op
->
width
);
}
#ifdef DEBUG
snprintf
(
op
->
str
,
OP_STR_SIZE
,
"%%%s"
,
reg_name
(
op
->
reg
,
op
->
width
));
#endif
}
#ifdef DEBUG
snprintf
(
op
->
str
,
OP_STR_SIZE
,
"0x%x"
,
op
->
addr
);
#endif
}
/* Eb <- Gb
* Ev <- Gv
*/
make_DHelper
(
G2E
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_dest
,
true
,
id_src
,
true
);
}
make_DHelper
(
mov_G2E
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_dest
,
false
,
id_src
,
true
);
}
/* Gb <- Eb
* Gv <- Ev
*/
make_DHelper
(
E2G
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_src
,
true
,
id_dest
,
true
);
}
make_DHelper
(
mov_E2G
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_src
,
true
,
id_dest
,
false
);
}
make_DHelper
(
lea_M2G
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_src
,
false
,
id_dest
,
false
);
}
/* AL <- Ib
* eAX <- Iv
*/
make_DHelper
(
I2a
)
{
make_DopHelper_funcname
(
a
)(
eip
,
id_dest
,
true
);
make_DopHelper_funcname
(
I
)(
eip
,
id_src
,
true
);
}
/* Gv <- EvIb
* Gv <- EvIv
* use for imul */
make_DHelper
(
I_E2G
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_src2
,
true
,
id_dest
,
false
);
make_DopHelper_funcname
(
I
)(
eip
,
id_src
,
true
);
}
/* Eb <- Ib
* Ev <- Iv
*/
make_DHelper
(
I2E
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_dest
,
true
,
NULL
,
false
);
make_DopHelper_funcname
(
I
)(
eip
,
id_src
,
true
);
}
make_DHelper
(
mov_I2E
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_dest
,
false
,
NULL
,
false
);
make_DopHelper_funcname
(
I
)(
eip
,
id_src
,
true
);
}
/* XX <- Ib
* eXX <- Iv
*/
make_DHelper
(
I2r
)
{
make_DopHelper_funcname
(
r
)(
eip
,
id_dest
,
true
);
make_DopHelper_funcname
(
I
)(
eip
,
id_src
,
true
);
}
make_DHelper
(
mov_I2r
)
{
make_DopHelper_funcname
(
r
)(
eip
,
id_dest
,
false
);
make_DopHelper_funcname
(
I
)(
eip
,
id_src
,
true
);
}
/* used by unary operations */
make_DHelper
(
I
)
{
make_DopHelper_funcname
(
I
)(
eip
,
id_dest
,
true
);
}
make_DHelper
(
r
)
{
make_DopHelper_funcname
(
r
)(
eip
,
id_dest
,
true
);
}
make_DHelper
(
E
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_dest
,
true
,
NULL
,
false
);
}
make_DHelper
(
setcc_E
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_dest
,
false
,
NULL
,
false
);
}
make_DHelper
(
gp7_E
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_dest
,
false
,
NULL
,
false
);
}
/* used by test in group3 */
make_DHelper
(
test_I
)
{
make_DopHelper_funcname
(
I
)(
eip
,
id_src
,
true
);
}
make_DHelper
(
SI2E
)
{
assert
(
id_dest
->
width
==
2
||
id_dest
->
width
==
4
);
make_DopHelper_funcname
(
rm
)(
eip
,
id_dest
,
true
,
NULL
,
false
);
id_src
->
width
=
1
;
make_DopHelper_funcname
(
SI
)(
eip
,
id_src
,
true
);
if
(
id_dest
->
width
==
2
)
{
id_src
->
val
&=
0xffff
;
/* I386 manual does not contain this abbreviation.
* We decode everything of modR/M byte by one time.
*/
/* Eb, Ew, Ev
* Gb, Gv
* Cd,
* M
* Rd
* Sw
*/
static
inline
void
rm
(
vaddr_t
*
eip
,
Operand
*
rm
,
bool
load_rm_val
,
Operand
*
reg
,
bool
load_reg_val
)
{
read_ModR_M
(
eip
,
rm
,
load_rm_val
,
reg
,
load_reg_val
);
}
}
make_DHelper
(
SI_E2G
)
{
assert
(
id_dest
->
width
==
2
||
id_dest
->
width
==
4
);
make_DopHelper_funcname
(
rm
)(
eip
,
id_src2
,
true
,
id_dest
,
false
);
id_src
->
width
=
1
;
make_DopHelper_funcname
(
SI
)(
eip
,
id_src
,
true
);
if
(
id_dest
->
width
==
2
)
{
id_src
->
val
&=
0xffff
;
/* Ob, Ov */
static
inline
make_DopHelper
(
O
)
{
op
->
type
=
OP_TYPE_MEM
;
rtl_li
(
&
op
->
addr
,
instr_fetch
(
eip
,
4
));
if
(
load_val
)
{
rtl_lm
(
&
op
->
val
,
&
op
->
addr
,
op
->
width
);
}
#ifdef DEBUG
snprintf
(
op
->
str
,
OP_STR_SIZE
,
"0x%x"
,
op
->
addr
);
#endif
}
}
}
// end namespace DopHelperImpl
make_DHelper
(
gp2_1_E
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_dest
,
true
,
NULL
,
false
);
id_src
->
type
=
OP_TYPE_IMM
;
id_src
->
imm
=
1
;
rtl_li
(
&
id_src
->
val
,
1
);
#ifdef DEBUG
sprintf
(
id_src
->
str
,
"$1"
);
#endif
}
make_DHelper
(
gp2_cl2E
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_dest
,
true
,
NULL
,
false
);
id_src
->
type
=
OP_TYPE_REG
;
id_src
->
reg
=
R_CL
;
rtl_lr
(
&
id_src
->
val
,
R_CL
,
1
);
#ifdef DEBUG
sprintf
(
id_src
->
str
,
"%%cl"
);
#endif
}
make_DHelper
(
gp2_Ib2E
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_dest
,
true
,
NULL
,
false
);
id_src
->
width
=
1
;
make_DopHelper_funcname
(
I
)(
eip
,
id_src
,
true
);
}
/* Ev <- GvIb
* use for shld/shrd */
make_DHelper
(
Ib_G2E
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_dest
,
true
,
id_src2
,
true
);
id_src
->
width
=
1
;
make_DopHelper_funcname
(
I
)(
eip
,
id_src
,
true
);
}
/* Ev <- GvCL
* use for shld/shrd */
make_DHelper
(
cl_G2E
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_dest
,
true
,
id_src2
,
true
);
id_src
->
type
=
OP_TYPE_REG
;
id_src
->
reg
=
R_CL
;
rtl_lr
(
&
id_src
->
val
,
R_CL
,
1
);
#ifdef DEBUG
sprintf
(
id_src
->
str
,
"%%cl"
);
#endif
}
make_DHelper
(
O2a
)
{
make_DopHelper_funcname
(
O
)(
eip
,
id_src
,
true
);
make_DopHelper_funcname
(
a
)(
eip
,
id_dest
,
false
);
}
make_DHelper
(
a2O
)
{
make_DopHelper_funcname
(
a
)(
eip
,
id_src
,
true
);
make_DopHelper_funcname
(
O
)(
eip
,
id_dest
,
false
);
}
make_DHelper
(
J
)
{
make_DopHelper_funcname
(
SI
)(
eip
,
id_dest
,
false
);
// the target address can be computed in the decode stage
decoding
.
jmp_eip
=
id_dest
->
simm
+
*
eip
;
}
make_DHelper
(
push_SI
)
{
make_DopHelper_funcname
(
SI
)(
eip
,
id_dest
,
true
);
}
make_DHelper
(
in_I2a
)
{
id_src
->
width
=
1
;
make_DopHelper_funcname
(
I
)(
eip
,
id_src
,
true
);
make_DopHelper_funcname
(
a
)(
eip
,
id_dest
,
false
);
}
make_DHelper
(
in_dx2a
)
{
id_src
->
type
=
OP_TYPE_REG
;
id_src
->
reg
=
R_DX
;
rtl_lr
(
&
id_src
->
val
,
R_DX
,
2
);
#ifdef DEBUG
sprintf
(
id_src
->
str
,
"(%%dx)"
);
#endif
make_DopHelper_funcname
(
a
)(
eip
,
id_dest
,
false
);
}
make_DHelper
(
out_a2I
)
{
make_DopHelper_funcname
(
a
)(
eip
,
id_src
,
true
);
id_dest
->
width
=
1
;
make_DopHelper_funcname
(
I
)(
eip
,
id_dest
,
true
);
}
namespace
DHelperImpl
{
make_DHelper
(
out_a2dx
)
{
make_DopHelper_funcname
(
a
)(
eip
,
id_src
,
true
);
id_dest
->
type
=
OP_TYPE_REG
;
id_dest
->
reg
=
R_DX
;
rtl_lr
(
&
id_dest
->
val
,
R_DX
,
2
);
#ifdef DEBUG
sprintf
(
id_dest
->
str
,
"(%%dx)"
);
#endif
}
/* Eb <- Gb
* Ev <- Gv
*/
make_DHelper
(
G2E
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_dest
,
true
,
id_src
,
true
);
}
make_DHelper
(
mov_G2E
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_dest
,
false
,
id_src
,
true
);
}
/* Gb <- Eb
* Gv <- Ev
*/
make_DHelper
(
E2G
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_src
,
true
,
id_dest
,
true
);
}
make_DHelper
(
mov_E2G
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_src
,
true
,
id_dest
,
false
);
}
make_DHelper
(
lea_M2G
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_src
,
false
,
id_dest
,
false
);
}
/* AL <- Ib
* eAX <- Iv
*/
make_DHelper
(
I2a
)
{
make_DopHelper_funcname
(
a
)(
eip
,
id_dest
,
true
);
make_DopHelper_funcname
(
I
)(
eip
,
id_src
,
true
);
}
/* Gv <- EvIb
* Gv <- EvIv
* use for imul */
make_DHelper
(
I_E2G
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_src2
,
true
,
id_dest
,
false
);
make_DopHelper_funcname
(
I
)(
eip
,
id_src
,
true
);
}
/* Eb <- Ib
* Ev <- Iv
*/
make_DHelper
(
I2E
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_dest
,
true
,
NULL
,
false
);
make_DopHelper_funcname
(
I
)(
eip
,
id_src
,
true
);
}
make_DHelper
(
mov_I2E
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_dest
,
false
,
NULL
,
false
);
make_DopHelper_funcname
(
I
)(
eip
,
id_src
,
true
);
}
/* XX <- Ib
* eXX <- Iv
*/
make_DHelper
(
I2r
)
{
make_DopHelper_funcname
(
r
)(
eip
,
id_dest
,
true
);
make_DopHelper_funcname
(
I
)(
eip
,
id_src
,
true
);
}
make_DHelper
(
mov_I2r
)
{
make_DopHelper_funcname
(
r
)(
eip
,
id_dest
,
false
);
make_DopHelper_funcname
(
I
)(
eip
,
id_src
,
true
);
}
/* used by unary operations */
make_DHelper
(
I
)
{
make_DopHelper_funcname
(
I
)(
eip
,
id_dest
,
true
);
}
make_DHelper
(
r
)
{
make_DopHelper_funcname
(
r
)(
eip
,
id_dest
,
true
);
}
make_DHelper
(
E
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_dest
,
true
,
NULL
,
false
);
}
make_DHelper
(
setcc_E
)
{
make_DopHelper_funcname
(
rm
)(
eip
,
id_dest
,
false
,
NULL
,
false
);