Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Xing Lin
qemu
Commits
927f621e
Commit
927f621e
authored
Mar 02, 2003
by
bellard
Browse files
added float support
git-svn-id:
svn://svn.savannah.nongnu.org/qemu/trunk@15
c046a42c-6fe2-441c-8c8c-71466251a162
parent
367e86e8
Changes
6
Hide whitespace changes
Inline
Side-by-side
Makefile
View file @
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
View file @
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
View file @
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
View file @
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
View file @
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
)