summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2008-08-11 20:19:42 +0000
committerjhb <jhb@FreeBSD.org>2008-08-11 20:19:42 +0000
commit7109016dfefb93289c49d2b57bc01804c1ceaf04 (patch)
tree1ca977ac3788d5ff41fd77d4be63895765b59d49
parent4c2ecbd8bd352951ebc3b34777ff61daf6b3f219 (diff)
downloadFreeBSD-src-7109016dfefb93289c49d2b57bc01804c1ceaf04.zip
FreeBSD-src-7109016dfefb93289c49d2b57bc01804c1ceaf04.tar.gz
Decode some more "exotic" instructions including: fxsave, fxrstor, ldmxcsr,
stmxcsr, clflush, lfence, mfence, sfence, syscall, sysret, sysenter, sysexit, pause, monitor, mwait, and swapgs (amd64 only). MFC after: 1 week
-rw-r--r--sys/amd64/amd64/db_disasm.c77
-rw-r--r--sys/i386/i386/db_disasm.c72
2 files changed, 131 insertions, 18 deletions
diff --git a/sys/amd64/amd64/db_disasm.c b/sys/amd64/amd64/db_disasm.c
index ab7aa49..a6dbf69 100644
--- a/sys/amd64/amd64/db_disasm.c
+++ b/sys/amd64/amd64/db_disasm.c
@@ -164,15 +164,37 @@ static const char * const db_Grp9[] = {
""
};
+static const char * const db_Grp15[] = {
+ "fxsave",
+ "fxrstor",
+ "ldmxcsr",
+ "stmxcsr",
+ "",
+ "",
+ "",
+ "clflush"
+};
+
+static const char * const db_Grp15b[] = {
+ "",
+ "",
+ "",
+ "",
+ "",
+ "lfence",
+ "mfence",
+ "sfence"
+};
+
static const struct inst db_inst_0f0x[] = {
/*00*/ { "", TRUE, NONE, op1(Ew), db_Grp6 },
/*01*/ { "", TRUE, NONE, op1(Ew), db_Grp7 },
/*02*/ { "lar", TRUE, LONG, op2(E,R), 0 },
/*03*/ { "lsl", TRUE, LONG, op2(E,R), 0 },
/*04*/ { "", FALSE, NONE, 0, 0 },
-/*05*/ { "", FALSE, NONE, 0, 0 },
+/*05*/ { "syscall",FALSE,NONE, 0, 0 },
/*06*/ { "clts", FALSE, NONE, 0, 0 },
-/*07*/ { "", FALSE, NONE, 0, 0 },
+/*07*/ { "sysret",FALSE, NONE, 0, 0 },
/*08*/ { "invd", FALSE, NONE, 0, 0 },
/*09*/ { "wbinvd",FALSE, NONE, 0, 0 },
@@ -209,10 +231,10 @@ static const struct inst db_inst_0f3x[] = {
/*31*/ { "rdtsc", FALSE, NONE, 0, 0 },
/*32*/ { "rdmsr", FALSE, NONE, 0, 0 },
/*33*/ { "rdpmc", FALSE, NONE, 0, 0 },
-/*34*/ { "", FALSE, NONE, 0, 0 },
-/*35*/ { "", FALSE, NONE, 0, 0 },
+/*34*/ { "sysenter",FALSE,NONE, 0, 0 },
+/*35*/ { "sysexit",FALSE,NONE, 0, 0 },
/*36*/ { "", FALSE, NONE, 0, 0 },
-/*37*/ { "", FALSE, NONE, 0, 0 },
+/*37*/ { "getsec",FALSE, NONE, 0, 0 },
/*38*/ { "", FALSE, NONE, 0, 0 },
/*39*/ { "", FALSE, NONE, 0, 0 },
@@ -300,8 +322,8 @@ static const struct inst db_inst_0fax[] = {
/*ab*/ { "bts", TRUE, LONG, op2(R,E), 0 },
/*ac*/ { "shrd", TRUE, LONG, op3(Ib,R,E), 0 },
/*ad*/ { "shrd", TRUE, LONG, op3(CL,R,E), 0 },
-/*a6*/ { "", FALSE, NONE, 0, 0 },
-/*a7*/ { "imul", TRUE, LONG, op2(E,R), 0 },
+/*ae*/ { "", TRUE, LONG, op1(E), db_Grp15 },
+/*af*/ { "imul", TRUE, LONG, op2(E,R), 0 },
};
static const struct inst db_inst_0fbx[] = {
@@ -1123,6 +1145,7 @@ db_disasm(loc, altfmt)
boolean_t first;
int displ;
int prefix;
+ int rep;
int imm;
int imm2;
long imm64;
@@ -1137,6 +1160,7 @@ db_disasm(loc, altfmt)
/*
* Get prefixes
*/
+ rep = FALSE;
prefix = TRUE;
do {
switch (inst) {
@@ -1171,7 +1195,7 @@ db_disasm(loc, altfmt)
db_printf("repne ");
break;
case 0xf3:
- db_printf("repe "); /* XXX repe VS rep */
+ rep = TRUE;
break;
default:
prefix = FALSE;
@@ -1184,6 +1208,14 @@ db_disasm(loc, altfmt)
if (prefix) {
get_value_inc(inst, loc, 1, FALSE);
}
+ if (rep == TRUE) {
+ if (inst == 0x90) {
+ db_printf("pause\n");
+ return (loc);
+ }
+ db_printf("repe "); /* XXX repe VS rep */
+ rep = FALSE;
+ }
} while (prefix);
if (inst >= 0xd8 && inst <= 0xdf) {
@@ -1216,7 +1248,8 @@ db_disasm(loc, altfmt)
if (ip->i_extra == db_Grp1 || ip->i_extra == db_Grp2 ||
ip->i_extra == db_Grp6 || ip->i_extra == db_Grp7 ||
- ip->i_extra == db_Grp8 || ip->i_extra == db_Grp9) {
+ ip->i_extra == db_Grp8 || ip->i_extra == db_Grp9 ||
+ ip->i_extra == db_Grp15) {
i_name = ((const char * const *)ip->i_extra)[f_reg(rex, regmodrm)];
}
else if (ip->i_extra == db_Grp3) {
@@ -1233,6 +1266,32 @@ db_disasm(loc, altfmt)
i_size = ip->i_size;
}
+ /* Special cases that don't fit well in the tables. */
+ if (ip->i_extra == db_Grp7 && f_mod(rex, regmodrm) == 3) {
+ switch (regmodrm) {
+ case 0xc8:
+ i_name = "monitor";
+ i_size = NONE;
+ i_mode = 0;
+ break;
+ case 0xc9:
+ i_name = "mwait";
+ i_size = NONE;
+ i_mode = 0;
+ break;
+ case 0xf8:
+ i_name = "swapgs";
+ i_size = NONE;
+ i_mode = 0;
+ break;
+ }
+ }
+ if (ip->i_extra == db_Grp15 && f_mod(rex, regmodrm) == 3) {
+ i_name = db_Grp15b[f_reg(rex, regmodrm)];
+ i_size = NONE;
+ i_mode = 0;
+ }
+
if (i_size == SDEP) {
if (size == WORD)
db_printf("%s", i_name);
diff --git a/sys/i386/i386/db_disasm.c b/sys/i386/i386/db_disasm.c
index b193314..719c9f7 100644
--- a/sys/i386/i386/db_disasm.c
+++ b/sys/i386/i386/db_disasm.c
@@ -153,15 +153,37 @@ static const char * const db_Grp9[] = {
""
};
+static const char * const db_Grp15[] = {
+ "fxsave",
+ "fxrstor",
+ "ldmxcsr",
+ "stmxcsr",
+ "",
+ "",
+ "",
+ "clflush"
+};
+
+static const char * const db_Grp15b[] = {
+ "",
+ "",
+ "",
+ "",
+ "",
+ "lfence",
+ "mfence",
+ "sfence"
+};
+
static const struct inst db_inst_0f0x[] = {
/*00*/ { "", TRUE, NONE, op1(Ew), db_Grp6 },
/*01*/ { "", TRUE, NONE, op1(Ew), db_Grp7 },
/*02*/ { "lar", TRUE, LONG, op2(E,R), 0 },
/*03*/ { "lsl", TRUE, LONG, op2(E,R), 0 },
/*04*/ { "", FALSE, NONE, 0, 0 },
-/*05*/ { "", FALSE, NONE, 0, 0 },
+/*05*/ { "syscall",FALSE,NONE, 0, 0 },
/*06*/ { "clts", FALSE, NONE, 0, 0 },
-/*07*/ { "", FALSE, NONE, 0, 0 },
+/*07*/ { "sysret",FALSE, NONE, 0, 0 },
/*08*/ { "invd", FALSE, NONE, 0, 0 },
/*09*/ { "wbinvd",FALSE, NONE, 0, 0 },
@@ -198,10 +220,10 @@ static const struct inst db_inst_0f3x[] = {
/*31*/ { "rdtsc", FALSE, NONE, 0, 0 },
/*32*/ { "rdmsr", FALSE, NONE, 0, 0 },
/*33*/ { "rdpmc", FALSE, NONE, 0, 0 },
-/*34*/ { "", FALSE, NONE, 0, 0 },
-/*35*/ { "", FALSE, NONE, 0, 0 },
+/*34*/ { "sysenter",FALSE,NONE, 0, 0 },
+/*35*/ { "sysexit",FALSE,NONE, 0, 0 },
/*36*/ { "", FALSE, NONE, 0, 0 },
-/*37*/ { "", FALSE, NONE, 0, 0 },
+/*37*/ { "getsec",FALSE, NONE, 0, 0 },
/*38*/ { "", FALSE, NONE, 0, 0 },
/*39*/ { "", FALSE, NONE, 0, 0 },
@@ -289,8 +311,8 @@ static const struct inst db_inst_0fax[] = {
/*ab*/ { "bts", TRUE, LONG, op2(R,E), 0 },
/*ac*/ { "shrd", TRUE, LONG, op3(Ib,R,E), 0 },
/*ad*/ { "shrd", TRUE, LONG, op3(CL,R,E), 0 },
-/*a6*/ { "", FALSE, NONE, 0, 0 },
-/*a7*/ { "imul", TRUE, LONG, op2(E,R), 0 },
+/*ae*/ { "", TRUE, LONG, op1(E), db_Grp15 },
+/*af*/ { "imul", TRUE, LONG, op2(E,R), 0 },
};
static const struct inst db_inst_0fbx[] = {
@@ -1122,6 +1144,7 @@ db_disasm(loc, altfmt)
boolean_t first;
int displ;
int prefix;
+ int rep;
int imm;
int imm2;
int len;
@@ -1135,6 +1158,7 @@ db_disasm(loc, altfmt)
/*
* Get prefixes
*/
+ rep = FALSE;
prefix = TRUE;
do {
switch (inst) {
@@ -1169,7 +1193,7 @@ db_disasm(loc, altfmt)
db_printf("repne ");
break;
case 0xf3:
- db_printf("repe "); /* XXX repe VS rep */
+ rep = TRUE;
break;
default:
prefix = FALSE;
@@ -1178,6 +1202,14 @@ db_disasm(loc, altfmt)
if (prefix) {
get_value_inc(inst, loc, 1, FALSE);
}
+ if (rep == TRUE) {
+ if (inst == 0x90) {
+ db_printf("pause\n");
+ return (loc);
+ }
+ db_printf("repe "); /* XXX repe VS rep */
+ rep = FALSE;
+ }
} while (prefix);
if (inst >= 0xd8 && inst <= 0xdf) {
@@ -1210,7 +1242,8 @@ db_disasm(loc, altfmt)
if (ip->i_extra == db_Grp1 || ip->i_extra == db_Grp2 ||
ip->i_extra == db_Grp6 || ip->i_extra == db_Grp7 ||
- ip->i_extra == db_Grp8 || ip->i_extra == db_Grp9) {
+ ip->i_extra == db_Grp8 || ip->i_extra == db_Grp9 ||
+ ip->i_extra == db_Grp15) {
i_name = ((const char * const *)ip->i_extra)[f_reg(regmodrm)];
}
else if (ip->i_extra == db_Grp3) {
@@ -1227,6 +1260,27 @@ db_disasm(loc, altfmt)
i_size = ip->i_size;
}
+ /* Special cases that don't fit well in the tables. */
+ if (ip->i_extra == db_Grp7 && f_mod(regmodrm) == 3) {
+ switch (regmodrm) {
+ case 0xc8:
+ i_name = "monitor";
+ i_size = NONE;
+ i_mode = 0;
+ break;
+ case 0xc9:
+ i_name = "mwait";
+ i_size = NONE;
+ i_mode = 0;
+ break;
+ }
+ }
+ if (ip->i_extra == db_Grp15 && f_mod(regmodrm) == 3) {
+ i_name = db_Grp15b[f_reg(regmodrm)];
+ i_size = NONE;
+ i_mode = 0;
+ }
+
if (i_size == SDEP) {
if (size == WORD)
db_printf("%s", i_name);
OpenPOWER on IntegriCloud