diff options
author | H. Peter Anvin <hpa@zytor.com> | 2008-10-15 11:51:24 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2008-10-23 23:03:59 -0700 |
commit | 941fcbb3ab7b0f2f6c37310d260a2ce6c69a3107 (patch) | |
tree | 16b743b4e65083c00435ce5a03ea56c67278a670 /disasm.c | |
parent | dcffe4b9f651bb420c62b7cffb5aa5169310763d (diff) | |
download | nasm-941fcbb3ab7b0f2f6c37310d260a2ce6c69a3107.tar.gz nasm-941fcbb3ab7b0f2f6c37310d260a2ce6c69a3107.tar.bz2 nasm-941fcbb3ab7b0f2f6c37310d260a2ce6c69a3107.zip |
disasm: extension byte support in the disassembler
Add support to the disassembler for the extension bytes (for operand
4+).
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'disasm.c')
-rw-r--r-- | disasm.c | 32 |
1 files changed, 20 insertions, 12 deletions
@@ -374,7 +374,9 @@ static int matches(const struct itemplate *t, uint8_t *data, int osize = prefix->osize; int asize = prefix->asize; int i, c; + int op1, op2; struct operand *opx; + uint8_t opex = 0; int s_field_for = -1; /* No 144/154 series code encountered */ bool vex_ok = false; int regmask = (segsize == 64) ? 15 : 7; @@ -396,7 +398,10 @@ static int matches(const struct itemplate *t, uint8_t *data, drep = P_REP; while ((c = *r++) != 0) { - opx = &ins->oprs[c & 3]; + op1 = (c & 3) + ((opex & 1) << 2); + op2 = ((c >> 3) & 3) + ((opex & 2) << 1); + opx = &ins->oprs[op1]; + opex = 0; switch (c) { case 01: @@ -408,6 +413,12 @@ static int matches(const struct itemplate *t, uint8_t *data, return false; break; + case 05: + case 06: + case 07: + opex = c; + break; + case4(010): { int t = *r++, d = *data++; @@ -529,17 +540,15 @@ static int matches(const struct itemplate *t, uint8_t *data, { int modrm = *data++; opx->segment |= SEG_RMREG; - data = do_ea(data, modrm, asize, segsize, - &ins->oprs[(c >> 3) & 3], ins); + data = do_ea(data, modrm, asize, segsize, &ins->oprs[op2], ins); if (!data) return false; - opx->basereg = ((modrm >> 3)&7)+ - (ins->rex & REX_R ? 8 : 0); + opx->basereg = ((modrm >> 3) & 7) + (ins->rex & REX_R ? 8 : 0); break; } case4(0140): - if (s_field_for == (c & 3)) { + if (s_field_for == op1) { opx->offset = gets8(data); data++; } else { @@ -550,13 +559,13 @@ static int matches(const struct itemplate *t, uint8_t *data, case4(0144): case4(0154): - s_field_for = (*data & 0x02) ? c & 3 : -1; + s_field_for = (*data & 0x02) ? op1 : -1; if ((*data++ & ~0x02) != *r++) return false; break; case4(0150): - if (s_field_for == (c & 3)) { + if (s_field_for == op1) { opx->offset = gets8(data); data++; } else { @@ -567,12 +576,12 @@ static int matches(const struct itemplate *t, uint8_t *data, case4(0160): ins->rex |= REX_D; - ins->drexdst = c & 3; + ins->drexdst = op1; break; case4(0164): ins->rex |= REX_D|REX_OC; - ins->drexdst = c & 3; + ins->drexdst = op1; break; case 0171: @@ -626,8 +635,7 @@ static int matches(const struct itemplate *t, uint8_t *data, int modrm = *data++; if (((modrm >> 3) & 07) != (c & 07)) return false; /* spare field doesn't match up */ - data = do_ea(data, modrm, asize, segsize, - &ins->oprs[(c >> 3) & 07], ins); + data = do_ea(data, modrm, asize, segsize, &ins->oprs[op2], ins); if (!data) return false; break; |