Module Name:    src
Committed By:   maxv
Date:           Mon Jan  7 18:13:34 UTC 2019

Modified Files:
        src/lib/libnvmm: libnvmm_x86.c

Log Message:
Optimize the legpref node: omit BRN (we don't care and it's the same as
OVR_CS), inline the loops, sort the checks from most to least likely
prefix, and use a compact structure.


To generate a diff of this commit:
cvs rdiff -u -r1.12 -r1.13 src/lib/libnvmm/libnvmm_x86.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/lib/libnvmm/libnvmm_x86.c
diff -u src/lib/libnvmm/libnvmm_x86.c:1.12 src/lib/libnvmm/libnvmm_x86.c:1.13
--- src/lib/libnvmm/libnvmm_x86.c:1.12	Mon Jan  7 16:30:25 2019
+++ src/lib/libnvmm/libnvmm_x86.c	Mon Jan  7 18:13:34 2019
@@ -1,4 +1,4 @@
-/*	$NetBSD: libnvmm_x86.c,v 1.12 2019/01/07 16:30:25 maxv Exp $	*/
+/*	$NetBSD: libnvmm_x86.c,v 1.13 2019/01/07 18:13:34 maxv Exp $	*/
 
 /*
  * Copyright (c) 2018 The NetBSD Foundation, Inc.
@@ -824,26 +824,25 @@ static void x86_emul_stos(struct nvmm_me
 static void x86_emul_lods(struct nvmm_mem *, void (*)(struct nvmm_mem *), uint64_t *);
 static void x86_emul_movs(struct nvmm_mem *, void (*)(struct nvmm_mem *), uint64_t *);
 
-enum x86_legpref {
-	/* Group 1 */
-	LEG_LOCK = 0,
-	LEG_REPN,	/* REPNE/REPNZ */
-	LEG_REP,	/* REP/REPE/REPZ */
-	/* Group 2 */
-	LEG_OVR_CS,
-	LEG_OVR_SS,
-	LEG_OVR_DS,
-	LEG_OVR_ES,
-	LEG_OVR_FS,
-	LEG_OVR_GS,
-	LEG_BRN_TAKEN,
-	LEG_BRN_NTAKEN,
-	/* Group 3 */
-	LEG_OPR_OVR,
-	/* Group 4 */
-	LEG_ADR_OVR,
-
-	NLEG
+/* Legacy prefixes. */
+#define LEG_LOCK	0xF0
+#define LEG_REPN	0xF2
+#define LEG_REP		0xF3
+#define LEG_OVR_CS	0x2E
+#define LEG_OVR_SS	0x36
+#define LEG_OVR_DS	0x3E
+#define LEG_OVR_ES	0x26
+#define LEG_OVR_FS	0x64
+#define LEG_OVR_GS	0x65
+#define LEG_OPR_OVR	0x66
+#define LEG_ADR_OVR	0x67
+
+struct x86_legpref {
+	bool opr_ovr:1;
+	bool adr_ovr:1;
+	bool rep:1;
+	bool repn:1;
+	int seg;
 };
 
 struct x86_rexpref {
@@ -940,7 +939,7 @@ struct x86_store {
 
 struct x86_instr {
 	size_t len;
-	bool legpref[NLEG];
+	struct x86_legpref legpref;
 	struct x86_rexpref rexpref;
 	size_t operand_size;
 	size_t address_size;
@@ -2133,13 +2132,13 @@ get_operand_size(struct x86_decode_fsm *
 		opsize = 8;
 	} else {
 		if (!fsm->is16bit) {
-			if (instr->legpref[LEG_OPR_OVR]) {
+			if (instr->legpref.opr_ovr) {
 				opsize = 2;
 			} else {
 				opsize = 4;
 			}
 		} else { /* 16bit */
-			if (instr->legpref[LEG_OPR_OVR]) {
+			if (instr->legpref.opr_ovr) {
 				opsize = 4;
 			} else {
 				opsize = 2;
@@ -2159,21 +2158,21 @@ static size_t
 get_address_size(struct x86_decode_fsm *fsm, struct x86_instr *instr)
 {
 	if (fsm->is64bit) {
-		if (__predict_false(instr->legpref[LEG_ADR_OVR])) {
+		if (__predict_false(instr->legpref.adr_ovr)) {
 			return 4;
 		}
 		return 8;
 	}
 
 	if (fsm->is32bit) {
-		if (__predict_false(instr->legpref[LEG_ADR_OVR])) {
+		if (__predict_false(instr->legpref.adr_ovr)) {
 			return 2;
 		}
 		return 4;
 	}
 
 	/* 16bit. */
-	if (__predict_false(instr->legpref[LEG_ADR_OVR])) {
+	if (__predict_false(instr->legpref.adr_ovr)) {
 		return 4;
 	}
 	return 2;
@@ -2344,51 +2343,44 @@ node_rex_prefix(struct x86_decode_fsm *f
 	return 0;
 }
 
-static const struct {
-	uint8_t byte;
-	int seg;
-} legpref_table[NLEG] = {
-	/* Group 1 */
-	[LEG_LOCK] = { 0xF0, -1 },
-	[LEG_REPN] = { 0xF2, -1 },
-	[LEG_REP]  = { 0xF3, -1 },
-	/* Group 2 */
-	[LEG_OVR_CS] = { 0x2E, NVMM_X64_SEG_CS },
-	[LEG_OVR_SS] = { 0x36, NVMM_X64_SEG_SS },
-	[LEG_OVR_DS] = { 0x3E, NVMM_X64_SEG_DS },
-	[LEG_OVR_ES] = { 0x26, NVMM_X64_SEG_ES },
-	[LEG_OVR_FS] = { 0x64, NVMM_X64_SEG_FS },
-	[LEG_OVR_GS] = { 0x65, NVMM_X64_SEG_GS },
-	[LEG_BRN_TAKEN]  = { 0x2E, -1 },
-	[LEG_BRN_NTAKEN] = { 0x3E, -1 },
-	/* Group 3 */
-	[LEG_OPR_OVR] = { 0x66, -1 },
-	/* Group 4 */
-	[LEG_ADR_OVR] = { 0x67, -1 },
-};
-
 static int
 node_legacy_prefix(struct x86_decode_fsm *fsm, struct x86_instr *instr)
 {
 	uint8_t byte;
-	size_t i;
 
 	if (fsm_read(fsm, &byte, sizeof(byte)) == -1) {
 		return -1;
 	}
 
-	for (i = 0; i < NLEG; i++) {
-		if (byte == legpref_table[i].byte)
-			break;
-	}
-
-	if (i == NLEG) {
-		fsm->fn = node_rex_prefix;
+	if (byte == LEG_OPR_OVR) {
+		instr->legpref.opr_ovr = 1;
+	} else if (byte == LEG_OVR_DS) {
+		instr->legpref.seg = NVMM_X64_SEG_DS;
+	} else if (byte == LEG_OVR_ES) {
+		instr->legpref.seg = NVMM_X64_SEG_ES;
+	} else if (byte == LEG_REP) {
+		instr->legpref.rep = 1;
+	} else if (byte == LEG_OVR_GS) {
+		instr->legpref.seg = NVMM_X64_SEG_GS;
+	} else if (byte == LEG_OVR_FS) {
+		instr->legpref.seg = NVMM_X64_SEG_FS;
+	} else if (byte == LEG_ADR_OVR) {
+		instr->legpref.adr_ovr = 1;
+	} else if (byte == LEG_OVR_CS) {
+		instr->legpref.seg = NVMM_X64_SEG_CS;
+	} else if (byte == LEG_OVR_SS) {
+		instr->legpref.seg = NVMM_X64_SEG_SS;
+	} else if (byte == LEG_REPN) {
+		instr->legpref.repn = 1;
+	} else if (byte == LEG_LOCK) {
+		/* ignore */
 	} else {
-		instr->legpref[i] = true;
-		fsm_advance(fsm, 1, node_legacy_prefix);
+		/* not a legacy prefix */
+		fsm_advance(fsm, 0, node_rex_prefix);
+		return 0;
 	}
 
+	fsm_advance(fsm, 1, node_legacy_prefix);
 	return 0;
 }
 
@@ -2400,6 +2392,7 @@ x86_decode(uint8_t *inst_bytes, size_t i
 	int ret;
 
 	memset(instr, 0, sizeof(*instr));
+	instr->legpref.seg = -1;
 
 	fsm.is64bit = is_64bit(state);
 	fsm.is32bit = is_32bit(state);
@@ -2660,16 +2653,8 @@ store_to_gva(struct nvmm_x64_state *stat
 		if (store->hardseg != 0) {
 			seg = store->hardseg;
 		} else {
-			if (instr->legpref[LEG_OVR_CS]) {
-				seg = NVMM_X64_SEG_CS;
-			} else if (instr->legpref[LEG_OVR_SS]) {
-				seg = NVMM_X64_SEG_SS;
-			} else if (instr->legpref[LEG_OVR_ES]) {
-				seg = NVMM_X64_SEG_ES;
-			} else if (instr->legpref[LEG_OVR_FS]) {
-				seg = NVMM_X64_SEG_FS;
-			} else if (instr->legpref[LEG_OVR_GS]) {
-				seg = NVMM_X64_SEG_GS;
+			if (__predict_false(instr->legpref.seg != -1)) {
+				seg = instr->legpref.seg;
 			} else {
 				seg = NVMM_X64_SEG_DS;
 			}
@@ -2688,7 +2673,7 @@ static int
 fetch_segment(struct nvmm_machine *mach, struct nvmm_x64_state *state)
 {
 	uint8_t inst_bytes[15], byte;
-	size_t i, n, fetchsize;
+	size_t i, fetchsize;
 	gvaddr_t gva;
 	int ret, seg;
 
@@ -2707,17 +2692,33 @@ fetch_segment(struct nvmm_machine *mach,
 		return -1;
 
 	seg = NVMM_X64_SEG_DS;
-	for (n = 0; n < fetchsize; n++) {
-		byte = inst_bytes[n];
-		for (i = 0; i < NLEG; i++) {
-			if (byte != legpref_table[i].byte)
-				continue;
-			if (i >= LEG_OVR_CS && i <= LEG_OVR_GS)
-				seg = legpref_table[i].seg;
-			break;
-		}
-		if (i == NLEG) {
-			break;
+	for (i = 0; i < fetchsize; i++) {
+		byte = inst_bytes[i];
+
+		if (byte == LEG_OVR_DS) {
+			seg = NVMM_X64_SEG_DS;
+		} else if (byte == LEG_OVR_ES) {
+			seg = NVMM_X64_SEG_ES;
+		} else if (byte == LEG_OVR_GS) {
+			seg = NVMM_X64_SEG_GS;
+		} else if (byte == LEG_OVR_FS) {
+			seg = NVMM_X64_SEG_FS;
+		} else if (byte == LEG_OVR_CS) {
+			seg = NVMM_X64_SEG_CS;
+		} else if (byte == LEG_OVR_SS) {
+			seg = NVMM_X64_SEG_SS;
+		} else if (byte == LEG_OPR_OVR) {
+			/* nothing */
+		} else if (byte == LEG_ADR_OVR) {
+			/* nothing */
+		} else if (byte == LEG_REP) {
+			/* nothing */
+		} else if (byte == LEG_REPN) {
+			/* nothing */
+		} else if (byte == LEG_LOCK) {
+			/* nothing */
+		} else {
+			return seg;
 		}
 	}
 
@@ -2901,7 +2902,7 @@ nvmm_assist_mem(struct nvmm_machine *mac
 		return -1;
 	}
 
-	if (__predict_false(instr.legpref[LEG_REPN])) {
+	if (__predict_false(instr.legpref.repn)) {
 		errno = ENODEV;
 		return -1;
 	}
@@ -2916,7 +2917,7 @@ nvmm_assist_mem(struct nvmm_machine *mac
 		return -1;
 	}
 
-	if (instr.legpref[LEG_REP]) {
+	if (instr.legpref.rep) {
 		cnt = rep_dec_apply(&state, instr.address_size);
 		if (cnt == 0) {
 			state.gprs[NVMM_X64_GPR_RIP] += instr.len;

Reply via email to