2009-01-01 Ulrich Drepper <drepper@redhat.com>
+ * i386_parse.y (instrtable_out): Optimize match_data table by not
+ emitting 0xff masks for leading bytes.
+ * i386_disasm.c (i386_disasm): Adjust reader of match_data.
+
* i386_disasm.c (i386_disasm): Reset bufcnt when not matched. We
don't expect snprintf to fail.
/* Disassembler for x86.
- Copyright (C) 2007, 2008 Red Hat, Inc.
+ Copyright (C) 2007, 2008, 2009 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2007.
while (curr < match_end)
{
uint_fast8_t len = *curr++;
- const uint8_t *start = curr;
+ uint_fast8_t clen = len >> 4;
+ len &= 0xf;
+ const uint8_t *next_curr = curr + clen + (len - clen) * 2;
assert (len > 0);
- assert (curr + 2 * len <= match_end);
+ assert (curr + clen + 2 * (len - clen) <= match_end);
const uint8_t *codep = data;
int correct_prefix = 0;
int opoff = 0;
- if (data > begin && codep[-1] == curr[1] && curr[0] == 0xff)
+ if (data > begin && codep[-1] == *curr && clen > 0)
{
/* We match a prefix byte. This is exactly one byte and
is matched exactly, without a mask. */
--len;
- start += 2;
+ --clen;
opoff = 8;
- curr += 2;
+ ++curr;
assert (last_prefix_bit != 0);
correct_prefix = last_prefix_bit;
}
size_t avail = len;
+ while (clen > 0)
+ {
+ if (*codep++ != *curr++)
+ goto not;
+ --avail;
+ --clen;
+ if (codep == end && avail > 0)
+ goto do_ret;
+ }
+
while (avail > 0)
{
uint_fast8_t masked = *codep++ & *curr++;
if (masked != *curr++)
{
not:
- curr = start + 2 * len;
+ curr = next_curr;
++cnt;
bufcnt = 0;
goto next_match;
are not used uninitialized. */
asm (""
: "=mr" (opoff), "=mr" (correct_prefix), "=mr" (codep),
- "=mr" (start), "=mr" (len));
+ "=mr" (next_curr), "=mr" (len));
}
size_t prefix_size = 0;
%{
/* Parser for i386 CPU description.
- Copyright (C) 2004, 2005, 2007, 2008 Red Hat, Inc.
+ Copyright (C) 2004, 2005, 2007, 2008, 2009 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 2004.
Red Hat elfutils is free software; you can redistribute it and/or modify
#include <math.h>
#include <obstack.h>
#include <search.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* First count the number of bytes. */
size_t totalbits = 0;
size_t zerobits = 0;
+ bool leading_p = true;
+ size_t leadingbits = 0;
struct bitvalue *b = instr->bytes;
while (b != NULL)
{
{
++totalbits;
zerobits = 0;
+ if (leading_p)
+ ++leadingbits;
}
else
{
zerobits = 0;
else
zerobits += b->field->bits;
+ leading_p = false;
}
b = b->next;
}
size_t nbytes = (totalbits - zerobits + 7) / 8;
assert (nbytes > 0);
+ size_t leadingbytes = leadingbits / 8;
- fprintf (outfile, " %#zx,", nbytes);
+ fprintf (outfile, " %#zx,", nbytes | (leadingbytes << 4));
/* Now create the mask and byte values. */
uint8_t byte = 0;
mask = (mask << 1) | 1;
if (++nbits == 8)
{
- fprintf (outfile, " %#" PRIx8 ", %#" PRIx8 ",", mask, byte);
+ if (leadingbytes > 0)
+ {
+ assert (mask == 0xff);
+ fprintf (outfile, " %#" PRIx8 ",", byte);
+ --leadingbytes;
+ }
+ else
+ fprintf (outfile, " %#" PRIx8 ", %#" PRIx8 ",",
+ mask, byte);
byte = mask = nbits = 0;
if (--nbytes == 0)
break;
}
else
{
+ assert (leadingbytes == 0);
+
unsigned long int remaining = b->field->bits;
while (nbits + remaining > 8)
{