Same some space by introducing shorthand byte codes for SSE prefixes
authorH. Peter Anvin <hpa@zytor.com>
Tue, 20 May 2008 16:46:24 +0000 (09:46 -0700)
committerH. Peter Anvin <hpa@zytor.com>
Tue, 20 May 2008 16:46:24 +0000 (09:46 -0700)
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
disasm.c
insns.pl

index 67dfcac..d10e5b0 100644 (file)
  * \335          - disassemble a rep (0xF3 byte) prefix as repe not rep.
  * \340          - reserve <operand 0> 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;
index 6afc88e..711304c 100644 (file)
--- 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;
index ac63909..e9dd72f 100644 (file)
--- 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";