From 52dc353868a9adba69df6bd72a30ab1eaff4388e Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 20 May 2008 19:29:04 -0700 Subject: [PATCH] Handle is4 bytes without meaningful information in the bottom bits Support is4 bytes without meaningful information in the bottom bits. This is equivalent to /is4=0 for the assembler, but makes the bottom bits don't care for the disassembler. --- assemble.c | 15 +++++++++++++-- disasm.c | 10 ++++++++++ insns.pl | 10 +++++++--- test/avx.asm | 10 ++++++++++ 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/assemble.c b/assemble.c index 1d440ead..c5f8172e 100644 --- a/assemble.c +++ b/assemble.c @@ -46,9 +46,11 @@ * operand 0..3. * \171 - placement of DREX suffix in the absence of an EA * \172\ab - the register number from operand a in bits 7..4, with - * the 4-bit immediate from operand b in bits 0..3. + * the 4-bit immediate from operand b in bits 3..0. * \173\xab - the register number from operand a in bits 7..4, with - * the value b in bits 0..3. + * the value b in bits 3..0. + * \174\a - the register number from operand a in bits 7..4, and + * an arbitrary value in bits 3..0 (assembled as zero.) * \2ab - a ModRM, calculated on EA in operand a, with the spare * field equal to digit b. * \250..\253 - same as \150..\153, except warn if the 64-bit operand @@ -1006,6 +1008,7 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits, break; case 0172: case 0173: + case 0174: codes++; length++; break; @@ -1611,6 +1614,14 @@ static void gencode(int32_t segment, int64_t offset, int bits, offset++; break; + case 0174: + c = *codes++; + opx = &ins->oprs[c]; + bytes[0] = nasm_regvals[opx->basereg] << 4; + out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG); + offset++; + break; + case 0250: case 0251: case 0252: diff --git a/disasm.c b/disasm.c index 378596a9..c3ae5413 100644 --- a/disasm.c +++ b/disasm.c @@ -656,6 +656,16 @@ static int matches(const struct itemplate *t, uint8_t *data, } break; + case 0174: + { + uint8_t ximm = *data++; + c = *r++; + + ins->oprs[c].basereg = ximm >> 4; + ins->oprs[c].segment |= SEG_RMREG; + } + break; + case4(0200): case4(0204): case4(0210): diff --git a/insns.pl b/insns.pl index 5b45d7e5..81997320 100644 --- a/insns.pl +++ b/insns.pl @@ -687,10 +687,14 @@ sub byte_code_compile($) { } $prefix_ok = 0; } elsif ($op eq '/is4') { - if (!defined($oppos{'i'} || !defined($oppos{'s'}))) { - die "$0: $line: $op without 'i' and 's' operands\n"; + if (!defined($oppos{'s'})) { + die "$0: $line: $op without 's' operand\n"; + } + if (defined($oppos{'i'})) { + push(@codes, 0172, ($oppos{'s'} << 3)+$oppos{'i'}); + } else { + push(@codes, 0174, $oppos{'s'}); } - push(@codes, 0172, ($oppos{'s'} << 3)+$oppos{'i'}); $prefix_ok = 0; } elsif ($op =~ /^\/is4\=([0-9]+)$/) { my $imm = $1; diff --git a/test/avx.asm b/test/avx.asm index 018135b2..11d3f1e0 100644 --- a/test/avx.asm +++ b/test/avx.asm @@ -1,4 +1,14 @@ bits 64 + vblendvpd xmm2,xmm1,xmm0,xmm0 + vblendvpd xmm2,xmm1,xmm0 + vblendvpd ymm2,ymm1,ymm0,ymm0 + vblendvpd ymm2,ymm1,ymm0 + + vcvtsi2sd xmm9,xmm10,ecx + vcvtsi2sd xmm9,xmm10,rcx + vcvtsi2sd xmm9,xmm10,dword [rdi] + vcvtsi2sd xmm9,xmm10,qword [rdi] + vpermil2ps xmm0,xmm1,[rdi],xmm3,0 vpermil2ps xmm0,xmm1,xmm2,[rdi],1 vpermil2ps ymm0,ymm1,ymm2,ymm3,2