summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2006-11-13 21:14:54 +0000
committerjhb <jhb@FreeBSD.org>2006-11-13 21:14:54 +0000
commitda229fb2a54f22882db72f2fc7f5eaea1691bc81 (patch)
tree6e447097bddb59a700f1df7e0ef12e50866cbe53 /sys/amd64
parent9c4d5bd7a3fa5429413c842e1b0e7eecb56b92ab (diff)
downloadFreeBSD-src-da229fb2a54f22882db72f2fc7f5eaea1691bc81.zip
FreeBSD-src-da229fb2a54f22882db72f2fc7f5eaea1691bc81.tar.gz
Various fixes:
- Remove an extra entry from the array for 0x0f prefixed instruction groups. This fixes decoding of instructions where the second opcode >= 0x80. - Add support for the 64-bit immediate mov instructions. - When short_addr is enabled, don't parse the modr/m byte for a 16-bit address, but as a 32-bit address. - Support %rip relative addressing. - Don't print a displacement of 0 if there is a base or index register. MFC after: 3 days
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/amd64/db_disasm.c144
1 files changed, 61 insertions, 83 deletions
diff --git a/sys/amd64/amd64/db_disasm.c b/sys/amd64/amd64/db_disasm.c
index 97582df..ab7aa49 100644
--- a/sys/amd64/amd64/db_disasm.c
+++ b/sys/amd64/amd64/db_disasm.c
@@ -84,6 +84,7 @@ __FBSDID("$FreeBSD$");
#define Ib 21 /* byte immediate, unsigned */
#define Ibs 22 /* byte immediate, signed */
#define Iw 23 /* word immediate, unsigned */
+#define Ilq 24 /* long/quad immediate, unsigned */
#define O 25 /* direct address */
#define Db 26 /* byte displacement from EIP */
#define Dl 27 /* long displacement from EIP */
@@ -351,7 +352,6 @@ static const struct inst * const db_inst_0f[] = {
0,
0,
0,
- 0,
db_inst_0f8x,
db_inst_0f9x,
db_inst_0fax,
@@ -752,14 +752,14 @@ static const struct inst db_inst_table[256] = {
/*b6*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 },
/*b7*/ { "mov", FALSE, BYTE, op2(I, Ri), 0 },
-/*b8*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
-/*b9*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
-/*ba*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
-/*bb*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
-/*bc*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
-/*bd*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
-/*be*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
-/*bf*/ { "mov", FALSE, LONG, op2(I, Ri), 0 },
+/*b8*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 },
+/*b9*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 },
+/*ba*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 },
+/*bb*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 },
+/*bc*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 },
+/*bd*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 },
+/*be*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 },
+/*bf*/ { "mov", FALSE, LONG, op2(Ilq, Ri), 0 },
/*c0*/ { "", TRUE, BYTE, op2(Ib, E), db_Grp2 },
/*c1*/ { "", TRUE, LONG, op2(Ib, E), db_Grp2 },
@@ -854,17 +854,6 @@ struct i_addr {
int ss;
};
-static const char * const db_index_reg_16[8] = {
- "%bx,%si",
- "%bx,%di",
- "%bp,%si",
- "%bp,%di",
- "%si",
- "%di",
- "%bp",
- "%bx"
-};
-
static const char * const db_reg[2][4][16] = {
{{"%al", "%cl", "%dl", "%bl", "%ah", "%ch", "%dh", "%bh",
@@ -927,7 +916,7 @@ db_read_address(loc, short_addr, rex, regmodrm, addrp)
int regmodrm;
struct i_addr * addrp; /* out */
{
- int mod, rm, sib, index, disp;
+ int mod, rm, sib, index, disp, size, have_sib;
mod = f_mod(rex, regmodrm);
rm = f_rm(rex, regmodrm);
@@ -940,68 +929,49 @@ db_read_address(loc, short_addr, rex, regmodrm, addrp)
addrp->is_reg = FALSE;
addrp->index = 0;
- if (short_addr) {
- addrp->index = 0;
- addrp->ss = 0;
- switch (mod) {
- case 0:
- if (rm == 6) {
- get_value_inc(disp, loc, 2, FALSE);
- addrp->disp = disp;
- addrp->base = 0;
- }
- else {
- addrp->disp = 0;
- addrp->base = db_index_reg_16[rm];
- }
- break;
- case 1:
- get_value_inc(disp, loc, 1, TRUE);
- disp &= 0xFFFF;
- addrp->disp = disp;
- addrp->base = db_index_reg_16[rm];
- break;
- case 2:
- get_value_inc(disp, loc, 2, FALSE);
- addrp->disp = disp;
- addrp->base = db_index_reg_16[rm];
- break;
- }
- }
- else {
- if (mod != 3 && rm == 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][QUAD][index];
- addrp->ss = sib_ss(rex, sib);
- }
-
- switch (mod) {
- case 0:
- if (rm == 5) {
- get_value_inc(addrp->disp, loc, 4, FALSE);
+ if (short_addr)
+ size = LONG;
+ else
+ size = QUAD;
+
+ 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[1][QUAD][rm];
- }
- break;
-
- case 1:
- get_value_inc(disp, loc, 1, TRUE);
- addrp->disp = disp;
- addrp->base = db_reg[1][QUAD][rm];
- break;
-
- case 2:
- get_value_inc(disp, loc, 4, FALSE);
- addrp->disp = disp;
- addrp->base = db_reg[1][QUAD][rm];
- break;
- }
+ else if (short_addr)
+ addrp->base = "%eip";
+ else
+ addrp->base = "%rip";
+ } 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);
}
@@ -1022,7 +992,8 @@ db_print_address(seg, size, rex, addrp)
db_printf("%s:", seg);
}
- db_printsym((db_addr_t)addrp->disp, DB_STGY_ANY);
+ if (addrp->disp != 0 || (addrp->base == 0 && addrp->index == 0))
+ db_printsym((db_addr_t)addrp->disp, DB_STGY_ANY);
if (addrp->base != 0 || addrp->index != 0) {
db_printf("(");
if (addrp->base)
@@ -1154,6 +1125,7 @@ db_disasm(loc, altfmt)
int prefix;
int imm;
int imm2;
+ long imm64;
int len;
struct i_addr address;
@@ -1426,6 +1398,12 @@ db_disasm(loc, altfmt)
db_printf("$%#r", imm);
break;
+ case Ilq:
+ len = db_lengths[rex & REX_W ? QUAD : LONG];
+ get_value_inc(imm64, loc, len, FALSE);
+ db_printf("$%#lr", imm64);
+ break;
+
case O:
len = (short_addr ? 2 : 4);
get_value_inc(displ, loc, len, FALSE);
OpenPOWER on IntegriCloud