Module Name:    src
Committed By:   msaitoh
Date:           Tue May 12 19:24:57 UTC 2015

Modified Files:
        src/sys/arch/amd64/amd64: db_disasm.c
        src/sys/arch/i386/i386: db_disasm.c

Log Message:
Catch up FreeBSD and OpenBSD's changes. Not completed but it's better than
before:
- Add support rdrand, rdseed, fxrstor, ldmxcsr, stmxcsr, xsare, xrstor,
  xsaveopt, cflush and some others.
- Check REX bit correctly.
- Print correct register.
- Fix a lot of bugs.
- KNF.


To generate a diff of this commit:
cvs rdiff -u -r1.20 -r1.21 src/sys/arch/amd64/amd64/db_disasm.c
cvs rdiff -u -r1.45 -r1.46 src/sys/arch/i386/i386/db_disasm.c

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

Modified files:

Index: src/sys/arch/amd64/amd64/db_disasm.c
diff -u src/sys/arch/amd64/amd64/db_disasm.c:1.20 src/sys/arch/amd64/amd64/db_disasm.c:1.21
--- src/sys/arch/amd64/amd64/db_disasm.c:1.20	Thu Oct 23 10:01:53 2014
+++ src/sys/arch/amd64/amd64/db_disasm.c	Tue May 12 19:24:57 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: db_disasm.c,v 1.20 2014/10/23 10:01:53 msaitoh Exp $	*/
+/*	$NetBSD: db_disasm.c,v 1.21 2015/05/12 19:24:57 msaitoh Exp $	*/
 
 /* 
  * Mach Operating System
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.20 2014/10/23 10:01:53 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.21 2015/05/12 19:24:57 msaitoh Exp $");
 
 #ifndef _KERNEL
 #include <sys/types.h>
@@ -68,6 +68,15 @@ __KERNEL_RCSID(0, "$NetBSD: db_disasm.c,
 #define	NONE	8
 
 /*
+ * REX prefix and bits
+ */
+#define REX_B	1
+#define REX_X	2
+#define REX_R	4
+#define REX_W	8
+#define REX	0x40
+
+/*
  * Addressing modes
  */
 #define	E	1			/* general effective address */
@@ -106,6 +115,7 @@ __KERNEL_RCSID(0, "$NetBSD: db_disasm.c,
 #define	XA	34			/* for 'fstcw %ax' */
 #define	Ed	35			/* address, double size */
 #define	Iq	36			/* word immediate, maybe 64bits */
+#define	Rv	40			/* register in 'r/m' field */
 
 struct inst {
 	const char *i_name;		/* name */
@@ -171,6 +181,17 @@ const char * const db_Grp9[] = {
 	"vmptrst"
 };
 
+const struct inst db_Grp9b[] = {
+	{ "",      true, NONE, 0,	 0 },
+	{ "",      true, NONE, 0,	 0 },
+	{ "",      true, NONE, 0,	 0 },
+	{ "",      true, NONE, 0,	 0 },
+	{ "",      true, NONE, 0,	 0 },
+	{ "",      true, NONE, 0,	 0 },
+	{ "rdrand",true, LONG, op1(Rv),	 0 },
+	{ "rdseed",true, LONG, op1(Rv),	 0 }
+};
+
 const struct inst db_inst_0f0x[] = {
 /*00*/	{ "",	   true,  NONE,  op1(Ew),     db_Grp6 },
 /*01*/	{ "",	   true,  NONE,  op1(Ew),     db_Grp7 },
@@ -191,6 +212,26 @@ const struct inst db_inst_0f0x[] = {
 /*0f*/	{ "",      false, NONE,  0,	      0 },  /* 3DNow */
 };
 
+const struct inst db_inst_0f1x[] = {
+/*10*/	{ "",      FALSE, NONE,  0,	      0 },
+/*11*/	{ "",      FALSE, NONE,  0,	      0 },
+/*12*/	{ "",      FALSE, NONE,  0,	      0 },
+/*13*/	{ "",      FALSE, NONE,  0,	      0 },
+/*14*/	{ "",      FALSE, NONE,  0,	      0 },
+/*15*/	{ "",      FALSE, NONE,  0,	      0 },
+/*16*/	{ "",      FALSE, NONE,  0,	      0 },
+/*17*/	{ "",      FALSE, NONE,  0,	      0 },
+
+/*18*/	{ "",      FALSE, NONE,  0,	      0 },
+/*19*/	{ "",      FALSE, NONE,  0,	      0 },
+/*1a*/	{ "",      FALSE, NONE,  0,	      0 },
+/*1b*/	{ "",      FALSE, NONE,  0,	      0 },
+/*1c*/	{ "",      FALSE, NONE,  0,	      0 },
+/*1d*/	{ "",      FALSE, NONE,  0,	      0 },
+/*1e*/	{ "",      FALSE, NONE,  0,	      0 },
+/*1f*/	{ "nopl",  TRUE,  SDEP,  0,	      "nopw" },
+};
+
 const struct inst db_inst_0f2x[] = {
 /*20*/	{ "mov",   true,  LONG,  op2(CR,E),   0 }, /* use E for reg */
 /*21*/	{ "mov",   true,  LONG,  op2(DR,E),   0 }, /* since mod == 11 */
@@ -352,7 +393,7 @@ const struct inst db_inst_0fcx[] = {
 
 const struct inst * const db_inst_0f[] = {
 	db_inst_0f0x,
-	NULL,
+	db_inst_0f1x,
 	db_inst_0f2x,
 	db_inst_0f3x,
 	db_inst_0f4x,
@@ -852,13 +893,13 @@ const struct inst db_bad_inst =
 	{ "???",   false, NONE,  0,	      0 }
 ;
 
-#define	f_mod(byte)	((byte)>>6)
-#define	f_reg(byte)	(((byte)>>3)&0x7)
-#define	f_rm(byte)	((byte)&0x7)
-
-#define	sib_ss(byte)	((byte)>>6)
-#define	sib_index(byte)	(((byte)>>3)&0x7)
-#define	sib_base(byte)	((byte)&0x7)
+#define	f_mod(rex, byte)	((byte)>>6)
+#define	f_reg(rex, byte)	((((byte)>>3)&0x7) | (rex & REX_R ? 0x8 : 0x0))
+#define	f_rm(rex, byte)		(((byte)&0x7) | (rex & REX_B ? 0x8 : 0x0))
+
+#define	sib_ss(rex, byte)	((byte)>>6)
+#define	sib_index(rex, byte)	((((byte)>>3)&0x7) | (rex & REX_X ? 0x8 : 0x0))
+#define	sib_base(rex, byte)	(((byte)&0x7) | (rex & REX_B ? 0x8 : 0x0))
 
 struct i_addr {
 	int		is_reg;	/* if reg, reg number is in 'disp' */
@@ -882,18 +923,25 @@ const char * const db_index_reg_32[8] = 
 #define DB_REG_DFLT	0
 #define DB_REG_REX	1
 
-const char * const db_reg[2][4][8] = {
-{
-    { "%al",  "%cl",  "%dl",  "%bl",  "%ah",  "%ch",  "%dh",  "%bh" },
-    { "%ax",  "%cx",  "%dx",  "%bx",  "%sp",  "%bp",  "%si",  "%di" },
-    { "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi" },
-    { "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi" }
-}, {
-    { "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b" },
-    { "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" },
-    { "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" },
-    { "%r8",  "%r9",  "%r10",  "%r11",  "%r12",  "%r13",  "%r14",  "%r15" }
-}};
+const char * const db_reg[2][4][16] = {
+	{{"%al",  "%cl",  "%dl",  "%bl",  "%ah",  "%ch",  "%dh",  "%bh",
+	  "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"},
+	 {"%ax",  "%cx",  "%dx",  "%bx",  "%sp",  "%bp",  "%si",  "%di",
+	  "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"},
+	 {"%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
+	  "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"},
+	 {"%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
+	  "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" }},
+
+	{{"%al",  "%cl",  "%dl",  "%bl",  "%spl",  "%bpl",  "%sil",  "%dil",
+	  "%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"},
+	 {"%ax",  "%cx",  "%dx",  "%bx",  "%sp",  "%bp",  "%si",  "%di",
+	  "%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w" },
+	 {"%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
+	  "%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d" },
+	 {"%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
+	  "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15" }}
+};
 
 const char * const db_seg_reg[8] = {
 	"%es", "%cs", "%ss", "%ds", "%fs", "%gs", "", ""
@@ -912,23 +960,6 @@ const int db_lengths[] = {
 	10,	/* EXTR */
 };
 
-#define	REX      	0x00
-#define	REX_b    	0x01
-#define	REX_x    	0x02
-#define	REX_xb   	0x03
-#define	REX_r    	0x04
-#define	REX_rb   	0x05
-#define	REX_rx   	0x06
-#define	REX_rxb  	0x07
-#define	REX_w    	0x08
-#define	REX_wb   	0x09
-#define	REX_wx   	0x0a
-#define	REX_wxb  	0x0b
-#define	REX_wr   	0x0c
-#define	REX_wrb  	0x0d
-#define	REX_wrx  	0x0e
-#define	REX_wrxb 	0x0f
-
 const char * const rex_str[0x10] = {
 	"rex      ",    /* 0x40 */
 	"rex.b    ",    /* 0x41 */
@@ -955,7 +986,7 @@ const char * const rex_str[0x10] = {
 	} while (0)
 
 
-db_addr_t db_read_address(db_addr_t, u_int, int, int, struct i_addr *);
+db_addr_t db_read_address(db_addr_t, int, u_int, int, struct i_addr *);
 void db_print_address(const char *, u_int, int, struct i_addr *);
 db_addr_t db_disasm_esc(db_addr_t, int, u_int, int, int, const char *);
 
@@ -963,14 +994,15 @@ db_addr_t db_disasm_esc(db_addr_t, int, 
  * Read address at location and return updated location.
  */
 db_addr_t
-db_read_address(db_addr_t loc, u_int rex, int short_addr, int regmodrm,
+db_read_address(db_addr_t loc, int short_addr, u_int rex, int regmodrm,
     struct i_addr *addrp)
 	/* addrp:		 out */
 {
-	int		mod, rm, sib, index, disp, ext;
+	int		mod, rm, sib, index, disp, size, have_sib;
 
-	mod = f_mod(regmodrm);
-	rm  = f_rm(regmodrm);
+	size = (short_addr ? LONG : QUAD);
+	mod = f_mod(rex, regmodrm);
+	rm  = f_rm(rex, regmodrm);
 
 	if (mod == 3) {
 		addrp->is_reg = true;
@@ -980,76 +1012,42 @@ db_read_address(db_addr_t loc, u_int rex
 	addrp->is_reg = false;
 	addrp->index = 0;
 
-	if (short_addr) {
-		/* x86_64 32 bit address mode */
-		if (mod != 3 && rm == 4) {
-			ext = ((rex & REX_x) != 0);
-			get_value_inc(sib, loc, 1, false);
-			rm = sib_base(sib);
-			index = sib_index(sib);
-			if (index != 4)
-				addrp->index = db_reg[ext][LONG][index];
-			addrp->ss = sib_ss(sib);
-		}
-
-		ext = ((rex & REX_b) != 0);
-		switch (mod) {
-		case 0:
-			if (rm == 5) {
-				get_value_inc(addrp->disp, loc, 4, false);
+	if ((rm & 0x7) == 4) {
+		get_value_inc(sib, loc, 1, false);
+		rm = sib_base(rex, sib);
+		index = sib_index(rex, sib);
+		if (index != 4)
+			addrp->index = db_reg[1][size][index];
+		addrp->ss = sib_ss(rex, sib);
+		have_sib = 1;
+	} else
+		have_sib = 0;
+
+	switch (mod) {
+	case 0:
+		if (rm == 5) {
+			get_value_inc(addrp->disp, loc, 4, false);
+			if (have_sib)
 				addrp->base = 0;
-			} else {
-				addrp->disp = 0;
-				addrp->base = db_reg[ext][LONG][rm];
-			}
-			break;
-		case 1:
-			get_value_inc(disp, loc, 1, true);
-			addrp->disp = disp;
-			addrp->base = db_reg[ext][LONG][rm];
-			break;
-		case 2:
-			get_value_inc(disp, loc, 4, false);
-			addrp->disp = disp;
-			addrp->base = db_reg[ext][LONG][rm];
-			break;
-		}
-	} else {
-		/* x86_64 64 bit address mode */
-
-		if (mod != 3 && rm == 4) {
-			ext = ((rex & REX_x) != 0);
-			get_value_inc(sib, loc, 1, false);
-			rm = sib_base(sib);
-			index = sib_index(sib);
-			if (index != 4)
-				addrp->index = db_reg[ext][QUAD][index];
-			addrp->ss = sib_ss(sib);
-		}
-
-		ext = ((rex & REX_b) != 0);
-		switch (mod) {
-		case 0:
-			if (rm == 5) {
-				/* x86_64 RIP-relative addressing */
-				get_value_inc(addrp->disp, loc, 4, false);
+			else if (short_addr)
+				addrp->base = "%eip";
+			else
 				addrp->base = "%rip";
-			} else {
-				addrp->disp = 0;
-				addrp->base = db_reg[ext][QUAD][rm];
-			}
-			break;
-		case 1:
-			get_value_inc(disp, loc, 1, true);
-			addrp->disp = disp;
-			addrp->base = db_reg[ext][QUAD][rm];
-			break;
-		case 2:
-			get_value_inc(disp, loc, 4, false);
-			addrp->disp = disp;
-			addrp->base = db_reg[ext][QUAD][rm];
-			break;
+		} else {
+			addrp->disp = 0;
+			addrp->base = db_reg[1][size][rm];
 		}
+		break;
+	case 1:
+		get_value_inc(disp, loc, 1, true);
+		addrp->disp = disp;
+		addrp->base = db_reg[1][size][rm];
+		break;
+	case 2:
+		get_value_inc(disp, loc, 4, false);
+		addrp->disp = disp;
+		addrp->base = db_reg[1][size][rm];
+		break;
 	}
 	return (loc);
 }
@@ -1058,7 +1056,7 @@ void
 db_print_address(const char * seg, u_int rex, int size, struct i_addr *addrp)
 {
 	if (addrp->is_reg) {
-		int ext = ((rex & REX_b) != 0);
+		int ext = ((rex & REX_B) != 0);
 		db_printf("%s", db_reg[ext][size][addrp->disp]);
 		return;
 	}
@@ -1093,13 +1091,17 @@ db_disasm_esc(db_addr_t loc, int inst, u
 	const char *	name;
 
 	get_value_inc(regmodrm, loc, 1, false);
-	fp = &db_Esc_inst[inst - 0xd8][f_reg(regmodrm)];
-	mod = f_mod(regmodrm);
+	fp = &db_Esc_inst[inst - 0xd8][f_reg(rex, regmodrm)];
+	mod = f_mod(rex, regmodrm);
 	if (mod != 3) {
+		if (*fp->f_name == '\0') {
+			db_printf("<bad instruction>");
+			return (loc);
+		}
 		/*
 		 * Normal address modes.
 		 */
-		loc = db_read_address(loc, rex, short_addr, regmodrm, &address);
+		loc = db_read_address(loc, short_addr, rex, regmodrm, &address);
 		db_printf("%s", fp->f_name);
 		switch (fp->f_size) {
 		case SNGL:
@@ -1132,24 +1134,30 @@ db_disasm_esc(db_addr_t loc, int inst, u
 		switch (fp->f_rrmode) {
 		case op2(ST,STI):
 			name = (fp->f_rrname) ? fp->f_rrname : fp->f_name;
-			db_printf("%s\t%%st,%%st(%d)", name, f_rm(regmodrm));
+			db_printf("%s\t%%st,%%st(%d)", name, f_rm(rex, regmodrm));
 			break;
 		case op2(STI,ST):
 			name = (fp->f_rrname) ? fp->f_rrname : fp->f_name;
-			db_printf("%s\t%%st(%d),%%st", name, f_rm(regmodrm));
+			db_printf("%s\t%%st(%d),%%st", name, f_rm(rex, regmodrm));
 			break;
 		case op1(STI):
 			name = (fp->f_rrname) ? fp->f_rrname : fp->f_name;
-			db_printf("%s\t%%st(%d)", name, f_rm(regmodrm));
+			db_printf("%s\t%%st(%d)", name, f_rm(rex, regmodrm));
 			break;
 		case op1(X):
-			db_printf("%s", ((const char * const *)fp->f_rrname)[f_rm(regmodrm)]);
+			name = ((const char * const *)fp->f_rrname)[f_rm(rex, regmodrm)];
+			if (*name == '\0')
+				goto bad;
+			db_printf("%s", name);
 			break;
 		case op1(XA):
-			db_printf("%s\t%%ax",
-			    ((const char * const *)fp->f_rrname)[f_rm(regmodrm)]);
+			name = ((const char * const *)fp->f_rrname)[f_rm(rex, regmodrm)];
+			if (*name == '\0')
+				goto bad;
+			db_printf("%s\t%%ax", name);
 			break;
 		default:
+		bad:
 			db_printf("<bad instruction>");
 			break;
 		}
@@ -1216,9 +1224,6 @@ db_disasm(db_addr_t loc, bool altfmt)
 	 */
 	prefix = true;
 	do {
-		if ((inst & 0xf0) == 0x40) {
-			rex |= inst;
-		} else
 		switch (inst) {
 		case 0x66:		/* data16 */
 			size = WORD;
@@ -1257,12 +1262,16 @@ db_disasm(db_addr_t loc, bool altfmt)
 			prefix = false;
 			break;
 		}
+		if (inst >= 0x40 && inst <= 0x4f) {
+			rex = inst;
+			prefix = true;
+		}
 		if (prefix)
 			get_value_inc(inst, loc, 1, false);
 	} while (prefix);
 
 	if (rex != 0) {
-		if (rex & REX_w)
+		if (rex & REX_W)
 			size = QUAD;
 		if (altfmt == true)				/* XXX */
 			db_printf("%s", rex_str[rex & 0x0f]);
@@ -1287,14 +1296,19 @@ db_disasm(db_addr_t loc, bool altfmt)
 
 	if (ip->i_has_modrm) {
 		get_value_inc(regmodrm, loc, 1, false);
-		loc = db_read_address(loc, rex, short_addr, regmodrm, &address);
+		loc = db_read_address(loc, short_addr, rex, regmodrm, &address);
 	}
 
 	i_name = ip->i_name;
 	i_size = ip->i_size;
 	i_mode = ip->i_mode;
 
-	if (ip->i_extra == (const char *)db_Grp1 ||
+	if (ip->i_extra == db_Grp9 && f_mod(rex, regmodrm) == 3) {
+		ip = &db_Grp9b[f_reg(rex, regmodrm)];
+		i_name = ip->i_name;
+		i_size = ip->i_size;
+		i_mode = ip->i_mode;
+	} else if (ip->i_extra == (const char *)db_Grp1 ||
 	    ip->i_extra == (const char *)db_Grp2 ||
 	    ip->i_extra == (const char *)db_Grp6 ||
 	    ip->i_extra == (const char *)db_Grp7 ||
@@ -1305,24 +1319,24 @@ db_disasm(db_addr_t loc, bool altfmt)
 			i_mode = 0;
 		} else {
 			i_name = ((const char * const *)ip->i_extra)
-			    [f_reg(regmodrm)];
+			    [f_reg(rex, regmodrm)];
 		}
 	} else if (ip->i_extra == (const char *)db_Grp3) {
 		ip = (const struct inst *)ip->i_extra;
-		ip = &ip[f_reg(regmodrm)];
+		ip = &ip[f_reg(rex, regmodrm)];
 		i_name = ip->i_name;
 		i_mode = ip->i_mode;
 	} else if (ip->i_extra == (const char *)db_Grp4 ||
-		   ip->i_extra == (const char *)db_Grp5) {
+	    ip->i_extra == (const char *)db_Grp5) {
 		ip = (const struct inst *)ip->i_extra;
-		ip = &ip[f_reg(regmodrm)];
+		ip = &ip[f_reg(rex, regmodrm)];
 		i_name = ip->i_name;
 		i_mode = ip->i_mode;
 		i_size = ip->i_size;
 	}
 
 	if (i_size == SDEP) {
-		if (size == WORD)
+		if (size == LONG)
 			db_printf("%s", i_name);
 		else
 			db_printf("%s", (const char *)ip->i_extra);
@@ -1348,9 +1362,7 @@ db_disasm(db_addr_t loc, bool altfmt)
 		}
 	}
 	db_printf("\t");
-	for (first = true;
-	     i_mode != 0;
-	     i_mode >>= 8, first = false) {
+	for (first = true; i_mode != 0; i_mode >>= 8, first = false) {
 		char tbuf[24];
 
 		if (!first)
@@ -1374,25 +1386,24 @@ db_disasm(db_addr_t loc, bool altfmt)
 			db_print_address(seg, rex, BYTE, &address);
 			break;
 		case R: {
-			int ext = ((rex & REX_r) != 0);
-			db_printf("%s", db_reg[ext][size][f_reg(regmodrm)]);
+			int ext = ((rex & REX_R) != 0);
+			db_printf("%s", db_reg[ext][size][f_reg(rex, regmodrm)]);
 			break;
 		    }
 		case Rw: {
-			int ext = ((rex & REX_r) != 0);
-			db_printf("%s", db_reg[ext][WORD][f_reg(regmodrm)]);
+			int ext = ((rex & REX_R) != 0);
+			db_printf("%s", db_reg[ext][WORD][f_reg(rex, regmodrm)]);
 			break;
 		    }
 		case Ri: {
-			int ext = ((rex & REX_b) != 0);
-			db_printf("%s", db_reg[ext][size][f_rm(inst)]);
+			db_printf("%s", db_reg[0][size][f_rm(rex, inst)]);
 			break;
 		    }
 		case S:
-			db_printf("%s", db_seg_reg[f_reg(regmodrm)]);
+			db_printf("%s", db_seg_reg[f_reg(rex, regmodrm)]);
 			break;
 		case Si:
-			db_printf("%s", db_seg_reg[f_reg(inst)]);
+			db_printf("%s", db_seg_reg[f_reg(rex, inst)]);
 			break;
 		case A:
 			db_printf("%s", db_reg[0][size][0]);	/* acc */
@@ -1417,13 +1428,13 @@ db_disasm(db_addr_t loc, bool altfmt)
 			db_printf("%%es:(%s)", short_addr ? "%edi" : "%rdi");
 			break;
 		case CR:
-			db_printf("%%cr%d", f_reg(regmodrm));
+			db_printf("%%cr%d", f_reg(rex, regmodrm));
 			break;
 		case DR:
-			db_printf("%%dr%d", f_reg(regmodrm));
+			db_printf("%%dr%d", f_reg(rex, regmodrm));
 			break;
 		case TR:
-			db_printf("%%tr%d", f_reg(regmodrm));
+			db_printf("%%tr%d", f_reg(rex, regmodrm));
 			break;
 		case Iq:
 			if (size == QUAD) {

Index: src/sys/arch/i386/i386/db_disasm.c
diff -u src/sys/arch/i386/i386/db_disasm.c:1.45 src/sys/arch/i386/i386/db_disasm.c:1.46
--- src/sys/arch/i386/i386/db_disasm.c:1.45	Tue May 12 05:18:50 2015
+++ src/sys/arch/i386/i386/db_disasm.c	Tue May 12 19:24:57 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: db_disasm.c,v 1.45 2015/05/12 05:18:50 msaitoh Exp $	*/
+/*	$NetBSD: db_disasm.c,v 1.46 2015/05/12 19:24:57 msaitoh Exp $	*/
 
 /* 
  * Mach Operating System
@@ -33,7 +33,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.45 2015/05/12 05:18:50 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_disasm.c,v 1.46 2015/05/12 19:24:57 msaitoh Exp $");
 
 #include <sys/param.h>
 #include <sys/proc.h>
@@ -56,6 +56,7 @@ __KERNEL_RCSID(0, "$NetBSD: db_disasm.c,
 #define	EXTR	6
 #define	SDEP	7
 #define	NONE	8
+#define	RDEP	9
 
 /*
  * Addressing modes
@@ -94,6 +95,10 @@ __KERNEL_RCSID(0, "$NetBSD: db_disasm.c,
 #define	STI	32			/* FP stack */
 #define	X	33			/* extended FP op */
 #define	XA	34			/* for 'fstcw %ax' */
+#define	El	35			/* address, long size */
+#define	Ril	36			/* long register in instruction */
+#define	Iba	37			/* byte immediate, don't print if 0xa */
+#define	MEx	38			/* memory, or an extension op */
 
 struct inst {
 	const char *i_name;		/* name */
@@ -126,15 +131,15 @@ const char * const db_Grp6[] = {
 	""
 };
 
-const char * const db_Grp7[] = {
-	"sgdt",
-	"sidt",
-	"lgdt",
-	"lidt",
-	"smsw",
-	"",
-	"lmsw",
-	"invlpg"
+struct inst db_Grp7[] = {
+	{ "sgdt",   FALSE, NONE, op1(E),     0 },
+	{ "sidt",   FALSE, NONE, op2(MEx,4), "monitor\0mwait\0clac\0stac"},
+	{ "lgdt",   FALSE, NONE, op2(MEx,2), "xgetbv\0xsetbv" },
+	{ "lidt",   FALSE, NONE, op1(E),     0 },
+	{ "smsw",   FALSE, NONE, op1(E),     0 },
+	{ "",       FALSE, NONE, 0,          0 },
+	{ "lmsw",   FALSE, NONE, op1(E),     0 },
+	{ "invlpg", FALSE, NONE, op2(MEx,2), "swapgs\0rdtscp" },
 };
 
 const char * const db_Grp8[] = {
@@ -148,20 +153,35 @@ const char * const db_Grp8[] = {
 	"btc"
 };
 
-const char * const db_Grp9[] = {
-	"",
-	"cmpxchg8b",
-	"",
-	"",
-	"",
-	"",
-	"",
-	"",
+struct inst db_Grp9[] = {
+	{ "fxsave",   FALSE, NONE, op1(E),     0 },
+	{ "fxrstor",  FALSE, NONE, op1(E),     0 },
+	{ "ldmxcsr",  FALSE, NONE, op1(E),     0 },
+	{ "stmxcsr",  FALSE, NONE, op1(E),     0 },
+	{ "xsave",    FALSE, NONE, op1(E),     0 },
+	{ "xrstor",   FALSE, NONE, op2(MEx,1), "lfence" },
+	{ "xsaveopt", FALSE, NONE, op2(MEx,1), "mfence" },
+	{ "clflush",  FALSE, NONE, op2(MEx,1), "sfence" },
+};
+
+const char * db_GrpA[] = {
+	"",		"cmpxchg8b",	"",		"",
+	"",		"",		"rdrand",	"rdseed"
+};
+
+const char * db_GrpB[] = {
+	"xstore-rng",	"xcrypt-ecb",	"xcrypt-cbc",	"xcrypt-ctr",
+	"xcrypt-cfb",	"xcrypt-ofb",	"",		""
+};
+
+const char * db_GrpC[] = {
+	"montmul",	"xsha1",	"xsha256",	"",
+	"",		"",		"",		""
 };
 
 const struct inst db_inst_0f0x[] = {
-/*00*/	{ "",	   true,  NONE,  op1(Ew),     db_Grp6 },
-/*01*/	{ "",	   true,  NONE,  op1(Ew),     db_Grp7 },
+/*00*/	{ NULL,	   true,  NONE,  op1(Ew),     db_Grp6 },
+/*01*/	{ "",	   true,  RDEP,  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 },
@@ -180,13 +200,13 @@ const struct inst db_inst_0f0x[] = {
 };
 
 const struct inst db_inst_0f2x[] = {
-/*20*/	{ "mov",   true,  LONG,  op2(CR,E),   0 }, /* use E for reg */
-/*21*/	{ "mov",   true,  LONG,  op2(DR,E),   0 }, /* since mod == 11 */
-/*22*/	{ "mov",   true,  LONG,  op2(E,CR),   0 },
-/*23*/	{ "mov",   true,  LONG,  op2(E,DR),   0 },
-/*24*/	{ "mov",   true,  LONG,  op2(TR,E),   0 },
+/*20*/	{ "mov",   true,  LONG,  op2(CR,El),  0 },
+/*21*/	{ "mov",   true,  LONG,  op2(DR,El),  0 },
+/*22*/	{ "mov",   true,  LONG,  op2(El,CR),  0 },
+/*23*/	{ "mov",   true,  LONG,  op2(El,DR),  0 },
+/*24*/	{ "mov",   true,  LONG,  op2(TR,El),  0 },
 /*25*/	{ "",      false, NONE,  0,	      0 },
-/*26*/	{ "mov",   true,  LONG,  op2(E,TR),   0 },
+/*26*/	{ "mov",   true,  LONG,  op2(El,TR),  0 },
 /*27*/	{ "",      false, NONE,  0,	      0 },
 
 /*28*/	{ "",      false, NONE,  0,	      0 },
@@ -286,8 +306,8 @@ const struct inst db_inst_0fax[] = {
 /*a3*/	{ "bt",    true,  LONG,  op2(R,E),    0 },
 /*a4*/	{ "shld",  true,  LONG,  op3(Ib,R,E), 0 },
 /*a5*/	{ "shld",  true,  LONG,  op3(CL,R,E), 0 },
-/*a6*/	{ "",      false, NONE,  0,	      0 },
-/*a7*/	{ "",      false, NONE,  0,	      0 },
+/*a6*/	{ NULL,    true,  NONE,  0,	      db_GrpC },
+/*a7*/	{ NULL,    true,  NONE,  0,	      db_GrpB },
 
 /*a8*/	{ "push",  false, NONE,  op1(Si),     0 },
 /*a9*/	{ "pop",   false, NONE,  op1(Si),     0 },
@@ -295,7 +315,7 @@ 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 },
-/*ae*/	{ "fxsave",true,  LONG,  0,	      0 },
+/*ae*/	{ "",      TRUE,  RDEP,  op1(E),      db_Grp9 },
 /*af*/	{ "imul",  true,  LONG,  op2(E,R),    0 },
 };
 
@@ -311,7 +331,7 @@ const struct inst db_inst_0fbx[] = {
 
 /*b8*/	{ "",      false, NONE,  0,	      0 },
 /*b9*/	{ "",      false, NONE,  0,	      0 },
-/*ba*/	{ "",      true,  LONG,  op2(Ib, E),  db_Grp8 },
+/*ba*/	{ NULL,    true,  LONG,  op2(Ib, E),  db_Grp8 },
 /*bb*/	{ "btc",   true,  LONG,  op2(R, E),   0 },
 /*bc*/	{ "bsf",   true,  LONG,  op2(E, R),   0 },
 /*bd*/	{ "bsr",   true,  LONG,  op2(E, R),   0 },
@@ -327,16 +347,16 @@ const struct inst db_inst_0fcx[] = {
 /*c4*/	{ "",	   false, NONE,	 0,	      0 },
 /*c5*/	{ "",	   false, NONE,	 0,	      0 },
 /*c6*/	{ "",	   false, NONE,	 0,	      0 },
-/*c7*/	{ "",	   true,  NONE,	 op1(E),      db_Grp9 },
+/*c7*/	{ NULL,	   true,  NONE,	 op1(E),      db_GrpA },
 
-/*c8*/	{ "bswap", false, LONG,  op1(Ri),     0 },
-/*c9*/	{ "bswap", false, LONG,  op1(Ri),     0 },
-/*ca*/	{ "bswap", false, LONG,  op1(Ri),     0 },
-/*cb*/	{ "bswap", false, LONG,  op1(Ri),     0 },
-/*cc*/	{ "bswap", false, LONG,  op1(Ri),     0 },
-/*cd*/	{ "bswap", false, LONG,  op1(Ri),     0 },
-/*ce*/	{ "bswap", false, LONG,  op1(Ri),     0 },
-/*cf*/	{ "bswap", false, LONG,  op1(Ri),     0 },
+/*c8*/	{ "bswap", false, LONG,  op1(Ril),     0 },
+/*c9*/	{ "bswap", false, LONG,  op1(Ril),     0 },
+/*ca*/	{ "bswap", false, LONG,  op1(Ril),     0 },
+/*cb*/	{ "bswap", false, LONG,  op1(Ril),     0 },
+/*cc*/	{ "bswap", false, LONG,  op1(Ril),     0 },
+/*cd*/	{ "bswap", false, LONG,  op1(Ril),     0 },
+/*ce*/	{ "bswap", false, LONG,  op1(Ril),     0 },
+/*cf*/	{ "bswap", false, LONG,  op1(Ril),     0 },
 };
 
 const struct inst * const db_inst_0f[] = {
@@ -592,7 +612,7 @@ const struct inst db_inst_table[256] = {
 /*29*/	{ "sub",   true,  LONG,  op2(R, E),  0 },
 /*2a*/	{ "sub",   true,  BYTE,  op2(E, R),  0 },
 /*2b*/	{ "sub",   true,  LONG,  op2(E, R),  0 },
-/*2c*/	{ "sub",   false, BYTE,  op2(Is, A), 0 },
+/*2c*/	{ "sub",   false, BYTE,  op2(I, A), 0 },
 /*2d*/	{ "sub",   false, LONG,  op2(Is, A), 0 },
 /*2e*/	{ "",      false, NONE,  0,	     0 },
 /*2f*/	{ "das",   false, NONE,  0,	     0 },
@@ -687,10 +707,10 @@ const struct inst db_inst_table[256] = {
 /*7e*/	{ "jle",   false, NONE,  op1(Db),     0 },
 /*7f*/	{ "jnle",  false, NONE,  op1(Db),     0 },
 
-/*80*/  { "",	   true,  BYTE,  op2(I, E),   db_Grp1 },
-/*81*/  { "",	   true,  LONG,  op2(I, E),   db_Grp1 },
-/*82*/  { "",	   true,  BYTE,  op2(Is,E),   db_Grp1 },
-/*83*/  { "",	   true,  LONG,  op2(Ibs,E),  db_Grp1 },
+/*80*/  { NULL,	   true,  BYTE,  op2(I, E),   db_Grp1 },
+/*81*/  { NULL,	   true,  LONG,  op2(I, E),   db_Grp1 },
+/*82*/  { NULL,	   true,  BYTE,  op2(I,E),    db_Grp1 },
+/*83*/  { NULL,	   true,  LONG,  op2(Ibs,E),  db_Grp1 },
 /*84*/	{ "test",  true,  BYTE,  op2(R, E),   0 },
 /*85*/	{ "test",  true,  LONG,  op2(R, E),   0 },
 /*86*/	{ "xchg",  true,  BYTE,  op2(R, E),   0 },
@@ -759,8 +779,8 @@ const struct inst db_inst_table[256] = {
 /*be*/	{ "mov",   false, LONG,  op2(I, Ri),  0 },
 /*bf*/	{ "mov",   false, LONG,  op2(I, Ri),  0 },
 
-/*c0*/	{ "",	   true,  BYTE,  op2(Ib, E),  db_Grp2 },
-/*c1*/	{ "",	   true,  LONG,  op2(Ib, E),  db_Grp2 },
+/*c0*/	{ NULL,	   true,  BYTE,  op2(Ib, E),  db_Grp2 },
+/*c1*/	{ NULL,	   true,  LONG,  op2(Ib, E),  db_Grp2 },
 /*c2*/	{ "ret",   false, NONE,  op1(Iw),     0 },
 /*c3*/	{ "ret",   false, NONE,  0,	      0 },
 /*c4*/	{ "les",   true,  LONG,  op2(E, R),   0 },
@@ -777,13 +797,13 @@ const struct inst db_inst_table[256] = {
 /*ce*/	{ "into",  false, NONE,  0,	      0 },
 /*cf*/	{ "iret",  false, NONE,  0,	      0 },
 
-/*d0*/	{ "",	   true,  BYTE,  op2(o1, E),  db_Grp2 },
-/*d1*/	{ "",	   true,  LONG,  op2(o1, E),  db_Grp2 },
-/*d2*/	{ "",	   true,  BYTE,  op2(CL, E),  db_Grp2 },
-/*d3*/	{ "",	   true,  LONG,  op2(CL, E),  db_Grp2 },
-/*d4*/	{ "aam",   true,  NONE,  0,	      0 },
-/*d5*/	{ "aad",   true,  NONE,  0,	      0 },
-/*d6*/	{ "",      false, NONE,  0,	      0 },
+/*d0*/	{ NULL,	   true,  BYTE,  op2(o1, E),  db_Grp2 },
+/*d1*/	{ NULL,	   true,  LONG,  op2(o1, E),  db_Grp2 },
+/*d2*/	{ NULL,	   true,  BYTE,  op2(CL, E),  db_Grp2 },
+/*d3*/	{ NULL,	   true,  LONG,  op2(CL, E),  db_Grp2 },
+/*d4*/	{ "aam",   true,  NONE,  op1(Iba),    0 },
+/*d5*/	{ "aad",   true,  NONE,  op1(Iba),    0 },
+/*d6*/	{ ".byte\t0xd6",FALSE, NONE, 0,       0 },
 /*d7*/	{ "xlat",  false, BYTE,  op1(BX),     0 },
 
 /*d8*/  { "",      true,  NONE,  0,	      db_Esc8 },
@@ -828,8 +848,8 @@ const struct inst db_inst_table[256] = {
 /*fb*/	{ "sti",   false, NONE,  0,	     0 },
 /*fc*/	{ "cld",   false, NONE,  0,	     0 },
 /*fd*/	{ "std",   false, NONE,  0,	     0 },
-/*fe*/	{ "",	   true,  NONE,  0,	     db_Grp4 },
-/*ff*/	{ "",	   true,  NONE,  0,	     db_Grp5 },
+/*fe*/	{ "",	   true,  RDEP,  0,	     db_Grp4 },
+/*ff*/	{ "",	   true,  RDEP,  0,	     db_Grp5 },
 };
 
 const struct inst db_bad_inst =
@@ -923,7 +943,7 @@ db_read_address(db_addr_t loc, int short
 		switch (mod) {
 		case 0:
 			if (rm == 6) {
-				get_value_inc(disp, loc, 2, true);
+				get_value_inc(disp, loc, 2, false);
 				addrp->disp = disp;
 				addrp->base = 0;
 			} else {
@@ -937,7 +957,7 @@ db_read_address(db_addr_t loc, int short
 			addrp->base = db_index_reg_16[rm];
 			break;
 		case 2:
-			get_value_inc(disp, loc, 2, true);
+			get_value_inc(disp, loc, 2, false);
 			addrp->disp = disp;
 			addrp->base = db_index_reg_16[rm];
 			break;
@@ -1004,12 +1024,7 @@ db_print_address(const char * seg, int s
  * and return updated location.
  */
 db_addr_t
-db_disasm_esc(
-    db_addr_t	loc,
-    int		inst,
-    int		short_addr,
-    int		size,
-    const char *seg)
+db_disasm_esc(db_addr_t loc, int inst, int short_addr, int size, const char *seg)
 {
 	int		regmodrm;
 	const struct finst	*fp;
@@ -1021,6 +1036,11 @@ db_disasm_esc(
 	fp = &db_Esc_inst[inst - 0xd8][f_reg(regmodrm)];
 	mod = f_mod(regmodrm);
 	if (mod != 3) {
+		if (*fp->f_name == '\0') {
+			db_printf("<bad instruction>");
+			return (loc);
+		}
+
 		/*
 		 * Normal address modes.
 		 */
@@ -1068,13 +1088,17 @@ db_disasm_esc(
 			db_printf("%s\t%%st(%d)", name, f_rm(regmodrm));
 			break;
 		case op1(X):
-			db_printf("%s", ((const char *const*)fp->f_rrname)[f_rm(regmodrm)]);
+			name = ((const char *const*)fp->f_rrname)[f_rm(regmodrm)];
+			if (*name == '\0')
+				goto bad;
+			db_printf("%s", name);
 			break;
 		case op1(XA):
 			db_printf("%s\t%%ax",
 			    ((const char *const*)fp->f_rrname)[f_rm(regmodrm)]);
 			break;
 		default:
+		bad:
 			db_printf("<bad instruction>");
 			break;
 		}
@@ -1089,9 +1113,7 @@ db_disasm_esc(
  * next instruction.
  */
 db_addr_t
-db_disasm(
-    db_addr_t	loc,
-    bool	altfmt)
+db_disasm(db_addr_t loc, bool altfmt)
 {
 	int	inst;
 	int	size;
@@ -1208,25 +1230,40 @@ db_disasm(
 	i_size = ip->i_size;
 	i_mode = ip->i_mode;
 
-	if (ip->i_extra == (const char *)db_Grp1 ||
-	    ip->i_extra == (const char *)db_Grp2 ||
-	    ip->i_extra == (const char *)db_Grp6 ||
-	    ip->i_extra == (const char *)db_Grp7 ||
-	    ip->i_extra == (const char *)db_Grp8 ||
-	    ip->i_extra == (const char *)db_Grp9) {
-		i_name = ((const char *const*)ip->i_extra)[f_reg(regmodrm)];
-	} else if (ip->i_extra == (const char *)db_Grp3) {
+	if (i_size == RDEP) {
+		/* sub-table to handle dependency on reg from ModR/M byte */
 		ip = (const struct inst *)ip->i_extra;
 		ip = &ip[f_reg(regmodrm)];
 		i_name = ip->i_name;
 		i_mode = ip->i_mode;
-	} else if (ip->i_extra == (const char *)db_Grp4 ||
-		   ip->i_extra == (const char *)db_Grp5) {
+		i_size = ip->i_size;
+	} else if (i_name == NULL) {
+		i_name = ((const char *const*)ip->i_extra)[f_reg(regmodrm)];
+	} else if (ip->i_extra == (const char *)db_Grp3) {
 		ip = (const struct inst *)ip->i_extra;
 		ip = &ip[f_reg(regmodrm)];
 		i_name = ip->i_name;
 		i_mode = ip->i_mode;
-		i_size = ip->i_size;
+	}
+
+	/* ModR/M-specific operation? */
+	if ((i_mode & 0xFF) == MEx) {
+		if (f_mod(regmodrm) != 3)
+			i_mode = op1(E);
+		else {
+			/* unknown extension? */
+			if (f_rm(regmodrm) > (i_mode >> 8))
+				i_name = "";
+			else {
+				/* skip to the specific op */
+				int i = f_rm(regmodrm);
+				i_name = ip->i_extra;
+				while (i-- > 0)
+					while (*i_name++)
+						;
+			}
+			i_mode = 0;
+		}
 	}
 
 	if (i_size == SDEP) {
@@ -1267,6 +1304,9 @@ db_disasm(
 			db_printf("*");
 			db_print_address(seg, size, &address);
 			break;
+		case El:
+			db_print_address(seg, LONG, &address);
+			break;
 		case Ew:
 			db_print_address(seg, WORD, &address);
 			break;
@@ -1282,6 +1322,9 @@ db_disasm(
 		case Ri:
 			db_printf("%s", db_reg[size][f_rm(inst)]);
 			break;
+		case Ril:
+			db_printf("%s", db_reg[LONG][f_rm(inst)]);
+			break;
 		case S:
 			db_printf("%s", db_seg_reg[f_reg(regmodrm)]);
 			break;
@@ -1336,6 +1379,13 @@ db_disasm(
 			db_format_radix(tbuf, 24, (unsigned int)imm, true);
 			db_printf("$%s", tbuf);
 			break;
+		case Iba:
+			get_value_inc(imm, loc, 1, false);
+			if (imm != 0x0a) {
+				db_format_radix(tbuf, 24, (unsigned int)imm, true);
+				db_printf("$%s", tbuf);
+			}
+			break;
 		case Ibs:
 			get_value_inc(imm, loc, 1, true);	/* signed */
 			db_format_radix(tbuf, 24, imm, true);

Reply via email to