Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src Implement XCHG, add associated tests, and add comments to ex...
details: https://anonhg.NetBSD.org/src/rev/b01f15909c5c
branches: trunk
changeset: 464615:b01f15909c5c
user: maxv <maxv%NetBSD.org@localhost>
date: Mon Oct 14 10:39:24 2019 +0000
description:
Implement XCHG, add associated tests, and add comments to explain. With
this in place the Windows 95 installer completes successfuly.
Part of PR/54611.
diffstat:
lib/libnvmm/libnvmm_x86.c | 116 ++++++++++++++++++++++++++++++----
tests/lib/libnvmm/h_mem_assist.c | 10 ++-
tests/lib/libnvmm/h_mem_assist_asm.S | 47 +++++++++++++-
3 files changed, 155 insertions(+), 18 deletions(-)
diffs (truncated from 343 to 300 lines):
diff -r 84b40334c5da -r b01f15909c5c lib/libnvmm/libnvmm_x86.c
--- a/lib/libnvmm/libnvmm_x86.c Mon Oct 14 06:40:40 2019 +0000
+++ b/lib/libnvmm/libnvmm_x86.c Mon Oct 14 10:39:24 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: libnvmm_x86.c,v 1.32 2019/10/13 17:32:15 maxv Exp $ */
+/* $NetBSD: libnvmm_x86.c,v 1.33 2019/10/14 10:39:24 maxv Exp $ */
/*
* Copyright (c) 2018-2019 The NetBSD Foundation, Inc.
@@ -838,13 +838,15 @@
/* -------------------------------------------------------------------------- */
struct x86_emul {
- bool read;
+ bool readreg;
+ bool backprop;
bool notouch;
void (*func)(struct nvmm_machine *, struct nvmm_mem *, uint64_t *);
};
static void x86_func_or(struct nvmm_machine *, struct nvmm_mem *, uint64_t *);
static void x86_func_and(struct nvmm_machine *, struct nvmm_mem *, uint64_t *);
+static void x86_func_xchg(struct nvmm_machine *, struct nvmm_mem *, uint64_t *);
static void x86_func_sub(struct nvmm_machine *, struct nvmm_mem *, uint64_t *);
static void x86_func_xor(struct nvmm_machine *, struct nvmm_mem *, uint64_t *);
static void x86_func_cmp(struct nvmm_machine *, struct nvmm_mem *, uint64_t *);
@@ -855,22 +857,28 @@
static void x86_func_movs(struct nvmm_machine *, struct nvmm_mem *, uint64_t *);
static const struct x86_emul x86_emul_or = {
- .read = true,
+ .readreg = true,
.func = x86_func_or
};
static const struct x86_emul x86_emul_and = {
- .read = true,
+ .readreg = true,
.func = x86_func_and
};
+static const struct x86_emul x86_emul_xchg = {
+ .readreg = true,
+ .backprop = true,
+ .func = x86_func_xchg
+};
+
static const struct x86_emul x86_emul_sub = {
- .read = true,
+ .readreg = true,
.func = x86_func_sub
};
static const struct x86_emul x86_emul_xor = {
- .read = true,
+ .readreg = true,
.func = x86_func_xor
};
@@ -1322,6 +1330,28 @@
},
/*
+ * XCHG
+ */
+ [0x86] = {
+ /* Eb, Gb */
+ .valid = true,
+ .regmodrm = true,
+ .regtorm = true,
+ .szoverride = false,
+ .defsize = OPSIZE_BYTE,
+ .emul = &x86_emul_xchg
+ },
+ [0x87] = {
+ /* Ev, Gv */
+ .valid = true,
+ .regmodrm = true,
+ .regtorm = true,
+ .szoverride = true,
+ .defsize = -1,
+ .emul = &x86_emul_xchg
+ },
+
+ /*
* MOV
*/
[0x88] = {
@@ -2616,10 +2646,10 @@
{ \
uint##sz##_t res; \
__asm __volatile ( \
- #instr " %2, %3;" \
- "mov %3, %1;" \
+ #instr" %2, %3;" \
+ "mov %3, %1;" \
"pushfq;" \
- "popq %0" \
+ "popq %0" \
: "=r" (*rflags), "=r" (res) \
: "r" (op1), "r" (op2)); \
return res; \
@@ -2677,7 +2707,7 @@
/*
* Emulation functions. We don't care about the order of the operands, except
- * for SUB, CMP and TEST. For these ones we look at mem->write todetermine who
+ * for SUB, CMP and TEST. For these ones we look at mem->write to determine who
* is op1 and who is op2.
*/
@@ -2746,6 +2776,28 @@
}
static void
+x86_func_xchg(struct nvmm_machine *mach, struct nvmm_mem *mem, uint64_t *gprs)
+{
+ uint64_t *op1, op2;
+
+ op1 = (uint64_t *)mem->data;
+ op2 = 0;
+
+ /* Fetch op2. */
+ mem->data = (uint8_t *)&op2;
+ mem->write = false;
+ (*mach->cbs.mem)(mem);
+
+ /* Write op1 in op2. */
+ mem->data = (uint8_t *)op1;
+ mem->write = true;
+ (*mach->cbs.mem)(mem);
+
+ /* Write op2 in op1. */
+ *op1 = op2;
+}
+
+static void
x86_func_sub(struct nvmm_machine *mach, struct nvmm_mem *mem, uint64_t *gprs)
{
uint64_t *retval = (uint64_t *)mem->data;
@@ -3154,7 +3206,9 @@
if (mem.write) {
switch (instr->src.type) {
case STORE_REG:
- if (instr->src.disp.type != DISP_NONE) {
+ /* The instruction was "reg -> mem". Fetch the register
+ * in membuf. */
+ if (__predict_false(instr->src.disp.type != DISP_NONE)) {
DISASSEMBLER_BUG();
}
val = state->gprs[instr->src.u.reg->num];
@@ -3162,16 +3216,20 @@
memcpy(mem.data, &val, mem.size);
break;
case STORE_IMM:
+ /* The instruction was "imm -> mem". Fetch the immediate
+ * in membuf. */
memcpy(mem.data, &instr->src.u.imm.data, mem.size);
break;
default:
DISASSEMBLER_BUG();
}
- } else if (instr->emul->read) {
- if (instr->dst.type != STORE_REG) {
+ } else if (instr->emul->readreg) {
+ /* The instruction was "mem -> reg", but the value of the
+ * register matters for the emul func. Fetch it in membuf. */
+ if (__predict_false(instr->dst.type != STORE_REG)) {
DISASSEMBLER_BUG();
}
- if (instr->dst.disp.type != DISP_NONE) {
+ if (__predict_false(instr->dst.disp.type != DISP_NONE)) {
DISASSEMBLER_BUG();
}
val = state->gprs[instr->dst.u.reg->num];
@@ -3181,8 +3239,19 @@
(*instr->emul->func)(mach, &mem, state->gprs);
- if (!instr->emul->notouch && !mem.write) {
- if (instr->dst.type != STORE_REG) {
+ if (instr->emul->notouch) {
+ /* We're done. */
+ return 0;
+ }
+
+ if (!mem.write) {
+ /* The instruction was "mem -> reg". The emul func has filled
+ * membuf with the memory content. Install membuf in the
+ * register. */
+ if (__predict_false(instr->dst.type != STORE_REG)) {
+ DISASSEMBLER_BUG();
+ }
+ if (__predict_false(instr->dst.disp.type != DISP_NONE)) {
DISASSEMBLER_BUG();
}
memcpy(&val, membuf, sizeof(uint64_t));
@@ -3190,6 +3259,21 @@
state->gprs[instr->dst.u.reg->num] &= ~instr->dst.u.reg->mask;
state->gprs[instr->dst.u.reg->num] |= val;
state->gprs[instr->dst.u.reg->num] &= ~instr->zeroextend_mask;
+ } else if (instr->emul->backprop) {
+ /* The instruction was "reg -> mem", but the memory must be
+ * back-propagated to the register. Install membuf in the
+ * register. */
+ if (__predict_false(instr->src.type != STORE_REG)) {
+ DISASSEMBLER_BUG();
+ }
+ if (__predict_false(instr->src.disp.type != DISP_NONE)) {
+ DISASSEMBLER_BUG();
+ }
+ memcpy(&val, membuf, sizeof(uint64_t));
+ val = __SHIFTIN(val, instr->src.u.reg->mask);
+ state->gprs[instr->src.u.reg->num] &= ~instr->src.u.reg->mask;
+ state->gprs[instr->src.u.reg->num] |= val;
+ state->gprs[instr->src.u.reg->num] &= ~instr->zeroextend_mask;
}
return 0;
diff -r 84b40334c5da -r b01f15909c5c tests/lib/libnvmm/h_mem_assist.c
--- a/tests/lib/libnvmm/h_mem_assist.c Mon Oct 14 06:40:40 2019 +0000
+++ b/tests/lib/libnvmm/h_mem_assist.c Mon Oct 14 10:39:24 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: h_mem_assist.c,v 1.13 2019/10/14 01:15:32 christos Exp $ */
+/* $NetBSD: h_mem_assist.c,v 1.14 2019/10/14 10:39:24 maxv Exp $ */
/*
* Copyright (c) 2018-2019 The NetBSD Foundation, Inc.
@@ -173,6 +173,8 @@
extern uint8_t test12_begin, test12_end;
extern uint8_t test13_begin, test13_end;
extern uint8_t test14_begin, test14_end;
+extern uint8_t test_64bit_15_begin, test_64bit_15_end;
+extern uint8_t test_64bit_16_begin, test_64bit_16_end;
static const struct test tests64[] = {
{ "test1 - MOV", &test1_begin, &test1_end, 0x3004, 0 },
@@ -189,6 +191,9 @@
{ "test12 - CMP", &test12_begin, &test12_end, 0x00000001, 0 },
{ "test13 - SUB", &test13_begin, &test13_end, 0x0000000F0000A0FF, 0 },
{ "test14 - TEST", &test14_begin, &test14_end, 0x00000001, 0 },
+ { "test15 - XCHG", &test_64bit_15_begin, &test_64bit_15_end, 0x123456, 0 },
+ { "test16 - XCHG", &test_64bit_16_begin, &test_64bit_16_end,
+ 0x123456, 0 },
{ NULL, NULL, NULL, -1, 0 }
};
@@ -371,6 +376,7 @@
extern uint8_t test_16bit_3_begin, test_16bit_3_end;
extern uint8_t test_16bit_4_begin, test_16bit_4_end;
extern uint8_t test_16bit_5_begin, test_16bit_5_end;
+extern uint8_t test_16bit_6_begin, test_16bit_6_end;
static const struct test tests16[] = {
{ "16bit test1 - MOV single", &test_16bit_1_begin, &test_16bit_1_end,
@@ -383,6 +389,8 @@
0x1011, 0x10f6 - 0x1000 },
{ "16bit test5 - disp16-only", &test_16bit_5_begin, &test_16bit_5_end,
0x12, 0x1234 - 0x1000 },
+ { "16bit test6 - XCHG", &test_16bit_6_begin, &test_16bit_6_end,
+ 0x1234, 0x1234 - 0x1000 },
{ NULL, NULL, NULL, -1, -1 }
};
diff -r 84b40334c5da -r b01f15909c5c tests/lib/libnvmm/h_mem_assist_asm.S
--- a/tests/lib/libnvmm/h_mem_assist_asm.S Mon Oct 14 06:40:40 2019 +0000
+++ b/tests/lib/libnvmm/h_mem_assist_asm.S Mon Oct 14 10:39:24 2019 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: h_mem_assist_asm.S,v 1.7 2019/10/13 17:32:15 maxv Exp $ */
+/* $NetBSD: h_mem_assist_asm.S,v 1.8 2019/10/14 10:39:24 maxv Exp $ */
/*
* Copyright (c) 2018-2019 The NetBSD Foundation, Inc.
@@ -43,6 +43,8 @@
.globl test12_begin, test12_end
.globl test13_begin, test13_end
.globl test14_begin, test14_end
+ .globl test_64bit_15_begin, test_64bit_15_end
+ .globl test_64bit_16_begin, test_64bit_16_end
.text
.code64
@@ -294,6 +296,35 @@
TEST_END
test14_end:
+ .align 64
+test_64bit_15_begin:
+ movq $0x1000,%rax
+ movq $0x120000,%rbx
+ movq $0x003400,%rcx
+ movq $0x000056,%rdx
+
+ xchgq %rbx,(%rax)
+ xchgw (%rax),%cx
+ xchgb %dl,(%rax)
+
+ TEST_END
+test_64bit_15_end:
+
Home |
Main Index |
Thread Index |
Old Index