From fff5a47e65c26bf8974bcd8fcc61b7b82430aa78 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin" Date: Tue, 20 May 2008 09:46:24 -0700 Subject: [PATCH] Same some space by introducing shorthand byte codes for SSE prefixes Properly done, all SSE instructions which has the 66/F2/F3 opcode multiplex need two prefixes: one to control the use of OSP and one to control the use of REP. However, it's a four-way select: np/66/F2/F3; so introduce shorthand bytecodes for that purpose. --- assemble.c | 27 +++++++++++++++++++++++++++ disasm.c | 20 ++++++++++++++++++++ insns.pl | 10 ++++++---- 3 files changed, 53 insertions(+), 4 deletions(-) diff --git a/assemble.c b/assemble.c index 67dfcac..d10e5b0 100644 --- a/assemble.c +++ b/assemble.c @@ -91,6 +91,10 @@ * \335 - disassemble a rep (0xF3 byte) prefix as repe not rep. * \340 - reserve bytes of uninitialized storage. * Operand 0 had better be a segmentless constant. + * \360 - no SSE prefix (== \364\331) + * \361 - 66 SSE prefix (== \366\331) + * \362 - F2 SSE prefix (== \364\332) + * \363 - F3 SSE prefix (== \364\333) * \364 - operand-size prefix (0x66) not permitted * \365 - address-size prefix (0x67) not permitted * \366 - operand-size prefix (0x66) used as opcode extension @@ -1077,6 +1081,13 @@ static int64_t calcsize(int32_t segment, int64_t offset, int bits, else length += ins->oprs[0].offset; break; + case 0360: + break; + case 0361: + case 0362: + case 0363: + length++; + break; case 0364: case 0365: break; @@ -1732,6 +1743,22 @@ static void gencode(int32_t segment, int64_t offset, int bits, } break; + case 0360: + break; + + case 0361: + bytes[0] = 0x66; + out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG); + offset += 1; + break; + + case 0362: + case 0363: + bytes[0] = c - 0362 + 0xf2; + out(offset, segment, bytes, OUT_RAWDATA, 1, NO_SEG, NO_SEG); + offset += 1; + break; + case 0364: case 0365: break; diff --git a/disasm.c b/disasm.c index 6afc88e..711304c 100644 --- a/disasm.c +++ b/disasm.c @@ -874,6 +874,26 @@ static int matches(const struct itemplate *t, uint8_t *data, case 0340: return false; + case 0360: + if (prefix->osp || prefix->rep) + return false; + break; + + case 0361: + if (!prefix->osp || prefix->rep) + return false; + break; + + case 0362: + if (prefix->osp || prefix->rep != 0xf2) + return false; + break; + + case 0363: + if (prefix->osp || prefix->rep != 0xf3) + return false; + break; + case 0364: if (prefix->osp) return false; diff --git a/insns.pl b/insns.pl index ac63909..e9dd72f 100644 --- a/insns.pl +++ b/insns.pl @@ -539,13 +539,13 @@ sub byte_code_compile($) { } elsif ($prefix_ok && $op =~ /^(66|f2|f3|np)$/) { # 66/F2/F3 prefix used as an opcode extension, or np = no prefix if ($op eq '66') { - push(@codes, 0366, 0331); + push(@codes, 0361); } elsif ($op eq 'f2') { - push(@codes, 0332, 0364); + push(@codes, 0362); } elsif ($op eq 'f3') { - push(@codes, 0333, 0364); + push(@codes, 0363); } else { - push(@codes, 0331, 0364); + push(@codes, 0360); } } elsif ($op =~ /^[0-9a-f]{2}$/) { if (defined($litix) && $litix+$codes[$litix]+1 == scalar @codes) { @@ -678,6 +678,7 @@ sub byte_code_compile($) { die "$0: $line: $op without 'i' and 's' operands\n"; } push(@codes, 0172, ($oppos{'s'} << 3)+$oppos{'i'}); + $prefix_ok = 0; } elsif ($op =~ /^(is4|imz2)\=([0-9]+)$/) { my $imm = $2; if (!defined($oppos{'s'})) { @@ -687,6 +688,7 @@ sub byte_code_compile($) { die "$0: $line: invalid imm4 value for $op: $imm\n"; } push(@codes, 0173, ($oppos{'s'} << 4) + $imm); + $prefix_ok = 0; } elsif ($op =~ /^([0-9a-f]{2})\+s$/) { if (!defined($oppos{'i'})) { die "$0: $op without 'i' operand\n"; -- 2.7.4