Line 1... |
Line 1... |
/* Table of opcodes for the OpenRISC 1000 ISA.
|
/* Table of opcodes for the OpenRISC 1000 ISA.
|
|
|
Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
|
Copyright 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
|
|
Copyright (C) 2008 Embecosm Limited
|
|
|
Contributed by Damjan Lampret (lampret@opencores.org).
|
Contributed by Damjan Lampret (lampret@opencores.org).
|
|
Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
|
|
|
This file is part of gen_or1k_isa, or1ksim, GDB and GAS.
|
This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
|
|
This file is also part of gen_or1k_isa, GDB and GAS.
|
|
|
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify it
|
it under the terms of the GNU General Public License as published by
|
under the terms of the GNU General Public License as published by the Free
|
the Free Software Foundation; either version 2 of the License, or
|
Software Foundation; either version 3 of the License, or (at your option)
|
(at your option) any later version.
|
any later version.
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|
|
|
/*
|
|
* $Log: not supported by cvs2svn $
|
|
* Revision 1.51 2006/01/19 19:25:10 nogj
|
|
* Pass the instruction operands as part of the op_queue structure.
|
|
*
|
|
* Revision 1.50 2005/11/18 18:15:21 nogj
|
|
* Execute l.ff1 instruction
|
|
*
|
|
* Revision 1.49 2005/11/06 16:23:07 nogj
|
|
* Fix parsing the destination register
|
|
*
|
|
* Revision 1.48 2005/11/03 19:01:50 lampret
|
|
* Added l.fl1
|
|
*
|
|
* Revision 1.47 2005/09/05 08:47:44 nogj
|
|
* Fix most warnings issued by gcc4
|
|
*
|
|
* Revision 1.46 2005/08/18 22:13:27 phoenix
|
|
* fixed l.maci encoding
|
|
*
|
|
* Revision 1.45 2005/04/27 19:13:13 nogj
|
|
* l.rfe does not have a delay slot. Don't mark it as such.
|
|
*
|
|
* Revision 1.44 2005/03/31 16:09:57 nogj
|
|
* Implement a dynamic recompiler to speed up the execution
|
|
*
|
|
* Revision 1.43 2005/03/31 16:01:59 nogj
|
|
* Reclasify l.trap and l.sys to be an exception instruction
|
|
*
|
|
* Revision 1.42 2005/03/16 12:25:56 nogj
|
|
* Fix the parameters to the l.ff1/l.maci instructions
|
|
*
|
|
* Revision 1.41 2005/02/09 17:41:03 nogj
|
|
* Mark a simulated cpu address as such, by introducing the new oraddr_t type
|
|
*
|
|
* Revision 1.40 2005/01/27 14:14:13 nogj
|
|
* Remove the global op structure
|
|
*
|
|
* Revision 1.39 2005/01/27 13:35:40 nogj
|
|
* * Fix generate.c to produce a execgen.c with less warnings.
|
|
* * Fix the --enable-simple configure option.
|
|
*
|
|
* Revision 1.38 2005/01/27 13:15:50 nogj
|
|
* Mark wich operand is the destination operand in the architechture definition
|
|
*
|
|
* Revision 1.37 2005/01/11 15:41:58 andreje
|
|
* l.ff1 instruction added
|
|
*
|
|
* Revision 1.36 2004/07/22 20:17:23 phoenix
|
|
* removed includes
|
|
*
|
|
* Revision 1.35 2004/07/19 23:07:37 phoenix
|
|
* Gyorgy Jeney: extensive cleanup
|
|
*
|
|
* Revision 1.34 2004/06/27 22:56:48 lampret
|
|
* Updated instruction set descriptions. Changed FP instructions encoding.
|
|
*
|
|
* Revision 1.33 2004/05/09 19:52:31 lampret
|
|
* Changed desciption of the l.cust5 insns
|
|
*
|
|
* Revision 1.31 2003/07/01 19:34:49 csanchez
|
|
* Added support for l.addc instruction.
|
|
*
|
|
* Revision 1.30 2003/01/28 03:49:24 lampret
|
|
* Added cvs log keywords
|
|
*
|
|
*/
|
|
|
|
#include <string.h>
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
#include <stdio.h>
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
#include <stdlib.h>
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
#include <ctype.h>
|
more details.
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
#ifdef HAVE_CONFIG_H
|
/* This program is commented throughout in a fashion suitable for processing
|
|
with Doxygen. */
|
|
|
|
|
|
/* Autoconf and/or portability configuration */
|
# include "config.h"
|
# include "config.h"
|
#endif
|
|
#ifdef HAS_EXECUTION
|
|
# ifdef HAVE_INTTYPES_H
|
|
# include <inttypes.h> /* ...but to get arch.h we need uint{8,16,32}_t... */
|
|
# endif
|
|
# include "port.h"
|
# include "port.h"
|
# include "arch.h" /* ...but to get abstract.h, we need oraddr_t... */
|
|
# include "abstract.h" /* To get struct iqueue_entry... */
|
|
# include "debug.h" /* To get debug() */
|
|
#endif
|
|
#include "opcode/or32.h"
|
|
|
|
/* **INDENT-OFF** */
|
/* System includes */
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
/* Package includes */
|
|
#include "opcode/or32.h"
|
|
|
/* We treat all letters the same in encode/decode routines so
|
/* We treat all letters the same in encode/decode routines so
|
we need to assign some characteristics to them like signess etc.*/
|
we need to assign some characteristics to them like signess etc.*/
|
CONST struct or32_letter or32_letters[] =
|
CONST struct or32_letter or32_letters[] = {
|
{
|
|
{ 'A', NUM_UNSIGNED },
|
{ 'A', NUM_UNSIGNED },
|
{ 'B', NUM_UNSIGNED },
|
{ 'B', NUM_UNSIGNED },
|
{ 'D', NUM_UNSIGNED },
|
{ 'D', NUM_UNSIGNED },
|
{ 'I', NUM_SIGNED },
|
{ 'I', NUM_SIGNED },
|
{ 'K', NUM_UNSIGNED },
|
{ 'K', NUM_UNSIGNED },
|
Line 135... |
Line 63... |
Recommendation: irrelevant instruction bits should be set with a value of
|
Recommendation: irrelevant instruction bits should be set with a value of
|
bits in same positions of instruction preceding current instruction in the
|
bits in same positions of instruction preceding current instruction in the
|
code (when assembling).
|
code (when assembling).
|
*/
|
*/
|
|
|
#ifdef HAS_EXECUTION
|
#ifdef HAVE_EXECUTION
|
# if SIMPLE_EXECUTION
|
# if SIMPLE_EXECUTION
|
# define EFN &l_none
|
# define EFN &l_none
|
# define EF(func) &(func)
|
# define EF(func) &(func)
|
# define EFI &l_invalid
|
# define EFI &l_invalid
|
# elif COMPLEX_EXECUTION
|
# elif COMPLEX_EXECUTION
|
Line 153... |
Line 81... |
# else /* DYNAMIC_EXECUTION */
|
# else /* DYNAMIC_EXECUTION */
|
# define EFN &l_none
|
# define EFN &l_none
|
# define EF(func) &(gen_ ##func)
|
# define EF(func) &(gen_ ##func)
|
# define EFI &gen_l_invalid
|
# define EFI &gen_l_invalid
|
# endif
|
# endif
|
#else /* HAS_EXECUTION */
|
#else /* HAVE_EXECUTION */
|
# define EFN &l_none
|
# define EFN &l_none
|
# define EF(func) EFN
|
# define EF(func) EFN
|
# define EFI EFN
|
# define EFI EFN
|
#endif /* HAS_EXECUTION */
|
#endif /* HAVE_EXECUTION */
|
|
|
CONST struct or32_opcode or32_opcodes[] =
|
CONST struct or32_opcode or32_opcodes[] = {
|
{
|
|
|
|
{ "l.j", "N", "00 0x0 NNNNN NNNNN NNNN NNNN NNNN NNNN",
|
{ "l.j", "N", "00 0x0 NNNNN NNNNN NNNN NNNN NNNN NNNN",
|
EF(l_j), OR32_IF_DELAY, it_jump },
|
EF(l_j), OR32_IF_DELAY, it_jump },
|
{ "l.jal", "N", "00 0x1 NNNNN NNNNN NNNN NNNN NNNN NNNN",
|
{ "l.jal", "N", "00 0x1 NNNNN NNNNN NNNN NNNN NNNN NNNN",
|
EF(l_jal), OR32_IF_DELAY, it_jump },
|
EF(l_jal), OR32_IF_DELAY, it_jump },
|
Line 642... |
Line 569... |
|
|
#undef EFI
|
#undef EFI
|
#undef EFN
|
#undef EFN
|
#undef EF
|
#undef EF
|
|
|
/* **INDENT-ON** */
|
CONST int num_opcodes =
|
|
((sizeof (or32_opcodes)) / (sizeof (struct or32_opcode))) - 1;
|
/* Define dummy, if debug is not defined. */
|
|
#ifndef HAS_DEBUG
|
|
#define debug(l, fmt...) ;
|
|
#endif
|
|
|
|
CONST int num_opcodes = ((sizeof(or32_opcodes)) / (sizeof(struct or32_opcode))) - 1;
|
|
|
|
/* Calculates instruction length in bytes. Always 4 for OR32. */
|
/* Calculates instruction length in bytes. Always 4 for OR32. */
|
int
|
int
|
insn_len(int insn_index)
|
insn_len(int insn_index)
|
{
|
{
|
Line 685... |
Line 606... |
CONST struct or32_opcode *pinsn;
|
CONST struct or32_opcode *pinsn;
|
char *enc;
|
char *enc;
|
int range = 0;
|
int range = 0;
|
|
|
/* Is value cached? */
|
/* Is value cached? */
|
if ((range = range_cache[(unsigned char)l])) return range;
|
if ((range = range_cache[(unsigned char) l]))
|
|
return range;
|
|
|
for(pinsn = or32_opcodes; strlen(pinsn->name); pinsn++)
|
for(pinsn = or32_opcodes; strlen(pinsn->name); pinsn++)
|
{
|
{
|
if (strchr(pinsn->encoding,l))
|
if (strchr(pinsn->encoding,l))
|
{
|
{
|
Line 728... |
Line 650... |
return or32_opcodes[index].name;
|
return or32_opcodes[index].name;
|
else
|
else
|
return "???";
|
return "???";
|
}
|
}
|
|
|
#if defined(HAS_EXECUTION) && SIMPLE_EXECUTION
|
#if defined(HAVE_EXECUTION) && SIMPLE_EXECUTION
|
void
|
void
|
l_none(struct iqueue_entry *current)
|
l_none(struct iqueue_entry *current)
|
{
|
{
|
}
|
}
|
#elif defined(HAS_EXECUTION) && DYNAMIC_EXECUTION
|
#elif defined(HAVE_EXECUTION) && DYNAMIC_EXECUTION
|
void
|
void
|
l_none(struct op_queue *opq, int *param_t, int delay_slot)
|
l_none(struct op_queue *opq, int *param_t, int delay_slot)
|
{
|
{
|
}
|
}
|
#else
|
#else
|
Line 799... |
Line 721... |
/* MM: Struct that holds runtime build information about instructions. */
|
/* MM: Struct that holds runtime build information about instructions. */
|
struct temp_insn_struct *ti;
|
struct temp_insn_struct *ti;
|
|
|
struct insn_op_struct *op_data, **op_start;
|
struct insn_op_struct *op_data, **op_start;
|
|
|
/* Recursive utility function used to find best match and to build automata. */
|
static void
|
|
or32_debug (int level, const char *format, ...)
|
|
{
|
|
#if DEBUG
|
|
char *p;
|
|
va_list ap;
|
|
|
|
if ((p = malloc (1000)) == NULL)
|
|
return;
|
|
va_start (ap, format);
|
|
(void) vsnprintf (p, 1000, format, ap);
|
|
va_end (ap);
|
|
printf ("%s\n", p);
|
|
fflush (stdout);
|
|
free (p);
|
|
#endif
|
|
}
|
|
|
|
/* Recursive utility function used to find best match and to build automata. */
|
static unsigned long *
|
static unsigned long *
|
cover_insn (unsigned long *cur, int pass, unsigned int mask)
|
cover_insn (unsigned long *cur, int pass, unsigned int mask)
|
{
|
{
|
int best_first = 0, best_len = 0, i, last_match = -1, ninstr = 0;
|
int best_first = 0, best_len = 0, i, last_match = -1, ninstr = 0;
|
unsigned long cur_mask = mask;
|
unsigned long cur_mask = mask;
|
Line 816... |
Line 755... |
cur_mask &= ti[i].insn_mask;
|
cur_mask &= ti[i].insn_mask;
|
ninstr++;
|
ninstr++;
|
last_match = i;
|
last_match = i;
|
}
|
}
|
|
|
debug(8, "%08X %08X\n", mask, cur_mask);
|
or32_debug (8, "%08X %08lX\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(8, "%i>I%i %s\n", cur - automata, last_match, or32_opcodes[last_match].name);
|
or32_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. */
|
for (i = 0; i < 32; i++)
|
for (i = 0; i < 32; i++)
|
{
|
{
|
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(9, " (%i(%08X & %08X>>%i = %08X, %08X)",len,m, cur_mask, i, (cur_mask >> (unsigned)i), (cur_mask >> (unsigned)i) & m);
|
or32_debug (9, " (%i(%08lX & %08lX>>%i = %08lX, %08lX)", 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(9, "!");
|
or32_debug (9, "!");
|
}
|
}
|
else
|
else
|
break;
|
break;
|
}
|
}
|
}
|
}
|
debug(9, "\n");
|
or32_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(8, "%i> #### %i << %i (%i) ####\n", cur - automata, best_len, best_first, ninstr);
|
or32_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 873... |
Line 819... |
int j;
|
int j;
|
unsigned long *c;
|
unsigned long *c;
|
curpass++;
|
curpass++;
|
for (j = 0; j < num_opcodes; j++)
|
for (j = 0; j < num_opcodes; j++)
|
if (ti[j].in_pass == pass
|
if (ti[j].in_pass == pass
|
&& ((ti[j].insn >> best_first) & cur_mask) == (unsigned long) i
|
&& ((ti[j].insn >> best_first) & cur_mask) ==
|
|
(unsigned long) 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(9, "%08X %08X %i\n", mask, cur_mask, best_first);
|
or32_debug (9, "%08X %08lX %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(8, "%i> #%X -> %u\n", next - automata, i, cur - automata);
|
or32_debug (8, "%i> #%X -> %u\n", next - automata, i,
|
|
cur - automata);
|
*next = cur - automata;
|
*next = cur - automata;
|
cur = c;
|
cur = c;
|
}
|
}
|
else
|
else
|
{
|
{
|
debug(8, "%i> N/A\n", next - automata);
|
or32_debug (8, "%i> N/A\n", next - automata);
|
*next = 0;
|
*next = 0;
|
}
|
}
|
next++;
|
next++;
|
}
|
}
|
}
|
}
|
Line 923... |
Line 871... |
int num_cur_op = 0;;
|
int num_cur_op = 0;;
|
|
|
i = 0;
|
i = 0;
|
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(9, "#%08X %08X\n", cur->type, cur->data);
|
or32_debug (9, "#%08lX %08lX\n", cur->type, cur->data);
|
cur++;
|
cur++;
|
return cur;
|
return cur;
|
}
|
}
|
|
|
while (*args != '\0')
|
while (*args != '\0')
|
Line 944... |
Line 893... |
}
|
}
|
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(9, "%s : %08X ------\n", opcode->name, arg);
|
or32_debug (9, "%s : %08lX ------\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 970... |
Line 919... |
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(6, "|%08X %08X\n", cur->type, cur->data);
|
or32_debug (6, "|%08lX %08lX\n", cur->type, cur->data);
|
cur++;
|
cur++;
|
num_cur_op++;
|
num_cur_op++;
|
}
|
}
|
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. */
|
/* Set the OPTYPE_DIS flag on all insn_op_structs that belong to this
|
/* Set the OPTYPE_DIS flag on all insn_op_structs that belong to this
|
* operand */
|
* operand */
|
while(num_cur_op > 0) {
|
while (num_cur_op > 0)
|
|
{
|
cur[-num_cur_op].type |= type | OPTYPE_DIS;
|
cur[-num_cur_op].type |= type | OPTYPE_DIS;
|
num_cur_op--;
|
num_cur_op--;
|
}
|
}
|
cur[-1].type |= OPTYPE_OP;
|
cur[-1].type |= OPTYPE_OP;
|
debug(9, ">%08X %08X\n", cur->type, cur->data);
|
or32_debug (9, ">%08lX %08lX\n", cur->type, cur->data);
|
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(9, ">%08X %08X\n", cur->type, cur->data);
|
or32_debug (9, ">%08lX %08lX\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(9, ">%08X %08X\n", cur->type, cur->data);
|
or32_debug (9, ">%08lX %08lX\n", cur->type, cur->data);
|
cur++;
|
cur++;
|
type = 0;
|
type = 0;
|
i++;
|
i++;
|
args++;
|
args++;
|
}
|
}
|
Line 1021... |
Line 971... |
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(9, "#%08X %08X\n", cur->type, cur->data);
|
or32_debug (9, "#%08lX %08lX\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 1035... |
Line 985... |
{
|
{
|
int i;
|
int i;
|
unsigned long *end;
|
unsigned long *end;
|
struct insn_op_struct *cur;
|
struct insn_op_struct *cur;
|
|
|
automata = (unsigned long *) malloc (MAX_AUTOMATA_SIZE * sizeof (unsigned long));
|
automata =
|
ti = (struct temp_insn_struct *) malloc (sizeof (struct temp_insn_struct) * num_opcodes);
|
(unsigned long *) malloc (MAX_AUTOMATA_SIZE * sizeof (unsigned long));
|
|
ti =
|
|
(struct temp_insn_struct *) malloc (sizeof (struct temp_insn_struct) *
|
|
num_opcodes);
|
|
|
nuncovered = num_opcodes;
|
nuncovered = num_opcodes;
|
|
|
#ifdef HAS_EXECUTION
|
#ifdef HAVE_EXECUTION
|
printf("Building automata... ");
|
printf("Building automata... ");
|
#endif
|
#endif
|
|
|
/* Build temporary information about instructions. */
|
/* Build temporary information about instructions. */
|
for (i = 0; i < num_opcodes; i++)
|
for (i = 0; i < num_opcodes; i++)
|
Line 1065... |
Line 1018... |
if (end - automata > MAX_AUTOMATA_SIZE)
|
if (end - automata > MAX_AUTOMATA_SIZE)
|
{
|
{
|
fprintf (stderr, "Automata too large. Increase MAX_AUTOMATA_SIZE.");
|
fprintf (stderr, "Automata too large. Increase MAX_AUTOMATA_SIZE.");
|
exit (1);
|
exit (1);
|
}
|
}
|
#ifdef HAS_EXECUTION
|
#ifdef HAVE_EXECUTION
|
printf("done, num uncovered: %i/%i.\n", nuncovered, num_opcodes);
|
printf("done, num uncovered: %i/%i.\n", nuncovered, num_opcodes);
|
#endif
|
#endif
|
|
|
#ifdef HAS_EXECUTION
|
#ifdef HAVE_EXECUTION
|
printf("Parsing operands data... ");
|
printf("Parsing operands data... ");
|
#endif
|
#endif
|
op_data = (struct insn_op_struct *) malloc (MAX_OP_TABLE_SIZE * sizeof (struct insn_op_struct));
|
op_data =
|
op_start = (struct insn_op_struct **) malloc (num_opcodes * sizeof (struct insn_op_struct *));
|
(struct insn_op_struct *) malloc (MAX_OP_TABLE_SIZE *
|
|
sizeof (struct insn_op_struct));
|
|
op_start =
|
|
(struct insn_op_struct **) malloc (num_opcodes *
|
|
sizeof (struct insn_op_struct *));
|
cur = op_data;
|
cur = op_data;
|
for (i = 0; i < num_opcodes; i++)
|
for (i = 0; i < num_opcodes; i++)
|
{
|
{
|
op_start[i] = cur;
|
op_start[i] = cur;
|
cur = parse_params (&or32_opcodes[i], cur);
|
cur = parse_params (&or32_opcodes[i], cur);
|
if (cur - op_data > MAX_OP_TABLE_SIZE)
|
if (cur - op_data > MAX_OP_TABLE_SIZE)
|
{
|
{
|
fprintf (stderr, "Operands table too small, increase MAX_OP_TABLE_SIZE.\n");
|
fprintf (stderr,
|
|
"Operands table too small, increase MAX_OP_TABLE_SIZE.\n");
|
exit (1);
|
exit (1);
|
}
|
}
|
}
|
}
|
#ifdef HAS_EXECUTION
|
#ifdef HAVE_EXECUTION
|
printf("done.\n");
|
printf("done.\n");
|
#endif
|
#endif
|
}
|
}
|
|
|
void destruct_automata ()
|
void
|
|
destruct_automata ()
|
{
|
{
|
free (ti);
|
free (ti);
|
free (automata);
|
free (automata);
|
free (op_data);
|
free (op_data);
|
free (op_start);
|
free (op_start);
|
}
|
}
|
|
|
/* Decodes instruction and returns instruction index. */
|
/* Decodes instruction and returns instruction index. */
|
int insn_decode (unsigned int insn)
|
int
|
|
insn_decode (unsigned int insn)
|
{
|
{
|
unsigned long *a = automata;
|
unsigned long *a = automata;
|
int i;
|
int i;
|
while (!(*a & LEAF_FLAG))
|
while (!(*a & LEAF_FLAG))
|
{
|
{
|
Line 1168... |
Line 1128... |
int param_pos = 0;
|
int param_pos = 0;
|
|
|
for (enc = enc_initial; *enc != '\0'; enc++)
|
for (enc = enc_initial; *enc != '\0'; enc++)
|
if (*enc == param_ch)
|
if (*enc == param_ch)
|
{
|
{
|
if (enc - 2 >= enc_initial && (*(enc - 2) == '0') && (*(enc - 1) == 'x'))
|
if (enc - 2 >= enc_initial && (*(enc - 2) == '0')
|
|
&& (*(enc - 1) == 'x'))
|
continue;
|
continue;
|
else
|
else
|
param_pos++;
|
param_pos++;
|
}
|
}
|
|
|
Line 1206... |
Line 1167... |
else if (*enc == param_ch)
|
else if (*enc == param_ch)
|
{
|
{
|
opc_pos--;
|
opc_pos--;
|
param_pos--;
|
param_pos--;
|
#if DEBUG
|
#if DEBUG
|
printf("\n ret=%x opc_pos=%x, param_pos=%x\n", ret, opc_pos, param_pos);
|
printf ("\n ret=%x opc_pos=%x, param_pos=%x\n", ret, opc_pos,
|
|
param_pos);
|
#endif
|
#endif
|
if (islower(param_ch))
|
if (islower(param_ch))
|
ret -= ((insn >> opc_pos) & 0x1) << param_pos;
|
ret -= ((insn >> opc_pos) & 0x1) << param_pos;
|
else
|
else
|
ret += ((insn >> opc_pos) & 0x1) << param_pos;
|
ret += ((insn >> opc_pos) & 0x1) << param_pos;
|
Line 1245... |
Line 1207... |
unsigned long insn;
|
unsigned long insn;
|
{
|
{
|
int regnum = or32_extract(param_ch, encoding, insn);
|
int regnum = or32_extract(param_ch, encoding, insn);
|
|
|
sprintf (dest, "r%d", regnum);
|
sprintf (dest, "r%d", regnum);
|
while (*dest) dest++;
|
while (*dest)
|
|
dest++;
|
return dest;
|
return dest;
|
}
|
}
|
|
|
/* Print immediate. Used only by print_insn. */
|
/* Print immediate. Used only by print_insn. */
|
|
|
Line 1271... |
Line 1234... |
else
|
else
|
sprintf (dest, "0x%x", imm);
|
sprintf (dest, "0x%x", imm);
|
}
|
}
|
else
|
else
|
sprintf (dest, "%#x", imm);
|
sprintf (dest, "%#x", imm);
|
while (*dest) dest++;
|
while (*dest)
|
|
dest++;
|
return dest;
|
return dest;
|
}
|
}
|
|
|
/* Disassemble one instruction from insn to disassemble.
|
/* Disassemble one instruction from insn to disassemble.
|
Return the size of the instruction. */
|
Return the size of the instruction. */
|
Line 1300... |
Line 1264... |
{
|
{
|
struct or32_opcode const *opcode = &or32_opcodes[index];
|
struct or32_opcode const *opcode = &or32_opcodes[index];
|
char *s;
|
char *s;
|
|
|
strcpy (dest, opcode->name);
|
strcpy (dest, opcode->name);
|
while (*dest) dest++;
|
while (*dest)
|
|
dest++;
|
*dest++ = ' ';
|
*dest++ = ' ';
|
*dest = 0;
|
*dest = 0;
|
|
|
for (s = opcode->args; *s != '\0'; ++s)
|
for (s = opcode->args; *s != '\0'; ++s)
|
{
|
{
|
Line 1317... |
Line 1282... |
dest = or32_print_register(dest, *++s, opcode->encoding, insn);
|
dest = or32_print_register(dest, *++s, opcode->encoding, insn);
|
break;
|
break;
|
|
|
default:
|
default:
|
if (strchr (opcode->encoding, *s))
|
if (strchr (opcode->encoding, *s))
|
dest = or32_print_immediate (dest, *s, opcode->encoding, insn);
|
dest =
|
else {
|
or32_print_immediate (dest, *s, opcode->encoding, insn);
|
|
else
|
|
{
|
*dest++ = *s;
|
*dest++ = *s;
|
*dest = 0;
|
*dest = 0;
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
else
|
else
|
{
|
{
|
/* This used to be %8x for binutils. */
|
/* This used to be %8x for binutils. */
|
sprintf(dest, ".word 0x%08lx", insn);
|
sprintf(dest, ".word 0x%08lx", insn);
|
while (*dest) dest++;
|
while (*dest)
|
|
dest++;
|
}
|
}
|
return insn_len (insn);
|
return insn_len (insn);
|
}
|
}
|
|
|
No newline at end of file
|
No newline at end of file
|