Line 27... |
Line 27... |
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
# include "config.h"
|
# include "config.h"
|
#endif
|
#endif
|
#include "opcode/or32.h"
|
#include "opcode/or32.h"
|
|
|
#ifndef debug
|
|
#define debug
|
|
#endif
|
|
|
|
/* **INDENT-OFF** */
|
/* **INDENT-OFF** */
|
|
|
CONST struct or32_letter or32_letters[] =
|
CONST struct or32_letter or32_letters[] =
|
{
|
{
|
{ 'A', NUM_UNSIGNED },
|
{ 'A', NUM_UNSIGNED },
|
Line 485... |
Line 481... |
cur_mask &= ti[i].insn_mask;
|
cur_mask &= ti[i].insn_mask;
|
ninstr++;
|
ninstr++;
|
last_match = i;
|
last_match = i;
|
}
|
}
|
|
|
debug("%08X %08X\n", mask, cur_mask);
|
debug(8, "%08X %08X\n", mask, cur_mask);
|
if (ninstr == 0)
|
if (ninstr == 0)
|
return 0;
|
return 0;
|
if (ninstr == 1)
|
if (ninstr == 1)
|
{
|
{
|
/* Leaf holds instruction index. */
|
/* Leaf holds instruction index. */
|
debug("%i>I%i %s\n", cur - automata, last_match, or32_opcodes[last_match].name);
|
debug(8, "%i>I%i %s\n", cur - automata, last_match, or32_opcodes[last_match].name);
|
*cur = LEAF_FLAG | last_match;
|
*cur = LEAF_FLAG | last_match;
|
cur++;
|
cur++;
|
nuncovered--;
|
nuncovered--;
|
} else {
|
} else {
|
/* Find longest match. */
|
/* Find longest match. */
|
Line 503... |
Line 499... |
{
|
{
|
int len;
|
int len;
|
for (len = best_len + 1; len < MIN(MAX_LEN, 33 - i); len++)
|
for (len = best_len + 1; len < MIN(MAX_LEN, 33 - i); len++)
|
{
|
{
|
unsigned long m = (1UL << ((unsigned long)len)) - 1;
|
unsigned long m = (1UL << ((unsigned long)len)) - 1;
|
/*debug(" (%i(%08X & %08X>>%i = %08X, %08X)",len,m, cur_mask, i, (cur_mask >> (unsigned)i), (cur_mask >> (unsigned)i) & m);*/
|
debug(9, " (%i(%08X & %08X>>%i = %08X, %08X)",len,m, cur_mask, i, (cur_mask >> (unsigned)i), (cur_mask >> (unsigned)i) & m);
|
if ((m & (cur_mask >> (unsigned)i)) == m)
|
if ((m & (cur_mask >> (unsigned)i)) == m)
|
{
|
{
|
best_len = len;
|
best_len = len;
|
best_first = i;
|
best_first = i;
|
/*debug("!");*/
|
debug(9, "!");
|
}
|
}
|
else
|
else
|
break;
|
break;
|
}
|
}
|
}
|
}
|
/*debug("\n");*/
|
debug(9, "\n");
|
if (!best_len)
|
if (!best_len)
|
{
|
{
|
fprintf (stderr, "%i instructions match mask 0x%08X:\n", ninstr, mask);
|
fprintf (stderr, "%i instructions match mask 0x%08X:\n", ninstr, mask);
|
for (i = 0; i < num_opcodes; i++)
|
for (i = 0; i < num_opcodes; i++)
|
if (ti[i].in_pass == pass)
|
if (ti[i].in_pass == pass)
|
fprintf (stderr, "%s ", or32_opcodes[i].name);
|
fprintf (stderr, "%s ", or32_opcodes[i].name);
|
|
|
fprintf (stderr, "\n");
|
fprintf (stderr, "\n");
|
exit (1);
|
exit (1);
|
}
|
}
|
debug("%i> #### %i << %i (%i) ####\n", cur - automata, best_len, best_first, ninstr);
|
debug(8, "%i> #### %i << %i (%i) ####\n", cur - automata, best_len, best_first, ninstr);
|
*cur = best_first;
|
*cur = best_first;
|
cur++;
|
cur++;
|
*cur = (1 << best_len) - 1;
|
*cur = (1 << best_len) - 1;
|
cur++;
|
cur++;
|
next = cur;
|
next = cur;
|
Line 546... |
Line 542... |
if (ti[j].in_pass == pass
|
if (ti[j].in_pass == pass
|
&& ((ti[j].insn >> best_first) & cur_mask) == i
|
&& ((ti[j].insn >> best_first) & cur_mask) == i
|
&& ((ti[j].insn_mask >> best_first) & cur_mask) == cur_mask)
|
&& ((ti[j].insn_mask >> best_first) & cur_mask) == cur_mask)
|
ti[j].in_pass = curpass;
|
ti[j].in_pass = curpass;
|
|
|
/*debug("%08X %08X %i\n", mask, cur_mask, best_first);*/
|
debug(9, "%08X %08X %i\n", mask, cur_mask, best_first);
|
c = cover_insn (cur, curpass, mask & (~(cur_mask << best_first)));
|
c = cover_insn (cur, curpass, mask & (~(cur_mask << best_first)));
|
if (c)
|
if (c)
|
{
|
{
|
debug("%i> #%X -> %u\n", next - automata, i, cur - automata);
|
debug(8, "%i> #%X -> %u\n", next - automata, i, cur - automata);
|
*next = cur - automata;
|
*next = cur - automata;
|
cur = c;
|
cur = c;
|
}
|
}
|
else
|
else
|
{
|
{
|
debug("%i> N/A\n", next - automata);
|
debug(8, "%i> N/A\n", next - automata);
|
*next = 0;
|
*next = 0;
|
}
|
}
|
next++;
|
next++;
|
}
|
}
|
}
|
}
|
Line 594... |
Line 590... |
type = 0;
|
type = 0;
|
/* In case we don't have any parameters, we add dummy read from r0. */
|
/* In case we don't have any parameters, we add dummy read from r0. */
|
if (!(*args)) {
|
if (!(*args)) {
|
cur->type = OPTYPE_REG | OPTYPE_OP | OPTYPE_LAST;
|
cur->type = OPTYPE_REG | OPTYPE_OP | OPTYPE_LAST;
|
cur->data = 0;
|
cur->data = 0;
|
debug("#%08X %08X\n", cur->type, cur->data);
|
debug(8, "#%08X %08X\n", cur->type, cur->data);
|
cur++;
|
cur++;
|
return cur;
|
return cur;
|
}
|
}
|
|
|
while (*args != '\0')
|
while (*args != '\0')
|
Line 610... |
Line 606... |
}
|
}
|
else if (isalpha (*args))
|
else if (isalpha (*args))
|
{
|
{
|
unsigned long arg;
|
unsigned long arg;
|
arg = insn_extract(*args, opcode->encoding);
|
arg = insn_extract(*args, opcode->encoding);
|
debug("%s : %08X ------\n", opcode->name, arg);
|
debug(3, "%s : %08X ------\n", opcode->name, arg);
|
if (letter_signed (*args))
|
if (letter_signed (*args))
|
{
|
{
|
type |= OPTYPE_SIG;
|
type |= OPTYPE_SIG;
|
type |= ((num_ones (arg) - 1) << OPTYPE_SBIT_SHR) & OPTYPE_SBIT;
|
type |= ((num_ones (arg) - 1) << OPTYPE_SBIT_SHR) & OPTYPE_SBIT;
|
}
|
}
|
Line 635... |
Line 631... |
tmp >>= 1;
|
tmp >>= 1;
|
}
|
}
|
cur->type = type | shr;
|
cur->type = type | shr;
|
cur->data = mask;
|
cur->data = mask;
|
arg &= ~(((1 << mask) - 1) << shr);
|
arg &= ~(((1 << mask) - 1) << shr);
|
debug("|%08X %08X\n", cur->type, cur->data);
|
debug(3, "|%08X %08X\n", cur->type, cur->data);
|
cur++;
|
cur++;
|
}
|
}
|
args++;
|
args++;
|
}
|
}
|
else if (*args == '(')
|
else if (*args == '(')
|
{
|
{
|
/* Next param is displacement. Later we will treat them as one operand. */
|
/* Next param is displacement. Later we will treat them as one operand. */
|
cur--;
|
cur--;
|
cur->type = type | cur->type | OPTYPE_DIS | OPTYPE_OP;
|
cur->type = type | cur->type | OPTYPE_DIS | OPTYPE_OP;
|
debug(">%08X %08X\n", cur->type, cur->data);
|
debug(3, ">%08X %08X\n", cur->type, cur->data);
|
cur++;
|
cur++;
|
type = 0;
|
type = 0;
|
i++;
|
i++;
|
args++;
|
args++;
|
}
|
}
|
else if (*args == OPERAND_DELIM)
|
else if (*args == OPERAND_DELIM)
|
{
|
{
|
cur--;
|
cur--;
|
cur->type = type | cur->type | OPTYPE_OP;
|
cur->type = type | cur->type | OPTYPE_OP;
|
debug(">%08X %08X\n", cur->type, cur->data);
|
debug(3, ">%08X %08X\n", cur->type, cur->data);
|
cur++;
|
cur++;
|
type = 0;
|
type = 0;
|
i++;
|
i++;
|
args++;
|
args++;
|
}
|
}
|
else if (*args == '0')
|
else if (*args == '0')
|
{
|
{
|
cur->type = type;
|
cur->type = type;
|
cur->data = 0;
|
cur->data = 0;
|
debug(">%08X %08X\n", cur->type, cur->data);
|
debug(3, ">%08X %08X\n", cur->type, cur->data);
|
cur++;
|
cur++;
|
type = 0;
|
type = 0;
|
i++;
|
i++;
|
args++;
|
args++;
|
}
|
}
|
Line 681... |
Line 677... |
exit (1);
|
exit (1);
|
}
|
}
|
}
|
}
|
cur--;
|
cur--;
|
cur->type = type | cur->type | OPTYPE_OP | OPTYPE_LAST;
|
cur->type = type | cur->type | OPTYPE_OP | OPTYPE_LAST;
|
debug("#%08X %08X\n", cur->type, cur->data);
|
debug(3, "#%08X %08X\n", cur->type, cur->data);
|
cur++;
|
cur++;
|
return cur;
|
return cur;
|
}
|
}
|
|
|
/* Constructs new automata based on or32_opcodes array. */
|
/* Constructs new automata based on or32_opcodes array. */
|
Line 710... |
Line 706... |
ones = insn_extract('1', encoding);
|
ones = insn_extract('1', encoding);
|
zeros = insn_extract('0', encoding);
|
zeros = insn_extract('0', encoding);
|
ti[i].insn_mask = ones | zeros;
|
ti[i].insn_mask = ones | zeros;
|
ti[i].insn = ones;
|
ti[i].insn = ones;
|
ti[i].in_pass = curpass = 0;
|
ti[i].in_pass = curpass = 0;
|
/*debug("%s: %s %08X %08X\n", or32_opcodes[i].name,
|
/*debug(9, "%s: %s %08X %08X\n", or32_opcodes[i].name,
|
or32_opcodes[i].encoding, ti[i].insn_mask, ti[i].insn);*/
|
or32_opcodes[i].encoding, ti[i].insn_mask, ti[i].insn);*/
|
}
|
}
|
|
|
/* Until all are covered search for best criteria to separate them. */
|
/* Until all are covered search for best criteria to separate them. */
|
end = cover_insn (automata, curpass, 0xFFFFFFFF);
|
end = cover_insn (automata, curpass, 0xFFFFFFFF);
|
Line 756... |
Line 752... |
unsigned long *a = automata;
|
unsigned long *a = automata;
|
int i;
|
int i;
|
while (!(*a & LEAF_FLAG))
|
while (!(*a & LEAF_FLAG))
|
{
|
{
|
unsigned int first = *a;
|
unsigned int first = *a;
|
debug("%i ", a - automata);
|
debug(8, "%i ", a - automata);
|
a++;
|
a++;
|
i = (insn >> first) & *a;
|
i = (insn >> first) & *a;
|
a++;
|
a++;
|
if (!*(a + i))
|
if (!*(a + i))
|
{ /* Invalid instruction found? */
|
{ /* Invalid instruction found? */
|
debug("XXX\n", i);
|
debug(8, "XXX\n", i);
|
return -1;
|
return -1;
|
}
|
}
|
a = automata + *(a + i);
|
a = automata + *(a + i);
|
}
|
}
|
i = *a & ~LEAF_FLAG;
|
i = *a & ~LEAF_FLAG;
|
debug("%i\n", i);
|
debug(8, "%i\n", i);
|
/* Final check - do we have direct match?
|
/* Final check - do we have direct match?
|
(based on or32_opcodes this should be the only possibility,
|
(based on or32_opcodes this should be the only possibility,
|
but in case of invalid/missing instruction we must perform a check) */
|
but in case of invalid/missing instruction we must perform a check) */
|
if ((ti[i].insn_mask & insn) == ti[i].insn)
|
if ((ti[i].insn_mask & insn) == ti[i].insn)
|
return i;
|
return i;
|