Fixing "or" and "and" emulation in long mode.
Original Change: https://android-review.googlesource.com/c/platform/external/qemu/+/1235432
Change-Id: Icfe74b0f9a67753487438ab22f2d76fe6492f7f4
Reviewed-on: https://fuchsia-review.googlesource.com/c/third_party/qemu/+/529280
Reviewed-by: Travis Geiselbrecht <travisg@google.com>
diff --git a/target/i386/hvf/x86_emu.c b/target/i386/hvf/x86_emu.c
index 92ab815..0dd47f3 100644
--- a/target/i386/hvf/x86_emu.c
+++ b/target/i386/hvf/x86_emu.c
@@ -86,6 +86,17 @@
FLAGS_FUNC##32(env, v1, v2, diff); \
break; \
} \
+ case 8: \
+ { \
+ uint64_t v1 = (uint64_t)decode->op[0].val; \
+ uint64_t v2 = (uint64_t)decode->op[1].val; \
+ uint64_t diff = v1 cmd v2; \
+ if (save_res) { \
+ write_val_ext(env, decode->op[0].ptr, diff, 8); \
+ } \
+ FLAGS_FUNC##64(env, v1, v2, diff); \
+ break; \
+ } \
default: \
VM_PANIC("bad size\n"); \
} \
diff --git a/target/i386/hvf/x86_flags.c b/target/i386/hvf/x86_flags.c
index ee6d33f..043e718 100644
--- a/target/i386/hvf/x86_flags.c
+++ b/target/i386/hvf/x86_flags.c
@@ -64,7 +64,9 @@
target_ulong temp = ((lf_carries) & (LF_MASK_AF)) | \
(((lf_carries) >> (size - 2)) << LF_BIT_PO); \
env->hvf_emul->lflags.result = (target_ulong)(int##size##_t)(lf_result); \
- if ((size) == 32) { \
+ if ((size) == 64) { \
+ temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \
+ } else if ((size) == 32) { \
temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \
} else if ((size) == 16) { \
temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \
@@ -83,6 +85,8 @@
SET_FLAGS_OSZAPC_SIZE(16, carries, result)
#define SET_FLAGS_OSZAPC_32(carries, result) \
SET_FLAGS_OSZAPC_SIZE(32, carries, result)
+#define SET_FLAGS_OSZAPC_64(carries, result) \
+ SET_FLAGS_OSZAPC_SIZE(64, carries, result)
/* ******************* */
/* OSZAP */
@@ -91,7 +95,9 @@
#define SET_FLAGS_OSZAP_SIZE(size, lf_carries, lf_result) { \
target_ulong temp = ((lf_carries) & (LF_MASK_AF)) | \
(((lf_carries) >> (size - 2)) << LF_BIT_PO); \
- if ((size) == 32) { \
+ if ((size) == 64) { \
+ temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \
+ } else if ((size) == 32) { \
temp = ((lf_carries) & ~(LF_MASK_PDB | LF_MASK_SD)); \
} else if ((size) == 16) { \
temp = ((lf_carries) & (LF_MASK_AF)) | ((lf_carries) << 16); \
@@ -113,6 +119,8 @@
SET_FLAGS_OSZAP_SIZE(16, carries, result)
#define SET_FLAGS_OSZAP_32(carries, result) \
SET_FLAGS_OSZAP_SIZE(32, carries, result)
+#define SET_FLAGS_OSZAP_64(carries, result) \
+ SET_FLAGS_OSZAP_SIZE(64, carries, result)
void SET_FLAGS_OxxxxC(CPUX86State *env, uint32_t new_of, uint32_t new_cf)
{
@@ -122,6 +130,12 @@
(new_cf << LF_BIT_CF);
}
+void SET_FLAGS_OSZAPC_SUB64(CPUX86State *env, uint64_t v1, uint64_t v2,
+ uint64_t diff)
+{
+ SET_FLAGS_OSZAPC_64(SUB_COUT_VEC(v1, v2, diff), diff);
+}
+
void SET_FLAGS_OSZAPC_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2,
uint32_t diff)
{
@@ -140,6 +154,12 @@
SET_FLAGS_OSZAPC_8(SUB_COUT_VEC(v1, v2, diff), diff);
}
+void SET_FLAGS_OSZAPC_ADD64(CPUX86State *env, uint64_t v1, uint64_t v2,
+ uint64_t diff)
+{
+ SET_FLAGS_OSZAPC_64(ADD_COUT_VEC(v1, v2, diff), diff);
+}
+
void SET_FLAGS_OSZAPC_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2,
uint32_t diff)
{
@@ -158,6 +178,12 @@
SET_FLAGS_OSZAPC_8(ADD_COUT_VEC(v1, v2, diff), diff);
}
+void SET_FLAGS_OSZAP_SUB64(CPUX86State *env, uint64_t v1, uint64_t v2,
+ uint64_t diff)
+{
+ SET_FLAGS_OSZAP_64(SUB_COUT_VEC(v1, v2, diff), diff);
+}
+
void SET_FLAGS_OSZAP_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2,
uint32_t diff)
{
@@ -176,6 +202,12 @@
SET_FLAGS_OSZAP_8(SUB_COUT_VEC(v1, v2, diff), diff);
}
+void SET_FLAGS_OSZAP_ADD64(CPUX86State *env, uint64_t v1, uint64_t v2,
+ uint64_t diff)
+{
+ SET_FLAGS_OSZAP_64(ADD_COUT_VEC(v1, v2, diff), diff);
+}
+
void SET_FLAGS_OSZAP_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2,
uint32_t diff)
{
@@ -195,6 +227,12 @@
}
+void SET_FLAGS_OSZAPC_LOGIC64(CPUX86State *env, uint64_t v1, uint64_t v2,
+ uint64_t diff)
+{
+ SET_FLAGS_OSZAPC_64(0UL, diff);
+}
+
void SET_FLAGS_OSZAPC_LOGIC32(CPUX86State *env, uint32_t v1, uint32_t v2,
uint32_t diff)
{
diff --git a/target/i386/hvf/x86_flags.h b/target/i386/hvf/x86_flags.h
index 785e80c..b0148a8 100644
--- a/target/i386/hvf/x86_flags.h
+++ b/target/i386/hvf/x86_flags.h
@@ -43,6 +43,8 @@
void SET_FLAGS_OxxxxC(CPUX86State *env, uint32_t new_of, uint32_t new_cf);
+void SET_FLAGS_OSZAPC_SUB64(CPUX86State *env, uint64_t v1, uint64_t v2,
+ uint64_t diff);
void SET_FLAGS_OSZAPC_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2,
uint32_t diff);
void SET_FLAGS_OSZAPC_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2,
@@ -50,6 +52,8 @@
void SET_FLAGS_OSZAPC_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2,
uint8_t diff);
+void SET_FLAGS_OSZAPC_ADD64(CPUX86State *env, uint64_t v1, uint64_t v2,
+ uint64_t diff);
void SET_FLAGS_OSZAPC_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2,
uint32_t diff);
void SET_FLAGS_OSZAPC_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2,
@@ -57,6 +61,8 @@
void SET_FLAGS_OSZAPC_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2,
uint8_t diff);
+void SET_FLAGS_OSZAP_SUB64(CPUX86State *env, uint64_t v1, uint64_t v2,
+ uint64_t diff);
void SET_FLAGS_OSZAP_SUB32(CPUX86State *env, uint32_t v1, uint32_t v2,
uint32_t diff);
void SET_FLAGS_OSZAP_SUB16(CPUX86State *env, uint16_t v1, uint16_t v2,
@@ -64,6 +70,8 @@
void SET_FLAGS_OSZAP_SUB8(CPUX86State *env, uint8_t v1, uint8_t v2,
uint8_t diff);
+void SET_FLAGS_OSZAP_ADD64(CPUX86State *env, uint64_t v1, uint64_t v2,
+ uint64_t diff);
void SET_FLAGS_OSZAP_ADD32(CPUX86State *env, uint32_t v1, uint32_t v2,
uint32_t diff);
void SET_FLAGS_OSZAP_ADD16(CPUX86State *env, uint16_t v1, uint16_t v2,
@@ -71,6 +79,8 @@
void SET_FLAGS_OSZAP_ADD8(CPUX86State *env, uint8_t v1, uint8_t v2,
uint8_t diff);
+void SET_FLAGS_OSZAPC_LOGIC64(CPUX86State *env, uint64_t v1, uint64_t v2,
+ uint64_t diff);
void SET_FLAGS_OSZAPC_LOGIC32(CPUX86State *env, uint32_t v1, uint32_t v2,
uint32_t diff);
void SET_FLAGS_OSZAPC_LOGIC16(CPUX86State *env, uint16_t v1, uint16_t v2,