From: Jaume Marti Farriol <jaume.martif@gmail.com>
To: qemu-devel@nongnu.org
Cc: "Paolo Bonzini" <pbonzini@redhat.com>,
"Alex Bennée" <alex.bennee@linaro.org>,
"Richard Henderson" <rth@twiddle.net>
Subject: [Qemu-devel] [PATCH v2 2/8] target-i386: x87 exception pointers using TCG.
Date: Thu, 28 Aug 2014 22:44:34 +0200 [thread overview]
Message-ID: <1409258680-15555-3-git-send-email-jaume.martif@gmail.com> (raw)
In-Reply-To: <1409258680-15555-1-git-send-email-jaume.martif@gmail.com>
Hello,
This patch modifies the helpers for the fpu instructions involved in saving to memory and restoring the x87 exception pointers.
Best regards,
Jaume
fpu_helper.c | 218 ++++++++++++++++++++++++++++++++++++++++++++---------------
1 file changed, 166 insertions(+), 52 deletions(-)
signed-off: jaume.martif@gmail.com
diff --git a/target-i386/fpu_helper.c b/target-i386/fpu_helper.c
index 1b2900d..6886031 100644
--- a/target-i386/fpu_helper.c
+++ b/target-i386/fpu_helper.c
@@ -56,6 +56,8 @@
#define floatx80_l2e make_floatx80(0x3fff, 0xb8aa3b295c17f0bcLL)
#define floatx80_l2t make_floatx80(0x4000, 0xd49a784bcd1b8afeLL)
+#define FPUS(env) ((env->fpus & ~0x3800) | ((env->fpstt & 0x7) << 11))
+
static inline void fpush(CPUX86State *env)
{
env->fpstt = (env->fpstt - 1) & 7;
@@ -604,6 +606,10 @@ void helper_fninit(CPUX86State *env)
env->fptags[5] = 1;
env->fptags[6] = 1;
env->fptags[7] = 1;
+ env->fpip = 0;
+ env->fpcs = 0;
+ env->fpdp = 0;
+ env->fpds = 0;
}
/* BCD ops */
@@ -961,13 +967,13 @@ void helper_fxam_ST0(CPUX86State *env)
}
}
-void helper_fstenv(CPUX86State *env, target_ulong ptr, int data32)
+void helper_fstenv(CPUX86State *env, target_ulong ptr, int data32,
+ int protected_mode)
{
- int fpus, fptag, exp, i;
+ int fptag, exp, i;
uint64_t mant;
CPU_LDoubleU tmp;
- fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
fptag = 0;
for (i = 7; i >= 0; i--) {
fptag <<= 2;
@@ -987,83 +993,150 @@ void helper_fstenv(CPUX86State *env, target_ulong ptr, int data32)
}
}
}
+
if (data32) {
/* 32 bit */
- cpu_stl_data(env, ptr, env->fpuc);
- cpu_stl_data(env, ptr + 4, fpus);
- cpu_stl_data(env, ptr + 8, fptag);
- cpu_stl_data(env, ptr + 12, 0); /* fpip */
- cpu_stl_data(env, ptr + 16, 0); /* fpcs */
- cpu_stl_data(env, ptr + 20, 0); /* fpoo */
- cpu_stl_data(env, ptr + 24, 0); /* fpos */
+ cpu_stw_data(env, ptr, env->fpuc);
+ cpu_stw_data(env, ptr + 4, FPUS(env));
+ cpu_stw_data(env, ptr + 8, fptag);
+ if (protected_mode) {
+ cpu_stl_data(env, ptr + 12, env->fpip);
+ cpu_stl_data(env, ptr + 16,
+ ((env->fpop & 0x7ff) << 16) | (env->fpcs & 0xffff));
+ cpu_stl_data(env, ptr + 20, env->fpdp);
+ cpu_stl_data(env, ptr + 24, env->fpds);
+ } else {
+ /* Real mode */
+ cpu_stl_data(env, ptr + 12, env->fpip); /* fpip[15..00] */
+ cpu_stl_data(env, ptr + 16, ((((env->fpip >> 16) & 0xffff) << 12) |
+ (env->fpop & 0x7ff))); /* fpip[31..16], fpop */
+ cpu_stl_data(env, ptr + 20, env->fpdp); /* fpdp[15..00] */
+ cpu_stl_data(env, ptr + 24,
+ (env->fpdp >> 4) & 0xffff000); /* fpdp[31..16] */
+ }
} else {
/* 16 bit */
cpu_stw_data(env, ptr, env->fpuc);
- cpu_stw_data(env, ptr + 2, fpus);
+ cpu_stw_data(env, ptr + 2, FPUS(env));
cpu_stw_data(env, ptr + 4, fptag);
- cpu_stw_data(env, ptr + 6, 0);
- cpu_stw_data(env, ptr + 8, 0);
- cpu_stw_data(env, ptr + 10, 0);
- cpu_stw_data(env, ptr + 12, 0);
+ if (protected_mode) {
+ cpu_stw_data(env, ptr + 6, env->fpip);
+ cpu_stw_data(env, ptr + 8, env->fpcs);
+ cpu_stw_data(env, ptr + 10, env->fpdp);
+ cpu_stw_data(env, ptr + 12, env->fpds);
+ } else {
+ /* Real mode */
+ cpu_stw_data(env, ptr + 6, env->fpip); /* fpip[15..0] */
+ cpu_stw_data(env, ptr + 8, ((env->fpip >> 4) & 0xf000) |
+ (env->fpop & 0x7ff)); /* fpip[19..16], fpop */
+ cpu_stw_data(env, ptr + 10, env->fpdp); /* fpdp[15..0] */
+ cpu_stw_data(env, ptr + 12,
+ (env->fpdp >> 4) & 0xf000); /* fpdp[19..16] */
+ }
}
+
+ env->fpip = 0;
+ env->fpcs = 0;
+ env->fpdp = 0;
+ env->fpds = 0;
}
-void helper_fldenv(CPUX86State *env, target_ulong ptr, int data32)
+void helper_fldenv(CPUX86State *env, target_ulong ptr, int data32,
+ int protected_mode)
{
- int i, fpus, fptag;
+ int tmp, i, fpus, fptag;
if (data32) {
+ /* 32 bit */
env->fpuc = cpu_lduw_data(env, ptr);
fpus = cpu_lduw_data(env, ptr + 4);
fptag = cpu_lduw_data(env, ptr + 8);
+ if (protected_mode) {
+ env->fpip = cpu_ldl_data(env, ptr + 12);
+ tmp = cpu_ldl_data(env, ptr + 16);
+ env->fpcs = tmp & 0xffff;
+ env->fpop = tmp >> 16;
+ env->fpdp = cpu_ldl_data(env, ptr + 20);
+ env->fpds = cpu_lduw_data(env, ptr + 24);
+ } else {
+ /* Real mode */
+ tmp = cpu_ldl_data(env, ptr + 16);
+ env->fpip = ((tmp & 0xffff000) << 4) |
+ cpu_lduw_data(env, ptr + 12);
+ env->fpop = tmp & 0x7ff;
+ env->fpdp = (cpu_ldl_data(env, ptr + 24) << 4) |
+ cpu_lduw_data(env, ptr + 20);
+ }
} else {
+ /* 16 bit */
env->fpuc = cpu_lduw_data(env, ptr);
fpus = cpu_lduw_data(env, ptr + 2);
fptag = cpu_lduw_data(env, ptr + 4);
+ if (protected_mode) {
+ /* Protected mode */
+ env->fpip = cpu_lduw_data(env, ptr + 6);
+ env->fpcs = cpu_lduw_data(env, ptr + 8);
+ env->fpdp = cpu_lduw_data(env, ptr + 10);
+ env->fpds = cpu_lduw_data(env, ptr + 12);
+ } else {
+ /* Real mode */
+ tmp = cpu_lduw_data(env, ptr + 8);
+ env->fpip = ((tmp & 0xf000) << 4) | cpu_lduw_data(env, ptr + 6);
+ env->fpop = tmp & 0x7ff;
+ env->fpdp = cpu_lduw_data(env, ptr + 12) << 4 |
+ cpu_lduw_data(env, ptr + 10);
+ }
}
+
env->fpstt = (fpus >> 11) & 7;
env->fpus = fpus & ~0x3800;
for (i = 0; i < 8; i++) {
env->fptags[i] = ((fptag & 3) == 3);
fptag >>= 2;
}
+
+ env->fpip &= 0xffffffff;
+ env->fpdp &= 0xffffffff;
+ if (!protected_mode) {
+ env->fpcs = 0;
+ env->fpds = 0;
+ }
}
-void helper_fsave(CPUX86State *env, target_ulong ptr, int data32)
+void helper_fsave(CPUX86State *env, target_ulong ptr, int data32,
+ int protected_mode)
{
floatx80 tmp;
int i;
- helper_fstenv(env, ptr, data32);
+ helper_fstenv(env, ptr, data32, protected_mode);
- ptr += (14 << data32);
+ if (data32) {
+ ptr += 28;
+ } else {
+ ptr += 14;
+ }
for (i = 0; i < 8; i++) {
tmp = ST(i);
helper_fstt(env, tmp, ptr);
ptr += 10;
}
- /* fninit */
- env->fpus = 0;
- env->fpstt = 0;
- env->fpuc = 0x37f;
- env->fptags[0] = 1;
- env->fptags[1] = 1;
- env->fptags[2] = 1;
- env->fptags[3] = 1;
- env->fptags[4] = 1;
- env->fptags[5] = 1;
- env->fptags[6] = 1;
- env->fptags[7] = 1;
+ helper_fninit(env);
}
-void helper_frstor(CPUX86State *env, target_ulong ptr, int data32)
+void helper_frstor(CPUX86State *env, target_ulong ptr, int data32,
+ int protected_mode)
{
floatx80 tmp;
int i;
- helper_fldenv(env, ptr, data32);
- ptr += (14 << data32);
+ helper_fldenv(env, ptr, data32, protected_mode);
+ if (data32) {
+ ptr += 28;
+ } else {
+ ptr += 14;
+ }
for (i = 0; i < 8; i++) {
tmp = helper_fldt(env, ptr);
@@ -1072,21 +1145,22 @@ void helper_frstor(CPUX86State *env, target_ulong ptr, int data32)
}
}
-#if defined(CONFIG_USER_ONLY)
-void cpu_x86_fsave(CPUX86State *env, target_ulong ptr, int data32)
+#if defined(CONFIG_USER_ONLY) && defined(TARGET_I386) && TARGET_ABI_BITS == 32
+
+void cpu_x86_fsave(CPUX86State *env, target_ulong ptr)
{
- helper_fsave(env, ptr, data32);
+ helper_fsave(env, ptr, 1, 1);
}
-void cpu_x86_frstor(CPUX86State *env, target_ulong ptr, int data32)
+void cpu_x86_frstor(CPUX86State *env, target_ulong ptr)
{
- helper_frstor(env, ptr, data32);
+ helper_frstor(env, ptr, 1, 1);
}
#endif
-void helper_fxsave(CPUX86State *env, target_ulong ptr, int data64)
+void helper_fxsave(CPUX86State *env, target_ulong ptr, int data32, int data64)
{
- int fpus, fptag, i, nb_xmm_regs;
+ int i, nb_xmm_regs, fptag;
floatx80 tmp;
target_ulong addr;
@@ -1095,25 +1169,36 @@ void helper_fxsave(CPUX86State *env, target_ulong ptr, int data64)
raise_exception(env, EXCP0D_GPF);
}
- fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11;
fptag = 0;
for (i = 0; i < 8; i++) {
fptag |= (env->fptags[i] << i);
}
+ fptag ^= 0xff;
+
cpu_stw_data(env, ptr, env->fpuc);
- cpu_stw_data(env, ptr + 2, fpus);
- cpu_stw_data(env, ptr + 4, fptag ^ 0xff);
+ cpu_stw_data(env, ptr + 2, FPUS(env));
+ cpu_stw_data(env, ptr + 4, fptag & 0xff);
+ cpu_stw_data(env, ptr + 6, env->fpop);
+
#ifdef TARGET_X86_64
if (data64) {
- cpu_stq_data(env, ptr + 0x08, 0); /* rip */
- cpu_stq_data(env, ptr + 0x10, 0); /* rdp */
+ /* 64 bit */
+ cpu_stq_data(env, ptr + 8, env->fpip);
+ cpu_stq_data(env, ptr + 16, env->fpdp);
} else
#endif
{
- cpu_stl_data(env, ptr + 0x08, 0); /* eip */
- cpu_stl_data(env, ptr + 0x0c, 0); /* sel */
- cpu_stl_data(env, ptr + 0x10, 0); /* dp */
- cpu_stl_data(env, ptr + 0x14, 0); /* sel */
+ if (data32) {
+ /* 32 bit */
+ cpu_stl_data(env, ptr + 8, env->fpip);
+ cpu_stl_data(env, ptr + 16, env->fpdp);
+ } else {
+ /* 16 bit */
+ cpu_stw_data(env, ptr + 8, env->fpip);
+ cpu_stw_data(env, ptr + 16, env->fpdp);
+ }
+ cpu_stw_data(env, ptr + 12, env->fpcs & 0xffff);
+ cpu_stw_data(env, ptr + 20, env->fpds & 0xffff);
}
addr = ptr + 0x20;
@@ -1146,7 +1231,7 @@ void helper_fxsave(CPUX86State *env, target_ulong ptr, int data64)
}
}
-void helper_fxrstor(CPUX86State *env, target_ulong ptr, int data64)
+void helper_fxrstor(CPUX86State *env, target_ulong ptr, int data32, int data64)
{
int i, fpus, fptag, nb_xmm_regs;
floatx80 tmp;
@@ -1167,6 +1252,30 @@ void helper_fxrstor(CPUX86State *env, target_ulong ptr, int data64)
env->fptags[i] = ((fptag >> i) & 1);
}
+ env->fpop = (cpu_lduw_data(env, ptr + 6) >> 5) & 0x7ff;
+
+#ifdef TARGET_X86_64
+ if (data64) {
+ /* 64 bit */
+ env->fpip = cpu_ldq_data(env, ptr + 8);
+ env->fpdp = cpu_ldq_data(env, ptr + 16);
+ } else
+#endif
+ {
+ if (data32) {
+ /* 32 bit */
+ env->fpip = cpu_ldl_data(env, ptr + 8);
+ env->fpdp = cpu_ldl_data(env, ptr + 16);
+ } else {
+ /* 16 bit */
+ env->fpip = cpu_lduw_data(env, ptr + 8);
+ env->fpdp = cpu_lduw_data(env, ptr + 16);
+ }
+
+ env->fpcs = cpu_lduw_data(env, ptr + 12);
+ env->fpds = cpu_lduw_data(env, ptr + 20);
+ }
+
addr = ptr + 0x20;
for (i = 0; i < 8; i++) {
tmp = helper_fldt(env, addr);
@@ -1195,6 +1304,11 @@ void helper_fxrstor(CPUX86State *env, target_ulong ptr, int data64)
}
}
}
+
+ if (!data64) {
+ env->fpip &= 0xffffffff;
+ env->fpdp &= 0xffffffff;
+ }
}
void cpu_get_fp80(uint64_t *pmant, uint16_t *pexp, floatx80 f)
next prev parent reply other threads:[~2014-08-28 20:41 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-08-28 20:44 [Qemu-devel] [PATCH v2 0/8] target-i386: x87 exception pointers using TCG Jaume Marti Farriol
2014-08-28 20:44 ` [Qemu-devel] [PATCH v2 1/8] " Jaume Marti Farriol
2014-08-29 22:19 ` Richard Henderson
2014-08-28 20:44 ` Jaume Marti Farriol [this message]
2014-08-29 22:57 ` [Qemu-devel] [PATCH v2 2/8] " Richard Henderson
2014-08-30 21:40 ` Jaume Martí
2014-08-28 20:44 ` [Qemu-devel] [PATCH v2 3/8] " Jaume Marti Farriol
2014-08-29 22:58 ` Richard Henderson
2014-08-30 21:42 ` Jaume Martí
2014-08-28 20:44 ` [Qemu-devel] [PATCH v2 4/8] " Jaume Marti Farriol
2014-08-29 22:59 ` Richard Henderson
2014-08-28 20:44 ` [Qemu-devel] [PATCH v2 5/8] " Jaume Marti Farriol
2014-08-28 20:44 ` [Qemu-devel] [PATCH v2 6/8] " Jaume Marti Farriol
2014-08-28 20:44 ` [Qemu-devel] [PATCH v2 7/8] " Jaume Marti Farriol
2014-08-28 20:44 ` [Qemu-devel] [PATCH v2 8/8] " Jaume Marti Farriol
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1409258680-15555-3-git-send-email-jaume.martif@gmail.com \
--to=jaume.martif@gmail.com \
--cc=alex.bennee@linaro.org \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=rth@twiddle.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).