summaryrefslogtreecommitdiff
path: root/disasm.c
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2008-10-15 11:51:24 -0700
committerH. Peter Anvin <hpa@zytor.com>2008-10-23 23:03:59 -0700
commit941fcbb3ab7b0f2f6c37310d260a2ce6c69a3107 (patch)
tree16b743b4e65083c00435ce5a03ea56c67278a670 /disasm.c
parentdcffe4b9f651bb420c62b7cffb5aa5169310763d (diff)
downloadnasm-941fcbb3ab7b0f2f6c37310d260a2ce6c69a3107.tar.gz
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.c32
1 files changed, 20 insertions, 12 deletions
diff --git a/disasm.c b/disasm.c
index 70bbfc1c..0c654ede 100644
--- a/disasm.c
+++ b/disasm.c
@@ -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;