Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libnvmm Optimize the legpref node: omit BRN (we don't ca...



details:   https://anonhg.NetBSD.org/src/rev/153e0fa9bc69
branches:  trunk
changeset: 447326:153e0fa9bc69
user:      maxv <maxv%NetBSD.org@localhost>
date:      Mon Jan 07 18:13:34 2019 +0000

description:
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.

diffstat:

 lib/libnvmm/libnvmm_x86.c |  171 +++++++++++++++++++++++----------------------
 1 files changed, 86 insertions(+), 85 deletions(-)

diffs (283 lines):

diff -r 56132c3d63a2 -r 153e0fa9bc69 lib/libnvmm/libnvmm_x86.c
--- a/lib/libnvmm/libnvmm_x86.c Mon Jan 07 18:08:28 2019 +0000
+++ b/lib/libnvmm/libnvmm_x86.c Mon Jan 07 18:13:34 2019 +0000
@@ -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_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_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 @@
                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 @@
 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 @@
        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 (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 {
+               /* not a legacy prefix */
+               fsm_advance(fsm, 0, node_rex_prefix);
+               return 0;
        }
 
-       if (i == NLEG) {
-               fsm->fn = node_rex_prefix;
-       } else {
-               instr->legpref[i] = true;
-               fsm_advance(fsm, 1, node_legacy_prefix);
-       }
-
+       fsm_advance(fsm, 1, node_legacy_prefix);
        return 0;
 }
 
@@ -2400,6 +2392,7 @@
        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 @@
                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 @@
 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 @@
                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 @@
                return -1;
        }
 
-       if (__predict_false(instr.legpref[LEG_REPN])) {
+       if (__predict_false(instr.legpref.repn)) {
                errno = ENODEV;
                return -1;
        }
@@ -2916,7 +2917,7 @@
                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;



Home | Main Index | Thread Index | Old Index