Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
qemu
提交
927f621e
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看板
提交
927f621e
编写于
3月 02, 2003
作者:
B
bellard
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
added float support
git-svn-id:
svn://svn.savannah.nongnu.org/qemu/trunk@15
c046a42c-6fe2-441c-8c8c-71466251a162
上级
367e86e8
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
934 addition
and
160 deletion
+934
-160
Makefile
Makefile
+4
-2
TODO
TODO
+1
-0
cpu-i386.h
cpu-i386.h
+51
-0
dyngen.c
dyngen.c
+4
-0
op-i386.c
op-i386.c
+727
-1
translate-i386.c
translate-i386.c
+147
-157
未找到文件。
Makefile
浏览文件 @
927f621e
...
...
@@ -8,6 +8,7 @@ LDFLAGS=-g
LIBS
=
CC
=
gcc
DEFINES
=
-DHAVE_BYTESWAP_H
OP_CFLAGS
=
$(CFLAGS)
-malign-functions
=
0
-mpreferred-stack-boundary
=
2
endif
ifeq
($(ARCH),ppc)
...
...
@@ -24,6 +25,7 @@ CRTEND=$(GCC_LIBS_DIR)/crtend.o
LDFLAGS
=
-static
-g
-nostdlib
$(CRT1)
$(CRTI)
$(CRTBEGIN)
LIBS
=
-L
$(LIBS_DIR)
-ltinyc
-lgcc
$(CRTEND)
$(CRTN)
DEFINES
=
-Dsocklen_t
=
int
OP_CFLAGS
=
$(CFLAGS)
endif
#########################################################
...
...
@@ -31,7 +33,7 @@ endif
DEFINES
+=
-D_GNU_SOURCE
-DGEMU
-DDOSEMU
-DNO_TRACE_MSGS
DEFINES
+=
-DCONFIG_PREFIX
=
\"
/usr/local
\"
LDSCRIPT
=
$(ARCH)
.ld
LIBS
+=
-ldl
LIBS
+=
-ldl
-lm
OBJS
=
i386/fp87.o i386/interp_main.o i386/interp_modrm.o i386/interp_16_32.o
\
i386/interp_32_16.o i386/interp_32_32.o i386/emu-utils.o
\
...
...
@@ -67,7 +69,7 @@ op-i386.h: op-i386.o dyngen
./dyngen
-o
$@
$<
op-i386.o
:
op-i386.c opreg_template.h ops_template.h
$(CC)
$(CFLAGS)
$(DEFINES)
-c
-o
$@
$<
$(CC)
$(
OP_
CFLAGS)
$(DEFINES)
-c
-o
$@
$<
%.o
:
%.c
$(CC)
$(CFLAGS)
$(DEFINES)
-c
-o
$@
$<
...
...
TODO
浏览文件 @
927f621e
...
...
@@ -3,3 +3,4 @@
- threads
- fix printf for doubles (fp87.c bug ?)
- make it self runnable (use same trick as ld.so : include its own relocator and libc)
- better FPU comparisons (ucom/com)
cpu-i386.h
浏览文件 @
927f621e
...
...
@@ -75,6 +75,16 @@ enum {
CC_OP_NB
,
};
#ifdef __i386__
#define USE_X86LDOUBLE
#endif
#ifdef USE_X86LDOUBLE
typedef
long
double
CPU86_LDouble
;
#else
typedef
double
CPU86_LDouble
;
#endif
typedef
struct
CPU86State
{
/* standard registers */
uint32_t
regs
[
8
];
...
...
@@ -91,10 +101,18 @@ typedef struct CPU86State {
uint8_t
*
segs_base
[
6
];
uint32_t
segs
[
6
];
/* FPU state */
CPU86_LDouble
fpregs
[
8
];
uint8_t
fptags
[
8
];
/* 0 = valid, 1 = empty */
unsigned
int
fpstt
;
/* top of stack index */
unsigned
int
fpus
;
unsigned
int
fpuc
;
/* emulator internal variables */
uint32_t
t0
;
/* temporary t0 storage */
uint32_t
t1
;
/* temporary t1 storage */
uint32_t
a0
;
/* temporary a0 storage (address) */
CPU86_LDouble
ft0
;
}
CPU86State
;
static
inline
int
ldub
(
void
*
ptr
)
...
...
@@ -122,6 +140,10 @@ static inline int ldl(void *ptr)
return
*
(
uint32_t
*
)
ptr
;
}
static
inline
uint64_t
ldq
(
void
*
ptr
)
{
return
*
(
uint64_t
*
)
ptr
;
}
static
inline
void
stb
(
void
*
ptr
,
int
v
)
{
...
...
@@ -138,11 +160,40 @@ static inline void stl(void *ptr, int v)
*
(
uint32_t
*
)
ptr
=
v
;
}
static
inline
void
stq
(
void
*
ptr
,
int
v
)
{
*
(
uint64_t
*
)
ptr
=
v
;
}
/* float access */
static
inline
float
ldfl
(
void
*
ptr
)
{
return
*
(
float
*
)
ptr
;
}
static
inline
double
ldfq
(
void
*
ptr
)
{
return
*
(
double
*
)
ptr
;
}
static
inline
void
stfl
(
void
*
ptr
,
float
v
)
{
*
(
float
*
)
ptr
=
v
;
}
static
inline
void
stfq
(
void
*
ptr
,
double
v
)
{
*
(
double
*
)
ptr
=
v
;
}
#ifndef IN_OP_I386
void
port_outb
(
int
addr
,
int
val
);
void
port_outw
(
int
addr
,
int
val
);
void
port_outl
(
int
addr
,
int
val
);
int
port_inb
(
int
addr
);
int
port_inw
(
int
addr
);
int
port_inl
(
int
addr
);
#endif
#endif
/* CPU_I386_H */
dyngen.c
浏览文件 @
927f621e
...
...
@@ -243,6 +243,8 @@ void gen_code(const char *name, unsigned long offset, unsigned long size,
if
(
n
>=
MAX_ARGS
)
error
(
"too many arguments in %s"
,
name
);
args_present
[
n
-
1
]
=
1
;
}
else
{
fprintf
(
outfile
,
"extern char %s;
\n
"
,
sym_name
);
}
}
}
...
...
@@ -257,6 +259,8 @@ void gen_code(const char *name, unsigned long offset, unsigned long size,
if
(
n
>=
MAX_ARGS
)
error
(
"too many arguments in %s"
,
name
);
args_present
[
n
-
1
]
=
1
;
}
else
{
fprintf
(
outfile
,
"extern char %s;
\n
"
,
sym_name
);
}
}
}
...
...
op-i386.c
浏览文件 @
927f621e
...
...
@@ -66,7 +66,13 @@ register struct CPU86State *env asm("l3");
#define CC_SRC (env->cc_src)
#define CC_DST (env->cc_dst)
#define CC_OP (env->cc_op)
#define CC_OP (env->cc_op)
/* float macros */
#define FT0 (env->ft0)
#define ST0 (env->fpregs[env->fpstt])
#define ST(n) (env->fpregs[(env->fpstt + (n)) & 7])
#define ST1 ST(1)
extern
int
__op_param1
,
__op_param2
,
__op_param3
;
#define PARAM1 ((long)(&__op_param1))
...
...
@@ -133,6 +139,44 @@ const uint8_t rclb_table[32] = {
6
,
7
,
8
,
0
,
1
,
2
,
3
,
4
,
};
#ifdef USE_X86LDOUBLE
/* an array of Intel 80-bit FP constants, to be loaded via integer ops */
typedef
unsigned
short
f15ld
[
5
];
const
f15ld
f15rk
[]
=
{
/*0*/
{
0x0000
,
0x0000
,
0x0000
,
0x0000
,
0x0000
},
/*1*/
{
0x0000
,
0x0000
,
0x0000
,
0x8000
,
0x3fff
},
/*pi*/
{
0xc235
,
0x2168
,
0xdaa2
,
0xc90f
,
0x4000
},
/*lg2*/
{
0xf799
,
0xfbcf
,
0x9a84
,
0x9a20
,
0x3ffd
},
/*ln2*/
{
0x79ac
,
0xd1cf
,
0x17f7
,
0xb172
,
0x3ffe
},
/*l2e*/
{
0xf0bc
,
0x5c17
,
0x3b29
,
0xb8aa
,
0x3fff
},
/*l2t*/
{
0x8afe
,
0xcd1b
,
0x784b
,
0xd49a
,
0x4000
}
};
#else
/* the same, 64-bit version */
typedef
unsigned
short
f15ld
[
4
];
const
f15ld
f15rk
[]
=
{
#ifndef WORDS_BIGENDIAN
/*0*/
{
0x0000
,
0x0000
,
0x0000
,
0x0000
},
/*1*/
{
0x0000
,
0x0000
,
0x0000
,
0x3ff0
},
/*pi*/
{
0x2d18
,
0x5444
,
0x21fb
,
0x4009
},
/*lg2*/
{
0x79ff
,
0x509f
,
0x4413
,
0x3fd3
},
/*ln2*/
{
0x39ef
,
0xfefa
,
0x2e42
,
0x3fe6
},
/*l2e*/
{
0x82fe
,
0x652b
,
0x1547
,
0x3ff7
},
/*l2t*/
{
0xa371
,
0x0979
,
0x934f
,
0x400a
}
#else
/*0*/
{
0x0000
,
0x0000
,
0x0000
,
0x0000
},
/*1*/
{
0x3ff0
,
0x0000
,
0x0000
,
0x0000
},
/*pi*/
{
0x4009
,
0x21fb
,
0x5444
,
0x2d18
},
/*lg2*/
{
0x3fd3
,
0x4413
,
0x509f
,
0x79ff
},
/*ln2*/
{
0x3fe6
,
0x2e42
,
0xfefa
,
0x39ef
},
/*l2e*/
{
0x3ff7
,
0x1547
,
0x652b
,
0x82fe
},
/*l2t*/
{
0x400a
,
0x934f
,
0x0979
,
0xa371
}
#endif
};
#endif
/* n must be a constant to be efficient */
static
inline
int
lshift
(
int
x
,
int
n
)
{
...
...
@@ -866,3 +910,685 @@ CCTable cc_table[CC_OP_NB] = {
[
CC_OP_SHLW
]
=
{
compute_all_shlw
,
compute_c_shlw
},
[
CC_OP_SHLL
]
=
{
compute_all_shll
,
compute_c_shll
},
};
/* floating point support */
#ifdef USE_X86LDOUBLE
/* use long double functions */
#define lrint lrintl
#define llrint llrintl
#define fabs fabsl
#define sin sinl
#define cos cosl
#define sqrt sqrtl
#define pow powl
#define log logl
#define tan tanl
#define atan2 atan2l
#define floor floorl
#define ceil ceill
#define rint rintl
#endif
extern
int
lrint
(
CPU86_LDouble
x
);
extern
int64_t
llrint
(
CPU86_LDouble
x
);
extern
CPU86_LDouble
fabs
(
CPU86_LDouble
x
);
extern
CPU86_LDouble
sin
(
CPU86_LDouble
x
);
extern
CPU86_LDouble
cos
(
CPU86_LDouble
x
);
extern
CPU86_LDouble
sqrt
(
CPU86_LDouble
x
);
extern
CPU86_LDouble
pow
(
CPU86_LDouble
,
CPU86_LDouble
);
extern
CPU86_LDouble
log
(
CPU86_LDouble
x
);
extern
CPU86_LDouble
tan
(
CPU86_LDouble
x
);
extern
CPU86_LDouble
atan2
(
CPU86_LDouble
,
CPU86_LDouble
);
extern
CPU86_LDouble
floor
(
CPU86_LDouble
x
);
extern
CPU86_LDouble
ceil
(
CPU86_LDouble
x
);
extern
CPU86_LDouble
rint
(
CPU86_LDouble
x
);
#define RC_MASK 0xc00
#define RC_NEAR 0x000
#define RC_DOWN 0x400
#define RC_UP 0x800
#define RC_CHOP 0xc00
#define MAXTAN 9223372036854775808.0
#ifdef USE_X86LDOUBLE
/* only for x86 */
typedef
union
{
long
double
d
;
struct
{
unsigned
long
long
lower
;
unsigned
short
upper
;
}
l
;
}
CPU86_LDoubleU
;
/* the following deal with x86 long double-precision numbers */
#define MAXEXPD 0x7fff
#define EXPBIAS 16383
#define EXPD(fp) (fp.l.upper & 0x7fff)
#define SIGND(fp) ((fp.l.upper) & 0x8000)
#define MANTD(fp) (fp.l.lower)
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7fff)) | EXPBIAS
#else
typedef
{
double
d
;
#ifndef WORDS_BIGENDIAN
struct
{
unsigned
long
lower
;
long
upper
;
}
l
;
#else
struct
{
long
upper
;
unsigned
long
lower
;
}
l
;
#endif
long
long
ll
;
}
CPU86_LDoubleU
;
/* the following deal with IEEE double-precision numbers */
#define MAXEXPD 0x7ff
#define EXPBIAS 1023
#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF)
#define SIGND(fp) ((fp.l.upper) & 0x80000000)
#define MANTD(fp) (fp.ll & ((1LL << 52) - 1))
#define BIASEXPONENT(fp) fp.l.upper = (fp.l.upper & ~(0x7ff << 20)) | (EXPBIAS << 20)
#endif
/* fp load FT0 */
void
OPPROTO
op_flds_FT0_A0
(
void
)
{
FT0
=
ldfl
((
void
*
)
A0
);
}
void
OPPROTO
op_fldl_FT0_A0
(
void
)
{
FT0
=
ldfq
((
void
*
)
A0
);
}
void
OPPROTO
op_fild_FT0_A0
(
void
)
{
FT0
=
(
CPU86_LDouble
)
ldsw
((
void
*
)
A0
);
}
void
OPPROTO
op_fildl_FT0_A0
(
void
)
{
FT0
=
(
CPU86_LDouble
)((
int32_t
)
ldl
((
void
*
)
A0
));
}
void
OPPROTO
op_fildll_FT0_A0
(
void
)
{
FT0
=
(
CPU86_LDouble
)((
int64_t
)
ldq
((
void
*
)
A0
));
}
/* fp load ST0 */
void
OPPROTO
op_flds_ST0_A0
(
void
)
{
ST0
=
ldfl
((
void
*
)
A0
);
}
void
OPPROTO
op_fldl_ST0_A0
(
void
)
{
ST0
=
ldfq
((
void
*
)
A0
);
}
void
OPPROTO
op_fild_ST0_A0
(
void
)
{
ST0
=
(
CPU86_LDouble
)
ldsw
((
void
*
)
A0
);
}
void
OPPROTO
op_fildl_ST0_A0
(
void
)
{
ST0
=
(
CPU86_LDouble
)((
int32_t
)
ldl
((
void
*
)
A0
));
}
void
OPPROTO
op_fildll_ST0_A0
(
void
)
{
ST0
=
(
CPU86_LDouble
)((
int64_t
)
ldq
((
void
*
)
A0
));
}
/* fp store */
void
OPPROTO
op_fsts_ST0_A0
(
void
)
{
stfl
((
void
*
)
A0
,
(
float
)
ST0
);
}
void
OPPROTO
op_fstl_ST0_A0
(
void
)
{
ST0
=
ldfq
((
void
*
)
A0
);
}
void
OPPROTO
op_fist_ST0_A0
(
void
)
{
int
val
;
val
=
lrint
(
ST0
);
stw
((
void
*
)
A0
,
val
);
}
void
OPPROTO
op_fistl_ST0_A0
(
void
)
{
int
val
;
val
=
lrint
(
ST0
);
stl
((
void
*
)
A0
,
val
);
}
void
OPPROTO
op_fistll_ST0_A0
(
void
)
{
int64_t
val
;
val
=
llrint
(
ST0
);
stq
((
void
*
)
A0
,
val
);
}
/* FPU move */
static
inline
void
fpush
(
void
)
{
env
->
fpstt
=
(
env
->
fpstt
-
1
)
&
7
;
env
->
fptags
[
env
->
fpstt
]
=
0
;
/* validate stack entry */
}
static
inline
void
fpop
(
void
)
{
env
->
fptags
[
env
->
fpstt
]
=
1
;
/* invvalidate stack entry */
env
->
fpstt
=
(
env
->
fpstt
+
1
)
&
7
;
}
void
OPPROTO
op_fpush
(
void
)
{
fpush
();
}
void
OPPROTO
op_fpop
(
void
)
{
fpop
();
}
void
OPPROTO
op_fdecstp
(
void
)
{
env
->
fpstt
=
(
env
->
fpstt
-
1
)
&
7
;
env
->
fpus
&=
(
~
0x4700
);
}
void
OPPROTO
op_fincstp
(
void
)
{
env
->
fpstt
=
(
env
->
fpstt
+
1
)
&
7
;
env
->
fpus
&=
(
~
0x4700
);
}
void
OPPROTO
op_fmov_ST0_FT0
(
void
)
{
ST0
=
FT0
;
}
void
OPPROTO
op_fmov_FT0_STN
(
void
)
{
FT0
=
ST
(
PARAM1
);
}
void
OPPROTO
op_fmov_ST0_STN
(
void
)
{
ST0
=
ST
(
PARAM1
);
}
void
OPPROTO
op_fmov_STN_ST0
(
void
)
{
ST
(
PARAM1
)
=
ST0
;
}
void
OPPROTO
op_fxchg_ST0_STN
(
void
)
{
CPU86_LDouble
tmp
;
tmp
=
ST
(
PARAM1
);
ST
(
PARAM1
)
=
ST0
;
ST0
=
tmp
;
}
/* FPU operations */
/* XXX: handle nans */
void
OPPROTO
op_fcom_ST0_FT0
(
void
)
{
env
->
fpus
&=
(
~
0x4500
);
/* (C3,C2,C0) <-- 000 */
if
(
ST0
<
FT0
)
env
->
fpus
|=
0x100
;
/* (C3,C2,C0) <-- 001 */
else
if
(
ST0
==
FT0
)
env
->
fpus
|=
0x4000
;
/* (C3,C2,C0) <-- 100 */
FORCE_RET
();
}
void
OPPROTO
op_fadd_ST0_FT0
(
void
)
{
ST0
+=
FT0
;
}
void
OPPROTO
op_fmul_ST0_FT0
(
void
)
{
ST0
*=
FT0
;
}
void
OPPROTO
op_fsub_ST0_FT0
(
void
)
{
ST0
-=
FT0
;
}
void
OPPROTO
op_fsubr_ST0_FT0
(
void
)
{
ST0
=
FT0
-
ST0
;
}
void
OPPROTO
op_fdiv_ST0_FT0
(
void
)
{
ST0
/=
FT0
;
}
void
OPPROTO
op_fdivr_ST0_FT0
(
void
)
{
ST0
=
FT0
/
ST0
;
}
/* fp operations between STN and ST0 */
void
OPPROTO
op_fadd_STN_ST0
(
void
)
{
ST
(
PARAM1
)
+=
ST0
;
}
void
OPPROTO
op_fmul_STN_ST0
(
void
)
{
ST
(
PARAM1
)
*=
ST0
;
}
void
OPPROTO
op_fsub_STN_ST0
(
void
)
{
ST
(
PARAM1
)
-=
ST0
;
}
void
OPPROTO
op_fsubr_STN_ST0
(
void
)
{
CPU86_LDouble
*
p
;
p
=
&
ST
(
PARAM1
);
*
p
=
ST0
-
*
p
;
}
void
OPPROTO
op_fdiv_STN_ST0
(
void
)
{
ST
(
PARAM1
)
/=
ST0
;
}
void
OPPROTO
op_fdivr_STN_ST0
(
void
)
{
CPU86_LDouble
*
p
;
p
=
&
ST
(
PARAM1
);
*
p
=
ST0
/
*
p
;
}
/* misc FPU operations */
void
OPPROTO
op_fchs_ST0
(
void
)
{
ST0
=
-
ST0
;
}
void
OPPROTO
op_fabs_ST0
(
void
)
{
ST0
=
fabs
(
ST0
);
}
void
OPPROTO
op_fxam_ST0
(
void
)
{
CPU86_LDoubleU
temp
;
int
expdif
;
temp
.
d
=
ST0
;
env
->
fpus
&=
(
~
0x4700
);
/* (C3,C2,C1,C0) <-- 0000 */
if
(
SIGND
(
temp
))
env
->
fpus
|=
0x200
;
/* C1 <-- 1 */
expdif
=
EXPD
(
temp
);
if
(
expdif
==
MAXEXPD
)
{
if
(
MANTD
(
temp
)
==
0
)
env
->
fpus
|=
0x500
/*Infinity*/
;
else
env
->
fpus
|=
0x100
/*NaN*/
;
}
else
if
(
expdif
==
0
)
{
if
(
MANTD
(
temp
)
==
0
)
env
->
fpus
|=
0x4000
/*Zero*/
;
else
env
->
fpus
|=
0x4400
/*Denormal*/
;
}
else
{
env
->
fpus
|=
0x400
;
}
FORCE_RET
();
}
void
OPPROTO
op_fld1_ST0
(
void
)
{
ST0
=
*
(
CPU86_LDouble
*
)
&
f15rk
[
1
];
}
void
OPPROTO
op_fld2t_ST0
(
void
)
{
ST0
=
*
(
CPU86_LDouble
*
)
&
f15rk
[
6
];
}
void
OPPROTO
op_fld2e_ST0
(
void
)
{
ST0
=
*
(
CPU86_LDouble
*
)
&
f15rk
[
5
];
}
void
OPPROTO
op_fldpi_ST0
(
void
)
{
ST0
=
*
(
CPU86_LDouble
*
)
&
f15rk
[
2
];
}
void
OPPROTO
op_fldlg2_ST0
(
void
)
{
ST0
=
*
(
CPU86_LDouble
*
)
&
f15rk
[
3
];
}
void
OPPROTO
op_fldln2_ST0
(
void
)
{
ST0
=
*
(
CPU86_LDouble
*
)
&
f15rk
[
4
];
}
void
OPPROTO
op_fldz_ST0
(
void
)
{
ST0
=
*
(
CPU86_LDouble
*
)
&
f15rk
[
0
];
}
void
OPPROTO
op_fldz_FT0
(
void
)
{
ST0
=
*
(
CPU86_LDouble
*
)
&
f15rk
[
0
];
}
void
helper_f2xm1
(
void
)
{
ST0
=
pow
(
2
.
0
,
ST0
)
-
1
.
0
;
}
void
helper_fyl2x
(
void
)
{
CPU86_LDouble
fptemp
;
fptemp
=
ST0
;
if
(
fptemp
>
0
.
0
){
fptemp
=
log
(
fptemp
)
/
log
(
2
.
0
);
/* log2(ST) */
ST1
*=
fptemp
;
fpop
();
}
else
{
env
->
fpus
&=
(
~
0x4700
);
env
->
fpus
|=
0x400
;
}
}
void
helper_fptan
(
void
)
{
CPU86_LDouble
fptemp
;
fptemp
=
ST0
;
if
((
fptemp
>
MAXTAN
)
||
(
fptemp
<
-
MAXTAN
))
{
env
->
fpus
|=
0x400
;
}
else
{
ST0
=
tan
(
fptemp
);
fpush
();
ST0
=
1
.
0
;
env
->
fpus
&=
(
~
0x400
);
/* C2 <-- 0 */
/* the above code is for |arg| < 2**52 only */
}
}
void
helper_fpatan
(
void
)
{
CPU86_LDouble
fptemp
,
fpsrcop
;
fpsrcop
=
ST1
;
fptemp
=
ST0
;
ST1
=
atan2
(
fpsrcop
,
fptemp
);
fpop
();
}
void
helper_fxtract
(
void
)
{
CPU86_LDoubleU
temp
;
unsigned
int
expdif
;
temp
.
d
=
ST0
;
expdif
=
EXPD
(
temp
)
-
EXPBIAS
;
/*DP exponent bias*/
ST0
=
expdif
;
fpush
();
BIASEXPONENT
(
temp
);
ST0
=
temp
.
d
;
}
void
helper_fprem1
(
void
)
{
CPU86_LDouble
dblq
,
fpsrcop
,
fptemp
;
CPU86_LDoubleU
fpsrcop1
,
fptemp1
;
int
expdif
;
int
q
;
fpsrcop
=
ST0
;
fptemp
=
ST1
;
fpsrcop1
.
d
=
fpsrcop
;
fptemp1
.
d
=
fptemp
;
expdif
=
EXPD
(
fpsrcop1
)
-
EXPD
(
fptemp1
);
if
(
expdif
<
53
)
{
dblq
=
fpsrcop
/
fptemp
;
dblq
=
(
dblq
<
0
.
0
)
?
ceil
(
dblq
)
:
floor
(
dblq
);
ST0
=
fpsrcop
-
fptemp
*
dblq
;
q
=
(
int
)
dblq
;
/* cutting off top bits is assumed here */
env
->
fpus
&=
(
~
0x4700
);
/* (C3,C2,C1,C0) <-- 0000 */
/* (C0,C1,C3) <-- (q2,q1,q0) */
env
->
fpus
|=
(
q
&
0x4
)
<<
6
;
/* (C0) <-- q2 */
env
->
fpus
|=
(
q
&
0x2
)
<<
8
;
/* (C1) <-- q1 */
env
->
fpus
|=
(
q
&
0x1
)
<<
14
;
/* (C3) <-- q0 */
}
else
{
env
->
fpus
|=
0x400
;
/* C2 <-- 1 */
fptemp
=
pow
(
2
.
0
,
expdif
-
50
);
fpsrcop
=
(
ST0
/
ST1
)
/
fptemp
;
/* fpsrcop = integer obtained by rounding to the nearest */
fpsrcop
=
(
fpsrcop
-
floor
(
fpsrcop
)
<
ceil
(
fpsrcop
)
-
fpsrcop
)
?
floor
(
fpsrcop
)
:
ceil
(
fpsrcop
);
ST0
-=
(
ST1
*
fpsrcop
*
fptemp
);
}
}
void
helper_fprem
(
void
)
{
CPU86_LDouble
dblq
,
fpsrcop
,
fptemp
;
CPU86_LDoubleU
fpsrcop1
,
fptemp1
;
int
expdif
;
int
q
;
fpsrcop
=
ST0
;
fptemp
=
ST1
;
fpsrcop1
.
d
=
fpsrcop
;
fptemp1
.
d
=
fptemp
;
expdif
=
EXPD
(
fpsrcop1
)
-
EXPD
(
fptemp1
);
if
(
expdif
<
53
)
{
dblq
=
fpsrcop
/
fptemp
;
dblq
=
(
dblq
<
0
.
0
)
?
ceil
(
dblq
)
:
floor
(
dblq
);
ST0
=
fpsrcop
-
fptemp
*
dblq
;
q
=
(
int
)
dblq
;
/* cutting off top bits is assumed here */
env
->
fpus
&=
(
~
0x4700
);
/* (C3,C2,C1,C0) <-- 0000 */
/* (C0,C1,C3) <-- (q2,q1,q0) */
env
->
fpus
|=
(
q
&
0x4
)
<<
6
;
/* (C0) <-- q2 */
env
->
fpus
|=
(
q
&
0x2
)
<<
8
;
/* (C1) <-- q1 */
env
->
fpus
|=
(
q
&
0x1
)
<<
14
;
/* (C3) <-- q0 */
}
else
{
env
->
fpus
|=
0x400
;
/* C2 <-- 1 */
fptemp
=
pow
(
2
.
0
,
expdif
-
50
);
fpsrcop
=
(
ST0
/
ST1
)
/
fptemp
;
/* fpsrcop = integer obtained by chopping */
fpsrcop
=
(
fpsrcop
<
0
.
0
)
?
-
(
floor
(
fabs
(
fpsrcop
)))
:
floor
(
fpsrcop
);
ST0
-=
(
ST1
*
fpsrcop
*
fptemp
);
}
}
void
helper_fyl2xp1
(
void
)
{
CPU86_LDouble
fptemp
;
fptemp
=
ST0
;
if
((
fptemp
+
1
.
0
)
>
0
.
0
)
{
fptemp
=
log
(
fptemp
+
1
.
0
)
/
log
(
2
.
0
);
/* log2(ST+1.0) */
ST1
*=
fptemp
;
fpop
();
}
else
{
env
->
fpus
&=
(
~
0x4700
);
env
->
fpus
|=
0x400
;
}
}
void
helper_fsqrt
(
void
)
{
CPU86_LDouble
fptemp
;
fptemp
=
ST0
;
if
(
fptemp
<
0
.
0
)
{
env
->
fpus
&=
(
~
0x4700
);
/* (C3,C2,C1,C0) <-- 0000 */
env
->
fpus
|=
0x400
;
}
ST0
=
sqrt
(
fptemp
);
}
void
helper_fsincos
(
void
)
{
CPU86_LDouble
fptemp
;
fptemp
=
ST0
;
if
((
fptemp
>
MAXTAN
)
||
(
fptemp
<
-
MAXTAN
))
{
env
->
fpus
|=
0x400
;
}
else
{
ST0
=
sin
(
fptemp
);
fpush
();
ST0
=
cos
(
fptemp
);
env
->
fpus
&=
(
~
0x400
);
/* C2 <-- 0 */
/* the above code is for |arg| < 2**63 only */
}
}
void
helper_frndint
(
void
)
{
ST0
=
rint
(
ST0
);
}
void
helper_fscale
(
void
)
{
CPU86_LDouble
fpsrcop
,
fptemp
;
fpsrcop
=
2
.
0
;
fptemp
=
pow
(
fpsrcop
,
ST1
);
ST0
*=
fptemp
;
}
void
helper_fsin
(
void
)
{
CPU86_LDouble
fptemp
;
fptemp
=
ST0
;
if
((
fptemp
>
MAXTAN
)
||
(
fptemp
<
-
MAXTAN
))
{
env
->
fpus
|=
0x400
;
}
else
{
ST0
=
sin
(
fptemp
);
env
->
fpus
&=
(
~
0x400
);
/* C2 <-- 0 */
/* the above code is for |arg| < 2**53 only */
}
}
void
helper_fcos
(
void
)
{
CPU86_LDouble
fptemp
;
fptemp
=
ST0
;
if
((
fptemp
>
MAXTAN
)
||
(
fptemp
<
-
MAXTAN
))
{
env
->
fpus
|=
0x400
;
}
else
{
ST0
=
cos
(
fptemp
);
env
->
fpus
&=
(
~
0x400
);
/* C2 <-- 0 */
/* the above code is for |arg5 < 2**63 only */
}
}
/* associated heplers to reduce generated code length and to simplify
relocation (FP constants are usually stored in .rodata section) */
void
OPPROTO
op_f2xm1
(
void
)
{
helper_f2xm1
();
}
void
OPPROTO
op_fyl2x
(
void
)
{
helper_fyl2x
();
}
void
OPPROTO
op_fptan
(
void
)
{
helper_fptan
();
}
void
OPPROTO
op_fpatan
(
void
)
{
helper_fpatan
();
}
void
OPPROTO
op_fxtract
(
void
)
{
helper_fxtract
();
}
void
OPPROTO
op_fprem1
(
void
)
{
helper_fprem1
();
}
void
OPPROTO
op_fprem
(
void
)
{
helper_fprem
();
}
void
OPPROTO
op_fyl2xp1
(
void
)
{
helper_fyl2xp1
();
}
void
OPPROTO
op_fsqrt
(
void
)
{
helper_fsqrt
();
}
void
OPPROTO
op_fsincos
(
void
)
{
helper_fsincos
();
}
void
OPPROTO
op_frndint
(
void
)
{
helper_frndint
();
}
void
OPPROTO
op_fscale
(
void
)
{
helper_fscale
();
}
void
OPPROTO
op_fsin
(
void
)
{
helper_fsin
();
}
void
OPPROTO
op_fcos
(
void
)
{
helper_fcos
();
}
translate-i386.c
浏览文件 @
927f621e
...
...
@@ -5,6 +5,7 @@
#include <inttypes.h>
#include <assert.h>
#define IN_OP_I386
#include "cpu-i386.h"
static
uint8_t
*
gen_code_ptr
;
...
...
@@ -39,7 +40,6 @@ typedef struct DisasContext {
int
prefix
;
int
aflag
,
dflag
;
uint8_t
*
pc
;
/* current pc */
uint8_t
*
runtime_pc
;
/* current pc in the runtime generated code */
int
cc_op
;
/* current CC operation */
int
f_st
;
}
DisasContext
;
...
...
@@ -68,18 +68,6 @@ enum {
OP_SAR
=
7
,
};
static
const
int
fp_ops
[
8
]
=
{
#if 0
OP_FADDQ, OP_FMULQ, OP_CMP, OP_CMP,
OP_FSUBQ, OP_FSUBQ, OP_FDIVQ, OP_FDIVQ
#endif
};
extern
char
cc_table
,
rclw_table
,
rclb_table
;
extern
char
helper_rcll_T0_T1_cc
;
extern
char
__udivdi3
,
__umoddi3
;
#include "op-i386.h"
/* operand size */
...
...
@@ -606,6 +594,28 @@ static GenOpFunc *gen_setcc_sub[3][8] = {
},
};
static
GenOpFunc
*
gen_op_fp_arith_ST0_FT0
[
8
]
=
{
gen_op_fadd_ST0_FT0
,
gen_op_fmul_ST0_FT0
,
gen_op_fcom_ST0_FT0
,
gen_op_fcom_ST0_FT0
,
gen_op_fsub_ST0_FT0
,
gen_op_fsubr_ST0_FT0
,
gen_op_fdiv_ST0_FT0
,
gen_op_fdivr_ST0_FT0
,
};
static
GenOpFunc1
*
gen_op_fp_arith_STN_ST0
[
8
]
=
{
gen_op_fadd_STN_ST0
,
gen_op_fmul_STN_ST0
,
NULL
,
NULL
,
gen_op_fsub_STN_ST0
,
gen_op_fsubr_STN_ST0
,
gen_op_fdiv_STN_ST0
,
gen_op_fdivr_STN_ST0
,
};
static
void
gen_op
(
DisasContext
*
s1
,
int
op
,
int
ot
,
int
d
,
int
s
)
{
if
(
d
!=
OR_TMP0
)
...
...
@@ -1345,12 +1355,12 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
/**************************/
/* push/pop */
case
0x50
...
0x57
:
/* push */
gen_op_mov_TN_reg
[
OT_LONG
][
0
][
(
b
&
7
)
]();
gen_op_mov_TN_reg
[
OT_LONG
][
0
][
b
&
7
]();
gen_op_pushl_T0
();
break
;
case
0x58
...
0x5f
:
/* pop */
gen_op_popl_T0
();
gen_op_mov_reg_T0
[
OT_LONG
][
reg
]();
gen_op_mov_reg_T0
[
OT_LONG
][
b
&
7
]();
break
;
case
0x68
:
/* push Iv */
case
0x6a
:
...
...
@@ -1581,7 +1591,6 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
/************************/
/* floats */
#if 0
case
0xd8
...
0xdf
:
modrm
=
ldub
(
s
->
pc
++
);
mod
=
(
modrm
>>
6
)
&
3
;
...
...
@@ -1597,52 +1606,29 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
case
0x20
...
0x27
:
/* fxxxl */
case
0x30
...
0x37
:
/* fixxx */
{
int op1, swap;
op1 = fp_ops[op & 7];
swap = 0;
if ((op & 7) == 5 || (op & 7) == 7)
swap = 1;
int
op1
;
op1
=
op
&
7
;
switch
(
op
>>
4
)
{
case
0
:
ot = OT_LONG;
is_int = 0;
gen_op_flds_FT0_A0
();
break
;
case
1
:
ot = OT_LONG;
is_int = 1;
gen_op_fildl_FT0_A0
();
break
;
case
2
:
ot = OT_QUAD;
is_int = 0;
gen_op_fldl_FT0_A0
();
break
;
case
3
:
default:
ot = OT_WORD;
is_int = 1;
gen_op_fild_FT0_A0
();
break
;
}
/* if integer, needs to convert to float */
if (is_int) {
/* XXX: potential loss of precision if large integer */
gen_ld(OP_LDUB + ot, OR_TMP0, reg_addr, offset_addr);
gen_insn2(OP_I2FL, OR_FTMP0, OR_TMP0);
} else {
gen_ld(OP_LDUB + ot, OR_FTMP0, reg_addr, offset_addr);
}
if (ot != OT_QUAD)
op1 += OP_FADDL - OP_FADDQ;
if (!swap)
gen_insn3(op1, OR_ST0, OR_ST0, OR_FTMP0);
else
gen_insn3(op1, OR_ST0, OR_FTMP0, OR_ST0);
if ((op & 7) == 3) {
gen_op_fp_arith_ST0_FT0
[
op1
]();
if
(
op1
==
3
)
{
/* fcomp needs pop */
gen_
insn0(OP_FPOP
);
gen_
op_fpop
(
);
}
}
break
;
...
...
@@ -1659,49 +1645,47 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
case
0x3a
:
/* fists */
case
0x3b
:
/* fistps */
switch(op >> 4) {
case 0:
ot = OT_LONG;
is_int = 0;
break;
case 1:
ot = OT_LONG;
is_int = 1;
break;
case 2:
ot = OT_QUAD;
is_int = 0;
break;
case 3:
default:
ot = OT_WORD;
is_int = 1;
break;
}
switch
(
op
&
7
)
{
case
0
:
gen_insn0(OP_FPUSH);
if (is_int) {
/* XXX: potential loss of precision */
gen_ld(OP_LDUB + ot, OR_TMP0, reg_addr, offset_addr);
gen_insn2(OP_I2FL, OR_ST0, OR_TMP0);
} else {
gen_ld(OP_LDUB + ot, OR_ST0, reg_addr, offset_addr);
gen_op_fpush
();
switch
(
op
>>
4
)
{
case
0
:
gen_op_flds_ST0_A0
();
break
;
case
1
:
gen_op_fildl_ST0_A0
();
break
;
case
2
:
gen_op_fldl_ST0_A0
();
break
;
case
3
:
default:
gen_op_fild_ST0_A0
();
break
;
}
break
;
default:
if (is_int) {
gen_insn2(OP_F2IL, OR_TMP0, OR_ST0);
gen_st(OP_STB + ot, OR_TMP0, reg_addr, offset_addr);
} else {
gen_st(OP_STB + ot, OR_ST0, reg_addr, offset_addr);
switch
(
op
>>
4
)
{
case
0
:
gen_op_fsts_ST0_A0
();
break
;
case
1
:
gen_op_fistl_ST0_A0
();
break
;
case
2
:
gen_op_fstl_ST0_A0
();
break
;
case
3
:
default:
gen_op_fist_ST0_A0
();
break
;
}
if
((
op
&
7
)
==
3
)
gen_
insn0(OP_FPOP
);
gen_
op_fpop
(
);
break
;
}
break
;
#if 0
case 0x2f: /* fnstsw mem */
gen_insn3(OP_FNSTS, OR_TMP0, OR_ZERO, OR_ZERO);
gen_st(OP_STW, OR_TMP0, reg_addr, offset_addr);
...
...
@@ -1711,15 +1695,14 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
case 0x3e: /* fbstp */
error("float BCD not hanlded");
return -1;
#endif
case
0x3d
:
/* fildll */
gen_insn0(OP_FPUSH);
gen_ld(OP_LDQ, OR_TMP0, reg_addr, offset_addr);
gen_insn2(OP_I2FQ, OR_ST0, OR_TMP0);
gen_op_fpush
();
gen_op_fildll_ST0_A0
();
break
;
case
0x3f
:
/* fistpll */
gen_insn2(OP_F2IQ, OR_TMP0, OR_ST0);
gen_st(OP_STQ, OR_TMP0, reg_addr, offset_addr);
gen_insn0(OP_FPOP);
gen_op_fistll_ST0_A0
();
gen_op_fpop
();
break
;
default:
error
(
"unhandled memory FP
\n
"
);
...
...
@@ -1727,22 +1710,19 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
}
}
else
{
/* register float ops */
opreg = rm
+ OR_ST0
;
opreg
=
rm
;
switch
(
op
)
{
case
0x08
:
/* fld sti */
gen_
insn0(OP_FPUSH
);
gen_
mov(OR_ST0, OR_ST0 + ((rm + 1) & 7)
);
gen_
op_fpush
(
);
gen_
op_fmov_ST0_STN
((
opreg
+
1
)
&
7
);
break
;
case
0x09
:
/* fxchg sti */
gen_mov(OR_TMP0, OR_ST0);
gen_mov(OR_ST0, opreg);
gen_mov(opreg, OR_TMP0);
gen_op_fxchg_ST0_STN
((
opreg
+
1
)
&
7
);
break
;
case
0x0a
:
/* grp d9/2 */
switch
(
rm
)
{
case
0
:
/* fnop */
gen_insn0(OP_NOP);
break
;
default:
error
(
"unhandled FP GRP d9/2
\n
"
);
...
...
@@ -1752,16 +1732,17 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
case
0x0c
:
/* grp d9/4 */
switch
(
rm
)
{
case
0
:
/* fchs */
gen_
insn3(OP_FSUBQ, OR_ST0, OR_ZERO, OR_ST0
);
gen_
op_fchs_ST0
(
);
break
;
case
1
:
/* fabs */
gen_
insn2(OP_FABSQ, OR_ST0, OR_ST0
);
gen_
op_fabs_ST0
(
);
break
;
case
4
:
/* ftst */
gen_insn3(OP_CMP, OR_ZERO, OR_ST0, OR_ZERO);
gen_op_fldz_FT0
();
gen_op_fcom_ST0_FT0
();
break
;
case
5
:
/* fxam */
gen_
insn3(OP_FSPECIAL, OR_ZERO, OR_ST0, OR_ZERO
);
gen_
op_fxam_ST0
(
);
break
;
default:
return
-
1
;
...
...
@@ -1769,76 +1750,88 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
break
;
case
0x0d
:
/* grp d9/5 */
{
if (rm == 7) {
error("bad GRP d9/5");
switch
(
rm
)
{
case
0
:
gen_op_fld1_ST0
();
break
;
case
1
:
gen_op_fld2t_ST0
();
break
;
case
2
:
gen_op_fld2e_ST0
();
break
;
case
3
:
gen_op_fldpi_ST0
();
break
;
case
4
:
gen_op_fldlg2_ST0
();
break
;
case
5
:
gen_op_fldln2_ST0
();
break
;
case
6
:
gen_op_fldz_ST0
();
break
;
default:
return
-
1
;
}
/* XXX: needs constant load or symbol table */
gen_insn0(OP_FPUSH);
gen_ld(OP_LDQ, OR_ST0, OR_ZERO,
(rm * 8) + FLOAT_CONST_ADDR);
}
break
;
case
0x0e
:
/* grp d9/6 */
switch
(
rm
)
{
case
0
:
/* f2xm1 */
gen_
insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ZERO
);
gen_
op_f2xm1
(
);
break
;
case
1
:
/* fyl2x */
gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST0, OR_ST1);
gen_insn0(OP_FPOP);
gen_op_fyl2x
();
break
;
case
2
:
/* fptan */
gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ZERO);
gen_insn0(OP_FPUSH);
/* load one */
gen_ld(OP_LDQ, OR_ST0, OR_ZERO,
(0 * 8) + FLOAT_CONST_ADDR);
gen_op_fptan
();
break
;
case
3
:
/* fpatan */
gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST0, OR_ST1);
gen_insn0(OP_FPOP);
gen_op_fpatan
();
break
;
case
4
:
/* fxtract */
gen_insn0(OP_FPUSH);
gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST1, OR_ZERO);
gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST1, OR_ZERO);
gen_op_fxtract
();
break
;
case
5
:
/* fprem1 */
gen_
insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ST1
);
gen_
op_fprem1
(
);
break
;
case
6
:
/* fdecstp */
gen_
insn0(OP_FPUSH
);
gen_
op_fdecstp
(
);
break
;
default:
case 7: /* f
de
cstp */
gen_
insn0(OP_FPOP
);
case
7
:
/* f
in
cstp */
gen_
op_fincstp
(
);
break
;
}
break
;
case
0x0f
:
/* grp d9/7 */
switch
(
rm
)
{
case
0
:
/* fprem */
gen_
insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ST1
);
gen_
op_fprem
(
);
break
;
case
1
:
/* fyl2xp1 */
gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST0, OR_ST1);
gen_insn0(OP_FPOP);
gen_op_fyl2xp1
();
break
;
case
2
:
/* fsqrt */
gen_op_fsqrt
();
break
;
case
3
:
/* fsincos */
gen_insn0(OP_FPUSH);
gen_insn3(OP_FSPECIAL, OR_ST0, OR_ST1, OR_ZERO);
gen_insn3(OP_FSPECIAL, OR_ST1, OR_ST1, OR_ZERO);
gen_op_fsincos
();
break
;
case
5
:
/* fscale */
gen_
insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ST1
);
gen_
op_fscale
(
);
break
;
case 2: /* fsqrt */
case
4
:
/* frndint */
gen_op_frndint
();
break
;
case
6
:
/* fsin */
gen_op_fsin
();
break
;
default:
case
7
:
/* fcos */
gen_
insn3(OP_FSPECIAL, OR_ST0, OR_ST0, OR_ZERO
);
gen_
op_fcos
(
);
break
;
}
break
;
...
...
@@ -1846,58 +1839,54 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
case
0x20
:
case
0x21
:
case
0x24
...
0x27
:
/* fxxx sti, st */
case
0x30
:
case
0x31
:
case
0x34
...
0x37
:
/* fxxxp sti, st */
{
int op1
, swap
;
int
op1
;
op1 = fp_ops[op & 7];
swap = 0;
if ((op & 7) == 5 || (op & 7) == 7)
swap = 1;
op1
=
op
&
7
;
if
(
op
>=
0x20
)
{
if (swap)
gen_insn3(op1, opreg, OR_ST0, opreg);
else
gen_insn3(op1, opreg, opreg, OR_ST0);
gen_op_fp_arith_STN_ST0
[
op1
](
opreg
);
}
else
{
if (swap)
gen_insn3(op1, OR_ST0, opreg, OR_ST0);
else
gen_insn3(op1, OR_ST0, OR_ST0, opreg);
gen_op_fmov_FT0_STN
(
opreg
);
gen_op_fp_arith_ST0_FT0
[
op1
]();
}
if
(
op
>=
0x30
)
gen_
insn0(OP_FPOP
);
gen_
op_fpop
(
);
}
break
;
case
0x02
:
/* fcom */
gen_insn3(OP_CMP, OR_ZERO, OR_ST0, opreg);
gen_op_fmov_FT0_STN
(
opreg
);
gen_op_fcom_ST0_FT0
();
break
;
case
0x03
:
/* fcomp */
gen_insn3(OP_CMP, OR_ZERO, OR_ST0, opreg);
gen_insn0(OP_FPOP);
gen_op_fmov_FT0_STN
(
opreg
);
gen_op_fcom_ST0_FT0
();
gen_op_fpop
();
break
;
case
0x15
:
/* da/5 */
switch
(
rm
)
{
case
1
:
/* fucompp */
gen_insn3(OP_CMP, OR_ZERO, OR_ST0, opreg);
gen_insn0(OP_FPOP);
gen_insn0(OP_FPOP);
gen_op_fmov_FT0_STN
(
1
);
gen_op_fcom_ST0_FT0
();
gen_op_fpop
();
gen_op_fpop
();
break
;
default:
return
-
1
;
}
break
;
case
0x2a
:
/* fst sti */
gen_
mov(opreg, OR_ST0
);
gen_
op_fmov_STN_ST0
(
opreg
);
break
;
case
0x2b
:
/* fstp sti */
gen_
mov(opreg, OR_ST0
);
gen_
insn0(OP_FPOP
);
gen_
op_fmov_STN_ST0
(
opreg
);
gen_
op_fpop
(
);
break
;
case
0x33
:
/* de/3 */
switch
(
rm
)
{
case
1
:
/* fcompp */
gen_insn3(OP_CMP, OR_ZERO, OR_ST0, opreg);
gen_insn0(OP_FPOP);
gen_insn0(OP_FPOP);
gen_op_fmov_FT0_STN
(
1
);
gen_op_fcom_ST0_FT0
();
gen_op_fpop
();
gen_op_fpop
();
break
;
default:
return
-
1
;
...
...
@@ -1905,9 +1894,11 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
break
;
case
0x3c
:
/* df/4 */
switch
(
rm
)
{
#if 0
case 0:
gen_insn3(OP_FNSTS, OR_EAX, OR_ZERO, OR_ZERO);
break;
#endif
default:
return
-
1
;
}
...
...
@@ -1918,7 +1909,6 @@ int disas_insn(DisasContext *s, uint8_t *pc_start)
}
}
break
;
#endif
/************************/
/* string ops */
case
0xa4
:
/* movsS */
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录