GC some stuff I thought was long gone.
This commit is contained in:
parent
6c3a332e94
commit
ca88f70eac
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=107495
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,210 +0,0 @@
|
||||
/* BFD back-end for TMS320C30 coff binaries.
|
||||
Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
|
||||
Contributed by Steven Haworth (steve@pm.cse.rmit.edu.au)
|
||||
|
||||
This file is part of BFD, the Binary File Descriptor library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) 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. */
|
||||
|
||||
#include "bfd.h"
|
||||
#include "sysdep.h"
|
||||
#include "libbfd.h"
|
||||
#include "bfdlink.h"
|
||||
#include "coff/tic30.h"
|
||||
#include "coff/internal.h"
|
||||
#include "libcoff.h"
|
||||
|
||||
static int coff_tic30_select_reloc PARAMS ((reloc_howto_type *));
|
||||
static void rtype2howto PARAMS ((arelent *, struct internal_reloc *));
|
||||
static void reloc_processing PARAMS ((arelent *, struct internal_reloc *, asymbol **, bfd *, asection *));
|
||||
|
||||
reloc_howto_type * tic30_coff_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));
|
||||
|
||||
#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
|
||||
|
||||
reloc_howto_type tic30_coff_howto_table[] =
|
||||
{
|
||||
HOWTO (R_TIC30_ABS16, 2, 1, 16, false, 0, 0, NULL,
|
||||
"16", false, 0x0000FFFF, 0x0000FFFF, false),
|
||||
HOWTO (R_TIC30_ABS24, 2, 2, 24, false, 8, complain_overflow_bitfield, NULL,
|
||||
"24", false, 0xFFFFFF00, 0xFFFFFF00, false),
|
||||
HOWTO (R_TIC30_LDP, 18, 0, 24, false, 0, complain_overflow_bitfield, NULL,
|
||||
"LDP", false, 0x00FF0000, 0x000000FF, false),
|
||||
HOWTO (R_TIC30_ABS32, 2, 2, 32, false, 0, complain_overflow_bitfield, NULL,
|
||||
"32", false, 0xFFFFFFFF, 0xFFFFFFFF, false),
|
||||
HOWTO (R_TIC30_PC16, 2, 1, 16, true, 0, complain_overflow_signed, NULL,
|
||||
"PCREL", false, 0x0000FFFF, 0x0000FFFF, false),
|
||||
EMPTY_HOWTO (-1)
|
||||
};
|
||||
|
||||
#ifndef coff_bfd_reloc_type_lookup
|
||||
#define coff_bfd_reloc_type_lookup tic30_coff_reloc_type_lookup
|
||||
|
||||
/* For the case statement use the code values used in tc_gen_reloc to
|
||||
map to the howto table entries that match those in both the aout
|
||||
and coff implementations. */
|
||||
|
||||
reloc_howto_type *
|
||||
tic30_coff_reloc_type_lookup (abfd, code)
|
||||
bfd *abfd ATTRIBUTE_UNUSED;
|
||||
bfd_reloc_code_real_type code;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case BFD_RELOC_8:
|
||||
case BFD_RELOC_TIC30_LDP:
|
||||
return &tic30_coff_howto_table[2];
|
||||
case BFD_RELOC_16:
|
||||
return &tic30_coff_howto_table[0];
|
||||
case BFD_RELOC_24:
|
||||
return &tic30_coff_howto_table[1];
|
||||
case BFD_RELOC_16_PCREL:
|
||||
return &tic30_coff_howto_table[4];
|
||||
case BFD_RELOC_32:
|
||||
return &tic30_coff_howto_table[3];
|
||||
default:
|
||||
return (reloc_howto_type *) NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Turn a howto into a reloc number. */
|
||||
|
||||
static int
|
||||
coff_tic30_select_reloc (howto)
|
||||
reloc_howto_type *howto;
|
||||
{
|
||||
return howto->type;
|
||||
}
|
||||
|
||||
#define SELECT_RELOC(x,howto) x.r_type = coff_tic30_select_reloc(howto)
|
||||
|
||||
#define BADMAG(x) TIC30BADMAG(x)
|
||||
#define TIC30 1 /* Customize coffcode.h */
|
||||
#define __A_MAGIC_SET__
|
||||
|
||||
/* Code to swap in the reloc */
|
||||
#define SWAP_IN_RELOC_OFFSET H_GET_32
|
||||
#define SWAP_OUT_RELOC_OFFSET H_PUT_32
|
||||
#define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) dst->r_stuff[0] = 'S'; \
|
||||
dst->r_stuff[1] = 'C';
|
||||
|
||||
/* Code to turn a r_type into a howto ptr, uses the above howto table. */
|
||||
|
||||
static void
|
||||
rtype2howto (internal, dst)
|
||||
arelent *internal;
|
||||
struct internal_reloc *dst;
|
||||
{
|
||||
switch (dst->r_type)
|
||||
{
|
||||
case R_TIC30_ABS16:
|
||||
internal->howto = &tic30_coff_howto_table[0];
|
||||
break;
|
||||
case R_TIC30_ABS24:
|
||||
internal->howto = &tic30_coff_howto_table[1];
|
||||
break;
|
||||
case R_TIC30_ABS32:
|
||||
internal->howto = &tic30_coff_howto_table[3];
|
||||
break;
|
||||
case R_TIC30_LDP:
|
||||
internal->howto = &tic30_coff_howto_table[2];
|
||||
break;
|
||||
case R_TIC30_PC16:
|
||||
internal->howto = &tic30_coff_howto_table[4];
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define RTYPE2HOWTO(internal, relocentry) rtype2howto (internal, relocentry)
|
||||
|
||||
/* Perform any necessary magic to the addend in a reloc entry */
|
||||
|
||||
#define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
|
||||
cache_ptr->addend = ext_reloc.r_offset;
|
||||
|
||||
#define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
|
||||
reloc_processing(relent, reloc, symbols, abfd, section)
|
||||
|
||||
static void
|
||||
reloc_processing (relent, reloc, symbols, abfd, section)
|
||||
arelent *relent;
|
||||
struct internal_reloc *reloc;
|
||||
asymbol **symbols;
|
||||
bfd *abfd;
|
||||
asection *section;
|
||||
{
|
||||
relent->address = reloc->r_vaddr;
|
||||
rtype2howto (relent, reloc);
|
||||
|
||||
if (reloc->r_symndx > 0)
|
||||
relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
|
||||
else
|
||||
relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
|
||||
|
||||
relent->addend = reloc->r_offset;
|
||||
relent->address -= section->vma;
|
||||
}
|
||||
|
||||
#include "coffcode.h"
|
||||
|
||||
const bfd_target tic30_coff_vec =
|
||||
{
|
||||
"coff-tic30", /* name */
|
||||
bfd_target_coff_flavour,
|
||||
BFD_ENDIAN_BIG, /* data byte order is big */
|
||||
BFD_ENDIAN_LITTLE, /* header byte order is little */
|
||||
|
||||
(HAS_RELOC | EXEC_P | /* object flags */
|
||||
HAS_LINENO | HAS_DEBUG |
|
||||
HAS_SYMS | HAS_LOCALS | WP_TEXT),
|
||||
|
||||
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
|
||||
'_', /* leading symbol underscore */
|
||||
'/', /* ar_pad_char */
|
||||
15, /* ar_max_namelen */
|
||||
bfd_getb64, bfd_getb_signed_64, bfd_putb64,
|
||||
bfd_getb32, bfd_getb_signed_32, bfd_putb32,
|
||||
bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
|
||||
bfd_getl64, bfd_getl_signed_64, bfd_putl64,
|
||||
bfd_getl32, bfd_getl_signed_32, bfd_putl32,
|
||||
bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
|
||||
|
||||
{_bfd_dummy_target, coff_object_p, /* bfd_check_format */
|
||||
bfd_generic_archive_p, _bfd_dummy_target},
|
||||
{bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
|
||||
bfd_false},
|
||||
{bfd_false, coff_write_object_contents, /* bfd_write_contents */
|
||||
_bfd_write_archive_contents, bfd_false},
|
||||
|
||||
BFD_JUMP_TABLE_GENERIC (coff),
|
||||
BFD_JUMP_TABLE_COPY (coff),
|
||||
BFD_JUMP_TABLE_CORE (_bfd_nocore),
|
||||
BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
|
||||
BFD_JUMP_TABLE_SYMBOLS (coff),
|
||||
BFD_JUMP_TABLE_RELOCS (coff),
|
||||
BFD_JUMP_TABLE_WRITE (coff),
|
||||
BFD_JUMP_TABLE_LINK (coff),
|
||||
BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
|
||||
|
||||
NULL,
|
||||
|
||||
COFF_SWAP_TABLE
|
||||
};
|
@ -1,338 +0,0 @@
|
||||
/* BFD back-end for Zilog Z800n COFF binaries.
|
||||
Copyright 1992, 1993, 1994, 1995, 1997, 1999, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Cygnus Support.
|
||||
Written by Steve Chamberlain, <sac@cygnus.com>.
|
||||
|
||||
This file is part of BFD, the Binary File Descriptor library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) 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. */
|
||||
|
||||
#include "bfd.h"
|
||||
#include "sysdep.h"
|
||||
#include "libbfd.h"
|
||||
#include "bfdlink.h"
|
||||
#include "coff/z8k.h"
|
||||
#include "coff/internal.h"
|
||||
#include "libcoff.h"
|
||||
|
||||
static void extra_case PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *, arelent *, bfd_byte *, unsigned int *, unsigned int *));
|
||||
static void reloc_processing PARAMS ((arelent *, struct internal_reloc *, asymbol **, bfd *, asection *));
|
||||
static void rtype2howto PARAMS ((arelent *, struct internal_reloc *));
|
||||
static int coff_z8k_select_reloc PARAMS ((reloc_howto_type *));
|
||||
|
||||
#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
|
||||
|
||||
static reloc_howto_type r_imm32 =
|
||||
HOWTO (R_IMM32, 0, 2, 32, false, 0,
|
||||
complain_overflow_bitfield, 0, "r_imm32", true, 0xffffffff,
|
||||
0xffffffff, false);
|
||||
|
||||
static reloc_howto_type r_imm4l =
|
||||
HOWTO (R_IMM4L, 0, 0, 4, false, 0,
|
||||
complain_overflow_bitfield, 0, "r_imm4l", true, 0xf, 0xf, false);
|
||||
|
||||
static reloc_howto_type r_da =
|
||||
HOWTO (R_IMM16, 0, 1, 16, false, 0,
|
||||
complain_overflow_bitfield, 0, "r_da", true, 0x0000ffff, 0x0000ffff,
|
||||
false);
|
||||
|
||||
static reloc_howto_type r_imm8 =
|
||||
HOWTO (R_IMM8, 0, 0, 8, false, 0,
|
||||
complain_overflow_bitfield, 0, "r_imm8", true, 0x000000ff, 0x000000ff,
|
||||
false);
|
||||
|
||||
static reloc_howto_type r_rel16 =
|
||||
HOWTO (R_REL16, 0, 1, 16, false, 0,
|
||||
complain_overflow_bitfield, 0, "r_rel16", true, 0x0000ffff, 0x0000ffff,
|
||||
true);
|
||||
|
||||
static reloc_howto_type r_jr =
|
||||
HOWTO (R_JR, 0, 0, 8, true, 0, complain_overflow_signed, 0,
|
||||
"r_jr", true, 0, 0, true);
|
||||
|
||||
static reloc_howto_type r_disp7 =
|
||||
HOWTO (R_DISP7, 0, 0, 7, true, 0, complain_overflow_bitfield, 0,
|
||||
"r_disp7", true, 0, 0, true);
|
||||
|
||||
static reloc_howto_type r_callr =
|
||||
HOWTO (R_CALLR, 0, 1, 12, true, 0, complain_overflow_signed, 0,
|
||||
"r_callr", true, 0xfff, 0xfff, true);
|
||||
|
||||
/* Turn a howto into a reloc number */
|
||||
|
||||
static int
|
||||
coff_z8k_select_reloc (howto)
|
||||
reloc_howto_type *howto;
|
||||
{
|
||||
return howto->type;
|
||||
}
|
||||
|
||||
#define SELECT_RELOC(x,howto) x.r_type = coff_z8k_select_reloc(howto)
|
||||
|
||||
#define BADMAG(x) Z8KBADMAG(x)
|
||||
#define Z8K 1 /* Customize coffcode.h */
|
||||
#define __A_MAGIC_SET__
|
||||
|
||||
/* Code to swap in the reloc. */
|
||||
#define SWAP_IN_RELOC_OFFSET H_GET_32
|
||||
#define SWAP_OUT_RELOC_OFFSET H_PUT_32
|
||||
#define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
|
||||
dst->r_stuff[0] = 'S'; \
|
||||
dst->r_stuff[1] = 'C';
|
||||
|
||||
/* Code to turn a r_type into a howto ptr, uses the above howto table. */
|
||||
|
||||
static void
|
||||
rtype2howto (internal, dst)
|
||||
arelent * internal;
|
||||
struct internal_reloc *dst;
|
||||
{
|
||||
switch (dst->r_type)
|
||||
{
|
||||
default:
|
||||
abort ();
|
||||
break;
|
||||
case R_IMM8:
|
||||
internal->howto = &r_imm8;
|
||||
break;
|
||||
case R_IMM16:
|
||||
internal->howto = &r_da;
|
||||
break;
|
||||
case R_JR:
|
||||
internal->howto = &r_jr;
|
||||
break;
|
||||
case R_DISP7:
|
||||
internal->howto = &r_disp7;
|
||||
break;
|
||||
case R_CALLR:
|
||||
internal->howto = &r_callr;
|
||||
break;
|
||||
case R_REL16:
|
||||
internal->howto = &r_rel16;
|
||||
break;
|
||||
case R_IMM32:
|
||||
internal->howto = &r_imm32;
|
||||
break;
|
||||
case R_IMM4L:
|
||||
internal->howto = &r_imm4l;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define RTYPE2HOWTO(internal, relocentry) rtype2howto (internal, relocentry)
|
||||
|
||||
/* Perform any necessary magic to the addend in a reloc entry. */
|
||||
|
||||
#define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
|
||||
cache_ptr->addend = ext_reloc.r_offset;
|
||||
|
||||
#define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
|
||||
reloc_processing(relent, reloc, symbols, abfd, section)
|
||||
|
||||
static void
|
||||
reloc_processing (relent, reloc, symbols, abfd, section)
|
||||
arelent * relent;
|
||||
struct internal_reloc * reloc;
|
||||
asymbol ** symbols;
|
||||
bfd * abfd;
|
||||
asection * section;
|
||||
{
|
||||
relent->address = reloc->r_vaddr;
|
||||
rtype2howto (relent, reloc);
|
||||
|
||||
if (reloc->r_symndx > 0)
|
||||
relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
|
||||
else
|
||||
relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
|
||||
|
||||
relent->addend = reloc->r_offset;
|
||||
relent->address -= section->vma;
|
||||
}
|
||||
|
||||
static void
|
||||
extra_case (in_abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr)
|
||||
bfd * in_abfd;
|
||||
struct bfd_link_info * link_info;
|
||||
struct bfd_link_order * link_order;
|
||||
arelent * reloc;
|
||||
bfd_byte * data;
|
||||
unsigned int * src_ptr;
|
||||
unsigned int * dst_ptr;
|
||||
{
|
||||
asection * input_section = link_order->u.indirect.section;
|
||||
|
||||
switch (reloc->howto->type)
|
||||
{
|
||||
case R_IMM8:
|
||||
bfd_put_8 (in_abfd,
|
||||
bfd_coff_reloc16_get_value (reloc, link_info, input_section),
|
||||
data + *dst_ptr);
|
||||
(*dst_ptr) += 1;
|
||||
(*src_ptr) += 1;
|
||||
break;
|
||||
|
||||
case R_IMM32:
|
||||
bfd_put_32 (in_abfd,
|
||||
/* 0x80000000 indicates a long segmented address. */
|
||||
bfd_coff_reloc16_get_value (reloc, link_info, input_section) | 0x80000000,
|
||||
data + *dst_ptr);
|
||||
(*dst_ptr) += 4;
|
||||
(*src_ptr) += 4;
|
||||
break;
|
||||
|
||||
case R_IMM4L:
|
||||
bfd_put_8 (in_abfd,
|
||||
((bfd_get_8 (in_abfd, data + *dst_ptr) & 0xf0)
|
||||
| (0x0f
|
||||
& bfd_coff_reloc16_get_value (reloc, link_info,
|
||||
input_section))),
|
||||
data + *dst_ptr);
|
||||
(*dst_ptr) += 1;
|
||||
(*src_ptr) += 1;
|
||||
break;
|
||||
|
||||
case R_IMM16:
|
||||
bfd_put_16 (in_abfd,
|
||||
bfd_coff_reloc16_get_value (reloc, link_info, input_section),
|
||||
data + *dst_ptr);
|
||||
(*dst_ptr) += 2;
|
||||
(*src_ptr) += 2;
|
||||
break;
|
||||
|
||||
case R_JR:
|
||||
{
|
||||
bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
|
||||
input_section);
|
||||
bfd_vma dot = (link_order->offset
|
||||
+ *dst_ptr
|
||||
+ input_section->output_section->vma);
|
||||
int gap = dst - dot - 1; /* -1, since we're in the odd byte of the
|
||||
word and the pc's been incremented. */
|
||||
|
||||
if (gap & 1)
|
||||
abort ();
|
||||
gap /= 2;
|
||||
if (gap > 128 || gap < -128)
|
||||
{
|
||||
if (! ((*link_info->callbacks->reloc_overflow)
|
||||
(link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
|
||||
reloc->howto->name, reloc->addend, input_section->owner,
|
||||
input_section, reloc->address)))
|
||||
abort ();
|
||||
}
|
||||
bfd_put_8 (in_abfd, gap, data + *dst_ptr);
|
||||
(*dst_ptr)++;
|
||||
(*src_ptr)++;
|
||||
break;
|
||||
}
|
||||
|
||||
case R_DISP7:
|
||||
{
|
||||
bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
|
||||
input_section);
|
||||
bfd_vma dot = (link_order->offset
|
||||
+ *dst_ptr
|
||||
+ input_section->output_section->vma);
|
||||
int gap = dst - dot - 1; /* -1, since we're in the odd byte of the
|
||||
word and the pc's been incremented. */
|
||||
|
||||
if (gap & 1)
|
||||
abort ();
|
||||
gap /= 2;
|
||||
|
||||
if (gap > 0 || gap < -128)
|
||||
{
|
||||
if (! ((*link_info->callbacks->reloc_overflow)
|
||||
(link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
|
||||
reloc->howto->name, reloc->addend, input_section->owner,
|
||||
input_section, reloc->address)))
|
||||
abort ();
|
||||
}
|
||||
bfd_put_8 (in_abfd,
|
||||
(bfd_get_8 ( in_abfd, data + *dst_ptr) & 0x80) + (-gap & 0x7f),
|
||||
data + *dst_ptr);
|
||||
(*dst_ptr)++;
|
||||
(*src_ptr)++;
|
||||
break;
|
||||
}
|
||||
|
||||
case R_CALLR:
|
||||
{
|
||||
bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
|
||||
input_section);
|
||||
bfd_vma dot = (link_order->offset
|
||||
+ *dst_ptr
|
||||
+ input_section->output_section->vma);
|
||||
int gap = dst - dot - 2;
|
||||
|
||||
if (gap & 1)
|
||||
abort ();
|
||||
gap /= 2;
|
||||
if (gap > 8191 || gap < -8192)
|
||||
{
|
||||
if (! ((*link_info->callbacks->reloc_overflow)
|
||||
(link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
|
||||
reloc->howto->name, reloc->addend, input_section->owner,
|
||||
input_section, reloc->address)))
|
||||
abort ();
|
||||
}
|
||||
bfd_put_16 (in_abfd,
|
||||
(bfd_get_16 ( in_abfd, data + *dst_ptr) & 0xf000) | (-gap & 0x0fff),
|
||||
data + *dst_ptr);
|
||||
(*dst_ptr) += 2;
|
||||
(*src_ptr) += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
case R_REL16:
|
||||
{
|
||||
bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
|
||||
input_section);
|
||||
bfd_vma dot = (link_order->offset
|
||||
+ *dst_ptr
|
||||
+ input_section->output_section->vma);
|
||||
int gap = dst - dot - 2;
|
||||
|
||||
if (gap > 32767 || gap < -32768)
|
||||
{
|
||||
if (! ((*link_info->callbacks->reloc_overflow)
|
||||
(link_info, bfd_asymbol_name (*reloc->sym_ptr_ptr),
|
||||
reloc->howto->name, reloc->addend, input_section->owner,
|
||||
input_section, reloc->address)))
|
||||
abort ();
|
||||
}
|
||||
bfd_put_16 (in_abfd, (bfd_vma) gap, data + *dst_ptr);
|
||||
(*dst_ptr) += 2;
|
||||
(*src_ptr) += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
#define coff_reloc16_extra_cases extra_case
|
||||
|
||||
#include "coffcode.h"
|
||||
|
||||
#undef coff_bfd_get_relocated_section_contents
|
||||
#undef coff_bfd_relax_section
|
||||
#define coff_bfd_get_relocated_section_contents \
|
||||
bfd_coff_reloc16_get_relocated_section_contents
|
||||
#define coff_bfd_relax_section bfd_coff_reloc16_relax_section
|
||||
|
||||
CREATE_BIG_COFF_TARGET_VEC (z8kcoff_vec, "coff-z8k", 0, 0, '_', NULL)
|
@ -1,120 +0,0 @@
|
||||
/* bfd back-end for mips support
|
||||
Copyright 1990, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 2000, 2002
|
||||
Free Software Foundation, Inc.
|
||||
Written by Steve Chamberlain of Cygnus Support.
|
||||
|
||||
This file is part of BFD, the Binary File Descriptor library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) 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. */
|
||||
|
||||
#include "bfd.h"
|
||||
#include "sysdep.h"
|
||||
#include "libbfd.h"
|
||||
|
||||
static const bfd_arch_info_type *mips_compatible
|
||||
PARAMS ((const bfd_arch_info_type *, const bfd_arch_info_type *));
|
||||
|
||||
/* The default routine tests bits_per_word, which is wrong on mips as
|
||||
mips word size doesn't correlate with reloc size. */
|
||||
|
||||
static const bfd_arch_info_type *
|
||||
mips_compatible (a, b)
|
||||
const bfd_arch_info_type *a;
|
||||
const bfd_arch_info_type *b;
|
||||
{
|
||||
if (a->arch != b->arch)
|
||||
return NULL;
|
||||
|
||||
if (a->mach > b->mach)
|
||||
return a;
|
||||
|
||||
if (b->mach > a->mach)
|
||||
return b;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
#define N(BITS_WORD, BITS_ADDR, NUMBER, PRINT, DEFAULT, NEXT) \
|
||||
{ \
|
||||
BITS_WORD, /* bits in a word */ \
|
||||
BITS_ADDR, /* bits in an address */ \
|
||||
8, /* 8 bits in a byte */ \
|
||||
bfd_arch_mips, \
|
||||
NUMBER, \
|
||||
"mips", \
|
||||
PRINT, \
|
||||
3, \
|
||||
DEFAULT, \
|
||||
mips_compatible, \
|
||||
bfd_default_scan, \
|
||||
NEXT, \
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
I_mips3000,
|
||||
I_mips3900,
|
||||
I_mips4000,
|
||||
I_mips4010,
|
||||
I_mips4100,
|
||||
I_mips4111,
|
||||
I_mips4300,
|
||||
I_mips4400,
|
||||
I_mips4600,
|
||||
I_mips4650,
|
||||
I_mips5000,
|
||||
I_mips6000,
|
||||
I_mips8000,
|
||||
I_mips10000,
|
||||
I_mips12000,
|
||||
I_mips16,
|
||||
I_mips5,
|
||||
I_mipsisa32,
|
||||
I_mipsisa64,
|
||||
I_sb1,
|
||||
};
|
||||
|
||||
#define NN(index) (&arch_info_struct[(index) + 1])
|
||||
|
||||
static const bfd_arch_info_type arch_info_struct[] =
|
||||
{
|
||||
N (32, 32, bfd_mach_mips3000, "mips:3000", false, NN(I_mips3000)),
|
||||
N (32, 32, bfd_mach_mips3900, "mips:3900", false, NN(I_mips3900)),
|
||||
N (64, 64, bfd_mach_mips4000, "mips:4000", false, NN(I_mips4000)),
|
||||
N (64, 64, bfd_mach_mips4010, "mips:4010", false, NN(I_mips4010)),
|
||||
N (64, 64, bfd_mach_mips4100, "mips:4100", false, NN(I_mips4100)),
|
||||
N (64, 64, bfd_mach_mips4111, "mips:4111", false, NN(I_mips4111)),
|
||||
N (64, 64, bfd_mach_mips4300, "mips:4300", false, NN(I_mips4300)),
|
||||
N (64, 64, bfd_mach_mips4400, "mips:4400", false, NN(I_mips4400)),
|
||||
N (64, 64, bfd_mach_mips4600, "mips:4600", false, NN(I_mips4600)),
|
||||
N (64, 64, bfd_mach_mips4650, "mips:4650", false, NN(I_mips4650)),
|
||||
N (64, 64, bfd_mach_mips5000, "mips:5000", false, NN(I_mips5000)),
|
||||
N (32, 32, bfd_mach_mips6000, "mips:6000", false, NN(I_mips6000)),
|
||||
N (64, 64, bfd_mach_mips8000, "mips:8000", false, NN(I_mips8000)),
|
||||
N (64, 64, bfd_mach_mips10000,"mips:10000", false, NN(I_mips10000)),
|
||||
N (64, 64, bfd_mach_mips12000,"mips:12000", false, NN(I_mips12000)),
|
||||
N (64, 64, bfd_mach_mips16, "mips:16", false, NN(I_mips16)),
|
||||
N (64, 64, bfd_mach_mips5, "mips:mips5", false, NN(I_mips5)),
|
||||
N (32, 32, bfd_mach_mipsisa32, "mips:isa32", false, NN(I_mipsisa32)),
|
||||
N (64, 64, bfd_mach_mipsisa64, "mips:isa64", false, NN(I_mipsisa64)),
|
||||
N (64, 64, bfd_mach_mips_sb1, "mips:sb1", false, 0),
|
||||
};
|
||||
|
||||
/* The default architecture is mips:3000, but with a machine number of
|
||||
zero. This lets the linker distinguish between a default setting
|
||||
of mips, and an explicit setting of mips:3000. */
|
||||
|
||||
const bfd_arch_info_type bfd_mips_arch =
|
||||
N (32, 32, 0, "mips", true, &arch_info_struct[0]);
|
@ -1,39 +0,0 @@
|
||||
/* BFD support for the Texas Instruments TMS320C30 architecture.
|
||||
Copyright 1998 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of BFD, the Binary File Descriptor library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) 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. */
|
||||
|
||||
#include "bfd.h"
|
||||
#include "sysdep.h"
|
||||
#include "libbfd.h"
|
||||
|
||||
const bfd_arch_info_type bfd_tic30_arch =
|
||||
{
|
||||
32, /* 32 bits in a word */
|
||||
32, /* 32 bits in an address */
|
||||
8, /* 8 bits in a byte */
|
||||
bfd_arch_tic30,
|
||||
0, /* only 1 machine */
|
||||
"tic30",
|
||||
"tms320c30",
|
||||
2,
|
||||
true, /* the one and only */
|
||||
bfd_default_compatible,
|
||||
bfd_default_scan,
|
||||
0,
|
||||
};
|
@ -1,100 +0,0 @@
|
||||
/* BFD support for the NEC V850 processor
|
||||
Copyright 1996, 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This file is part of BFD, the Binary File Descriptor library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) 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. */
|
||||
|
||||
#include "bfd.h"
|
||||
#include "sysdep.h"
|
||||
#include "libbfd.h"
|
||||
#include "safe-ctype.h"
|
||||
|
||||
static boolean scan PARAMS ((const struct bfd_arch_info *, const char *));
|
||||
|
||||
static boolean
|
||||
scan (info, string)
|
||||
const struct bfd_arch_info * info;
|
||||
const char * string;
|
||||
{
|
||||
const char *ptr_src;
|
||||
const char *ptr_tst;
|
||||
unsigned long number;
|
||||
enum bfd_architecture arch;
|
||||
|
||||
/* First test for an exact match. */
|
||||
if (strcasecmp (string, info->printable_name) == 0)
|
||||
return true;
|
||||
|
||||
/* See how much of the supplied string matches with the
|
||||
architecture, eg the string m68k:68020 would match the m68k entry
|
||||
up to the :, then we get left with the machine number. */
|
||||
for (ptr_src = string, ptr_tst = info->arch_name;
|
||||
*ptr_src && *ptr_tst;
|
||||
ptr_src++, ptr_tst++)
|
||||
if (*ptr_src != *ptr_tst)
|
||||
break;
|
||||
|
||||
/* Chewed up as much of the architecture as will match;
|
||||
if there is a colon present skip it. */
|
||||
if (*ptr_src == ':')
|
||||
ptr_src ++;
|
||||
|
||||
if (*ptr_src == 0)
|
||||
/* Nothing more, then only keep this one if it is
|
||||
the default machine for this architecture. */
|
||||
return info->the_default;
|
||||
|
||||
number = 0;
|
||||
while (ISDIGIT (*ptr_src))
|
||||
{
|
||||
number = number * 10 + * ptr_src - '0';
|
||||
ptr_src ++;
|
||||
}
|
||||
|
||||
switch (number)
|
||||
{
|
||||
case bfd_mach_v850e: arch = bfd_arch_v850; break;
|
||||
case bfd_mach_v850ea: arch = bfd_arch_v850; break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (arch != info->arch)
|
||||
return false;
|
||||
|
||||
if (number != info->mach)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define N(number, print, default, next) \
|
||||
{ 32, 32, 8, bfd_arch_v850, number, "v850", print, 2, default, \
|
||||
bfd_default_compatible, scan, next }
|
||||
|
||||
#define NEXT NULL
|
||||
|
||||
static const bfd_arch_info_type arch_info_struct[] =
|
||||
{
|
||||
N (bfd_mach_v850e, "v850e", false, & arch_info_struct[1]),
|
||||
N (bfd_mach_v850ea, "v850ea", false, NULL)
|
||||
};
|
||||
|
||||
#undef NEXT
|
||||
#define NEXT & arch_info_struct[0]
|
||||
|
||||
const bfd_arch_info_type bfd_v850_arch =
|
||||
N (bfd_mach_v850, "v850", true, NEXT);
|
@ -1,193 +0,0 @@
|
||||
/* BFD library support routines for the Z800n architecture.
|
||||
Copyright 1992, 1993, 1994, 2000, 2001 Free Software Foundation, Inc.
|
||||
Hacked by Steve Chamberlain of Cygnus Support.
|
||||
|
||||
This file is part of BFD, the Binary File Descriptor library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) 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. */
|
||||
|
||||
#include "bfd.h"
|
||||
#include "sysdep.h"
|
||||
#include "libbfd.h"
|
||||
|
||||
static boolean scan_mach
|
||||
PARAMS ((const struct bfd_arch_info *, const char *));
|
||||
static const bfd_arch_info_type *compatible
|
||||
PARAMS ((const bfd_arch_info_type *, const bfd_arch_info_type *));
|
||||
|
||||
#if 0 /* not used currently */
|
||||
/*
|
||||
Relocations for the Z8K
|
||||
|
||||
*/
|
||||
static bfd_reloc_status_type
|
||||
howto16_callback (abfd, reloc_entry, symbol_in, data,
|
||||
ignore_input_section, ignore_bfd)
|
||||
bfd *abfd;
|
||||
arelent *reloc_entry;
|
||||
struct symbol_cache_entry *symbol_in;
|
||||
PTR data;
|
||||
asection *ignore_input_section;
|
||||
bfd *ignore_bfd;
|
||||
{
|
||||
long relocation = 0;
|
||||
bfd_vma addr = reloc_entry->address;
|
||||
long x = bfd_get_16 (abfd, (bfd_byte *) data + addr);
|
||||
|
||||
HOWTO_PREPARE (relocation, symbol_in);
|
||||
|
||||
x = (x + relocation + reloc_entry->addend);
|
||||
|
||||
bfd_put_16 (abfd, x, (bfd_byte *) data + addr);
|
||||
return bfd_reloc_ok;
|
||||
}
|
||||
|
||||
static bfd_reloc_status_type
|
||||
howto8_callback (abfd, reloc_entry, symbol_in, data,
|
||||
ignore_input_section, ignore_bfd)
|
||||
bfd *abfd;
|
||||
arelent *reloc_entry;
|
||||
struct symbol_cache_entry *symbol_in;
|
||||
PTR data;
|
||||
asection *ignore_input_section;
|
||||
bfd *ignore_bfd;
|
||||
{
|
||||
long relocation = 0;
|
||||
bfd_vma addr = reloc_entry->address;
|
||||
long x = bfd_get_8 (abfd, (bfd_byte *) data + addr);
|
||||
|
||||
HOWTO_PREPARE (relocation, symbol_in);
|
||||
|
||||
x = (x + relocation + reloc_entry->addend);
|
||||
|
||||
bfd_put_8 (abfd, x, (bfd_byte *) data + addr);
|
||||
return bfd_reloc_ok;
|
||||
}
|
||||
|
||||
static bfd_reloc_status_type
|
||||
howto8_FFnn_callback (abfd, reloc_entry, symbol_in, data,
|
||||
ignore_input_section, ignore_bfd)
|
||||
bfd *abfd;
|
||||
arelent *reloc_entry;
|
||||
struct symbol_cache_entry *symbol_in;
|
||||
PTR data;
|
||||
asection *ignore_input_section;
|
||||
bfd *ignore_bfd;
|
||||
{
|
||||
long relocation = 0;
|
||||
bfd_vma addr = reloc_entry->address;
|
||||
|
||||
long x = bfd_get_8 (abfd, (bfd_byte *) data + addr);
|
||||
abort ();
|
||||
HOWTO_PREPARE (relocation, symbol_in);
|
||||
|
||||
x = (x + relocation + reloc_entry->addend);
|
||||
|
||||
bfd_put_8 (abfd, x, (bfd_byte *) data + addr);
|
||||
return bfd_reloc_ok;
|
||||
}
|
||||
|
||||
static bfd_reloc_status_type
|
||||
howto8_pcrel_callback (abfd, reloc_entry, symbol_in, data,
|
||||
ignore_input_section, ignore_bfd)
|
||||
bfd *abfd;
|
||||
arelent *reloc_entry;
|
||||
struct symbol_cache_entry *symbol_in;
|
||||
PTR data;
|
||||
asection *ignore_input_section;
|
||||
bfd *ignore_bfd;
|
||||
{
|
||||
long relocation = 0;
|
||||
bfd_vma addr = reloc_entry->address;
|
||||
long x = bfd_get_8 (abfd, (bfd_byte *) data + addr);
|
||||
abort ();
|
||||
HOWTO_PREPARE (relocation, symbol_in);
|
||||
|
||||
x = (x + relocation + reloc_entry->addend);
|
||||
|
||||
bfd_put_8 (abfd, x, (bfd_byte *) data + addr);
|
||||
return bfd_reloc_ok;
|
||||
}
|
||||
|
||||
static reloc_howto_type howto_16
|
||||
= NEWHOWTO (howto16_callback, "abs16", 1, false, false);
|
||||
static reloc_howto_type howto_8
|
||||
= NEWHOWTO (howto8_callback, "abs8", 0, false, false);
|
||||
|
||||
static reloc_howto_type howto_8_FFnn
|
||||
= NEWHOWTO (howto8_FFnn_callback, "ff00+abs8", 0, false, false);
|
||||
|
||||
static reloc_howto_type howto_8_pcrel
|
||||
= NEWHOWTO (howto8_pcrel_callback, "pcrel8", 0, false, true);
|
||||
|
||||
static reloc_howto_type *
|
||||
local_bfd_reloc_type_lookup (arch, code)
|
||||
const struct bfd_arch_info *arch;
|
||||
bfd_reloc_code_real_type code;
|
||||
{
|
||||
switch (code)
|
||||
{
|
||||
case BFD_RELOC_16:
|
||||
return &howto_16;
|
||||
case BFD_RELOC_8_FFnn:
|
||||
return &howto_8_FFnn;
|
||||
case BFD_RELOC_8:
|
||||
return &howto_8;
|
||||
case BFD_RELOC_8_PCREL:
|
||||
return &howto_8_pcrel;
|
||||
default:
|
||||
return (reloc_howto_type *) NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static boolean
|
||||
scan_mach (info, string)
|
||||
const struct bfd_arch_info *info;
|
||||
const char *string;
|
||||
{
|
||||
if (strcmp (string, "z8001") == 0 || strcmp (string, "z8k") == 0)
|
||||
{
|
||||
return bfd_mach_z8001 == info->mach;
|
||||
}
|
||||
if (strcmp (string, "z8002") == 0)
|
||||
{
|
||||
return bfd_mach_z8002 == info->mach;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* This routine is provided two arch_infos and returns whether
|
||||
they'd be compatible */
|
||||
|
||||
static const bfd_arch_info_type *
|
||||
compatible (a, b)
|
||||
const bfd_arch_info_type *a;
|
||||
const bfd_arch_info_type *b;
|
||||
{
|
||||
if (a->arch != b->arch || a->mach != b->mach)
|
||||
return NULL;
|
||||
return a;
|
||||
}
|
||||
|
||||
static const bfd_arch_info_type arch_info_struct[] =
|
||||
{
|
||||
{32, 32, 8, bfd_arch_z8k, bfd_mach_z8001, "z8k", "z8001", 1, false, compatible, scan_mach, 0,},
|
||||
};
|
||||
|
||||
const bfd_arch_info_type bfd_z8k_arch =
|
||||
{
|
||||
32, 16, 8, bfd_arch_z8k, bfd_mach_z8002, "z8k", "z8002", 1, true, compatible, scan_mach, &arch_info_struct[0],
|
||||
};
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,487 +0,0 @@
|
||||
/* BFD backend for MIPS BSD (a.out) binaries.
|
||||
Copyright 1993, 1994, 1995, 1997, 1998, 1999, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
Written by Ralph Campbell.
|
||||
|
||||
This file is part of BFD, the Binary File Descriptor library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) 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. */
|
||||
|
||||
#define BYTES_IN_WORD 4
|
||||
/* #define ENTRY_CAN_BE_ZERO */
|
||||
#define N_HEADER_IN_TEXT(x) 1
|
||||
#define N_SHARED_LIB(x) 0
|
||||
#define N_TXTADDR(x) \
|
||||
(N_MAGIC(x) != ZMAGIC ? (x).a_entry : /* object file or NMAGIC */\
|
||||
TEXT_START_ADDR + EXEC_BYTES_SIZE /* no padding */\
|
||||
)
|
||||
#define N_DATADDR(x) (N_TXTADDR(x)+N_TXTSIZE(x))
|
||||
#define TEXT_START_ADDR 4096
|
||||
#define TARGET_PAGE_SIZE 4096
|
||||
#define SEGMENT_SIZE TARGET_PAGE_SIZE
|
||||
#define DEFAULT_ARCH bfd_arch_mips
|
||||
#define MACHTYPE_OK(mtype) ((mtype) == M_UNKNOWN \
|
||||
|| (mtype) == M_MIPS1 || (mtype) == M_MIPS2)
|
||||
#define MY_symbol_leading_char '\0'
|
||||
|
||||
/* Do not "beautify" the CONCAT* macro args. Traditional C will not
|
||||
remove whitespace added here, and thus will fail to concatenate
|
||||
the tokens. */
|
||||
#define MY(OP) CONCAT2 (mipsbsd_,OP)
|
||||
|
||||
#include "bfd.h"
|
||||
#include "sysdep.h"
|
||||
#include "libbfd.h"
|
||||
#include "libaout.h"
|
||||
|
||||
#define SET_ARCH_MACH(ABFD, EXEC) \
|
||||
MY(set_arch_mach) (ABFD, N_MACHTYPE (EXEC)); \
|
||||
MY(choose_reloc_size) (ABFD);
|
||||
static void MY(set_arch_mach) PARAMS ((bfd *abfd, unsigned long machtype));
|
||||
static void MY(choose_reloc_size) PARAMS ((bfd *abfd));
|
||||
|
||||
#define MY_write_object_contents MY(write_object_contents)
|
||||
static boolean MY(write_object_contents) PARAMS ((bfd *abfd));
|
||||
|
||||
/* We can't use MY(x) here because it leads to a recursive call to CONCAT2
|
||||
when expanded inside JUMP_TABLE. */
|
||||
#define MY_bfd_reloc_type_lookup mipsbsd_reloc_howto_type_lookup
|
||||
#define MY_canonicalize_reloc mipsbsd_canonicalize_reloc
|
||||
|
||||
#define MY_bfd_link_hash_table_create _bfd_generic_link_hash_table_create
|
||||
#define MY_bfd_link_add_symbols _bfd_generic_link_add_symbols
|
||||
#define MY_final_link_callback unused
|
||||
#define MY_bfd_final_link _bfd_generic_final_link
|
||||
|
||||
#define MY_backend_data &MY(backend_data)
|
||||
#define MY_BFD_TARGET
|
||||
|
||||
#include "aout-target.h"
|
||||
|
||||
static bfd_reloc_status_type mips_fix_jmp_addr
|
||||
PARAMS ((bfd *, arelent *, struct symbol_cache_entry *, PTR, asection *,
|
||||
bfd *, char **));
|
||||
static reloc_howto_type *MY(reloc_howto_type_lookup)
|
||||
PARAMS ((bfd *, bfd_reloc_code_real_type));
|
||||
|
||||
long MY(canonicalize_reloc) PARAMS ((bfd *, sec_ptr, arelent **, asymbol **));
|
||||
|
||||
static void
|
||||
MY(set_arch_mach) (abfd, machtype)
|
||||
bfd *abfd;
|
||||
unsigned long machtype;
|
||||
{
|
||||
enum bfd_architecture arch;
|
||||
unsigned int machine;
|
||||
|
||||
/* Determine the architecture and machine type of the object file. */
|
||||
switch (machtype)
|
||||
{
|
||||
case M_MIPS1:
|
||||
arch = bfd_arch_mips;
|
||||
machine = 3000;
|
||||
break;
|
||||
|
||||
case M_MIPS2:
|
||||
arch = bfd_arch_mips;
|
||||
machine = 4000;
|
||||
break;
|
||||
|
||||
default:
|
||||
arch = bfd_arch_obscure;
|
||||
machine = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
bfd_set_arch_mach (abfd, arch, machine);
|
||||
}
|
||||
|
||||
/* Determine the size of a relocation entry, based on the architecture */
|
||||
static void
|
||||
MY (choose_reloc_size) (abfd)
|
||||
bfd *abfd;
|
||||
{
|
||||
switch (bfd_get_arch (abfd))
|
||||
{
|
||||
case bfd_arch_sparc:
|
||||
case bfd_arch_a29k:
|
||||
case bfd_arch_mips:
|
||||
obj_reloc_entry_size (abfd) = RELOC_EXT_SIZE;
|
||||
break;
|
||||
default:
|
||||
obj_reloc_entry_size (abfd) = RELOC_STD_SIZE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write an object file in BSD a.out format.
|
||||
Section contents have already been written. We write the
|
||||
file header, symbols, and relocation. */
|
||||
|
||||
static boolean
|
||||
MY (write_object_contents) (abfd)
|
||||
bfd *abfd;
|
||||
{
|
||||
struct external_exec exec_bytes;
|
||||
struct internal_exec *execp = exec_hdr (abfd);
|
||||
|
||||
/* Magic number, maestro, please! */
|
||||
switch (bfd_get_arch (abfd))
|
||||
{
|
||||
case bfd_arch_m68k:
|
||||
switch (bfd_get_mach (abfd))
|
||||
{
|
||||
case bfd_mach_m68010:
|
||||
N_SET_MACHTYPE (*execp, M_68010);
|
||||
break;
|
||||
default:
|
||||
case bfd_mach_m68020:
|
||||
N_SET_MACHTYPE (*execp, M_68020);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case bfd_arch_sparc:
|
||||
N_SET_MACHTYPE (*execp, M_SPARC);
|
||||
break;
|
||||
case bfd_arch_i386:
|
||||
N_SET_MACHTYPE (*execp, M_386);
|
||||
break;
|
||||
case bfd_arch_a29k:
|
||||
N_SET_MACHTYPE (*execp, M_29K);
|
||||
break;
|
||||
case bfd_arch_mips:
|
||||
switch (bfd_get_mach (abfd))
|
||||
{
|
||||
case 4000:
|
||||
case 6000:
|
||||
N_SET_MACHTYPE (*execp, M_MIPS2);
|
||||
break;
|
||||
default:
|
||||
N_SET_MACHTYPE (*execp, M_MIPS1);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
N_SET_MACHTYPE (*execp, M_UNKNOWN);
|
||||
}
|
||||
|
||||
MY (choose_reloc_size) (abfd);
|
||||
|
||||
WRITE_HEADERS (abfd, execp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* MIPS relocation types. */
|
||||
#define MIPS_RELOC_32 0
|
||||
#define MIPS_RELOC_JMP 1
|
||||
#define MIPS_RELOC_WDISP16 2
|
||||
#define MIPS_RELOC_HI16 3
|
||||
#define MIPS_RELOC_HI16_S 4
|
||||
#define MIPS_RELOC_LO16 5
|
||||
|
||||
/* This is only called when performing a BFD_RELOC_MIPS_JMP relocation.
|
||||
The jump destination address is formed from the upper 4 bits of the
|
||||
"current" program counter concatenated with the jump instruction's
|
||||
26 bit field and two trailing zeros.
|
||||
If the destination address is not in the same segment as the "current"
|
||||
program counter, then we need to signal an error. */
|
||||
|
||||
static bfd_reloc_status_type
|
||||
mips_fix_jmp_addr (abfd, reloc_entry, symbol, data, input_section, output_bfd,
|
||||
error_message)
|
||||
bfd *abfd ATTRIBUTE_UNUSED;
|
||||
arelent *reloc_entry;
|
||||
struct symbol_cache_entry *symbol;
|
||||
PTR data ATTRIBUTE_UNUSED;
|
||||
asection *input_section;
|
||||
bfd *output_bfd;
|
||||
char **error_message ATTRIBUTE_UNUSED;
|
||||
{
|
||||
bfd_vma relocation, pc;
|
||||
|
||||
/* If this is a partial relocation, just continue. */
|
||||
if (output_bfd != (bfd *)NULL)
|
||||
return bfd_reloc_continue;
|
||||
|
||||
/* If this is an undefined symbol, return error */
|
||||
if (bfd_is_und_section (symbol->section)
|
||||
&& (symbol->flags & BSF_WEAK) == 0)
|
||||
return bfd_reloc_undefined;
|
||||
|
||||
/* Work out which section the relocation is targetted at and the
|
||||
initial relocation command value. */
|
||||
if (bfd_is_com_section (symbol->section))
|
||||
relocation = 0;
|
||||
else
|
||||
relocation = symbol->value;
|
||||
|
||||
relocation += symbol->section->output_section->vma;
|
||||
relocation += symbol->section->output_offset;
|
||||
relocation += reloc_entry->addend;
|
||||
|
||||
pc = input_section->output_section->vma + input_section->output_offset +
|
||||
reloc_entry->address + 4;
|
||||
|
||||
if ((relocation & 0xF0000000) != (pc & 0xF0000000))
|
||||
return bfd_reloc_overflow;
|
||||
|
||||
return bfd_reloc_continue;
|
||||
}
|
||||
|
||||
/* This is only called when performing a BFD_RELOC_HI16_S relocation.
|
||||
We need to see if bit 15 is set in the result. If it is, we add
|
||||
0x10000 and continue normally. This will compensate for the sign extension
|
||||
when the low bits are added at run time. */
|
||||
|
||||
static bfd_reloc_status_type
|
||||
mips_fix_hi16_s PARAMS ((bfd *, arelent *, asymbol *, PTR,
|
||||
asection *, bfd *, char **));
|
||||
|
||||
static bfd_reloc_status_type
|
||||
mips_fix_hi16_s (abfd, reloc_entry, symbol, data, input_section,
|
||||
output_bfd, error_message)
|
||||
bfd *abfd ATTRIBUTE_UNUSED;
|
||||
arelent *reloc_entry;
|
||||
asymbol *symbol;
|
||||
PTR data ATTRIBUTE_UNUSED;
|
||||
asection *input_section ATTRIBUTE_UNUSED;
|
||||
bfd *output_bfd;
|
||||
char **error_message ATTRIBUTE_UNUSED;
|
||||
{
|
||||
bfd_vma relocation;
|
||||
|
||||
/* If this is a partial relocation, just continue. */
|
||||
if (output_bfd != (bfd *)NULL)
|
||||
return bfd_reloc_continue;
|
||||
|
||||
/* If this is an undefined symbol, return error. */
|
||||
if (bfd_is_und_section (symbol->section)
|
||||
&& (symbol->flags & BSF_WEAK) == 0)
|
||||
return bfd_reloc_undefined;
|
||||
|
||||
/* Work out which section the relocation is targetted at and the
|
||||
initial relocation command value. */
|
||||
if (bfd_is_com_section (symbol->section))
|
||||
relocation = 0;
|
||||
else
|
||||
relocation = symbol->value;
|
||||
|
||||
relocation += symbol->section->output_section->vma;
|
||||
relocation += symbol->section->output_offset;
|
||||
relocation += reloc_entry->addend;
|
||||
|
||||
if (relocation & 0x8000)
|
||||
reloc_entry->addend += 0x10000;
|
||||
|
||||
return bfd_reloc_continue;
|
||||
}
|
||||
|
||||
static reloc_howto_type mips_howto_table_ext[] = {
|
||||
{MIPS_RELOC_32, 0, 2, 32, false, 0, complain_overflow_bitfield, 0,
|
||||
"32", false, 0, 0xffffffff, false},
|
||||
{MIPS_RELOC_JMP, 2, 2, 26, false, 0, complain_overflow_dont,
|
||||
mips_fix_jmp_addr,
|
||||
"MIPS_JMP", false, 0, 0x03ffffff, false},
|
||||
{MIPS_RELOC_WDISP16, 2, 2, 16, true, 0, complain_overflow_signed, 0,
|
||||
"WDISP16", false, 0, 0x0000ffff, false},
|
||||
{MIPS_RELOC_HI16, 16, 2, 16, false, 0, complain_overflow_bitfield, 0,
|
||||
"HI16", false, 0, 0x0000ffff, false},
|
||||
{MIPS_RELOC_HI16_S, 16, 2, 16, false, 0, complain_overflow_bitfield,
|
||||
mips_fix_hi16_s,
|
||||
"HI16_S", false, 0, 0x0000ffff, false},
|
||||
{MIPS_RELOC_LO16, 0, 2, 16, false, 0, complain_overflow_dont, 0,
|
||||
"LO16", false, 0, 0x0000ffff, false},
|
||||
};
|
||||
|
||||
static reloc_howto_type *
|
||||
MY(reloc_howto_type_lookup) (abfd, code)
|
||||
bfd *abfd;
|
||||
bfd_reloc_code_real_type code;
|
||||
{
|
||||
|
||||
if (bfd_get_arch (abfd) != bfd_arch_mips)
|
||||
return 0;
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case BFD_RELOC_CTOR:
|
||||
case BFD_RELOC_32:
|
||||
return (&mips_howto_table_ext[MIPS_RELOC_32]);
|
||||
case BFD_RELOC_MIPS_JMP:
|
||||
return (&mips_howto_table_ext[MIPS_RELOC_JMP]);
|
||||
case BFD_RELOC_16_PCREL_S2:
|
||||
return (&mips_howto_table_ext[MIPS_RELOC_WDISP16]);
|
||||
case BFD_RELOC_HI16:
|
||||
return (&mips_howto_table_ext[MIPS_RELOC_HI16]);
|
||||
case BFD_RELOC_HI16_S:
|
||||
return (&mips_howto_table_ext[MIPS_RELOC_HI16_S]);
|
||||
case BFD_RELOC_LO16:
|
||||
return (&mips_howto_table_ext[MIPS_RELOC_LO16]);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* This is just like the standard aoutx.h version but we need to do our
|
||||
own mapping of external reloc type values to howto entries. */
|
||||
long
|
||||
MY(canonicalize_reloc) (abfd, section, relptr, symbols)
|
||||
bfd *abfd;
|
||||
sec_ptr section;
|
||||
arelent **relptr;
|
||||
asymbol **symbols;
|
||||
{
|
||||
arelent *tblptr = section->relocation;
|
||||
unsigned int count, c;
|
||||
extern reloc_howto_type NAME(aout,ext_howto_table)[];
|
||||
|
||||
/* If we have already read in the relocation table, return the values. */
|
||||
if (section->flags & SEC_CONSTRUCTOR)
|
||||
{
|
||||
arelent_chain *chain = section->constructor_chain;
|
||||
|
||||
for (count = 0; count < section->reloc_count; count++)
|
||||
{
|
||||
*relptr++ = &chain->relent;
|
||||
chain = chain->next;
|
||||
}
|
||||
*relptr = 0;
|
||||
return section->reloc_count;
|
||||
}
|
||||
|
||||
if (tblptr && section->reloc_count)
|
||||
{
|
||||
for (count = 0; count++ < section->reloc_count;)
|
||||
*relptr++ = tblptr++;
|
||||
*relptr = 0;
|
||||
return section->reloc_count;
|
||||
}
|
||||
|
||||
if (!NAME(aout,slurp_reloc_table) (abfd, section, symbols))
|
||||
return -1;
|
||||
tblptr = section->relocation;
|
||||
|
||||
/* fix up howto entries. */
|
||||
for (count = 0; count++ < section->reloc_count;)
|
||||
{
|
||||
c = tblptr->howto - NAME(aout,ext_howto_table);
|
||||
tblptr->howto = &mips_howto_table_ext[c];
|
||||
|
||||
*relptr++ = tblptr++;
|
||||
}
|
||||
*relptr = 0;
|
||||
return section->reloc_count;
|
||||
}
|
||||
|
||||
static const struct aout_backend_data MY(backend_data) = {
|
||||
0, /* zmagic contiguous */
|
||||
1, /* text incl header */
|
||||
0, /* entry is text address */
|
||||
0, /* exec_hdr_flags */
|
||||
TARGET_PAGE_SIZE, /* text vma */
|
||||
MY_set_sizes,
|
||||
0, /* text size includes exec header */
|
||||
0, /* add_dynamic_symbols */
|
||||
0, /* add_one_symbol */
|
||||
0, /* link_dynamic_object */
|
||||
0, /* write_dynamic_symbol */
|
||||
0, /* check_dynamic_reloc */
|
||||
0 /* finish_dynamic_link */
|
||||
};
|
||||
|
||||
extern const bfd_target aout_mips_big_vec;
|
||||
|
||||
const bfd_target aout_mips_little_vec =
|
||||
{
|
||||
"a.out-mips-little", /* name */
|
||||
bfd_target_aout_flavour,
|
||||
BFD_ENDIAN_LITTLE, /* target byte order (little) */
|
||||
BFD_ENDIAN_LITTLE, /* target headers byte order (little) */
|
||||
(HAS_RELOC | EXEC_P | /* object flags */
|
||||
HAS_LINENO | HAS_DEBUG |
|
||||
HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
|
||||
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
|
||||
MY_symbol_leading_char,
|
||||
' ', /* ar_pad_char */
|
||||
15, /* ar_max_namelen */
|
||||
bfd_getl64, bfd_getl_signed_64, bfd_putl64,
|
||||
bfd_getl32, bfd_getl_signed_32, bfd_putl32,
|
||||
bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
|
||||
bfd_getl64, bfd_getl_signed_64, bfd_putl64,
|
||||
bfd_getl32, bfd_getl_signed_32, bfd_putl32,
|
||||
bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
|
||||
{_bfd_dummy_target, MY_object_p, /* bfd_check_format */
|
||||
bfd_generic_archive_p, MY_core_file_p},
|
||||
{bfd_false, MY_mkobject, /* bfd_set_format */
|
||||
_bfd_generic_mkarchive, bfd_false},
|
||||
{bfd_false, MY_write_object_contents, /* bfd_write_contents */
|
||||
_bfd_write_archive_contents, bfd_false},
|
||||
|
||||
BFD_JUMP_TABLE_GENERIC (MY),
|
||||
BFD_JUMP_TABLE_COPY (MY),
|
||||
BFD_JUMP_TABLE_CORE (MY),
|
||||
BFD_JUMP_TABLE_ARCHIVE (MY),
|
||||
BFD_JUMP_TABLE_SYMBOLS (MY),
|
||||
BFD_JUMP_TABLE_RELOCS (MY),
|
||||
BFD_JUMP_TABLE_WRITE (MY),
|
||||
BFD_JUMP_TABLE_LINK (MY),
|
||||
BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
|
||||
|
||||
& aout_mips_big_vec,
|
||||
|
||||
(PTR) MY_backend_data
|
||||
};
|
||||
|
||||
const bfd_target aout_mips_big_vec =
|
||||
{
|
||||
"a.out-mips-big", /* name */
|
||||
bfd_target_aout_flavour,
|
||||
BFD_ENDIAN_BIG, /* target byte order (big) */
|
||||
BFD_ENDIAN_BIG, /* target headers byte order (big) */
|
||||
(HAS_RELOC | EXEC_P | /* object flags */
|
||||
HAS_LINENO | HAS_DEBUG |
|
||||
HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
|
||||
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_CODE | SEC_DATA),
|
||||
MY_symbol_leading_char,
|
||||
' ', /* ar_pad_char */
|
||||
15, /* ar_max_namelen */
|
||||
bfd_getb64, bfd_getb_signed_64, bfd_putb64,
|
||||
bfd_getb32, bfd_getb_signed_32, bfd_putb32,
|
||||
bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
|
||||
bfd_getb64, bfd_getb_signed_64, bfd_putb64,
|
||||
bfd_getb32, bfd_getb_signed_32, bfd_putb32,
|
||||
bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
|
||||
{_bfd_dummy_target, MY_object_p, /* bfd_check_format */
|
||||
bfd_generic_archive_p, MY_core_file_p},
|
||||
{bfd_false, MY_mkobject, /* bfd_set_format */
|
||||
_bfd_generic_mkarchive, bfd_false},
|
||||
{bfd_false, MY_write_object_contents, /* bfd_write_contents */
|
||||
_bfd_write_archive_contents, bfd_false},
|
||||
|
||||
BFD_JUMP_TABLE_GENERIC (MY),
|
||||
BFD_JUMP_TABLE_COPY (MY),
|
||||
BFD_JUMP_TABLE_CORE (MY),
|
||||
BFD_JUMP_TABLE_ARCHIVE (MY),
|
||||
BFD_JUMP_TABLE_SYMBOLS (MY),
|
||||
BFD_JUMP_TABLE_RELOCS (MY),
|
||||
BFD_JUMP_TABLE_WRITE (MY),
|
||||
BFD_JUMP_TABLE_LINK (MY),
|
||||
BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
|
||||
|
||||
& aout_mips_little_vec,
|
||||
|
||||
(PTR) MY_backend_data
|
||||
};
|
@ -1,998 +0,0 @@
|
||||
/* BFD back-end for MIPS PE COFF files.
|
||||
Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
||||
2000, 2001 Free Software Foundation, Inc.
|
||||
Modified from coff-i386.c by DJ Delorie, dj@cygnus.com
|
||||
|
||||
This file is part of BFD, the Binary File Descriptor library.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) 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. */
|
||||
|
||||
#define COFF_WITH_PE
|
||||
#define COFF_LONG_SECTION_NAMES
|
||||
#define PCRELOFFSET true
|
||||
|
||||
#include "bfd.h"
|
||||
#include "sysdep.h"
|
||||
#include "libbfd.h"
|
||||
|
||||
#include "coff/mipspe.h"
|
||||
|
||||
#include "coff/internal.h"
|
||||
|
||||
#include "coff/pe.h"
|
||||
|
||||
#include "libcoff.h"
|
||||
|
||||
static bfd_reloc_status_type coff_mips_reloc
|
||||
PARAMS ((bfd *, arelent *, asymbol *, PTR, asection *, bfd *, char **));
|
||||
static reloc_howto_type *coff_mips_rtype_to_howto
|
||||
PARAMS ((bfd *, asection *, struct internal_reloc *,
|
||||
struct coff_link_hash_entry *, struct internal_syment *,
|
||||
|
||||
bfd_vma *));
|
||||
#if 0
|
||||
static void mips_ecoff_swap_reloc_in PARAMS ((bfd *, PTR,
|
||||
struct internal_reloc *));
|
||||
static void mips_ecoff_swap_reloc_out PARAMS ((bfd *,
|
||||
const struct internal_reloc *,
|
||||
PTR));
|
||||
static void mips_adjust_reloc_in PARAMS ((bfd *,
|
||||
const struct internal_reloc *,
|
||||
arelent *));
|
||||
static void mips_adjust_reloc_out PARAMS ((bfd *, const arelent *,
|
||||
struct internal_reloc *));
|
||||
#endif
|
||||
|
||||
static boolean in_reloc_p PARAMS ((bfd *, reloc_howto_type *));
|
||||
static reloc_howto_type * coff_mips_reloc_type_lookup PARAMS ((bfd *, bfd_reloc_code_real_type));
|
||||
static void mips_swap_reloc_in PARAMS ((bfd *, PTR, PTR));
|
||||
static unsigned int mips_swap_reloc_out PARAMS ((bfd *, PTR, PTR));
|
||||
static boolean coff_pe_mips_relocate_section
|
||||
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
|
||||
struct internal_reloc *, struct internal_syment *, asection **));
|
||||
|
||||
#define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (2)
|
||||
/* The page size is a guess based on ELF. */
|
||||
|
||||
#define COFF_PAGE_SIZE 0x1000
|
||||
|
||||
/* For some reason when using mips COFF the value stored in the .text
|
||||
section for a reference to a common symbol is the value itself plus
|
||||
any desired offset. Ian Taylor, Cygnus Support. */
|
||||
|
||||
/* If we are producing relocateable output, we need to do some
|
||||
adjustments to the object file that are not done by the
|
||||
bfd_perform_relocation function. This function is called by every
|
||||
reloc type to make any required adjustments. */
|
||||
|
||||
static bfd_reloc_status_type
|
||||
coff_mips_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd,
|
||||
error_message)
|
||||
bfd *abfd;
|
||||
arelent *reloc_entry;
|
||||
asymbol *symbol;
|
||||
PTR data;
|
||||
asection *input_section ATTRIBUTE_UNUSED;
|
||||
bfd *output_bfd;
|
||||
char **error_message ATTRIBUTE_UNUSED;
|
||||
{
|
||||
symvalue diff;
|
||||
|
||||
if (output_bfd == (bfd *) NULL)
|
||||
return bfd_reloc_continue;
|
||||
|
||||
if (bfd_is_com_section (symbol->section))
|
||||
{
|
||||
#ifndef COFF_WITH_PE
|
||||
/* We are relocating a common symbol. The current value in the
|
||||
object file is ORIG + OFFSET, where ORIG is the value of the
|
||||
common symbol as seen by the object file when it was compiled
|
||||
(this may be zero if the symbol was undefined) and OFFSET is
|
||||
the offset into the common symbol (normally zero, but may be
|
||||
non-zero when referring to a field in a common structure).
|
||||
ORIG is the negative of reloc_entry->addend, which is set by
|
||||
the CALC_ADDEND macro below. We want to replace the value in
|
||||
the object file with NEW + OFFSET, where NEW is the value of
|
||||
the common symbol which we are going to put in the final
|
||||
object file. NEW is symbol->value. */
|
||||
diff = symbol->value + reloc_entry->addend;
|
||||
#else
|
||||
/* In PE mode, we do not offset the common symbol. */
|
||||
diff = reloc_entry->addend;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* For some reason bfd_perform_relocation always effectively
|
||||
ignores the addend for a COFF target when producing
|
||||
relocateable output. This seems to be always wrong for 386
|
||||
COFF, so we handle the addend here instead. */
|
||||
diff = reloc_entry->addend;
|
||||
}
|
||||
|
||||
#ifdef COFF_WITH_PE
|
||||
#if 0
|
||||
/* dj - handle it like any other reloc? */
|
||||
/* FIXME: How should this case be handled? */
|
||||
if (reloc_entry->howto->type == MIPS_R_RVA && diff != 0)
|
||||
abort ();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define DOIT(x) \
|
||||
x = ((x & ~howto->dst_mask) | (((x & howto->src_mask) + (diff >> howto->rightshift)) & howto->dst_mask))
|
||||
|
||||
if (diff != 0)
|
||||
{
|
||||
reloc_howto_type *howto = reloc_entry->howto;
|
||||
unsigned char *addr = (unsigned char *) data + reloc_entry->address;
|
||||
|
||||
switch (howto->size)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
char x = bfd_get_8 (abfd, addr);
|
||||
DOIT (x);
|
||||
bfd_put_8 (abfd, x, addr);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
{
|
||||
short x = bfd_get_16 (abfd, addr);
|
||||
DOIT (x);
|
||||
bfd_put_16 (abfd, (bfd_vma) x, addr);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
{
|
||||
long x = bfd_get_32 (abfd, addr);
|
||||
DOIT (x);
|
||||
bfd_put_32 (abfd, (bfd_vma) x, addr);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Now let bfd_perform_relocation finish everything up. */
|
||||
return bfd_reloc_continue;
|
||||
}
|
||||
|
||||
#ifdef COFF_WITH_PE
|
||||
/* Return true if this relocation should
|
||||
appear in the output .reloc section. */
|
||||
|
||||
static boolean
|
||||
in_reloc_p (abfd, howto)
|
||||
bfd * abfd ATTRIBUTE_UNUSED;
|
||||
reloc_howto_type *howto;
|
||||
{
|
||||
return ! howto->pc_relative && howto->type != MIPS_R_RVA;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef PCRELOFFSET
|
||||
#define PCRELOFFSET false
|
||||
#endif
|
||||
|
||||
static reloc_howto_type howto_table[] =
|
||||
{
|
||||
/* Reloc type 0 is ignored. The reloc reading code ensures that
|
||||
this is a reference to the .abs section, which will cause
|
||||
bfd_perform_relocation to do nothing. */
|
||||
HOWTO (MIPS_R_ABSOLUTE, /* type */
|
||||
0, /* rightshift */
|
||||
0, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
8, /* bitsize */
|
||||
false, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_dont, /* complain_on_overflow */
|
||||
0, /* special_function */
|
||||
"IGNORE", /* name */
|
||||
false, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
0, /* dst_mask */
|
||||
false), /* pcrel_offset */
|
||||
|
||||
/* A 16 bit reference to a symbol, normally from a data section. */
|
||||
HOWTO (MIPS_R_REFHALF, /* type */
|
||||
0, /* rightshift */
|
||||
1, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
16, /* bitsize */
|
||||
false, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_bitfield, /* complain_on_overflow */
|
||||
coff_mips_reloc, /* special_function */
|
||||
"REFHALF", /* name */
|
||||
true, /* partial_inplace */
|
||||
0xffff, /* src_mask */
|
||||
0xffff, /* dst_mask */
|
||||
false), /* pcrel_offset */
|
||||
|
||||
/* A 32 bit reference to a symbol, normally from a data section. */
|
||||
HOWTO (MIPS_R_REFWORD, /* type */
|
||||
0, /* rightshift */
|
||||
2, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
32, /* bitsize */
|
||||
false, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_bitfield, /* complain_on_overflow */
|
||||
coff_mips_reloc, /* special_function */
|
||||
"REFWORD", /* name */
|
||||
true, /* partial_inplace */
|
||||
0xffffffff, /* src_mask */
|
||||
0xffffffff, /* dst_mask */
|
||||
false), /* pcrel_offset */
|
||||
|
||||
/* A 26 bit absolute jump address. */
|
||||
HOWTO (MIPS_R_JMPADDR, /* type */
|
||||
2, /* rightshift */
|
||||
2, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
26, /* bitsize */
|
||||
false, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_dont, /* complain_on_overflow */
|
||||
/* This needs complex overflow
|
||||
detection, because the upper four
|
||||
bits must match the PC. */
|
||||
coff_mips_reloc, /* special_function */
|
||||
"JMPADDR", /* name */
|
||||
true, /* partial_inplace */
|
||||
0x3ffffff, /* src_mask */
|
||||
0x3ffffff, /* dst_mask */
|
||||
false), /* pcrel_offset */
|
||||
|
||||
/* The high 16 bits of a symbol value. Handled by the function
|
||||
mips_refhi_reloc. */
|
||||
HOWTO (MIPS_R_REFHI, /* type */
|
||||
16, /* rightshift */
|
||||
2, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
16, /* bitsize */
|
||||
false, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_bitfield, /* complain_on_overflow */
|
||||
coff_mips_reloc, /* special_function */
|
||||
"REFHI", /* name */
|
||||
true, /* partial_inplace */
|
||||
0xffff, /* src_mask */
|
||||
0xffff, /* dst_mask */
|
||||
false), /* pcrel_offset */
|
||||
|
||||
/* The low 16 bits of a symbol value. */
|
||||
HOWTO (MIPS_R_REFLO, /* type */
|
||||
0, /* rightshift */
|
||||
2, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
16, /* bitsize */
|
||||
false, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_dont, /* complain_on_overflow */
|
||||
coff_mips_reloc, /* special_function */
|
||||
"REFLO", /* name */
|
||||
true, /* partial_inplace */
|
||||
0xffff, /* src_mask */
|
||||
0xffff, /* dst_mask */
|
||||
false), /* pcrel_offset */
|
||||
|
||||
/* A reference to an offset from the gp register. Handled by the
|
||||
function mips_gprel_reloc. */
|
||||
HOWTO (MIPS_R_GPREL, /* type */
|
||||
0, /* rightshift */
|
||||
2, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
16, /* bitsize */
|
||||
false, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_signed, /* complain_on_overflow */
|
||||
coff_mips_reloc, /* special_function */
|
||||
"GPREL", /* name */
|
||||
true, /* partial_inplace */
|
||||
0xffff, /* src_mask */
|
||||
0xffff, /* dst_mask */
|
||||
false), /* pcrel_offset */
|
||||
|
||||
/* A reference to a literal using an offset from the gp register.
|
||||
Handled by the function mips_gprel_reloc. */
|
||||
HOWTO (MIPS_R_LITERAL, /* type */
|
||||
0, /* rightshift */
|
||||
2, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
16, /* bitsize */
|
||||
false, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_signed, /* complain_on_overflow */
|
||||
coff_mips_reloc, /* special_function */
|
||||
"LITERAL", /* name */
|
||||
true, /* partial_inplace */
|
||||
0xffff, /* src_mask */
|
||||
0xffff, /* dst_mask */
|
||||
false), /* pcrel_offset */
|
||||
|
||||
EMPTY_HOWTO (8),
|
||||
EMPTY_HOWTO (9),
|
||||
EMPTY_HOWTO (10),
|
||||
EMPTY_HOWTO (11),
|
||||
EMPTY_HOWTO (12),
|
||||
EMPTY_HOWTO (13),
|
||||
EMPTY_HOWTO (14),
|
||||
EMPTY_HOWTO (15),
|
||||
EMPTY_HOWTO (16),
|
||||
EMPTY_HOWTO (17),
|
||||
EMPTY_HOWTO (18),
|
||||
EMPTY_HOWTO (19),
|
||||
EMPTY_HOWTO (20),
|
||||
EMPTY_HOWTO (21),
|
||||
EMPTY_HOWTO (22),
|
||||
EMPTY_HOWTO (23),
|
||||
EMPTY_HOWTO (24),
|
||||
EMPTY_HOWTO (25),
|
||||
EMPTY_HOWTO (26),
|
||||
EMPTY_HOWTO (27),
|
||||
EMPTY_HOWTO (28),
|
||||
EMPTY_HOWTO (29),
|
||||
EMPTY_HOWTO (30),
|
||||
EMPTY_HOWTO (31),
|
||||
EMPTY_HOWTO (32),
|
||||
EMPTY_HOWTO (33),
|
||||
HOWTO (MIPS_R_RVA, /* type */
|
||||
0, /* rightshift */
|
||||
2, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
32, /* bitsize */
|
||||
false, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_bitfield, /* complain_on_overflow */
|
||||
coff_mips_reloc, /* special_function */
|
||||
"rva32", /* name */
|
||||
true, /* partial_inplace */
|
||||
0xffffffff, /* src_mask */
|
||||
0xffffffff, /* dst_mask */
|
||||
false), /* pcrel_offset */
|
||||
EMPTY_HOWTO (35),
|
||||
EMPTY_HOWTO (36),
|
||||
HOWTO (MIPS_R_PAIR, /* type */
|
||||
0, /* rightshift */
|
||||
2, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
32, /* bitsize */
|
||||
false, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_bitfield, /* complain_on_overflow */
|
||||
coff_mips_reloc, /* special_function */
|
||||
"PAIR", /* name */
|
||||
true, /* partial_inplace */
|
||||
0xffffffff, /* src_mask */
|
||||
0xffffffff, /* dst_mask */
|
||||
false), /* pcrel_offset */
|
||||
};
|
||||
|
||||
/* Turn a howto into a reloc nunmber */
|
||||
|
||||
#define SELECT_RELOC(x,howto) { x.r_type = howto->type; }
|
||||
#define BADMAG(x) MIPSBADMAG(x)
|
||||
#define MIPS 1 /* Customize coffcode.h */
|
||||
|
||||
#define RTYPE2HOWTO(cache_ptr, dst) \
|
||||
(cache_ptr)->howto = howto_table + (dst)->r_type;
|
||||
|
||||
/* Compute the addend of a reloc. If the reloc is to a common symbol,
|
||||
the object file contains the value of the common symbol. By the
|
||||
time this is called, the linker may be using a different symbol
|
||||
from a different object file with a different value. Therefore, we
|
||||
hack wildly to locate the original symbol from this file so that we
|
||||
can make the correct adjustment. This macro sets coffsym to the
|
||||
symbol from the original file, and uses it to set the addend value
|
||||
correctly. If this is not a common symbol, the usual addend
|
||||
calculation is done, except that an additional tweak is needed for
|
||||
PC relative relocs.
|
||||
FIXME: This macro refers to symbols and asect; these are from the
|
||||
calling function, not the macro arguments. */
|
||||
|
||||
#define CALC_ADDEND(abfd, ptr, reloc, cache_ptr) \
|
||||
{ \
|
||||
coff_symbol_type *coffsym = (coff_symbol_type *) NULL; \
|
||||
if (ptr && bfd_asymbol_bfd (ptr) != abfd) \
|
||||
coffsym = (obj_symbols (abfd) \
|
||||
+ (cache_ptr->sym_ptr_ptr - symbols)); \
|
||||
else if (ptr) \
|
||||
coffsym = coff_symbol_from (abfd, ptr); \
|
||||
if (coffsym != (coff_symbol_type *) NULL \
|
||||
&& coffsym->native->u.syment.n_scnum == 0) \
|
||||
cache_ptr->addend = - coffsym->native->u.syment.n_value; \
|
||||
else if (ptr && bfd_asymbol_bfd (ptr) == abfd \
|
||||
&& ptr->section != (asection *) NULL) \
|
||||
cache_ptr->addend = - (ptr->section->vma + ptr->value); \
|
||||
else \
|
||||
cache_ptr->addend = 0; \
|
||||
if (ptr && howto_table[reloc.r_type].pc_relative) \
|
||||
cache_ptr->addend += asect->vma; \
|
||||
}
|
||||
|
||||
/* Convert an rtype to howto for the COFF backend linker. */
|
||||
|
||||
static reloc_howto_type *
|
||||
coff_mips_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
|
||||
bfd *abfd ATTRIBUTE_UNUSED;
|
||||
asection *sec;
|
||||
struct internal_reloc *rel;
|
||||
struct coff_link_hash_entry *h;
|
||||
struct internal_syment *sym;
|
||||
bfd_vma *addendp;
|
||||
{
|
||||
|
||||
reloc_howto_type *howto;
|
||||
|
||||
howto = howto_table + rel->r_type;
|
||||
|
||||
#ifdef COFF_WITH_PE
|
||||
*addendp = 0;
|
||||
#endif
|
||||
|
||||
if (howto->pc_relative)
|
||||
*addendp += sec->vma;
|
||||
|
||||
if (sym != NULL && sym->n_scnum == 0 && sym->n_value != 0)
|
||||
{
|
||||
/* This is a common symbol. The section contents include the
|
||||
size (sym->n_value) as an addend. The relocate_section
|
||||
function will be adding in the final value of the symbol. We
|
||||
need to subtract out the current size in order to get the
|
||||
correct result. */
|
||||
|
||||
BFD_ASSERT (h != NULL);
|
||||
|
||||
#ifndef COFF_WITH_PE
|
||||
/* I think we *do* want to bypass this. If we don't, I have
|
||||
seen some data parameters get the wrong relocation address.
|
||||
If I link two versions with and without this section bypassed
|
||||
and then do a binary comparison, the addresses which are
|
||||
different can be looked up in the map. The case in which
|
||||
this section has been bypassed has addresses which correspond
|
||||
to values I can find in the map. */
|
||||
*addendp -= sym->n_value;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef COFF_WITH_PE
|
||||
/* If the output symbol is common (in which case this must be a
|
||||
relocateable link), we need to add in the final size of the
|
||||
common symbol. */
|
||||
if (h != NULL && h->root.type == bfd_link_hash_common)
|
||||
*addendp += h->root.u.c.size;
|
||||
#endif
|
||||
|
||||
#ifdef COFF_WITH_PE
|
||||
if (howto->pc_relative)
|
||||
{
|
||||
*addendp -= 4;
|
||||
|
||||
/* If the symbol is defined, then the generic code is going to
|
||||
add back the symbol value in order to cancel out an
|
||||
adjustment it made to the addend. However, we set the addend
|
||||
to 0 at the start of this function. We need to adjust here,
|
||||
to avoid the adjustment the generic code will make. FIXME:
|
||||
This is getting a bit hackish. */
|
||||
if (sym != NULL && sym->n_scnum != 0)
|
||||
*addendp -= sym->n_value;
|
||||
}
|
||||
|
||||
if (rel->r_type == MIPS_R_RVA)
|
||||
{
|
||||
*addendp -= pe_data(sec->output_section->owner)->pe_opthdr.ImageBase;
|
||||
}
|
||||
#endif
|
||||
|
||||
return howto;
|
||||
}
|
||||
|
||||
#define coff_rtype_to_howto coff_mips_rtype_to_howto
|
||||
|
||||
#define coff_bfd_reloc_type_lookup coff_mips_reloc_type_lookup
|
||||
|
||||
/* Get the howto structure for a generic reloc type. */
|
||||
|
||||
static reloc_howto_type *
|
||||
coff_mips_reloc_type_lookup (abfd, code)
|
||||
bfd *abfd ATTRIBUTE_UNUSED;
|
||||
bfd_reloc_code_real_type code;
|
||||
{
|
||||
int mips_type;
|
||||
|
||||
switch (code)
|
||||
{
|
||||
case BFD_RELOC_16:
|
||||
mips_type = MIPS_R_REFHALF;
|
||||
break;
|
||||
case BFD_RELOC_32:
|
||||
case BFD_RELOC_CTOR:
|
||||
mips_type = MIPS_R_REFWORD;
|
||||
break;
|
||||
case BFD_RELOC_MIPS_JMP:
|
||||
mips_type = MIPS_R_JMPADDR;
|
||||
break;
|
||||
case BFD_RELOC_HI16_S:
|
||||
mips_type = MIPS_R_REFHI;
|
||||
break;
|
||||
case BFD_RELOC_LO16:
|
||||
mips_type = MIPS_R_REFLO;
|
||||
break;
|
||||
case BFD_RELOC_GPREL16:
|
||||
mips_type = MIPS_R_GPREL;
|
||||
break;
|
||||
case BFD_RELOC_MIPS_LITERAL:
|
||||
mips_type = MIPS_R_LITERAL;
|
||||
break;
|
||||
/* FIXME?
|
||||
case BFD_RELOC_16_PCREL_S2:
|
||||
mips_type = MIPS_R_PCREL16;
|
||||
break;
|
||||
case BFD_RELOC_PCREL_HI16_S:
|
||||
mips_type = MIPS_R_RELHI;
|
||||
break;
|
||||
case BFD_RELOC_PCREL_LO16:
|
||||
mips_type = MIPS_R_RELLO;
|
||||
break;
|
||||
case BFD_RELOC_GPREL32:
|
||||
mips_type = MIPS_R_SWITCH;
|
||||
break;
|
||||
*/
|
||||
case BFD_RELOC_RVA:
|
||||
mips_type = MIPS_R_RVA;
|
||||
break;
|
||||
default:
|
||||
return (reloc_howto_type *) NULL;
|
||||
}
|
||||
|
||||
return &howto_table[mips_type];
|
||||
}
|
||||
|
||||
static void
|
||||
mips_swap_reloc_in (abfd, src, dst)
|
||||
bfd *abfd;
|
||||
PTR src;
|
||||
PTR dst;
|
||||
{
|
||||
static struct internal_reloc pair_prev;
|
||||
RELOC *reloc_src = (RELOC *) src;
|
||||
struct internal_reloc *reloc_dst = (struct internal_reloc *) dst;
|
||||
|
||||
reloc_dst->r_vaddr = H_GET_32 (abfd, reloc_src->r_vaddr);
|
||||
reloc_dst->r_symndx = H_GET_S32 (abfd, reloc_src->r_symndx);
|
||||
reloc_dst->r_type = H_GET_16 (abfd, reloc_src->r_type);
|
||||
reloc_dst->r_size = 0;
|
||||
reloc_dst->r_extern = 0;
|
||||
reloc_dst->r_offset = 0;
|
||||
|
||||
switch (reloc_dst->r_type)
|
||||
{
|
||||
case MIPS_R_REFHI:
|
||||
pair_prev = *reloc_dst;
|
||||
break;
|
||||
case MIPS_R_PAIR:
|
||||
reloc_dst->r_offset = reloc_dst->r_symndx;
|
||||
if (reloc_dst->r_offset & 0x8000)
|
||||
reloc_dst->r_offset -= 0x10000;
|
||||
/*printf ("dj: pair offset is %08x\n", reloc_dst->r_offset);*/
|
||||
reloc_dst->r_symndx = pair_prev.r_symndx;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
mips_swap_reloc_out (abfd, src, dst)
|
||||
bfd *abfd;
|
||||
PTR src;
|
||||
PTR dst;
|
||||
{
|
||||
static int prev_offset = 1;
|
||||
static bfd_vma prev_addr = 0;
|
||||
struct internal_reloc *reloc_src = (struct internal_reloc *)src;
|
||||
struct external_reloc *reloc_dst = (struct external_reloc *)dst;
|
||||
|
||||
switch (reloc_src->r_type)
|
||||
{
|
||||
case MIPS_R_REFHI:
|
||||
prev_addr = reloc_src->r_vaddr;
|
||||
prev_offset = reloc_src->r_offset;
|
||||
break;
|
||||
case MIPS_R_REFLO:
|
||||
if (reloc_src->r_vaddr == prev_addr)
|
||||
{
|
||||
/* FIXME: only slightly hackish. If we see a REFLO pointing to
|
||||
the same address as a REFHI, we assume this is the matching
|
||||
PAIR reloc and output it accordingly. The symndx is really
|
||||
the low 16 bits of the addend */
|
||||
H_PUT_32 (abfd, reloc_src->r_vaddr, reloc_dst->r_vaddr);
|
||||
H_PUT_32 (abfd, reloc_src->r_symndx, reloc_dst->r_symndx);
|
||||
H_PUT_16 (abfd, MIPS_R_PAIR, reloc_dst->r_type);
|
||||
return RELSZ;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
H_PUT_32 (abfd, reloc_src->r_vaddr, reloc_dst->r_vaddr);
|
||||
H_PUT_32 (abfd, reloc_src->r_symndx, reloc_dst->r_symndx);
|
||||
|
||||
H_PUT_16 (abfd, reloc_src->r_type, reloc_dst->r_type);
|
||||
return RELSZ;
|
||||
}
|
||||
|
||||
#define coff_swap_reloc_in mips_swap_reloc_in
|
||||
#define coff_swap_reloc_out mips_swap_reloc_out
|
||||
#define NO_COFF_RELOCS
|
||||
|
||||
static boolean
|
||||
coff_pe_mips_relocate_section (output_bfd, info, input_bfd,
|
||||
input_section, contents, relocs, syms,
|
||||
sections)
|
||||
bfd *output_bfd;
|
||||
struct bfd_link_info *info;
|
||||
bfd *input_bfd;
|
||||
asection *input_section;
|
||||
bfd_byte *contents;
|
||||
struct internal_reloc *relocs;
|
||||
struct internal_syment *syms;
|
||||
asection **sections;
|
||||
{
|
||||
bfd_vma gp;
|
||||
boolean gp_undefined;
|
||||
size_t adjust;
|
||||
struct internal_reloc *rel;
|
||||
struct internal_reloc *rel_end;
|
||||
unsigned int i;
|
||||
boolean got_lo;
|
||||
|
||||
if (info->relocateable)
|
||||
{
|
||||
(*_bfd_error_handler) (_("\
|
||||
%s: `ld -r' not supported with PE MIPS objects\n"),
|
||||
bfd_archive_filename (input_bfd));
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return false;
|
||||
}
|
||||
|
||||
BFD_ASSERT (input_bfd->xvec->byteorder
|
||||
== output_bfd->xvec->byteorder);
|
||||
|
||||
#if 0
|
||||
printf ("dj: relocate %s(%s) %08x\n",
|
||||
input_bfd->filename, input_section->name,
|
||||
input_section->output_section->vma + input_section->output_offset);
|
||||
#endif
|
||||
|
||||
gp = _bfd_get_gp_value (output_bfd);
|
||||
if (gp == 0)
|
||||
gp_undefined = true;
|
||||
else
|
||||
gp_undefined = false;
|
||||
|
||||
got_lo = false;
|
||||
|
||||
adjust = 0;
|
||||
|
||||
rel = relocs;
|
||||
rel_end = rel + input_section->reloc_count;
|
||||
for (i = 0; rel < rel_end; rel++, i++)
|
||||
{
|
||||
long symndx;
|
||||
struct coff_link_hash_entry *h;
|
||||
struct internal_syment *sym;
|
||||
bfd_vma addend = 0;
|
||||
bfd_vma val, tmp, targ, src, low;
|
||||
reloc_howto_type *howto;
|
||||
unsigned char *mem = contents + rel->r_vaddr;
|
||||
|
||||
symndx = rel->r_symndx;
|
||||
|
||||
if (symndx == -1)
|
||||
{
|
||||
h = NULL;
|
||||
sym = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
h = obj_coff_sym_hashes (input_bfd)[symndx];
|
||||
sym = syms + symndx;
|
||||
}
|
||||
|
||||
/* COFF treats common symbols in one of two ways. Either the
|
||||
size of the symbol is included in the section contents, or it
|
||||
is not. We assume that the size is not included, and force
|
||||
the rtype_to_howto function to adjust the addend as needed. */
|
||||
|
||||
if (sym != NULL && sym->n_scnum != 0)
|
||||
addend = - sym->n_value;
|
||||
else
|
||||
addend = 0;
|
||||
|
||||
howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h,
|
||||
sym, &addend);
|
||||
if (howto == NULL)
|
||||
return false;
|
||||
|
||||
/* If we are doing a relocateable link, then we can just ignore
|
||||
a PC relative reloc that is pcrel_offset. It will already
|
||||
have the correct value. If this is not a relocateable link,
|
||||
then we should ignore the symbol value. */
|
||||
if (howto->pc_relative && howto->pcrel_offset)
|
||||
{
|
||||
if (info->relocateable)
|
||||
continue;
|
||||
if (sym != NULL && sym->n_scnum != 0)
|
||||
addend += sym->n_value;
|
||||
}
|
||||
|
||||
val = 0;
|
||||
|
||||
if (h == NULL)
|
||||
{
|
||||
asection *sec;
|
||||
|
||||
if (symndx == -1)
|
||||
{
|
||||
sec = bfd_abs_section_ptr;
|
||||
val = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
sec = sections[symndx];
|
||||
val = (sec->output_section->vma
|
||||
+ sec->output_offset
|
||||
+ sym->n_value);
|
||||
if (! obj_pe (input_bfd))
|
||||
val -= sec->vma;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
{
|
||||
asection *sec;
|
||||
|
||||
sec = h->root.u.def.section;
|
||||
val = (h->root.u.def.value
|
||||
+ sec->output_section->vma
|
||||
+ sec->output_offset);
|
||||
}
|
||||
|
||||
else if (! info->relocateable)
|
||||
{
|
||||
if (! ((*info->callbacks->undefined_symbol)
|
||||
(info, h->root.root.string, input_bfd, input_section,
|
||||
rel->r_vaddr - input_section->vma, true)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
src = rel->r_vaddr + input_section->output_section->vma
|
||||
+ input_section->output_offset;
|
||||
#if 0
|
||||
printf ("dj: reloc %02x %-8s a=%08x/%08x(%08x) v=%08x+%08x %s\n",
|
||||
rel->r_type, howto_table[rel->r_type].name,
|
||||
src, rel->r_vaddr, *(unsigned long *)mem, val, rel->r_offset,
|
||||
h?h->root.root.string:"(none)");
|
||||
#endif
|
||||
|
||||
/* OK, at this point the following variables are set up:
|
||||
src = VMA of the memory we're fixing up
|
||||
mem = pointer to memory we're fixing up
|
||||
val = VMA of what we need to refer to
|
||||
*/
|
||||
|
||||
#define UI(x) (*_bfd_error_handler) (_("%s: unimplemented %s\n"), \
|
||||
bfd_archive_filename (input_bfd), x); \
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
|
||||
switch (rel->r_type)
|
||||
{
|
||||
case MIPS_R_ABSOLUTE:
|
||||
/* ignore these */
|
||||
break;
|
||||
|
||||
case MIPS_R_REFHALF:
|
||||
UI("refhalf");
|
||||
break;
|
||||
|
||||
case MIPS_R_REFWORD:
|
||||
tmp = bfd_get_32(input_bfd, mem);
|
||||
/* printf ("refword: src=%08x targ=%08x+%08x\n", src, tmp, val); */
|
||||
tmp += val;
|
||||
bfd_put_32(input_bfd, tmp, mem);
|
||||
break;
|
||||
|
||||
case MIPS_R_JMPADDR:
|
||||
tmp = bfd_get_32(input_bfd, mem);
|
||||
targ = val + (tmp&0x03ffffff)*4;
|
||||
if ((src & 0xf0000000) != (targ & 0xf0000000))
|
||||
{
|
||||
(*_bfd_error_handler) (_("%s: jump too far away\n"),
|
||||
bfd_archive_filename (input_bfd));
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return false;
|
||||
}
|
||||
tmp &= 0xfc000000;
|
||||
tmp |= (targ/4) & 0x3ffffff;
|
||||
bfd_put_32(input_bfd, tmp, mem);
|
||||
break;
|
||||
|
||||
case MIPS_R_REFHI:
|
||||
tmp = bfd_get_32(input_bfd, mem);
|
||||
switch (rel[1].r_type)
|
||||
{
|
||||
case MIPS_R_PAIR:
|
||||
/* MS PE object */
|
||||
targ = val + rel[1].r_offset + ((tmp & 0xffff) << 16);
|
||||
break;
|
||||
case MIPS_R_REFLO:
|
||||
/* GNU COFF object */
|
||||
low = bfd_get_32(input_bfd, contents + rel[1].r_vaddr);
|
||||
low &= 0xffff;
|
||||
if (low & 0x8000)
|
||||
low -= 0x10000;
|
||||
targ = val + low + ((tmp & 0xffff) << 16);
|
||||
break;
|
||||
default:
|
||||
(*_bfd_error_handler) (_("%s: bad pair/reflo after refhi\n"),
|
||||
bfd_archive_filename (input_bfd));
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return false;
|
||||
}
|
||||
tmp &= 0xffff0000;
|
||||
tmp |= (targ >> 16) & 0xffff;
|
||||
bfd_put_32(input_bfd, tmp, mem);
|
||||
break;
|
||||
|
||||
case MIPS_R_REFLO:
|
||||
tmp = bfd_get_32(input_bfd, mem);
|
||||
targ = val + (tmp & 0xffff);
|
||||
/* printf ("refword: src=%08x targ=%08x\n", src, targ); */
|
||||
tmp &= 0xffff0000;
|
||||
tmp |= targ & 0xffff;
|
||||
bfd_put_32(input_bfd, tmp, mem);
|
||||
break;
|
||||
|
||||
case MIPS_R_GPREL:
|
||||
case MIPS_R_LITERAL:
|
||||
UI("gprel");
|
||||
break;
|
||||
|
||||
case MIPS_R_SECTION:
|
||||
UI("section");
|
||||
break;
|
||||
|
||||
case MIPS_R_SECREL:
|
||||
UI("secrel");
|
||||
break;
|
||||
|
||||
case MIPS_R_SECRELLO:
|
||||
UI("secrello");
|
||||
break;
|
||||
|
||||
case MIPS_R_SECRELHI:
|
||||
UI("secrelhi");
|
||||
break;
|
||||
|
||||
case MIPS_R_RVA:
|
||||
tmp = bfd_get_32 (input_bfd, mem);
|
||||
/* printf ("rva: src=%08x targ=%08x+%08x\n", src, tmp, val); */
|
||||
tmp += val
|
||||
- pe_data (input_section->output_section->owner)->pe_opthdr.ImageBase;
|
||||
bfd_put_32 (input_bfd, tmp, mem);
|
||||
break;
|
||||
|
||||
case MIPS_R_PAIR:
|
||||
/* ignore these */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#define coff_relocate_section coff_pe_mips_relocate_section
|
||||
|
||||
#ifdef TARGET_UNDERSCORE
|
||||
|
||||
/* If mips gcc uses underscores for symbol names, then it does not use
|
||||
a leading dot for local labels, so if TARGET_UNDERSCORE is defined
|
||||
we treat all symbols starting with L as local. */
|
||||
|
||||
static boolean coff_mips_is_local_label_name PARAMS ((bfd *, const char *));
|
||||
|
||||
static boolean
|
||||
coff_mips_is_local_label_name (abfd, name)
|
||||
bfd *abfd;
|
||||
const char *name;
|
||||
{
|
||||
if (name[0] == 'L')
|
||||
return true;
|
||||
|
||||
return _bfd_coff_is_local_label_name (abfd, name);
|
||||
}
|
||||
|
||||
#define coff_bfd_is_local_label_name coff_mips_is_local_label_name
|
||||
|
||||
#endif /* TARGET_UNDERSCORE */
|
||||
|
||||
#define COFF_NO_HACK_SCNHDR_SIZE
|
||||
|
||||
#include "coffcode.h"
|
||||
|
||||
const bfd_target
|
||||
#ifdef TARGET_SYM
|
||||
TARGET_SYM =
|
||||
#else
|
||||
mipslpe_vec =
|
||||
#endif
|
||||
{
|
||||
#ifdef TARGET_NAME
|
||||
TARGET_NAME,
|
||||
#else
|
||||
"pe-mips", /* name */
|
||||
#endif
|
||||
bfd_target_coff_flavour,
|
||||
BFD_ENDIAN_LITTLE, /* data byte order is little */
|
||||
BFD_ENDIAN_LITTLE, /* header byte order is little */
|
||||
|
||||
(HAS_RELOC | EXEC_P | /* object flags */
|
||||
HAS_LINENO | HAS_DEBUG |
|
||||
HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
|
||||
|
||||
#ifndef COFF_WITH_PE
|
||||
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
|
||||
| SEC_CODE | SEC_DATA),
|
||||
#else
|
||||
(SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC /* section flags */
|
||||
| SEC_CODE | SEC_DATA
|
||||
| SEC_LINK_ONCE | SEC_LINK_DUPLICATES),
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_UNDERSCORE
|
||||
TARGET_UNDERSCORE, /* leading underscore */
|
||||
#else
|
||||
0, /* leading underscore */
|
||||
#endif
|
||||
'/', /* ar_pad_char */
|
||||
15, /* ar_max_namelen */
|
||||
|
||||
bfd_getl64, bfd_getl_signed_64, bfd_putl64,
|
||||
bfd_getl32, bfd_getl_signed_32, bfd_putl32,
|
||||
bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
|
||||
bfd_getl64, bfd_getl_signed_64, bfd_putl64,
|
||||
bfd_getl32, bfd_getl_signed_32, bfd_putl32,
|
||||
bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
|
||||
|
||||
/* Note that we allow an object file to be treated as a core file as well. */
|
||||
{_bfd_dummy_target, coff_object_p, /* bfd_check_format */
|
||||
bfd_generic_archive_p, coff_object_p},
|
||||
{bfd_false, coff_mkobject, _bfd_generic_mkarchive, /* bfd_set_format */
|
||||
bfd_false},
|
||||
{bfd_false, coff_write_object_contents, /* bfd_write_contents */
|
||||
_bfd_write_archive_contents, bfd_false},
|
||||
|
||||
BFD_JUMP_TABLE_GENERIC (coff),
|
||||
BFD_JUMP_TABLE_COPY (coff),
|
||||
BFD_JUMP_TABLE_CORE (_bfd_nocore),
|
||||
BFD_JUMP_TABLE_ARCHIVE (_bfd_archive_coff),
|
||||
BFD_JUMP_TABLE_SYMBOLS (coff),
|
||||
BFD_JUMP_TABLE_RELOCS (coff),
|
||||
BFD_JUMP_TABLE_WRITE (coff),
|
||||
BFD_JUMP_TABLE_LINK (coff),
|
||||
BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
|
||||
|
||||
NULL,
|
||||
|
||||
COFF_SWAP_TABLE
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@ -1,134 +0,0 @@
|
||||
#ifndef BISON_Y_TAB_H
|
||||
# define BISON_Y_TAB_H
|
||||
|
||||
#ifndef YYSTYPE
|
||||
typedef union
|
||||
{
|
||||
struct accelerator acc;
|
||||
struct accelerator *pacc;
|
||||
struct dialog_control *dialog_control;
|
||||
struct menuitem *menuitem;
|
||||
struct
|
||||
{
|
||||
struct rcdata_item *first;
|
||||
struct rcdata_item *last;
|
||||
} rcdata;
|
||||
struct rcdata_item *rcdata_item;
|
||||
struct stringtable_data *stringtable;
|
||||
struct fixed_versioninfo *fixver;
|
||||
struct ver_info *verinfo;
|
||||
struct ver_stringinfo *verstring;
|
||||
struct ver_varinfo *vervar;
|
||||
struct res_id id;
|
||||
struct res_res_info res_info;
|
||||
struct
|
||||
{
|
||||
unsigned short on;
|
||||
unsigned short off;
|
||||
} memflags;
|
||||
struct
|
||||
{
|
||||
unsigned long val;
|
||||
/* Nonzero if this number was explicitly specified as long. */
|
||||
int dword;
|
||||
} i;
|
||||
unsigned long il;
|
||||
unsigned short is;
|
||||
const char *s;
|
||||
struct
|
||||
{
|
||||
unsigned long length;
|
||||
const char *s;
|
||||
} ss;
|
||||
} yystype;
|
||||
# define YYSTYPE yystype
|
||||
# define YYSTYPE_IS_TRIVIAL 1
|
||||
#endif
|
||||
# define BEG 257
|
||||
# define END 258
|
||||
# define ACCELERATORS 259
|
||||
# define VIRTKEY 260
|
||||
# define ASCII 261
|
||||
# define NOINVERT 262
|
||||
# define SHIFT 263
|
||||
# define CONTROL 264
|
||||
# define ALT 265
|
||||
# define BITMAP 266
|
||||
# define CURSOR 267
|
||||
# define DIALOG 268
|
||||
# define DIALOGEX 269
|
||||
# define EXSTYLE 270
|
||||
# define CAPTION 271
|
||||
# define CLASS 272
|
||||
# define STYLE 273
|
||||
# define AUTO3STATE 274
|
||||
# define AUTOCHECKBOX 275
|
||||
# define AUTORADIOBUTTON 276
|
||||
# define CHECKBOX 277
|
||||
# define COMBOBOX 278
|
||||
# define CTEXT 279
|
||||
# define DEFPUSHBUTTON 280
|
||||
# define EDITTEXT 281
|
||||
# define GROUPBOX 282
|
||||
# define LISTBOX 283
|
||||
# define LTEXT 284
|
||||
# define PUSHBOX 285
|
||||
# define PUSHBUTTON 286
|
||||
# define RADIOBUTTON 287
|
||||
# define RTEXT 288
|
||||
# define SCROLLBAR 289
|
||||
# define STATE3 290
|
||||
# define USERBUTTON 291
|
||||
# define BEDIT 292
|
||||
# define HEDIT 293
|
||||
# define IEDIT 294
|
||||
# define FONT 295
|
||||
# define ICON 296
|
||||
# define LANGUAGE 297
|
||||
# define CHARACTERISTICS 298
|
||||
# define VERSIONK 299
|
||||
# define MENU 300
|
||||
# define MENUEX 301
|
||||
# define MENUITEM 302
|
||||
# define SEPARATOR 303
|
||||
# define POPUP 304
|
||||
# define CHECKED 305
|
||||
# define GRAYED 306
|
||||
# define HELP 307
|
||||
# define INACTIVE 308
|
||||
# define MENUBARBREAK 309
|
||||
# define MENUBREAK 310
|
||||
# define MESSAGETABLE 311
|
||||
# define RCDATA 312
|
||||
# define STRINGTABLE 313
|
||||
# define VERSIONINFO 314
|
||||
# define FILEVERSION 315
|
||||
# define PRODUCTVERSION 316
|
||||
# define FILEFLAGSMASK 317
|
||||
# define FILEFLAGS 318
|
||||
# define FILEOS 319
|
||||
# define FILETYPE 320
|
||||
# define FILESUBTYPE 321
|
||||
# define BLOCKSTRINGFILEINFO 322
|
||||
# define BLOCKVARFILEINFO 323
|
||||
# define VALUE 324
|
||||
# define BLOCK 325
|
||||
# define MOVEABLE 326
|
||||
# define FIXED 327
|
||||
# define PURE 328
|
||||
# define IMPURE 329
|
||||
# define PRELOAD 330
|
||||
# define LOADONCALL 331
|
||||
# define DISCARDABLE 332
|
||||
# define NOT 333
|
||||
# define QUOTEDSTRING 334
|
||||
# define STRING 335
|
||||
# define NUMBER 336
|
||||
# define SIZEDSTRING 337
|
||||
# define IGNORED_TOKEN 338
|
||||
# define NEG 339
|
||||
|
||||
|
||||
extern YYSTYPE yylval;
|
||||
|
||||
#endif /* not BISON_Y_TAB_H */
|
File diff suppressed because it is too large
Load Diff
@ -1,55 +0,0 @@
|
||||
/* tc-tic30.h -- Header file for tc-tic30.c
|
||||
Copyright 1998, 2000 Free Software Foundation, Inc.
|
||||
Contributed by Steven Haworth (steve@pm.cse.rmit.edu.au)
|
||||
|
||||
This file is part of GAS, the GNU Assembler.
|
||||
|
||||
GAS is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GAS 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 GAS; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
|
||||
#ifndef _TC_TIC30_H_
|
||||
#define _TC_TIC30_H_
|
||||
|
||||
#define TC_TIC30 1
|
||||
|
||||
#ifdef OBJ_AOUT
|
||||
#define TARGET_FORMAT "a.out-tic30"
|
||||
#endif
|
||||
|
||||
#define TARGET_ARCH bfd_arch_tic30
|
||||
#define TARGET_BYTES_BIG_ENDIAN 1
|
||||
|
||||
#define WORKING_DOT_WORD
|
||||
|
||||
char *output_invalid PARAMS ((int c));
|
||||
|
||||
#define END_OF_INSN '\0'
|
||||
#define MAX_OPERANDS 6
|
||||
#define DIRECT_REFERENCE '@'
|
||||
#define INDIRECT_REFERENCE '*'
|
||||
#define PARALLEL_SEPARATOR '|'
|
||||
#define INSN_SIZE 4
|
||||
|
||||
/* Define this to 1 if you want the debug output to be on stdout,
|
||||
otherwise stderr will be used. If stderr is used, there will be a
|
||||
better synchronisation with the as_bad outputs, but you can't
|
||||
capture the output. */
|
||||
#define USE_STDOUT 0
|
||||
|
||||
#define tc_unrecognized_line tic30_unrecognized_line
|
||||
|
||||
extern int tic30_unrecognized_line PARAMS ((int));
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,98 +0,0 @@
|
||||
/* tc-v850.h -- Header file for tc-v850.c.
|
||||
Copyright 1996, 1997, 1998, 2000, 2001, 2002
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GAS, the GNU Assembler.
|
||||
|
||||
GAS is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GAS 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 GAS; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
|
||||
#define TC_V850
|
||||
|
||||
#include "elf/v850.h"
|
||||
|
||||
#define TARGET_BYTES_BIG_ENDIAN 0
|
||||
|
||||
#ifndef BFD_ASSEMBLER
|
||||
#error V850 support requires BFD_ASSEMBLER
|
||||
#endif
|
||||
|
||||
/* The target BFD architecture. */
|
||||
#define TARGET_ARCH bfd_arch_v850
|
||||
|
||||
/* The target BFD format. */
|
||||
#define TARGET_FORMAT "elf32-v850"
|
||||
|
||||
#define md_operand(x)
|
||||
|
||||
#define obj_fix_adjustable(fixP) v850_fix_adjustable(fixP)
|
||||
extern boolean v850_fix_adjustable PARAMS ((struct fix *));
|
||||
|
||||
#define TC_FORCE_RELOCATION(fixp) v850_force_relocation(fixp)
|
||||
extern int v850_force_relocation PARAMS ((struct fix *));
|
||||
|
||||
#ifdef OBJ_ELF
|
||||
/* This arranges for gas/write.c to not apply a relocation if
|
||||
obj_fix_adjustable() says it is not adjustable. */
|
||||
#define TC_FIX_ADJUSTABLE(fixP) obj_fix_adjustable (fixP)
|
||||
#endif
|
||||
|
||||
/* Permit temporary numeric labels. */
|
||||
#define LOCAL_LABELS_FB 1
|
||||
|
||||
#define DIFF_EXPR_OK /* foo-. gets turned into PC relative relocs. */
|
||||
|
||||
/* We don't need to handle .word strangely. */
|
||||
#define WORKING_DOT_WORD
|
||||
|
||||
#define md_number_to_chars number_to_chars_littleendian
|
||||
|
||||
/* We need to handle lo(), hi(), etc etc in .hword, .word, etc
|
||||
directives, so we have to parse "cons" expressions ourselves. */
|
||||
#define TC_PARSE_CONS_EXPRESSION(EXP, NBYTES) parse_cons_expression_v850 (EXP)
|
||||
extern void parse_cons_expression_v850 PARAMS ((expressionS *));
|
||||
|
||||
#define TC_CONS_FIX_NEW cons_fix_new_v850
|
||||
extern void cons_fix_new_v850 PARAMS ((fragS *, int, int, expressionS *));
|
||||
|
||||
#define TC_GENERIC_RELAX_TABLE md_relax_table
|
||||
extern const struct relax_type md_relax_table[];
|
||||
|
||||
/* This section must be in the small data area (pointed to by GP). */
|
||||
#define SHF_V850_GPREL 0x10000000
|
||||
/* This section must be in the tiny data area (pointed to by EP). */
|
||||
#define SHF_V850_EPREL 0x20000000
|
||||
/* This section must be in the zero data area (pointed to by R0). */
|
||||
#define SHF_V850_R0REL 0x40000000
|
||||
|
||||
#define ELF_TC_SPECIAL_SECTIONS \
|
||||
{ ".sdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_GPREL }, \
|
||||
{ ".rosdata", SHT_PROGBITS, SHF_ALLOC + SHF_V850_GPREL }, \
|
||||
{ ".sbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_GPREL }, \
|
||||
{ ".scommon", SHT_V850_SCOMMON, SHF_ALLOC + SHF_WRITE + SHF_V850_GPREL }, \
|
||||
{ ".tdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_EPREL }, \
|
||||
{ ".tbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_EPREL }, \
|
||||
{ ".tcommon", SHT_V850_TCOMMON, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, \
|
||||
{ ".zdata", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, \
|
||||
{ ".rozdata", SHT_PROGBITS, SHF_ALLOC + SHF_V850_R0REL }, \
|
||||
{ ".zbss", SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, \
|
||||
{ ".zcommon", SHT_V850_ZCOMMON, SHF_ALLOC + SHF_WRITE + SHF_V850_R0REL }, \
|
||||
{ ".call_table_data", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE }, \
|
||||
{ ".call_table_text", SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_EXECINSTR },
|
||||
|
||||
#define MD_PCREL_FROM_SECTION(fixP,section) v850_pcrel_from_section (fixP, section)
|
||||
extern long v850_pcrel_from_section PARAMS ((struct fix *, asection *));
|
||||
|
||||
#define DWARF2_LINE_MIN_INSN_LENGTH 2
|
File diff suppressed because it is too large
Load Diff
@ -1,53 +0,0 @@
|
||||
/* This file is tc-z8k.h
|
||||
Copyright 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1995, 1997, 1998,
|
||||
2000
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GAS, the GNU Assembler.
|
||||
|
||||
GAS is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2, or (at your option)
|
||||
any later version.
|
||||
|
||||
GAS 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 GAS; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
|
||||
#define TC_Z8K
|
||||
#define TARGET_BYTES_BIG_ENDIAN 1
|
||||
|
||||
#if ANSI_PROTOTYPES
|
||||
struct internal_reloc;
|
||||
#endif
|
||||
|
||||
#define WORKING_DOT_WORD
|
||||
|
||||
#ifndef BFD_ASSEMBLER
|
||||
#define LOCAL_LABEL(x) 0
|
||||
#endif
|
||||
|
||||
/* This macro translates between an internal fix and an coff reloc type */
|
||||
#define TC_COFF_FIX2RTYPE(fixP) abort ();
|
||||
|
||||
#define BFD_ARCH bfd_arch_z8k
|
||||
#define COFF_MAGIC 0x8000
|
||||
#define TC_COUNT_RELOC(x) (1)
|
||||
#define IGNORE_NONSTANDARD_ESCAPES
|
||||
|
||||
#define TC_RELOC_MANGLE(s,a,b,c) tc_reloc_mangle(a,b,c)
|
||||
extern void tc_reloc_mangle
|
||||
PARAMS ((struct fix *, struct internal_reloc *, bfd_vma));
|
||||
|
||||
#define DO_NOT_STRIP 0
|
||||
#define LISTING_HEADER "Zilog Z8000 GAS "
|
||||
#define NEED_FX_R_TYPE 1
|
||||
#define RELOC_32 1234
|
||||
|
||||
#define md_operand(x)
|
@ -1,363 +0,0 @@
|
||||
@c Copyright 1997 Free Software Foundation, Inc.
|
||||
@c This is part of the GAS manual.
|
||||
@c For copying conditions, see the file as.texinfo.
|
||||
|
||||
@node V850-Dependent
|
||||
@chapter v850 Dependent Features
|
||||
|
||||
@cindex V850 support
|
||||
@menu
|
||||
* V850 Options:: Options
|
||||
* V850 Syntax:: Syntax
|
||||
* V850 Floating Point:: Floating Point
|
||||
* V850 Directives:: V850 Machine Directives
|
||||
* V850 Opcodes:: Opcodes
|
||||
@end menu
|
||||
|
||||
@node V850 Options
|
||||
@section Options
|
||||
@cindex V850 options (none)
|
||||
@cindex options for V850 (none)
|
||||
@code{@value{AS}} supports the following additional command-line options
|
||||
for the V850 processor family:
|
||||
|
||||
@cindex command line options, V850
|
||||
@cindex V850 command line options
|
||||
@table @code
|
||||
|
||||
@cindex @code{-wsigned_overflow} command line option, V850
|
||||
@item -wsigned_overflow
|
||||
Causes warnings to be produced when signed immediate values overflow the
|
||||
space available for then within their opcodes. By default this option
|
||||
is disabled as it is possible to receive spurious warnings due to using
|
||||
exact bit patterns as immediate constants.
|
||||
|
||||
@cindex @code{-wunsigned_overflow} command line option, V850
|
||||
@item -wunsigned_overflow
|
||||
Causes warnings to be produced when unsigned immediate values overflow
|
||||
the space available for then within their opcodes. By default this
|
||||
option is disabled as it is possible to receive spurious warnings due to
|
||||
using exact bit patterns as immediate constants.
|
||||
|
||||
@cindex @code{-mv850} command line option, V850
|
||||
@item -mv850
|
||||
Specifies that the assembled code should be marked as being targeted at
|
||||
the V850 processor. This allows the linker to detect attempts to link
|
||||
such code with code assembled for other processors.
|
||||
|
||||
@cindex @code{-mv850e} command line option, V850
|
||||
@item -mv850e
|
||||
Specifies that the assembled code should be marked as being targeted at
|
||||
the V850E processor. This allows the linker to detect attempts to link
|
||||
such code with code assembled for other processors.
|
||||
|
||||
@cindex @code{-mv850any} command line option, V850
|
||||
@item -mv850any
|
||||
Specifies that the assembled code should be marked as being targeted at
|
||||
the V850 processor but support instructions that are specific to the
|
||||
extended variants of the process. This allows the production of
|
||||
binaries that contain target specific code, but which are also intended
|
||||
to be used in a generic fashion. For example libgcc.a contains generic
|
||||
routines used by the code produced by GCC for all versions of the v850
|
||||
architecture, together with support routines only used by the V850E
|
||||
architecture.
|
||||
|
||||
@end table
|
||||
|
||||
|
||||
@node V850 Syntax
|
||||
@section Syntax
|
||||
@menu
|
||||
* V850-Chars:: Special Characters
|
||||
* V850-Regs:: Register Names
|
||||
@end menu
|
||||
|
||||
@node V850-Chars
|
||||
@subsection Special Characters
|
||||
|
||||
@cindex line comment character, V850
|
||||
@cindex V850 line comment character
|
||||
@samp{#} is the line comment character.
|
||||
@node V850-Regs
|
||||
@subsection Register Names
|
||||
|
||||
@cindex V850 register names
|
||||
@cindex register names, V850
|
||||
@code{@value{AS}} supports the following names for registers:
|
||||
@table @code
|
||||
@cindex @code{zero} register, V850
|
||||
@item general register 0
|
||||
r0, zero
|
||||
@item general register 1
|
||||
r1
|
||||
@item general register 2
|
||||
r2, hp
|
||||
@cindex @code{sp} register, V850
|
||||
@item general register 3
|
||||
r3, sp
|
||||
@cindex @code{gp} register, V850
|
||||
@item general register 4
|
||||
r4, gp
|
||||
@cindex @code{tp} register, V850
|
||||
@item general register 5
|
||||
r5, tp
|
||||
@item general register 6
|
||||
r6
|
||||
@item general register 7
|
||||
r7
|
||||
@item general register 8
|
||||
r8
|
||||
@item general register 9
|
||||
r9
|
||||
@item general register 10
|
||||
r10
|
||||
@item general register 11
|
||||
r11
|
||||
@item general register 12
|
||||
r12
|
||||
@item general register 13
|
||||
r13
|
||||
@item general register 14
|
||||
r14
|
||||
@item general register 15
|
||||
r15
|
||||
@item general register 16
|
||||
r16
|
||||
@item general register 17
|
||||
r17
|
||||
@item general register 18
|
||||
r18
|
||||
@item general register 19
|
||||
r19
|
||||
@item general register 20
|
||||
r20
|
||||
@item general register 21
|
||||
r21
|
||||
@item general register 22
|
||||
r22
|
||||
@item general register 23
|
||||
r23
|
||||
@item general register 24
|
||||
r24
|
||||
@item general register 25
|
||||
r25
|
||||
@item general register 26
|
||||
r26
|
||||
@item general register 27
|
||||
r27
|
||||
@item general register 28
|
||||
r28
|
||||
@item general register 29
|
||||
r29
|
||||
@cindex @code{ep} register, V850
|
||||
@item general register 30
|
||||
r30, ep
|
||||
@cindex @code{lp} register, V850
|
||||
@item general register 31
|
||||
r31, lp
|
||||
@cindex @code{eipc} register, V850
|
||||
@item system register 0
|
||||
eipc
|
||||
@cindex @code{eipsw} register, V850
|
||||
@item system register 1
|
||||
eipsw
|
||||
@cindex @code{fepc} register, V850
|
||||
@item system register 2
|
||||
fepc
|
||||
@cindex @code{fepsw} register, V850
|
||||
@item system register 3
|
||||
fepsw
|
||||
@cindex @code{ecr} register, V850
|
||||
@item system register 4
|
||||
ecr
|
||||
@cindex @code{psw} register, V850
|
||||
@item system register 5
|
||||
psw
|
||||
@cindex @code{ctpc} register, V850
|
||||
@item system register 16
|
||||
ctpc
|
||||
@cindex @code{ctpsw} register, V850
|
||||
@item system register 17
|
||||
ctpsw
|
||||
@cindex @code{dbpc} register, V850
|
||||
@item system register 18
|
||||
dbpc
|
||||
@cindex @code{dbpsw} register, V850
|
||||
@item system register 19
|
||||
dbpsw
|
||||
@cindex @code{ctbp} register, V850
|
||||
@item system register 20
|
||||
ctbp
|
||||
@end table
|
||||
|
||||
@node V850 Floating Point
|
||||
@section Floating Point
|
||||
|
||||
@cindex floating point, V850 (@sc{ieee})
|
||||
@cindex V850 floating point (@sc{ieee})
|
||||
The V850 family uses @sc{ieee} floating-point numbers.
|
||||
|
||||
@node V850 Directives
|
||||
@section V850 Machine Directives
|
||||
|
||||
@cindex machine directives, V850
|
||||
@cindex V850 machine directives
|
||||
@table @code
|
||||
@cindex @code{offset} directive, V850
|
||||
@item .offset @var{<expression>}
|
||||
Moves the offset into the current section to the specified amount.
|
||||
|
||||
@cindex @code{section} directive, V850
|
||||
@item .section "name", <type>
|
||||
This is an extension to the standard .section directive. It sets the
|
||||
current section to be <type> and creates an alias for this section
|
||||
called "name".
|
||||
|
||||
@cindex @code{.v850} directive, V850
|
||||
@item .v850
|
||||
Specifies that the assembled code should be marked as being targeted at
|
||||
the V850 processor. This allows the linker to detect attempts to link
|
||||
such code with code assembled for other processors.
|
||||
|
||||
@cindex @code{.v850e} directive, V850
|
||||
@item .v850e
|
||||
Specifies that the assembled code should be marked as being targeted at
|
||||
the V850E processor. This allows the linker to detect attempts to link
|
||||
such code with code assembled for other processors.
|
||||
|
||||
@end table
|
||||
|
||||
@node V850 Opcodes
|
||||
@section Opcodes
|
||||
|
||||
@cindex V850 opcodes
|
||||
@cindex opcodes for V850
|
||||
@code{@value{AS}} implements all the standard V850 opcodes.
|
||||
|
||||
@code{@value{AS}} also implements the following pseudo ops:
|
||||
|
||||
@table @code
|
||||
|
||||
@cindex @code{hi0} pseudo-op, V850
|
||||
@item hi0()
|
||||
Computes the higher 16 bits of the given expression and stores it into
|
||||
the immediate operand field of the given instruction. For example:
|
||||
|
||||
@samp{mulhi hi0(here - there), r5, r6}
|
||||
|
||||
computes the difference between the address of labels 'here' and
|
||||
'there', takes the upper 16 bits of this difference, shifts it down 16
|
||||
bits and then mutliplies it by the lower 16 bits in register 5, putting
|
||||
the result into register 6.
|
||||
|
||||
@cindex @code{lo} pseudo-op, V850
|
||||
@item lo()
|
||||
Computes the lower 16 bits of the given expression and stores it into
|
||||
the immediate operand field of the given instruction. For example:
|
||||
|
||||
@samp{addi lo(here - there), r5, r6}
|
||||
|
||||
computes the difference between the address of labels 'here' and
|
||||
'there', takes the lower 16 bits of this difference and adds it to
|
||||
register 5, putting the result into register 6.
|
||||
|
||||
@cindex @code{hi} pseudo-op, V850
|
||||
@item hi()
|
||||
Computes the higher 16 bits of the given expression and then adds the
|
||||
value of the most significant bit of the lower 16 bits of the expression
|
||||
and stores the result into the immediate operand field of the given
|
||||
instruction. For example the following code can be used to compute the
|
||||
address of the label 'here' and store it into register 6:
|
||||
|
||||
@samp{movhi hi(here), r0, r6}
|
||||
@samp{movea lo(here), r6, r6}
|
||||
|
||||
The reason for this special behaviour is that movea performs a sign
|
||||
extention on its immediate operand. So for example if the address of
|
||||
'here' was 0xFFFFFFFF then without the special behaviour of the hi()
|
||||
pseudo-op the movhi instruction would put 0xFFFF0000 into r6, then the
|
||||
movea instruction would takes its immediate operand, 0xFFFF, sign extend
|
||||
it to 32 bits, 0xFFFFFFFF, and then add it into r6 giving 0xFFFEFFFF
|
||||
which is wrong (the fifth nibble is E). With the hi() pseudo op adding
|
||||
in the top bit of the lo() pseudo op, the movhi instruction actually
|
||||
stores 0 into r6 (0xFFFF + 1 = 0x0000), so that the movea instruction
|
||||
stores 0xFFFFFFFF into r6 - the right value.
|
||||
|
||||
@cindex @code{hilo} pseudo-op, V850
|
||||
@item hilo()
|
||||
Computes the 32 bit value of the given expression and stores it into
|
||||
the immediate operand field of the given instruction (which must be a
|
||||
mov instruction). For example:
|
||||
|
||||
@samp{mov hilo(here), r6}
|
||||
|
||||
computes the absolute address of label 'here' and puts the result into
|
||||
register 6.
|
||||
|
||||
@cindex @code{sdaoff} pseudo-op, V850
|
||||
@item sdaoff()
|
||||
Computes the offset of the named variable from the start of the Small
|
||||
Data Area (whoes address is held in register 4, the GP register) and
|
||||
stores the result as a 16 bit signed value in the immediate operand
|
||||
field of the given instruction. For example:
|
||||
|
||||
@samp{ld.w sdaoff(_a_variable)[gp],r6}
|
||||
|
||||
loads the contents of the location pointed to by the label '_a_variable'
|
||||
into register 6, provided that the label is located somewhere within +/-
|
||||
32K of the address held in the GP register. [Note the linker assumes
|
||||
that the GP register contains a fixed address set to the address of the
|
||||
label called '__gp'. This can either be set up automatically by the
|
||||
linker, or specifically set by using the @samp{--defsym __gp=<value>}
|
||||
command line option].
|
||||
|
||||
@cindex @code{tdaoff} pseudo-op, V850
|
||||
@item tdaoff()
|
||||
Computes the offset of the named variable from the start of the Tiny
|
||||
Data Area (whoes address is held in register 30, the EP register) and
|
||||
stores the result as a 4,5, 7 or 8 bit unsigned value in the immediate
|
||||
operand field of the given instruction. For example:
|
||||
|
||||
@samp{sld.w tdaoff(_a_variable)[ep],r6}
|
||||
|
||||
loads the contents of the location pointed to by the label '_a_variable'
|
||||
into register 6, provided that the label is located somewhere within +256
|
||||
bytes of the address held in the EP register. [Note the linker assumes
|
||||
that the EP register contains a fixed address set to the address of the
|
||||
label called '__ep'. This can either be set up automatically by the
|
||||
linker, or specifically set by using the @samp{--defsym __ep=<value>}
|
||||
command line option].
|
||||
|
||||
@cindex @code{zdaoff} pseudo-op, V850
|
||||
@item zdaoff()
|
||||
Computes the offset of the named variable from address 0 and stores the
|
||||
result as a 16 bit signed value in the immediate operand field of the
|
||||
given instruction. For example:
|
||||
|
||||
@samp{movea zdaoff(_a_variable),zero,r6}
|
||||
|
||||
puts the address of the label '_a_variable' into register 6, assuming
|
||||
that the label is somewhere within the first 32K of memory. (Strictly
|
||||
speaking it also possible to access the last 32K of memory as well, as
|
||||
the offsets are signed).
|
||||
|
||||
@cindex @code{ctoff} pseudo-op, V850
|
||||
@item ctoff()
|
||||
Computes the offset of the named variable from the start of the Call
|
||||
Table Area (whoes address is helg in system register 20, the CTBP
|
||||
register) and stores the result a 6 or 16 bit unsigned value in the
|
||||
immediate field of then given instruction or piece of data. For
|
||||
example:
|
||||
|
||||
@samp{callt ctoff(table_func1)}
|
||||
|
||||
will put the call the function whoes address is held in the call table
|
||||
at the location labeled 'table_func1'.
|
||||
|
||||
@end table
|
||||
|
||||
|
||||
For information on the V850 instruction set, see @cite{V850
|
||||
Family 32-/16-Bit single-Chip Microcontroller Architecture Manual} from NEC.
|
||||
Ltd.
|
||||
|
@ -1,380 +0,0 @@
|
||||
@c Copyright 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
|
||||
@c This is part of the GAS manual.
|
||||
@c For copying conditions, see the file as.texinfo.
|
||||
@ifset GENERIC
|
||||
@page
|
||||
@node Z8000-Dependent
|
||||
@chapter Z8000 Dependent Features
|
||||
@end ifset
|
||||
@ifclear GENERIC
|
||||
@node Machine Dependencies
|
||||
@chapter Z8000 Dependent Features
|
||||
@end ifclear
|
||||
|
||||
@cindex Z8000 support
|
||||
The Z8000 @value{AS} supports both members of the Z8000 family: the
|
||||
unsegmented Z8002, with 16 bit addresses, and the segmented Z8001 with
|
||||
24 bit addresses.
|
||||
|
||||
When the assembler is in unsegmented mode (specified with the
|
||||
@code{unsegm} directive), an address takes up one word (16 bit)
|
||||
sized register. When the assembler is in segmented mode (specified with
|
||||
the @code{segm} directive), a 24-bit address takes up a long (32 bit)
|
||||
register. @xref{Z8000 Directives,,Assembler Directives for the Z8000},
|
||||
for a list of other Z8000 specific assembler directives.
|
||||
|
||||
@menu
|
||||
* Z8000 Options:: No special command-line options for Z8000
|
||||
* Z8000 Syntax:: Assembler syntax for the Z8000
|
||||
* Z8000 Directives:: Special directives for the Z8000
|
||||
* Z8000 Opcodes:: Opcodes
|
||||
@end menu
|
||||
|
||||
@node Z8000 Options
|
||||
@section Options
|
||||
|
||||
@cindex Z8000 options
|
||||
@cindex options, Z8000
|
||||
@code{@value{AS}} has no additional command-line options for the Zilog
|
||||
Z8000 family.
|
||||
|
||||
@node Z8000 Syntax
|
||||
@section Syntax
|
||||
@menu
|
||||
* Z8000-Chars:: Special Characters
|
||||
* Z8000-Regs:: Register Names
|
||||
* Z8000-Addressing:: Addressing Modes
|
||||
@end menu
|
||||
|
||||
@node Z8000-Chars
|
||||
@subsection Special Characters
|
||||
|
||||
@cindex line comment character, Z8000
|
||||
@cindex Z8000 line comment character
|
||||
@samp{!} is the line comment character.
|
||||
|
||||
@cindex line separator, Z8000
|
||||
@cindex statement separator, Z8000
|
||||
@cindex Z8000 line separator
|
||||
You can use @samp{;} instead of a newline to separate statements.
|
||||
|
||||
@node Z8000-Regs
|
||||
@subsection Register Names
|
||||
|
||||
@cindex Z8000 registers
|
||||
@cindex registers, Z8000
|
||||
The Z8000 has sixteen 16 bit registers, numbered 0 to 15. You can refer
|
||||
to different sized groups of registers by register number, with the
|
||||
prefix @samp{r} for 16 bit registers, @samp{rr} for 32 bit registers and
|
||||
@samp{rq} for 64 bit registers. You can also refer to the contents of
|
||||
the first eight (of the sixteen 16 bit registers) by bytes. They are
|
||||
named @samp{r@var{n}h} and @samp{r@var{n}l}.
|
||||
|
||||
@smallexample
|
||||
@exdent @emph{byte registers}
|
||||
r0l r0h r1h r1l r2h r2l r3h r3l
|
||||
r4h r4l r5h r5l r6h r6l r7h r7l
|
||||
|
||||
@exdent @emph{word registers}
|
||||
r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15
|
||||
|
||||
@exdent @emph{long word registers}
|
||||
rr0 rr2 rr4 rr6 rr8 rr10 rr12 rr14
|
||||
|
||||
@exdent @emph{quad word registers}
|
||||
rq0 rq4 rq8 rq12
|
||||
@end smallexample
|
||||
|
||||
@node Z8000-Addressing
|
||||
@subsection Addressing Modes
|
||||
|
||||
@cindex addressing modes, Z8000
|
||||
@cindex Z800 addressing modes
|
||||
@value{AS} understands the following addressing modes for the Z8000:
|
||||
|
||||
@table @code
|
||||
@item r@var{n}
|
||||
Register direct
|
||||
|
||||
@item @@r@var{n}
|
||||
Indirect register
|
||||
|
||||
@item @var{addr}
|
||||
Direct: the 16 bit or 24 bit address (depending on whether the assembler
|
||||
is in segmented or unsegmented mode) of the operand is in the instruction.
|
||||
|
||||
@item address(r@var{n})
|
||||
Indexed: the 16 or 24 bit address is added to the 16 bit register to produce
|
||||
the final address in memory of the operand.
|
||||
|
||||
@item r@var{n}(#@var{imm})
|
||||
Base Address: the 16 or 24 bit register is added to the 16 bit sign
|
||||
extended immediate displacement to produce the final address in memory
|
||||
of the operand.
|
||||
|
||||
@item r@var{n}(r@var{m})
|
||||
Base Index: the 16 or 24 bit register r@var{n} is added to the sign
|
||||
extended 16 bit index register r@var{m} to produce the final address in
|
||||
memory of the operand.
|
||||
|
||||
@item #@var{xx}
|
||||
Immediate data @var{xx}.
|
||||
@end table
|
||||
|
||||
@node Z8000 Directives
|
||||
@section Assembler Directives for the Z8000
|
||||
|
||||
@cindex Z8000 directives
|
||||
@cindex directives, Z8000
|
||||
The Z8000 port of @value{AS} includes these additional assembler directives,
|
||||
for compatibility with other Z8000 assemblers. As shown, these do not
|
||||
begin with @samp{.} (unlike the ordinary @value{AS} directives).
|
||||
|
||||
@table @code
|
||||
@kindex segm
|
||||
@item segm
|
||||
Generates code for the segmented Z8001.
|
||||
|
||||
@kindex unsegm
|
||||
@item unsegm
|
||||
Generates code for the unsegmented Z8002.
|
||||
|
||||
@kindex name
|
||||
@item name
|
||||
Synonym for @code{.file}
|
||||
|
||||
@kindex global
|
||||
@item global
|
||||
Synonym for @code{.global}
|
||||
|
||||
@kindex wval
|
||||
@item wval
|
||||
Synonym for @code{.word}
|
||||
|
||||
@kindex lval
|
||||
@item lval
|
||||
Synonym for @code{.long}
|
||||
|
||||
@kindex bval
|
||||
@item bval
|
||||
Synonym for @code{.byte}
|
||||
|
||||
@kindex sval
|
||||
@item sval
|
||||
Assemble a string. @code{sval} expects one string literal, delimited by
|
||||
single quotes. It assembles each byte of the string into consecutive
|
||||
addresses. You can use the escape sequence @samp{%@var{xx}} (where
|
||||
@var{xx} represents a two-digit hexadecimal number) to represent the
|
||||
character whose @sc{ascii} value is @var{xx}. Use this feature to
|
||||
describe single quote and other characters that may not appear in string
|
||||
literals as themselves. For example, the C statement @w{@samp{char *a =
|
||||
"he said \"it's 50% off\"";}} is represented in Z8000 assembly language
|
||||
(shown with the assembler output in hex at the left) as
|
||||
|
||||
@iftex
|
||||
@begingroup
|
||||
@let@nonarrowing=@comment
|
||||
@end iftex
|
||||
@smallexample
|
||||
68652073 sval 'he said %22it%27s 50%25 off%22%00'
|
||||
61696420
|
||||
22697427
|
||||
73203530
|
||||
25206F66
|
||||
662200
|
||||
@end smallexample
|
||||
@iftex
|
||||
@endgroup
|
||||
@end iftex
|
||||
|
||||
@kindex rsect
|
||||
@item rsect
|
||||
synonym for @code{.section}
|
||||
|
||||
@kindex block
|
||||
@item block
|
||||
synonym for @code{.space}
|
||||
|
||||
@kindex even
|
||||
@item even
|
||||
special case of @code{.align}; aligns output to even byte boundary.
|
||||
@end table
|
||||
|
||||
@node Z8000 Opcodes
|
||||
@section Opcodes
|
||||
|
||||
@cindex Z8000 opcode summary
|
||||
@cindex opcode summary, Z8000
|
||||
@cindex mnemonics, Z8000
|
||||
@cindex instruction summary, Z8000
|
||||
For detailed information on the Z8000 machine instruction set, see
|
||||
@cite{Z8000 Technical Manual}.
|
||||
|
||||
@ifset SMALL
|
||||
@c this table, due to the multi-col faking and hardcoded order, looks silly
|
||||
@c except in smallbook. See comments below "@set SMALL" near top of this file.
|
||||
|
||||
The following table summarizes the opcodes and their arguments:
|
||||
@iftex
|
||||
@begingroup
|
||||
@let@nonarrowing=@comment
|
||||
@end iftex
|
||||
@smallexample
|
||||
|
||||
rs @r{16 bit source register}
|
||||
rd @r{16 bit destination register}
|
||||
rbs @r{8 bit source register}
|
||||
rbd @r{8 bit destination register}
|
||||
rrs @r{32 bit source register}
|
||||
rrd @r{32 bit destination register}
|
||||
rqs @r{64 bit source register}
|
||||
rqd @r{64 bit destination register}
|
||||
addr @r{16/24 bit address}
|
||||
imm @r{immediate data}
|
||||
|
||||
adc rd,rs clrb addr cpsir @@rd,@@rs,rr,cc
|
||||
adcb rbd,rbs clrb addr(rd) cpsirb @@rd,@@rs,rr,cc
|
||||
add rd,@@rs clrb rbd dab rbd
|
||||
add rd,addr com @@rd dbjnz rbd,disp7
|
||||
add rd,addr(rs) com addr dec @@rd,imm4m1
|
||||
add rd,imm16 com addr(rd) dec addr(rd),imm4m1
|
||||
add rd,rs com rd dec addr,imm4m1
|
||||
addb rbd,@@rs comb @@rd dec rd,imm4m1
|
||||
addb rbd,addr comb addr decb @@rd,imm4m1
|
||||
addb rbd,addr(rs) comb addr(rd) decb addr(rd),imm4m1
|
||||
addb rbd,imm8 comb rbd decb addr,imm4m1
|
||||
addb rbd,rbs comflg flags decb rbd,imm4m1
|
||||
addl rrd,@@rs cp @@rd,imm16 di i2
|
||||
addl rrd,addr cp addr(rd),imm16 div rrd,@@rs
|
||||
addl rrd,addr(rs) cp addr,imm16 div rrd,addr
|
||||
addl rrd,imm32 cp rd,@@rs div rrd,addr(rs)
|
||||
addl rrd,rrs cp rd,addr div rrd,imm16
|
||||
and rd,@@rs cp rd,addr(rs) div rrd,rs
|
||||
and rd,addr cp rd,imm16 divl rqd,@@rs
|
||||
and rd,addr(rs) cp rd,rs divl rqd,addr
|
||||
and rd,imm16 cpb @@rd,imm8 divl rqd,addr(rs)
|
||||
and rd,rs cpb addr(rd),imm8 divl rqd,imm32
|
||||
andb rbd,@@rs cpb addr,imm8 divl rqd,rrs
|
||||
andb rbd,addr cpb rbd,@@rs djnz rd,disp7
|
||||
andb rbd,addr(rs) cpb rbd,addr ei i2
|
||||
andb rbd,imm8 cpb rbd,addr(rs) ex rd,@@rs
|
||||
andb rbd,rbs cpb rbd,imm8 ex rd,addr
|
||||
bit @@rd,imm4 cpb rbd,rbs ex rd,addr(rs)
|
||||
bit addr(rd),imm4 cpd rd,@@rs,rr,cc ex rd,rs
|
||||
bit addr,imm4 cpdb rbd,@@rs,rr,cc exb rbd,@@rs
|
||||
bit rd,imm4 cpdr rd,@@rs,rr,cc exb rbd,addr
|
||||
bit rd,rs cpdrb rbd,@@rs,rr,cc exb rbd,addr(rs)
|
||||
bitb @@rd,imm4 cpi rd,@@rs,rr,cc exb rbd,rbs
|
||||
bitb addr(rd),imm4 cpib rbd,@@rs,rr,cc ext0e imm8
|
||||
bitb addr,imm4 cpir rd,@@rs,rr,cc ext0f imm8
|
||||
bitb rbd,imm4 cpirb rbd,@@rs,rr,cc ext8e imm8
|
||||
bitb rbd,rs cpl rrd,@@rs ext8f imm8
|
||||
bpt cpl rrd,addr exts rrd
|
||||
call @@rd cpl rrd,addr(rs) extsb rd
|
||||
call addr cpl rrd,imm32 extsl rqd
|
||||
call addr(rd) cpl rrd,rrs halt
|
||||
calr disp12 cpsd @@rd,@@rs,rr,cc in rd,@@rs
|
||||
clr @@rd cpsdb @@rd,@@rs,rr,cc in rd,imm16
|
||||
clr addr cpsdr @@rd,@@rs,rr,cc inb rbd,@@rs
|
||||
clr addr(rd) cpsdrb @@rd,@@rs,rr,cc inb rbd,imm16
|
||||
clr rd cpsi @@rd,@@rs,rr,cc inc @@rd,imm4m1
|
||||
clrb @@rd cpsib @@rd,@@rs,rr,cc inc addr(rd),imm4m1
|
||||
inc addr,imm4m1 ldb rbd,rs(rx) mult rrd,addr(rs)
|
||||
inc rd,imm4m1 ldb rd(imm16),rbs mult rrd,imm16
|
||||
incb @@rd,imm4m1 ldb rd(rx),rbs mult rrd,rs
|
||||
incb addr(rd),imm4m1 ldctl ctrl,rs multl rqd,@@rs
|
||||
incb addr,imm4m1 ldctl rd,ctrl multl rqd,addr
|
||||
incb rbd,imm4m1 ldd @@rs,@@rd,rr multl rqd,addr(rs)
|
||||
ind @@rd,@@rs,ra lddb @@rs,@@rd,rr multl rqd,imm32
|
||||
indb @@rd,@@rs,rba lddr @@rs,@@rd,rr multl rqd,rrs
|
||||
inib @@rd,@@rs,ra lddrb @@rs,@@rd,rr neg @@rd
|
||||
inibr @@rd,@@rs,ra ldi @@rd,@@rs,rr neg addr
|
||||
iret ldib @@rd,@@rs,rr neg addr(rd)
|
||||
jp cc,@@rd ldir @@rd,@@rs,rr neg rd
|
||||
jp cc,addr ldirb @@rd,@@rs,rr negb @@rd
|
||||
jp cc,addr(rd) ldk rd,imm4 negb addr
|
||||
jr cc,disp8 ldl @@rd,rrs negb addr(rd)
|
||||
ld @@rd,imm16 ldl addr(rd),rrs negb rbd
|
||||
ld @@rd,rs ldl addr,rrs nop
|
||||
ld addr(rd),imm16 ldl rd(imm16),rrs or rd,@@rs
|
||||
ld addr(rd),rs ldl rd(rx),rrs or rd,addr
|
||||
ld addr,imm16 ldl rrd,@@rs or rd,addr(rs)
|
||||
ld addr,rs ldl rrd,addr or rd,imm16
|
||||
ld rd(imm16),rs ldl rrd,addr(rs) or rd,rs
|
||||
ld rd(rx),rs ldl rrd,imm32 orb rbd,@@rs
|
||||
ld rd,@@rs ldl rrd,rrs orb rbd,addr
|
||||
ld rd,addr ldl rrd,rs(imm16) orb rbd,addr(rs)
|
||||
ld rd,addr(rs) ldl rrd,rs(rx) orb rbd,imm8
|
||||
ld rd,imm16 ldm @@rd,rs,n orb rbd,rbs
|
||||
ld rd,rs ldm addr(rd),rs,n out @@rd,rs
|
||||
ld rd,rs(imm16) ldm addr,rs,n out imm16,rs
|
||||
ld rd,rs(rx) ldm rd,@@rs,n outb @@rd,rbs
|
||||
lda rd,addr ldm rd,addr(rs),n outb imm16,rbs
|
||||
lda rd,addr(rs) ldm rd,addr,n outd @@rd,@@rs,ra
|
||||
lda rd,rs(imm16) ldps @@rs outdb @@rd,@@rs,rba
|
||||
lda rd,rs(rx) ldps addr outib @@rd,@@rs,ra
|
||||
ldar rd,disp16 ldps addr(rs) outibr @@rd,@@rs,ra
|
||||
ldb @@rd,imm8 ldr disp16,rs pop @@rd,@@rs
|
||||
ldb @@rd,rbs ldr rd,disp16 pop addr(rd),@@rs
|
||||
ldb addr(rd),imm8 ldrb disp16,rbs pop addr,@@rs
|
||||
ldb addr(rd),rbs ldrb rbd,disp16 pop rd,@@rs
|
||||
ldb addr,imm8 ldrl disp16,rrs popl @@rd,@@rs
|
||||
ldb addr,rbs ldrl rrd,disp16 popl addr(rd),@@rs
|
||||
ldb rbd,@@rs mbit popl addr,@@rs
|
||||
ldb rbd,addr mreq rd popl rrd,@@rs
|
||||
ldb rbd,addr(rs) mres push @@rd,@@rs
|
||||
ldb rbd,imm8 mset push @@rd,addr
|
||||
ldb rbd,rbs mult rrd,@@rs push @@rd,addr(rs)
|
||||
ldb rbd,rs(imm16) mult rrd,addr push @@rd,imm16
|
||||
push @@rd,rs set addr,imm4 subl rrd,imm32
|
||||
pushl @@rd,@@rs set rd,imm4 subl rrd,rrs
|
||||
pushl @@rd,addr set rd,rs tcc cc,rd
|
||||
pushl @@rd,addr(rs) setb @@rd,imm4 tccb cc,rbd
|
||||
pushl @@rd,rrs setb addr(rd),imm4 test @@rd
|
||||
res @@rd,imm4 setb addr,imm4 test addr
|
||||
res addr(rd),imm4 setb rbd,imm4 test addr(rd)
|
||||
res addr,imm4 setb rbd,rs test rd
|
||||
res rd,imm4 setflg imm4 testb @@rd
|
||||
res rd,rs sinb rbd,imm16 testb addr
|
||||
resb @@rd,imm4 sinb rd,imm16 testb addr(rd)
|
||||
resb addr(rd),imm4 sind @@rd,@@rs,ra testb rbd
|
||||
resb addr,imm4 sindb @@rd,@@rs,rba testl @@rd
|
||||
resb rbd,imm4 sinib @@rd,@@rs,ra testl addr
|
||||
resb rbd,rs sinibr @@rd,@@rs,ra testl addr(rd)
|
||||
resflg imm4 sla rd,imm8 testl rrd
|
||||
ret cc slab rbd,imm8 trdb @@rd,@@rs,rba
|
||||
rl rd,imm1or2 slal rrd,imm8 trdrb @@rd,@@rs,rba
|
||||
rlb rbd,imm1or2 sll rd,imm8 trib @@rd,@@rs,rbr
|
||||
rlc rd,imm1or2 sllb rbd,imm8 trirb @@rd,@@rs,rbr
|
||||
rlcb rbd,imm1or2 slll rrd,imm8 trtdrb @@ra,@@rb,rbr
|
||||
rldb rbb,rba sout imm16,rs trtib @@ra,@@rb,rr
|
||||
rr rd,imm1or2 soutb imm16,rbs trtirb @@ra,@@rb,rbr
|
||||
rrb rbd,imm1or2 soutd @@rd,@@rs,ra trtrb @@ra,@@rb,rbr
|
||||
rrc rd,imm1or2 soutdb @@rd,@@rs,rba tset @@rd
|
||||
rrcb rbd,imm1or2 soutib @@rd,@@rs,ra tset addr
|
||||
rrdb rbb,rba soutibr @@rd,@@rs,ra tset addr(rd)
|
||||
rsvd36 sra rd,imm8 tset rd
|
||||
rsvd38 srab rbd,imm8 tsetb @@rd
|
||||
rsvd78 sral rrd,imm8 tsetb addr
|
||||
rsvd7e srl rd,imm8 tsetb addr(rd)
|
||||
rsvd9d srlb rbd,imm8 tsetb rbd
|
||||
rsvd9f srll rrd,imm8 xor rd,@@rs
|
||||
rsvdb9 sub rd,@@rs xor rd,addr
|
||||
rsvdbf sub rd,addr xor rd,addr(rs)
|
||||
sbc rd,rs sub rd,addr(rs) xor rd,imm16
|
||||
sbcb rbd,rbs sub rd,imm16 xor rd,rs
|
||||
sc imm8 sub rd,rs xorb rbd,@@rs
|
||||
sda rd,rs subb rbd,@@rs xorb rbd,addr
|
||||
sdab rbd,rs subb rbd,addr xorb rbd,addr(rs)
|
||||
sdal rrd,rs subb rbd,addr(rs) xorb rbd,imm8
|
||||
sdl rd,rs subb rbd,imm8 xorb rbd,rbs
|
||||
sdlb rbd,rs subb rbd,rbs xorb rbd,rbs
|
||||
sdll rrd,rs subl rrd,@@rs
|
||||
set @@rd,imm4 subl rrd,addr
|
||||
set addr(rd),imm4 subl rrd,addr(rs)
|
||||
@end smallexample
|
||||
@iftex
|
||||
@endgroup
|
||||
@end iftex
|
||||
@end ifset
|
||||
|
@ -1,789 +0,0 @@
|
||||
/* mips.h. Mips opcode list for GDB, the GNU debugger.
|
||||
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Ralph Campbell and OSF
|
||||
Commented and modified by Ian Lance Taylor, Cygnus Support
|
||||
|
||||
This file is part of GDB, GAS, and the GNU binutils.
|
||||
|
||||
GDB, GAS, and the GNU binutils are free software; you can redistribute
|
||||
them and/or modify them under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either version
|
||||
1, or (at your option) any later version.
|
||||
|
||||
GDB, GAS, and the GNU binutils are distributed in the hope that they
|
||||
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 file; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef _MIPS_H_
|
||||
#define _MIPS_H_
|
||||
|
||||
/* These are bit masks and shift counts to use to access the various
|
||||
fields of an instruction. To retrieve the X field of an
|
||||
instruction, use the expression
|
||||
(i >> OP_SH_X) & OP_MASK_X
|
||||
To set the same field (to j), use
|
||||
i = (i &~ (OP_MASK_X << OP_SH_X)) | (j << OP_SH_X)
|
||||
|
||||
Make sure you use fields that are appropriate for the instruction,
|
||||
of course.
|
||||
|
||||
The 'i' format uses OP, RS, RT and IMMEDIATE.
|
||||
|
||||
The 'j' format uses OP and TARGET.
|
||||
|
||||
The 'r' format uses OP, RS, RT, RD, SHAMT and FUNCT.
|
||||
|
||||
The 'b' format uses OP, RS, RT and DELTA.
|
||||
|
||||
The floating point 'i' format uses OP, RS, RT and IMMEDIATE.
|
||||
|
||||
The floating point 'r' format uses OP, FMT, FT, FS, FD and FUNCT.
|
||||
|
||||
A breakpoint instruction uses OP, CODE and SPEC (10 bits of the
|
||||
breakpoint instruction are not defined; Kane says the breakpoint
|
||||
code field in BREAK is 20 bits; yet MIPS assemblers and debuggers
|
||||
only use ten bits). An optional two-operand form of break/sdbbp
|
||||
allows the lower ten bits to be set too, and MIPS32 and later
|
||||
architectures allow 20 bits to be set with a signal operand
|
||||
(using CODE20).
|
||||
|
||||
The syscall instruction uses CODE20.
|
||||
|
||||
The general coprocessor instructions use COPZ. */
|
||||
|
||||
#define OP_MASK_OP 0x3f
|
||||
#define OP_SH_OP 26
|
||||
#define OP_MASK_RS 0x1f
|
||||
#define OP_SH_RS 21
|
||||
#define OP_MASK_FR 0x1f
|
||||
#define OP_SH_FR 21
|
||||
#define OP_MASK_FMT 0x1f
|
||||
#define OP_SH_FMT 21
|
||||
#define OP_MASK_BCC 0x7
|
||||
#define OP_SH_BCC 18
|
||||
#define OP_MASK_CODE 0x3ff
|
||||
#define OP_SH_CODE 16
|
||||
#define OP_MASK_CODE2 0x3ff
|
||||
#define OP_SH_CODE2 6
|
||||
#define OP_MASK_RT 0x1f
|
||||
#define OP_SH_RT 16
|
||||
#define OP_MASK_FT 0x1f
|
||||
#define OP_SH_FT 16
|
||||
#define OP_MASK_CACHE 0x1f
|
||||
#define OP_SH_CACHE 16
|
||||
#define OP_MASK_RD 0x1f
|
||||
#define OP_SH_RD 11
|
||||
#define OP_MASK_FS 0x1f
|
||||
#define OP_SH_FS 11
|
||||
#define OP_MASK_PREFX 0x1f
|
||||
#define OP_SH_PREFX 11
|
||||
#define OP_MASK_CCC 0x7
|
||||
#define OP_SH_CCC 8
|
||||
#define OP_MASK_CODE20 0xfffff /* 20 bit syscall/breakpoint code. */
|
||||
#define OP_SH_CODE20 6
|
||||
#define OP_MASK_SHAMT 0x1f
|
||||
#define OP_SH_SHAMT 6
|
||||
#define OP_MASK_FD 0x1f
|
||||
#define OP_SH_FD 6
|
||||
#define OP_MASK_TARGET 0x3ffffff
|
||||
#define OP_SH_TARGET 0
|
||||
#define OP_MASK_COPZ 0x1ffffff
|
||||
#define OP_SH_COPZ 0
|
||||
#define OP_MASK_IMMEDIATE 0xffff
|
||||
#define OP_SH_IMMEDIATE 0
|
||||
#define OP_MASK_DELTA 0xffff
|
||||
#define OP_SH_DELTA 0
|
||||
#define OP_MASK_FUNCT 0x3f
|
||||
#define OP_SH_FUNCT 0
|
||||
#define OP_MASK_SPEC 0x3f
|
||||
#define OP_SH_SPEC 0
|
||||
#define OP_SH_LOCC 8 /* FP condition code. */
|
||||
#define OP_SH_HICC 18 /* FP condition code. */
|
||||
#define OP_MASK_CC 0x7
|
||||
#define OP_SH_COP1NORM 25 /* Normal COP1 encoding. */
|
||||
#define OP_MASK_COP1NORM 0x1 /* a single bit. */
|
||||
#define OP_SH_COP1SPEC 21 /* COP1 encodings. */
|
||||
#define OP_MASK_COP1SPEC 0xf
|
||||
#define OP_MASK_COP1SCLR 0x4
|
||||
#define OP_MASK_COP1CMP 0x3
|
||||
#define OP_SH_COP1CMP 4
|
||||
#define OP_SH_FORMAT 21 /* FP short format field. */
|
||||
#define OP_MASK_FORMAT 0x7
|
||||
#define OP_SH_TRUE 16
|
||||
#define OP_MASK_TRUE 0x1
|
||||
#define OP_SH_GE 17
|
||||
#define OP_MASK_GE 0x01
|
||||
#define OP_SH_UNSIGNED 16
|
||||
#define OP_MASK_UNSIGNED 0x1
|
||||
#define OP_SH_HINT 16
|
||||
#define OP_MASK_HINT 0x1f
|
||||
#define OP_SH_MMI 0 /* Multimedia (parallel) op. */
|
||||
#define OP_MASK_MMI 0x3f
|
||||
#define OP_SH_MMISUB 6
|
||||
#define OP_MASK_MMISUB 0x1f
|
||||
#define OP_MASK_PERFREG 0x1f /* Performance monitoring. */
|
||||
#define OP_SH_PERFREG 1
|
||||
#define OP_SH_SEL 0 /* Coprocessor select field. */
|
||||
#define OP_MASK_SEL 0x7 /* The sel field of mfcZ and mtcZ. */
|
||||
#define OP_SH_CODE19 6 /* 19 bit wait code. */
|
||||
#define OP_MASK_CODE19 0x7ffff
|
||||
|
||||
/* This structure holds information for a particular instruction. */
|
||||
|
||||
struct mips_opcode
|
||||
{
|
||||
/* The name of the instruction. */
|
||||
const char *name;
|
||||
/* A string describing the arguments for this instruction. */
|
||||
const char *args;
|
||||
/* The basic opcode for the instruction. When assembling, this
|
||||
opcode is modified by the arguments to produce the actual opcode
|
||||
that is used. If pinfo is INSN_MACRO, then this is 0. */
|
||||
unsigned long match;
|
||||
/* If pinfo is not INSN_MACRO, then this is a bit mask for the
|
||||
relevant portions of the opcode when disassembling. If the
|
||||
actual opcode anded with the match field equals the opcode field,
|
||||
then we have found the correct instruction. If pinfo is
|
||||
INSN_MACRO, then this field is the macro identifier. */
|
||||
unsigned long mask;
|
||||
/* For a macro, this is INSN_MACRO. Otherwise, it is a collection
|
||||
of bits describing the instruction, notably any relevant hazard
|
||||
information. */
|
||||
unsigned long pinfo;
|
||||
/* A collection of bits describing the instruction sets of which this
|
||||
instruction or macro is a member. */
|
||||
unsigned long membership;
|
||||
};
|
||||
|
||||
/* These are the characters which may appears in the args field of an
|
||||
instruction. They appear in the order in which the fields appear
|
||||
when the instruction is used. Commas and parentheses in the args
|
||||
string are ignored when assembling, and written into the output
|
||||
when disassembling.
|
||||
|
||||
Each of these characters corresponds to a mask field defined above.
|
||||
|
||||
"<" 5 bit shift amount (OP_*_SHAMT)
|
||||
">" shift amount between 32 and 63, stored after subtracting 32 (OP_*_SHAMT)
|
||||
"a" 26 bit target address (OP_*_TARGET)
|
||||
"b" 5 bit base register (OP_*_RS)
|
||||
"c" 10 bit breakpoint code (OP_*_CODE)
|
||||
"d" 5 bit destination register specifier (OP_*_RD)
|
||||
"h" 5 bit prefx hint (OP_*_PREFX)
|
||||
"i" 16 bit unsigned immediate (OP_*_IMMEDIATE)
|
||||
"j" 16 bit signed immediate (OP_*_DELTA)
|
||||
"k" 5 bit cache opcode in target register position (OP_*_CACHE)
|
||||
"o" 16 bit signed offset (OP_*_DELTA)
|
||||
"p" 16 bit PC relative branch target address (OP_*_DELTA)
|
||||
"q" 10 bit extra breakpoint code (OP_*_CODE2)
|
||||
"r" 5 bit same register used as both source and target (OP_*_RS)
|
||||
"s" 5 bit source register specifier (OP_*_RS)
|
||||
"t" 5 bit target register (OP_*_RT)
|
||||
"u" 16 bit upper 16 bits of address (OP_*_IMMEDIATE)
|
||||
"v" 5 bit same register used as both source and destination (OP_*_RS)
|
||||
"w" 5 bit same register used as both target and destination (OP_*_RT)
|
||||
"U" 5 bit same destination register in both OP_*_RD and OP_*_RT
|
||||
(used by clo and clz)
|
||||
"C" 25 bit coprocessor function code (OP_*_COPZ)
|
||||
"B" 20 bit syscall/breakpoint function code (OP_*_CODE20)
|
||||
"J" 19 bit wait function code (OP_*_CODE19)
|
||||
"x" accept and ignore register name
|
||||
"z" must be zero register
|
||||
|
||||
Floating point instructions:
|
||||
"D" 5 bit destination register (OP_*_FD)
|
||||
"M" 3 bit compare condition code (OP_*_CCC) (only used for mips4 and up)
|
||||
"N" 3 bit branch condition code (OP_*_BCC) (only used for mips4 and up)
|
||||
"S" 5 bit fs source 1 register (OP_*_FS)
|
||||
"T" 5 bit ft source 2 register (OP_*_FT)
|
||||
"R" 5 bit fr source 3 register (OP_*_FR)
|
||||
"V" 5 bit same register used as floating source and destination (OP_*_FS)
|
||||
"W" 5 bit same register used as floating target and destination (OP_*_FT)
|
||||
|
||||
Coprocessor instructions:
|
||||
"E" 5 bit target register (OP_*_RT)
|
||||
"G" 5 bit destination register (OP_*_RD)
|
||||
"H" 3 bit sel field for (d)mtc* and (d)mfc* (OP_*_SEL)
|
||||
"P" 5 bit performance-monitor register (OP_*_PERFREG)
|
||||
|
||||
Macro instructions:
|
||||
"A" General 32 bit expression
|
||||
"I" 32 bit immediate
|
||||
"F" 64 bit floating point constant in .rdata
|
||||
"L" 64 bit floating point constant in .lit8
|
||||
"f" 32 bit floating point constant
|
||||
"l" 32 bit floating point constant in .lit4
|
||||
|
||||
Other:
|
||||
"()" parens surrounding optional value
|
||||
"," separates operands
|
||||
|
||||
Characters used so far, for quick reference when adding more:
|
||||
"<>(),"
|
||||
"ABCDEFGHIJLMNPRSTUVW"
|
||||
"abcdfhijklopqrstuvwxz"
|
||||
*/
|
||||
|
||||
/* These are the bits which may be set in the pinfo field of an
|
||||
instructions, if it is not equal to INSN_MACRO. */
|
||||
|
||||
/* Modifies the general purpose register in OP_*_RD. */
|
||||
#define INSN_WRITE_GPR_D 0x00000001
|
||||
/* Modifies the general purpose register in OP_*_RT. */
|
||||
#define INSN_WRITE_GPR_T 0x00000002
|
||||
/* Modifies general purpose register 31. */
|
||||
#define INSN_WRITE_GPR_31 0x00000004
|
||||
/* Modifies the floating point register in OP_*_FD. */
|
||||
#define INSN_WRITE_FPR_D 0x00000008
|
||||
/* Modifies the floating point register in OP_*_FS. */
|
||||
#define INSN_WRITE_FPR_S 0x00000010
|
||||
/* Modifies the floating point register in OP_*_FT. */
|
||||
#define INSN_WRITE_FPR_T 0x00000020
|
||||
/* Reads the general purpose register in OP_*_RS. */
|
||||
#define INSN_READ_GPR_S 0x00000040
|
||||
/* Reads the general purpose register in OP_*_RT. */
|
||||
#define INSN_READ_GPR_T 0x00000080
|
||||
/* Reads the floating point register in OP_*_FS. */
|
||||
#define INSN_READ_FPR_S 0x00000100
|
||||
/* Reads the floating point register in OP_*_FT. */
|
||||
#define INSN_READ_FPR_T 0x00000200
|
||||
/* Reads the floating point register in OP_*_FR. */
|
||||
#define INSN_READ_FPR_R 0x00000400
|
||||
/* Modifies coprocessor condition code. */
|
||||
#define INSN_WRITE_COND_CODE 0x00000800
|
||||
/* Reads coprocessor condition code. */
|
||||
#define INSN_READ_COND_CODE 0x00001000
|
||||
/* TLB operation. */
|
||||
#define INSN_TLB 0x00002000
|
||||
/* Reads coprocessor register other than floating point register. */
|
||||
#define INSN_COP 0x00004000
|
||||
/* Instruction loads value from memory, requiring delay. */
|
||||
#define INSN_LOAD_MEMORY_DELAY 0x00008000
|
||||
/* Instruction loads value from coprocessor, requiring delay. */
|
||||
#define INSN_LOAD_COPROC_DELAY 0x00010000
|
||||
/* Instruction has unconditional branch delay slot. */
|
||||
#define INSN_UNCOND_BRANCH_DELAY 0x00020000
|
||||
/* Instruction has conditional branch delay slot. */
|
||||
#define INSN_COND_BRANCH_DELAY 0x00040000
|
||||
/* Conditional branch likely: if branch not taken, insn nullified. */
|
||||
#define INSN_COND_BRANCH_LIKELY 0x00080000
|
||||
/* Moves to coprocessor register, requiring delay. */
|
||||
#define INSN_COPROC_MOVE_DELAY 0x00100000
|
||||
/* Loads coprocessor register from memory, requiring delay. */
|
||||
#define INSN_COPROC_MEMORY_DELAY 0x00200000
|
||||
/* Reads the HI register. */
|
||||
#define INSN_READ_HI 0x00400000
|
||||
/* Reads the LO register. */
|
||||
#define INSN_READ_LO 0x00800000
|
||||
/* Modifies the HI register. */
|
||||
#define INSN_WRITE_HI 0x01000000
|
||||
/* Modifies the LO register. */
|
||||
#define INSN_WRITE_LO 0x02000000
|
||||
/* Takes a trap (easier to keep out of delay slot). */
|
||||
#define INSN_TRAP 0x04000000
|
||||
/* Instruction stores value into memory. */
|
||||
#define INSN_STORE_MEMORY 0x08000000
|
||||
/* Instruction uses single precision floating point. */
|
||||
#define FP_S 0x10000000
|
||||
/* Instruction uses double precision floating point. */
|
||||
#define FP_D 0x20000000
|
||||
/* Instruction is part of the tx39's integer multiply family. */
|
||||
#define INSN_MULT 0x40000000
|
||||
/* Instruction synchronize shared memory. */
|
||||
#define INSN_SYNC 0x80000000
|
||||
|
||||
/* Instruction is actually a macro. It should be ignored by the
|
||||
disassembler, and requires special treatment by the assembler. */
|
||||
#define INSN_MACRO 0xffffffff
|
||||
|
||||
/* Masks used to mark instructions to indicate which MIPS ISA level
|
||||
they were introduced in. ISAs, as defined below, are logical
|
||||
ORs of these bits, indicatingthat they support the instructions
|
||||
defined at the given level. */
|
||||
|
||||
#define INSN_ISA_MASK 0x00000fff
|
||||
#define INSN_ISA1 0x00000010
|
||||
#define INSN_ISA2 0x00000020
|
||||
#define INSN_ISA3 0x00000040
|
||||
#define INSN_ISA4 0x00000080
|
||||
#define INSN_ISA5 0x00000100
|
||||
#define INSN_ISA32 0x00000200
|
||||
#define INSN_ISA64 0x00000400
|
||||
|
||||
/* Chip specific instructions. These are bitmasks. */
|
||||
|
||||
/* MIPS R4650 instruction. */
|
||||
#define INSN_4650 0x00010000
|
||||
/* LSI R4010 instruction. */
|
||||
#define INSN_4010 0x00020000
|
||||
/* NEC VR4100 instruction. */
|
||||
#define INSN_4100 0x00040000
|
||||
/* Toshiba R3900 instruction. */
|
||||
#define INSN_3900 0x00080000
|
||||
/* MIPS R10000 instruction. */
|
||||
#define INSN_10000 0x00100000
|
||||
/* Broadcom SB-1 instruction. */
|
||||
#define INSN_SB1 0x00200000
|
||||
|
||||
/* MIPS ISA defines, use instead of hardcoding ISA level. */
|
||||
|
||||
#define ISA_UNKNOWN 0 /* Gas internal use. */
|
||||
#define ISA_MIPS1 (INSN_ISA1)
|
||||
#define ISA_MIPS2 (ISA_MIPS1 | INSN_ISA2)
|
||||
#define ISA_MIPS3 (ISA_MIPS2 | INSN_ISA3)
|
||||
#define ISA_MIPS4 (ISA_MIPS3 | INSN_ISA4)
|
||||
#define ISA_MIPS5 (ISA_MIPS4 | INSN_ISA5)
|
||||
#define ISA_MIPS32 (ISA_MIPS2 | INSN_ISA32)
|
||||
#define ISA_MIPS64 (ISA_MIPS5 | INSN_ISA32 | INSN_ISA64)
|
||||
|
||||
/* CPU defines, use instead of hardcoding processor number. Keep this
|
||||
in sync with bfd/archures.c in order for machine selection to work. */
|
||||
#define CPU_UNKNOWN 0 /* Gas internal use. */
|
||||
#define CPU_R2000 2000
|
||||
#define CPU_R3000 3000
|
||||
#define CPU_R3900 3900
|
||||
#define CPU_R4000 4000
|
||||
#define CPU_R4010 4010
|
||||
#define CPU_VR4100 4100
|
||||
#define CPU_R4111 4111
|
||||
#define CPU_R4300 4300
|
||||
#define CPU_R4400 4400
|
||||
#define CPU_R4600 4600
|
||||
#define CPU_R4650 4650
|
||||
#define CPU_R5000 5000
|
||||
#define CPU_R6000 6000
|
||||
#define CPU_R8000 8000
|
||||
#define CPU_R10000 10000
|
||||
#define CPU_R12000 12000
|
||||
#define CPU_MIPS16 16
|
||||
#define CPU_MIPS32 32
|
||||
#define CPU_MIPS5 5
|
||||
#define CPU_MIPS64 64
|
||||
#define CPU_SB1 12310201 /* octal 'SB', 01. */
|
||||
|
||||
/* Test for membership in an ISA including chip specific ISAs.
|
||||
INSN is pointer to an element of the opcode table; ISA is the
|
||||
specified ISA to test against; and CPU is the CPU specific ISA
|
||||
to test, or zero if no CPU specific ISA test is desired. */
|
||||
|
||||
#define OPCODE_IS_MEMBER(insn, isa, cpu) \
|
||||
(((insn)->membership & isa) != 0 \
|
||||
|| (cpu == CPU_R4650 && ((insn)->membership & INSN_4650) != 0) \
|
||||
|| (cpu == CPU_R4010 && ((insn)->membership & INSN_4010) != 0) \
|
||||
|| ((cpu == CPU_VR4100 || cpu == CPU_R4111) \
|
||||
&& ((insn)->membership & INSN_4100) != 0) \
|
||||
|| (cpu == CPU_R3900 && ((insn)->membership & INSN_3900) != 0) \
|
||||
|| ((cpu == CPU_R10000 || cpu == CPU_R12000) \
|
||||
&& ((insn)->membership & INSN_10000) != 0) \
|
||||
|| (cpu == CPU_SB1 && ((insn)->membership & INSN_SB1) != 0) \
|
||||
|| 0) /* Please keep this term for easier source merging. */
|
||||
|
||||
/* This is a list of macro expanded instructions.
|
||||
|
||||
_I appended means immediate
|
||||
_A appended means address
|
||||
_AB appended means address with base register
|
||||
_D appended means 64 bit floating point constant
|
||||
_S appended means 32 bit floating point constant. */
|
||||
|
||||
enum
|
||||
{
|
||||
M_ABS,
|
||||
M_ADD_I,
|
||||
M_ADDU_I,
|
||||
M_AND_I,
|
||||
M_BEQ,
|
||||
M_BEQ_I,
|
||||
M_BEQL_I,
|
||||
M_BGE,
|
||||
M_BGEL,
|
||||
M_BGE_I,
|
||||
M_BGEL_I,
|
||||
M_BGEU,
|
||||
M_BGEUL,
|
||||
M_BGEU_I,
|
||||
M_BGEUL_I,
|
||||
M_BGT,
|
||||
M_BGTL,
|
||||
M_BGT_I,
|
||||
M_BGTL_I,
|
||||
M_BGTU,
|
||||
M_BGTUL,
|
||||
M_BGTU_I,
|
||||
M_BGTUL_I,
|
||||
M_BLE,
|
||||
M_BLEL,
|
||||
M_BLE_I,
|
||||
M_BLEL_I,
|
||||
M_BLEU,
|
||||
M_BLEUL,
|
||||
M_BLEU_I,
|
||||
M_BLEUL_I,
|
||||
M_BLT,
|
||||
M_BLTL,
|
||||
M_BLT_I,
|
||||
M_BLTL_I,
|
||||
M_BLTU,
|
||||
M_BLTUL,
|
||||
M_BLTU_I,
|
||||
M_BLTUL_I,
|
||||
M_BNE,
|
||||
M_BNE_I,
|
||||
M_BNEL_I,
|
||||
M_DABS,
|
||||
M_DADD_I,
|
||||
M_DADDU_I,
|
||||
M_DDIV_3,
|
||||
M_DDIV_3I,
|
||||
M_DDIVU_3,
|
||||
M_DDIVU_3I,
|
||||
M_DIV_3,
|
||||
M_DIV_3I,
|
||||
M_DIVU_3,
|
||||
M_DIVU_3I,
|
||||
M_DLA_AB,
|
||||
M_DLI,
|
||||
M_DMUL,
|
||||
M_DMUL_I,
|
||||
M_DMULO,
|
||||
M_DMULO_I,
|
||||
M_DMULOU,
|
||||
M_DMULOU_I,
|
||||
M_DREM_3,
|
||||
M_DREM_3I,
|
||||
M_DREMU_3,
|
||||
M_DREMU_3I,
|
||||
M_DSUB_I,
|
||||
M_DSUBU_I,
|
||||
M_DSUBU_I_2,
|
||||
M_J_A,
|
||||
M_JAL_1,
|
||||
M_JAL_2,
|
||||
M_JAL_A,
|
||||
M_L_DOB,
|
||||
M_L_DAB,
|
||||
M_LA_AB,
|
||||
M_LB_A,
|
||||
M_LB_AB,
|
||||
M_LBU_A,
|
||||
M_LBU_AB,
|
||||
M_LD_A,
|
||||
M_LD_OB,
|
||||
M_LD_AB,
|
||||
M_LDC1_AB,
|
||||
M_LDC2_AB,
|
||||
M_LDC3_AB,
|
||||
M_LDL_AB,
|
||||
M_LDR_AB,
|
||||
M_LH_A,
|
||||
M_LH_AB,
|
||||
M_LHU_A,
|
||||
M_LHU_AB,
|
||||
M_LI,
|
||||
M_LI_D,
|
||||
M_LI_DD,
|
||||
M_LI_S,
|
||||
M_LI_SS,
|
||||
M_LL_AB,
|
||||
M_LLD_AB,
|
||||
M_LS_A,
|
||||
M_LW_A,
|
||||
M_LW_AB,
|
||||
M_LWC0_A,
|
||||
M_LWC0_AB,
|
||||
M_LWC1_A,
|
||||
M_LWC1_AB,
|
||||
M_LWC2_A,
|
||||
M_LWC2_AB,
|
||||
M_LWC3_A,
|
||||
M_LWC3_AB,
|
||||
M_LWL_A,
|
||||
M_LWL_AB,
|
||||
M_LWR_A,
|
||||
M_LWR_AB,
|
||||
M_LWU_AB,
|
||||
M_MOVE,
|
||||
M_MUL,
|
||||
M_MUL_I,
|
||||
M_MULO,
|
||||
M_MULO_I,
|
||||
M_MULOU,
|
||||
M_MULOU_I,
|
||||
M_NOR_I,
|
||||
M_OR_I,
|
||||
M_REM_3,
|
||||
M_REM_3I,
|
||||
M_REMU_3,
|
||||
M_REMU_3I,
|
||||
M_ROL,
|
||||
M_ROL_I,
|
||||
M_ROR,
|
||||
M_ROR_I,
|
||||
M_S_DA,
|
||||
M_S_DOB,
|
||||
M_S_DAB,
|
||||
M_S_S,
|
||||
M_SC_AB,
|
||||
M_SCD_AB,
|
||||
M_SD_A,
|
||||
M_SD_OB,
|
||||
M_SD_AB,
|
||||
M_SDC1_AB,
|
||||
M_SDC2_AB,
|
||||
M_SDC3_AB,
|
||||
M_SDL_AB,
|
||||
M_SDR_AB,
|
||||
M_SEQ,
|
||||
M_SEQ_I,
|
||||
M_SGE,
|
||||
M_SGE_I,
|
||||
M_SGEU,
|
||||
M_SGEU_I,
|
||||
M_SGT,
|
||||
M_SGT_I,
|
||||
M_SGTU,
|
||||
M_SGTU_I,
|
||||
M_SLE,
|
||||
M_SLE_I,
|
||||
M_SLEU,
|
||||
M_SLEU_I,
|
||||
M_SLT_I,
|
||||
M_SLTU_I,
|
||||
M_SNE,
|
||||
M_SNE_I,
|
||||
M_SB_A,
|
||||
M_SB_AB,
|
||||
M_SH_A,
|
||||
M_SH_AB,
|
||||
M_SW_A,
|
||||
M_SW_AB,
|
||||
M_SWC0_A,
|
||||
M_SWC0_AB,
|
||||
M_SWC1_A,
|
||||
M_SWC1_AB,
|
||||
M_SWC2_A,
|
||||
M_SWC2_AB,
|
||||
M_SWC3_A,
|
||||
M_SWC3_AB,
|
||||
M_SWL_A,
|
||||
M_SWL_AB,
|
||||
M_SWR_A,
|
||||
M_SWR_AB,
|
||||
M_SUB_I,
|
||||
M_SUBU_I,
|
||||
M_SUBU_I_2,
|
||||
M_TEQ_I,
|
||||
M_TGE_I,
|
||||
M_TGEU_I,
|
||||
M_TLT_I,
|
||||
M_TLTU_I,
|
||||
M_TNE_I,
|
||||
M_TRUNCWD,
|
||||
M_TRUNCWS,
|
||||
M_ULD,
|
||||
M_ULD_A,
|
||||
M_ULH,
|
||||
M_ULH_A,
|
||||
M_ULHU,
|
||||
M_ULHU_A,
|
||||
M_ULW,
|
||||
M_ULW_A,
|
||||
M_USH,
|
||||
M_USH_A,
|
||||
M_USW,
|
||||
M_USW_A,
|
||||
M_USD,
|
||||
M_USD_A,
|
||||
M_XOR_I,
|
||||
M_COP0,
|
||||
M_COP1,
|
||||
M_COP2,
|
||||
M_COP3,
|
||||
M_NUM_MACROS
|
||||
};
|
||||
|
||||
|
||||
/* The order of overloaded instructions matters. Label arguments and
|
||||
register arguments look the same. Instructions that can have either
|
||||
for arguments must apear in the correct order in this table for the
|
||||
assembler to pick the right one. In other words, entries with
|
||||
immediate operands must apear after the same instruction with
|
||||
registers.
|
||||
|
||||
Many instructions are short hand for other instructions (i.e., The
|
||||
jal <register> instruction is short for jalr <register>). */
|
||||
|
||||
extern const struct mips_opcode mips_builtin_opcodes[];
|
||||
extern const int bfd_mips_num_builtin_opcodes;
|
||||
extern struct mips_opcode *mips_opcodes;
|
||||
extern int bfd_mips_num_opcodes;
|
||||
#define NUMOPCODES bfd_mips_num_opcodes
|
||||
|
||||
|
||||
/* The rest of this file adds definitions for the mips16 TinyRISC
|
||||
processor. */
|
||||
|
||||
/* These are the bitmasks and shift counts used for the different
|
||||
fields in the instruction formats. Other than OP, no masks are
|
||||
provided for the fixed portions of an instruction, since they are
|
||||
not needed.
|
||||
|
||||
The I format uses IMM11.
|
||||
|
||||
The RI format uses RX and IMM8.
|
||||
|
||||
The RR format uses RX, and RY.
|
||||
|
||||
The RRI format uses RX, RY, and IMM5.
|
||||
|
||||
The RRR format uses RX, RY, and RZ.
|
||||
|
||||
The RRI_A format uses RX, RY, and IMM4.
|
||||
|
||||
The SHIFT format uses RX, RY, and SHAMT.
|
||||
|
||||
The I8 format uses IMM8.
|
||||
|
||||
The I8_MOVR32 format uses RY and REGR32.
|
||||
|
||||
The IR_MOV32R format uses REG32R and MOV32Z.
|
||||
|
||||
The I64 format uses IMM8.
|
||||
|
||||
The RI64 format uses RY and IMM5.
|
||||
*/
|
||||
|
||||
#define MIPS16OP_MASK_OP 0x1f
|
||||
#define MIPS16OP_SH_OP 11
|
||||
#define MIPS16OP_MASK_IMM11 0x7ff
|
||||
#define MIPS16OP_SH_IMM11 0
|
||||
#define MIPS16OP_MASK_RX 0x7
|
||||
#define MIPS16OP_SH_RX 8
|
||||
#define MIPS16OP_MASK_IMM8 0xff
|
||||
#define MIPS16OP_SH_IMM8 0
|
||||
#define MIPS16OP_MASK_RY 0x7
|
||||
#define MIPS16OP_SH_RY 5
|
||||
#define MIPS16OP_MASK_IMM5 0x1f
|
||||
#define MIPS16OP_SH_IMM5 0
|
||||
#define MIPS16OP_MASK_RZ 0x7
|
||||
#define MIPS16OP_SH_RZ 2
|
||||
#define MIPS16OP_MASK_IMM4 0xf
|
||||
#define MIPS16OP_SH_IMM4 0
|
||||
#define MIPS16OP_MASK_REGR32 0x1f
|
||||
#define MIPS16OP_SH_REGR32 0
|
||||
#define MIPS16OP_MASK_REG32R 0x1f
|
||||
#define MIPS16OP_SH_REG32R 3
|
||||
#define MIPS16OP_EXTRACT_REG32R(i) ((((i) >> 5) & 7) | ((i) & 0x18))
|
||||
#define MIPS16OP_MASK_MOVE32Z 0x7
|
||||
#define MIPS16OP_SH_MOVE32Z 0
|
||||
#define MIPS16OP_MASK_IMM6 0x3f
|
||||
#define MIPS16OP_SH_IMM6 5
|
||||
|
||||
/* These are the characters which may appears in the args field of an
|
||||
instruction. They appear in the order in which the fields appear
|
||||
when the instruction is used. Commas and parentheses in the args
|
||||
string are ignored when assembling, and written into the output
|
||||
when disassembling.
|
||||
|
||||
"y" 3 bit register (MIPS16OP_*_RY)
|
||||
"x" 3 bit register (MIPS16OP_*_RX)
|
||||
"z" 3 bit register (MIPS16OP_*_RZ)
|
||||
"Z" 3 bit register (MIPS16OP_*_MOVE32Z)
|
||||
"v" 3 bit same register as source and destination (MIPS16OP_*_RX)
|
||||
"w" 3 bit same register as source and destination (MIPS16OP_*_RY)
|
||||
"0" zero register ($0)
|
||||
"S" stack pointer ($sp or $29)
|
||||
"P" program counter
|
||||
"R" return address register ($ra or $31)
|
||||
"X" 5 bit MIPS register (MIPS16OP_*_REGR32)
|
||||
"Y" 5 bit MIPS register (MIPS16OP_*_REG32R)
|
||||
"6" 6 bit unsigned break code (MIPS16OP_*_IMM6)
|
||||
"a" 26 bit jump address
|
||||
"e" 11 bit extension value
|
||||
"l" register list for entry instruction
|
||||
"L" register list for exit instruction
|
||||
|
||||
The remaining codes may be extended. Except as otherwise noted,
|
||||
the full extended operand is a 16 bit signed value.
|
||||
"<" 3 bit unsigned shift count * 0 (MIPS16OP_*_RZ) (full 5 bit unsigned)
|
||||
">" 3 bit unsigned shift count * 0 (MIPS16OP_*_RX) (full 5 bit unsigned)
|
||||
"[" 3 bit unsigned shift count * 0 (MIPS16OP_*_RZ) (full 6 bit unsigned)
|
||||
"]" 3 bit unsigned shift count * 0 (MIPS16OP_*_RX) (full 6 bit unsigned)
|
||||
"4" 4 bit signed immediate * 0 (MIPS16OP_*_IMM4) (full 15 bit signed)
|
||||
"5" 5 bit unsigned immediate * 0 (MIPS16OP_*_IMM5)
|
||||
"H" 5 bit unsigned immediate * 2 (MIPS16OP_*_IMM5)
|
||||
"W" 5 bit unsigned immediate * 4 (MIPS16OP_*_IMM5)
|
||||
"D" 5 bit unsigned immediate * 8 (MIPS16OP_*_IMM5)
|
||||
"j" 5 bit signed immediate * 0 (MIPS16OP_*_IMM5)
|
||||
"8" 8 bit unsigned immediate * 0 (MIPS16OP_*_IMM8)
|
||||
"V" 8 bit unsigned immediate * 4 (MIPS16OP_*_IMM8)
|
||||
"C" 8 bit unsigned immediate * 8 (MIPS16OP_*_IMM8)
|
||||
"U" 8 bit unsigned immediate * 0 (MIPS16OP_*_IMM8) (full 16 bit unsigned)
|
||||
"k" 8 bit signed immediate * 0 (MIPS16OP_*_IMM8)
|
||||
"K" 8 bit signed immediate * 8 (MIPS16OP_*_IMM8)
|
||||
"p" 8 bit conditional branch address (MIPS16OP_*_IMM8)
|
||||
"q" 11 bit branch address (MIPS16OP_*_IMM11)
|
||||
"A" 8 bit PC relative address * 4 (MIPS16OP_*_IMM8)
|
||||
"B" 5 bit PC relative address * 8 (MIPS16OP_*_IMM5)
|
||||
"E" 5 bit PC relative address * 4 (MIPS16OP_*_IMM5)
|
||||
*/
|
||||
|
||||
/* For the mips16, we use the same opcode table format and a few of
|
||||
the same flags. However, most of the flags are different. */
|
||||
|
||||
/* Modifies the register in MIPS16OP_*_RX. */
|
||||
#define MIPS16_INSN_WRITE_X 0x00000001
|
||||
/* Modifies the register in MIPS16OP_*_RY. */
|
||||
#define MIPS16_INSN_WRITE_Y 0x00000002
|
||||
/* Modifies the register in MIPS16OP_*_RZ. */
|
||||
#define MIPS16_INSN_WRITE_Z 0x00000004
|
||||
/* Modifies the T ($24) register. */
|
||||
#define MIPS16_INSN_WRITE_T 0x00000008
|
||||
/* Modifies the SP ($29) register. */
|
||||
#define MIPS16_INSN_WRITE_SP 0x00000010
|
||||
/* Modifies the RA ($31) register. */
|
||||
#define MIPS16_INSN_WRITE_31 0x00000020
|
||||
/* Modifies the general purpose register in MIPS16OP_*_REG32R. */
|
||||
#define MIPS16_INSN_WRITE_GPR_Y 0x00000040
|
||||
/* Reads the register in MIPS16OP_*_RX. */
|
||||
#define MIPS16_INSN_READ_X 0x00000080
|
||||
/* Reads the register in MIPS16OP_*_RY. */
|
||||
#define MIPS16_INSN_READ_Y 0x00000100
|
||||
/* Reads the register in MIPS16OP_*_MOVE32Z. */
|
||||
#define MIPS16_INSN_READ_Z 0x00000200
|
||||
/* Reads the T ($24) register. */
|
||||
#define MIPS16_INSN_READ_T 0x00000400
|
||||
/* Reads the SP ($29) register. */
|
||||
#define MIPS16_INSN_READ_SP 0x00000800
|
||||
/* Reads the RA ($31) register. */
|
||||
#define MIPS16_INSN_READ_31 0x00001000
|
||||
/* Reads the program counter. */
|
||||
#define MIPS16_INSN_READ_PC 0x00002000
|
||||
/* Reads the general purpose register in MIPS16OP_*_REGR32. */
|
||||
#define MIPS16_INSN_READ_GPR_X 0x00004000
|
||||
/* Is a branch insn. */
|
||||
#define MIPS16_INSN_BRANCH 0x00010000
|
||||
|
||||
/* The following flags have the same value for the mips16 opcode
|
||||
table:
|
||||
INSN_UNCOND_BRANCH_DELAY
|
||||
INSN_COND_BRANCH_DELAY
|
||||
INSN_COND_BRANCH_LIKELY (never used)
|
||||
INSN_READ_HI
|
||||
INSN_READ_LO
|
||||
INSN_WRITE_HI
|
||||
INSN_WRITE_LO
|
||||
INSN_TRAP
|
||||
INSN_ISA3
|
||||
*/
|
||||
|
||||
extern const struct mips_opcode mips16_opcodes[];
|
||||
extern const int bfd_mips16_num_opcodes;
|
||||
|
||||
#endif /* _MIPS_H_ */
|
@ -1,691 +0,0 @@
|
||||
/* tic30.h -- Header file for TI TMS320C30 opcode table
|
||||
Copyright 1998 Free Software Foundation, Inc.
|
||||
Contributed by Steven Haworth (steve@pm.cse.rmit.edu.au)
|
||||
|
||||
This file is part of GDB, GAS, and the GNU binutils.
|
||||
|
||||
GDB, GAS, and the GNU binutils are free software; you can redistribute
|
||||
them and/or modify them under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either version
|
||||
1, or (at your option) any later version.
|
||||
|
||||
GDB, GAS, and the GNU binutils are distributed in the hope that they
|
||||
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 file; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
|
||||
02111-1307, USA. */
|
||||
|
||||
/* FIXME: The opcode table should be in opcodes/tic30-opc.c, not in a
|
||||
header file. */
|
||||
|
||||
#ifndef _TMS320_H_
|
||||
#define _TMS320_H_
|
||||
|
||||
struct _register
|
||||
{
|
||||
char *name;
|
||||
unsigned char opcode;
|
||||
unsigned char regtype;
|
||||
};
|
||||
|
||||
typedef struct _register reg;
|
||||
|
||||
#define REG_Rn 0x01
|
||||
#define REG_ARn 0x02
|
||||
#define REG_DP 0x03
|
||||
#define REG_OTHER 0x04
|
||||
|
||||
static const reg tic30_regtab[] = {
|
||||
{ "r0", 0x00, REG_Rn },
|
||||
{ "r1", 0x01, REG_Rn },
|
||||
{ "r2", 0x02, REG_Rn },
|
||||
{ "r3", 0x03, REG_Rn },
|
||||
{ "r4", 0x04, REG_Rn },
|
||||
{ "r5", 0x05, REG_Rn },
|
||||
{ "r6", 0x06, REG_Rn },
|
||||
{ "r7", 0x07, REG_Rn },
|
||||
{ "ar0",0x08, REG_ARn },
|
||||
{ "ar1",0x09, REG_ARn },
|
||||
{ "ar2",0x0A, REG_ARn },
|
||||
{ "ar3",0x0B, REG_ARn },
|
||||
{ "ar4",0x0C, REG_ARn },
|
||||
{ "ar5",0x0D, REG_ARn },
|
||||
{ "ar6",0x0E, REG_ARn },
|
||||
{ "ar7",0x0F, REG_ARn },
|
||||
{ "dp", 0x10, REG_DP },
|
||||
{ "ir0",0x11, REG_OTHER },
|
||||
{ "ir1",0x12, REG_OTHER },
|
||||
{ "bk", 0x13, REG_OTHER },
|
||||
{ "sp", 0x14, REG_OTHER },
|
||||
{ "st", 0x15, REG_OTHER },
|
||||
{ "ie", 0x16, REG_OTHER },
|
||||
{ "if", 0x17, REG_OTHER },
|
||||
{ "iof",0x18, REG_OTHER },
|
||||
{ "rs", 0x19, REG_OTHER },
|
||||
{ "re", 0x1A, REG_OTHER },
|
||||
{ "rc", 0x1B, REG_OTHER },
|
||||
{ "R0", 0x00, REG_Rn },
|
||||
{ "R1", 0x01, REG_Rn },
|
||||
{ "R2", 0x02, REG_Rn },
|
||||
{ "R3", 0x03, REG_Rn },
|
||||
{ "R4", 0x04, REG_Rn },
|
||||
{ "R5", 0x05, REG_Rn },
|
||||
{ "R6", 0x06, REG_Rn },
|
||||
{ "R7", 0x07, REG_Rn },
|
||||
{ "AR0",0x08, REG_ARn },
|
||||
{ "AR1",0x09, REG_ARn },
|
||||
{ "AR2",0x0A, REG_ARn },
|
||||
{ "AR3",0x0B, REG_ARn },
|
||||
{ "AR4",0x0C, REG_ARn },
|
||||
{ "AR5",0x0D, REG_ARn },
|
||||
{ "AR6",0x0E, REG_ARn },
|
||||
{ "AR7",0x0F, REG_ARn },
|
||||
{ "DP", 0x10, REG_DP },
|
||||
{ "IR0",0x11, REG_OTHER },
|
||||
{ "IR1",0x12, REG_OTHER },
|
||||
{ "BK", 0x13, REG_OTHER },
|
||||
{ "SP", 0x14, REG_OTHER },
|
||||
{ "ST", 0x15, REG_OTHER },
|
||||
{ "IE", 0x16, REG_OTHER },
|
||||
{ "IF", 0x17, REG_OTHER },
|
||||
{ "IOF",0x18, REG_OTHER },
|
||||
{ "RS", 0x19, REG_OTHER },
|
||||
{ "RE", 0x1A, REG_OTHER },
|
||||
{ "RC", 0x1B, REG_OTHER },
|
||||
{ "", 0, 0 }
|
||||
};
|
||||
|
||||
static const reg *const tic30_regtab_end
|
||||
= tic30_regtab + sizeof(tic30_regtab)/sizeof(tic30_regtab[0]);
|
||||
|
||||
/* Indirect Addressing Modes Modification Fields */
|
||||
/* Indirect Addressing with Displacement */
|
||||
#define PreDisp_Add 0x00
|
||||
#define PreDisp_Sub 0x01
|
||||
#define PreDisp_Add_Mod 0x02
|
||||
#define PreDisp_Sub_Mod 0x03
|
||||
#define PostDisp_Add_Mod 0x04
|
||||
#define PostDisp_Sub_Mod 0x05
|
||||
#define PostDisp_Add_Circ 0x06
|
||||
#define PostDisp_Sub_Circ 0x07
|
||||
/* Indirect Addressing with Index Register IR0 */
|
||||
#define PreIR0_Add 0x08
|
||||
#define PreIR0_Sub 0x09
|
||||
#define PreIR0_Add_Mod 0x0A
|
||||
#define PreIR0_Sub_Mod 0x0B
|
||||
#define PostIR0_Add_Mod 0x0C
|
||||
#define PostIR0_Sub_Mod 0x0D
|
||||
#define PostIR0_Add_Circ 0x0E
|
||||
#define PostIR0_Sub_Circ 0x0F
|
||||
/* Indirect Addressing with Index Register IR1 */
|
||||
#define PreIR1_Add 0x10
|
||||
#define PreIR1_Sub 0x11
|
||||
#define PreIR1_Add_Mod 0x12
|
||||
#define PreIR1_Sub_Mod 0x13
|
||||
#define PostIR1_Add_Mod 0x14
|
||||
#define PostIR1_Sub_Mod 0x15
|
||||
#define PostIR1_Add_Circ 0x16
|
||||
#define PostIR1_Sub_Circ 0x17
|
||||
/* Indirect Addressing (Special Cases) */
|
||||
#define IndirectOnly 0x18
|
||||
#define PostIR0_Add_BitRev 0x19
|
||||
|
||||
typedef struct {
|
||||
char *syntax;
|
||||
unsigned char modfield;
|
||||
unsigned char displacement;
|
||||
} ind_addr_type;
|
||||
|
||||
#define IMPLIED_DISP 0x01
|
||||
#define DISP_REQUIRED 0x02
|
||||
#define NO_DISP 0x03
|
||||
|
||||
static const ind_addr_type tic30_indaddr_tab[] = {
|
||||
{ "*+ar", PreDisp_Add, IMPLIED_DISP },
|
||||
{ "*-ar", PreDisp_Sub, IMPLIED_DISP },
|
||||
{ "*++ar", PreDisp_Add_Mod, IMPLIED_DISP },
|
||||
{ "*--ar", PreDisp_Sub_Mod, IMPLIED_DISP },
|
||||
{ "*ar++", PostDisp_Add_Mod, IMPLIED_DISP },
|
||||
{ "*ar--", PostDisp_Sub_Mod, IMPLIED_DISP },
|
||||
{ "*ar++%", PostDisp_Add_Circ, IMPLIED_DISP },
|
||||
{ "*ar--%", PostDisp_Sub_Circ, IMPLIED_DISP },
|
||||
{ "*+ar()", PreDisp_Add, DISP_REQUIRED },
|
||||
{ "*-ar()", PreDisp_Sub, DISP_REQUIRED },
|
||||
{ "*++ar()", PreDisp_Add_Mod, DISP_REQUIRED },
|
||||
{ "*--ar()", PreDisp_Sub_Mod, DISP_REQUIRED },
|
||||
{ "*ar++()", PostDisp_Add_Mod, DISP_REQUIRED },
|
||||
{ "*ar--()", PostDisp_Sub_Mod, DISP_REQUIRED },
|
||||
{ "*ar++()%", PostDisp_Add_Circ, DISP_REQUIRED },
|
||||
{ "*ar--()%", PostDisp_Sub_Circ, DISP_REQUIRED },
|
||||
{ "*+ar(ir0)", PreIR0_Add, NO_DISP },
|
||||
{ "*-ar(ir0)", PreIR0_Sub, NO_DISP },
|
||||
{ "*++ar(ir0)", PreIR0_Add_Mod, NO_DISP },
|
||||
{ "*--ar(ir0)", PreIR0_Sub_Mod, NO_DISP },
|
||||
{ "*ar++(ir0)", PostIR0_Add_Mod, NO_DISP },
|
||||
{ "*ar--(ir0)", PostIR0_Sub_Mod, NO_DISP },
|
||||
{ "*ar++(ir0)%",PostIR0_Add_Circ, NO_DISP },
|
||||
{ "*ar--(ir0)%",PostIR0_Sub_Circ, NO_DISP },
|
||||
{ "*+ar(ir1)", PreIR1_Add, NO_DISP },
|
||||
{ "*-ar(ir1)", PreIR1_Sub, NO_DISP },
|
||||
{ "*++ar(ir1)", PreIR1_Add_Mod, NO_DISP },
|
||||
{ "*--ar(ir1)", PreIR1_Sub_Mod, NO_DISP },
|
||||
{ "*ar++(ir1)", PostIR1_Add_Mod, NO_DISP },
|
||||
{ "*ar--(ir1)", PostIR1_Sub_Mod, NO_DISP },
|
||||
{ "*ar++(ir1)%",PostIR1_Add_Circ, NO_DISP },
|
||||
{ "*ar--(ir1)%",PostIR1_Sub_Circ, NO_DISP },
|
||||
{ "*ar", IndirectOnly, NO_DISP },
|
||||
{ "*ar++(ir0)b",PostIR0_Add_BitRev, NO_DISP },
|
||||
{ "", 0,0 }
|
||||
};
|
||||
|
||||
static const ind_addr_type *const tic30_indaddrtab_end
|
||||
= tic30_indaddr_tab + sizeof(tic30_indaddr_tab)/sizeof(tic30_indaddr_tab[0]);
|
||||
|
||||
/* Possible operand types */
|
||||
/* Register types */
|
||||
#define Rn 0x0001
|
||||
#define ARn 0x0002
|
||||
#define DPReg 0x0004
|
||||
#define OtherReg 0x0008
|
||||
/* Addressing mode types */
|
||||
#define Direct 0x0010
|
||||
#define Indirect 0x0020
|
||||
#define Imm16 0x0040
|
||||
#define Disp 0x0080
|
||||
#define Imm24 0x0100
|
||||
#define Abs24 0x0200
|
||||
/* 3 operand addressing mode types */
|
||||
#define op3T1 0x0400
|
||||
#define op3T2 0x0800
|
||||
/* Interrupt vector */
|
||||
#define IVector 0x1000
|
||||
/* Not required */
|
||||
#define NotReq 0x2000
|
||||
|
||||
#define GAddr1 Rn | Direct | Indirect | Imm16
|
||||
#define GAddr2 GAddr1 | AllReg
|
||||
#define TAddr1 op3T1 | Rn | Indirect
|
||||
#define TAddr2 op3T2 | Rn | Indirect
|
||||
#define Reg Rn | ARn
|
||||
#define AllReg Reg | DPReg | OtherReg
|
||||
|
||||
typedef struct _template
|
||||
{
|
||||
char *name;
|
||||
unsigned int operands; /* how many operands */
|
||||
unsigned int base_opcode; /* base_opcode is the fundamental opcode byte */
|
||||
/* the bits in opcode_modifier are used to generate the final opcode from
|
||||
the base_opcode. These bits also are used to detect alternate forms of
|
||||
the same instruction */
|
||||
unsigned int opcode_modifier;
|
||||
|
||||
/* opcode_modifier bits: */
|
||||
#define AddressMode 0x00600000
|
||||
#define PCRel 0x02000000
|
||||
#define StackOp 0x001F0000
|
||||
#define Rotate StackOp
|
||||
|
||||
/* operand_types[i] describes the type of operand i. This is made
|
||||
by OR'ing together all of the possible type masks. (e.g.
|
||||
'operand_types[i] = Reg|Imm' specifies that operand i can be
|
||||
either a register or an immediate operand */
|
||||
unsigned int operand_types[3];
|
||||
/* This defines the number type of an immediate argument to an instruction. */
|
||||
int imm_arg_type;
|
||||
#define Imm_None 0
|
||||
#define Imm_Float 1
|
||||
#define Imm_SInt 2
|
||||
#define Imm_UInt 3
|
||||
}
|
||||
template;
|
||||
|
||||
static const template tic30_optab[] = {
|
||||
{ "absf" ,2,0x00000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "absi" ,2,0x00800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "addc" ,2,0x01000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "addc3" ,3,0x20000000,AddressMode, { TAddr1|AllReg, TAddr2|AllReg, AllReg }, Imm_None },
|
||||
{ "addf" ,2,0x01800000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "addf3" ,3,0x20800000,AddressMode, { TAddr1, TAddr2, Rn }, Imm_None },
|
||||
{ "addi" ,2,0x02000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "addi3" ,3,0x21000000,AddressMode, { TAddr1|AllReg, TAddr2|AllReg, AllReg }, Imm_None },
|
||||
{ "and" ,2,0x02800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_UInt },
|
||||
{ "and3" ,3,0x21800000,AddressMode, { TAddr1|AllReg, TAddr2|AllReg, AllReg }, Imm_None },
|
||||
{ "andn" ,2,0x03000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_UInt },
|
||||
{ "andn3" ,3,0x22000000,AddressMode, { TAddr1|AllReg, TAddr2|AllReg, AllReg }, Imm_None },
|
||||
{ "ash" ,2,0x03800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ash3" ,3,0x22800000,AddressMode, { TAddr1|AllReg, TAddr2|AllReg, AllReg }, Imm_None },
|
||||
{ "b" ,1,0x68000000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bu" ,1,0x68000000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "blo" ,1,0x68010000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bls" ,1,0x68020000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bhi" ,1,0x68030000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bhs" ,1,0x68040000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "beq" ,1,0x68050000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bne" ,1,0x68060000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "blt" ,1,0x68070000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "ble" ,1,0x68080000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bgt" ,1,0x68090000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bge" ,1,0x680A0000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bz" ,1,0x68050000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bnz" ,1,0x68060000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bp" ,1,0x68090000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bn" ,1,0x68070000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bnn" ,1,0x680A0000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bnv" ,1,0x680C0000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bv" ,1,0x680D0000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bnuf" ,1,0x680E0000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "buf" ,1,0x680F0000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bnc" ,1,0x68040000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bc" ,1,0x68010000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bnlv" ,1,0x68100000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "blv" ,1,0x68110000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bnluf" ,1,0x68120000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bluf" ,1,0x68130000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bzuf" ,1,0x68140000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bd" ,1,0x68200000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bud" ,1,0x68200000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "blod" ,1,0x68210000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "blsd" ,1,0x68220000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bhid" ,1,0x68230000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bhsd" ,1,0x68240000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "beqd" ,1,0x68250000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bned" ,1,0x68260000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bltd" ,1,0x68270000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bled" ,1,0x68280000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bgtd" ,1,0x68290000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bged" ,1,0x682A0000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bzd" ,1,0x68250000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bnzd" ,1,0x68260000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bpd" ,1,0x68290000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bnd" ,1,0x68270000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bnnd" ,1,0x682A0000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bnvd" ,1,0x682C0000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bvd" ,1,0x682D0000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bnufd" ,1,0x682E0000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bufd" ,1,0x682F0000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bncd" ,1,0x68240000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bcd" ,1,0x68210000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bnlvd" ,1,0x68300000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "blvd" ,1,0x68310000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bnlufd" ,1,0x68320000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "blufd" ,1,0x68330000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "bzufd" ,1,0x68340000,PCRel, { AllReg|Disp, 0, 0 }, Imm_None },
|
||||
{ "br" ,1,0x60000000,0, { Imm24, 0, 0 }, Imm_UInt },
|
||||
{ "brd" ,1,0x61000000,0, { Imm24, 0, 0 }, Imm_UInt },
|
||||
{ "call" ,1,0x62000000,0, { Imm24, 0, 0 }, Imm_UInt },
|
||||
{ "callu" ,1,0x70000000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "calllo" ,1,0x70010000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "callls" ,1,0x70020000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "callhi" ,1,0x70030000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "callhs" ,1,0x70040000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "calleq" ,1,0x70050000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "callne" ,1,0x70060000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "calllt" ,1,0x70070000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "callle" ,1,0x70080000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "callgt" ,1,0x70090000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "callge" ,1,0x700A0000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "callz" ,1,0x70050000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "callnz" ,1,0x70060000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "callp" ,1,0x70090000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "calln" ,1,0x70070000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "callnn" ,1,0x700A0000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "callnv" ,1,0x700C0000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "callv" ,1,0x700D0000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "callnuf",1,0x700E0000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "calluf" ,1,0x700F0000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "callnc" ,1,0x70040000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "callc" ,1,0x70010000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "callnlv",1,0x70100000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "calllv" ,1,0x70110000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "callnluf",1,0x70120000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "callluf",1,0x70130000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "callzuf",1,0x70140000,PCRel, { AllReg|Disp, 0, 0 }, Imm_UInt },
|
||||
{ "cmpf" ,2,0x04000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "cmpf3" ,2,0x23000000,AddressMode, { TAddr1, TAddr2, 0 }, Imm_None },
|
||||
{ "cmpi" ,2,0x04800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "cmpi3" ,2,0x23800000,AddressMode, { TAddr1|AllReg, TAddr2|AllReg, 0 }, Imm_None },
|
||||
{ "db" ,2,0x6C000000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbu" ,2,0x6C000000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dblo" ,2,0x6C010000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbls" ,2,0x6C020000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbhi" ,2,0x6C030000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbhs" ,2,0x6C040000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbeq" ,2,0x6C050000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbne" ,2,0x6C060000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dblt" ,2,0x6C070000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dble" ,2,0x6C080000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbgt" ,2,0x6C090000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbge" ,2,0x6C0A0000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbz" ,2,0x6C050000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbnz" ,2,0x6C060000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbp" ,2,0x6C090000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbn" ,2,0x6C070000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbnn" ,2,0x6C0A0000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbnv" ,2,0x6C0C0000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbv" ,2,0x6C0D0000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbnuf" ,2,0x6C0E0000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbuf" ,2,0x6C0F0000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbnc" ,2,0x6C040000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbc" ,2,0x6C010000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbnlv" ,2,0x6C100000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dblv" ,2,0x6C110000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbnluf" ,2,0x6C120000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbluf" ,2,0x6C130000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbzuf" ,2,0x6C140000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbd" ,2,0x6C200000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbud" ,2,0x6C200000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dblod" ,2,0x6C210000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dblsd" ,2,0x6C220000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbhid" ,2,0x6C230000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbhsd" ,2,0x6C240000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbeqd" ,2,0x6C250000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbned" ,2,0x6C260000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbltd" ,2,0x6C270000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbled" ,2,0x6C280000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbgtd" ,2,0x6C290000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbged" ,2,0x6C2A0000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbzd" ,2,0x6C250000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbnzd" ,2,0x6C260000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbpd" ,2,0x6C290000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbnd" ,2,0x6C270000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbnnd" ,2,0x6C2A0000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbnvd" ,2,0x6C2C0000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbvd" ,2,0x6C2D0000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbnufd" ,2,0x6C2E0000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbufd" ,2,0x6C2F0000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbncd" ,2,0x6C240000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbcd" ,2,0x6C210000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbnlvd" ,2,0x6C300000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dblvd" ,2,0x6C310000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbnlufd",2,0x6C320000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dblufd" ,2,0x6C330000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "dbzufd" ,2,0x6C340000,PCRel, { ARn, AllReg|Disp, 0 }, Imm_None },
|
||||
{ "fix" ,2,0x05000000,AddressMode, { GAddr1, AllReg, 0 }, Imm_Float },
|
||||
{ "float" ,2,0x05800000,AddressMode, { GAddr2, Rn, 0 }, Imm_SInt },
|
||||
{ "iack" ,1,0x1B000000,AddressMode, { Direct|Indirect, 0, 0 }, Imm_None },
|
||||
{ "idle" ,0,0x06000000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "idle2" ,0,0x06000001,0, { 0, 0, 0 }, Imm_None }, /* LC31 Only */
|
||||
{ "lde" ,2,0x06800000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldf" ,2,0x07000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfu" ,2,0x40000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldflo" ,2,0x40800000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfls" ,2,0x41000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfhi" ,2,0x41800000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfhs" ,2,0x42000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfeq" ,2,0x42800000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfne" ,2,0x43000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldflt" ,2,0x43800000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfle" ,2,0x44000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfgt" ,2,0x44800000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfge" ,2,0x45000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfz" ,2,0x42800000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfnz" ,2,0x43000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfp" ,2,0x44800000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfn" ,2,0x43800000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfnn" ,2,0x45000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfnv" ,2,0x46000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfv" ,2,0x46800000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfnuf" ,2,0x47000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfuf" ,2,0x47800000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfnc" ,2,0x42000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfc" ,2,0x40800000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfnlv" ,2,0x48000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldflv" ,2,0x48800000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfnluf",2,0x49000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfluf" ,2,0x49800000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfzuf" ,2,0x4A000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldfi" ,2,0x07800000,AddressMode, { Direct|Indirect, Rn, 0 }, Imm_None },
|
||||
{ "ldi" ,2,0x08000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldiu" ,2,0x50000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldilo" ,2,0x50800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldils" ,2,0x51000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldihi" ,2,0x51800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldihs" ,2,0x52000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldieq" ,2,0x52800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldine" ,2,0x53000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldilt" ,2,0x53800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldile" ,2,0x54000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldigt" ,2,0x54800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldige" ,2,0x55000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldiz" ,2,0x52800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldinz" ,2,0x53000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldip" ,2,0x54800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldin" ,2,0x53800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldinn" ,2,0x55000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldinv" ,2,0x56000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldiv" ,2,0x56800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldinuf" ,2,0x57000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldiuf" ,2,0x57800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldinc" ,2,0x52000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldic" ,2,0x50800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldinlv" ,2,0x58000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldilv" ,2,0x58800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldinluf",2,0x59000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldiluf" ,2,0x59800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldizuf" ,2,0x5A000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "ldii" ,2,0x08800000,AddressMode, { Direct|Indirect, AllReg, 0 }, Imm_None },
|
||||
{ "ldm" ,2,0x09000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "ldp" ,2,0x08700000,0, { Abs24|Direct, DPReg|NotReq, 0 }, Imm_UInt },
|
||||
{ "lopower",0,0x10800001,0, { 0, 0, 0 }, Imm_None }, /* LC31 Only */
|
||||
{ "lsh" ,2,0x09800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_UInt },
|
||||
{ "lsh3" ,3,0x24000000,AddressMode, { TAddr1|AllReg, TAddr2|AllReg, AllReg }, Imm_None },
|
||||
{ "maxspeed",0,0x10800000,0, { 0, 0, 0 }, Imm_None }, /* LC31 Only */
|
||||
{ "mpyf" ,2,0x0A000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "mpyf3" ,3,0x24800000,AddressMode, { TAddr1, TAddr2, Rn }, Imm_None },
|
||||
{ "mpyi" ,2,0x0A800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "mpyi3" ,3,0x25000000,AddressMode, { TAddr1|AllReg, TAddr2|AllReg, AllReg }, Imm_None },
|
||||
{ "negb" ,2,0x0B000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "negf" ,2,0x0B800000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "negi" ,2,0x0C000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "nop" ,1,0x0C800000,AddressMode, { AllReg|Indirect|NotReq, 0, 0 }, Imm_None },
|
||||
{ "norm" ,2,0x0D000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float }, /*Check another source*/
|
||||
{ "not" ,2,0x0D800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_UInt },
|
||||
{ "or" ,2,0x10000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_UInt },
|
||||
{ "or3" ,3,0x25800000,AddressMode, { TAddr1|AllReg, TAddr2|AllReg, AllReg }, Imm_None },
|
||||
{ "pop" ,1,0x0E200000,StackOp, { AllReg, 0, 0 }, Imm_None },
|
||||
{ "popf" ,1,0x0EA00000,StackOp, { Rn, 0, 0 }, Imm_None },
|
||||
{ "push" ,1,0x0F200000,StackOp, { AllReg, 0, 0 }, Imm_None },
|
||||
{ "pushf" ,1,0x0FA00000,StackOp, { Rn, 0, 0 }, Imm_None },
|
||||
{ "reti" ,0,0x78000000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retiu" ,0,0x78000000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retilo" ,0,0x78010000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retils" ,0,0x78020000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retihi" ,0,0x78030000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retihs" ,0,0x78040000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retieq" ,0,0x78050000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retine" ,0,0x78060000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retilt" ,0,0x78070000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retile" ,0,0x78080000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retigt" ,0,0x78090000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retige" ,0,0x780A0000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retiz" ,0,0x78050000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retinz" ,0,0x78060000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retip" ,0,0x78090000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retin" ,0,0x78070000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retinn" ,0,0x780A0000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retinv" ,0,0x780C0000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retiv" ,0,0x780D0000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retinuf",0,0x780E0000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retiuf" ,0,0x780F0000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retinc" ,0,0x78040000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retic" ,0,0x78010000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retinlv",0,0x78100000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retilv" ,0,0x78110000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retinluf",0,0x78120000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retiluf",0,0x78130000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retizuf",0,0x78140000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "rets" ,0,0x78800000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retsu" ,0,0x78800000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retslo" ,0,0x78810000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retsls" ,0,0x78820000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retshi" ,0,0x78830000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retshs" ,0,0x78840000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retseq" ,0,0x78850000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retsne" ,0,0x78860000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retslt" ,0,0x78870000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retsle" ,0,0x78880000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retsgt" ,0,0x78890000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retsge" ,0,0x788A0000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retsz" ,0,0x78850000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retsnz" ,0,0x78860000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retsp" ,0,0x78890000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retsn" ,0,0x78870000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retsnn" ,0,0x788A0000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retsnv" ,0,0x788C0000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retsv" ,0,0x788D0000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retsnuf",0,0x788E0000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retsuf" ,0,0x788F0000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retsnc" ,0,0x78840000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retsc" ,0,0x78810000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retsnlv",0,0x78900000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retslv" ,0,0x78910000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retsnluf",0,0x78920000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retsluf",0,0x78930000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "retszuf",0,0x78940000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "rnd" ,2,0x11000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "rol" ,1,0x11E00001,Rotate, { AllReg, 0, 0 }, Imm_None },
|
||||
{ "rolc" ,1,0x12600001,Rotate, { AllReg, 0, 0 }, Imm_None },
|
||||
{ "ror" ,1,0x12E0FFFF,Rotate, { AllReg, 0, 0 }, Imm_None },
|
||||
{ "rorc" ,1,0x1360FFFF,Rotate, { AllReg, 0, 0 }, Imm_None },
|
||||
{ "rptb" ,1,0x64000000,0, { Imm24, 0, 0 }, Imm_UInt },
|
||||
{ "rpts" ,1,0x139B0000,AddressMode, { GAddr2, 0, 0 }, Imm_UInt },
|
||||
{ "sigi" ,0,0x16000000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "stf" ,2,0x14000000,AddressMode, { Rn, Direct|Indirect, 0 }, Imm_Float },
|
||||
{ "stfi" ,2,0x14800000,AddressMode, { Rn, Direct|Indirect, 0 }, Imm_Float },
|
||||
{ "sti" ,2,0x15000000,AddressMode, { AllReg, Direct|Indirect, 0 }, Imm_SInt },
|
||||
{ "stii" ,2,0x15800000,AddressMode, { AllReg, Direct|Indirect, 0 }, Imm_SInt },
|
||||
{ "subb" ,2,0x16800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "subb3" ,3,0x26000000,AddressMode, { TAddr1|AllReg, TAddr2|AllReg, AllReg }, Imm_None },
|
||||
{ "subc" ,2,0x17000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_UInt },
|
||||
{ "subf" ,2,0x17800000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "subf3" ,3,0x26800000,AddressMode, { TAddr1, TAddr2, Rn }, Imm_None },
|
||||
{ "subi" ,2,0x18000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "subi3" ,3,0x27000000,AddressMode, { TAddr1|AllReg, TAddr2|AllReg, AllReg }, Imm_None },
|
||||
{ "subrb" ,2,0x18800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "subrf" ,2,0x19000000,AddressMode, { GAddr1, Rn, 0 }, Imm_Float },
|
||||
{ "subri" ,2,0x19800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_SInt },
|
||||
{ "swi" ,0,0x66000000,0, { 0, 0, 0 }, Imm_None },
|
||||
{ "trap" ,1,0x74800020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "trapu" ,1,0x74800020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "traplo" ,1,0x74810020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "trapls" ,1,0x74820020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "traphi" ,1,0x74830020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "traphs" ,1,0x74840020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "trapeq" ,1,0x74850020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "trapne" ,1,0x74860020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "traplt" ,1,0x74870020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "traple" ,1,0x74880020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "trapgt" ,1,0x74890020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "trapge" ,1,0x748A0020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "trapz" ,1,0x74850020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "trapnz" ,1,0x74860020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "trapp" ,1,0x74890020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "trapn" ,1,0x74870020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "trapnn" ,1,0x748A0020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "trapnv" ,1,0x748C0020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "trapv" ,1,0x748D0020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "trapnuf",1,0x748E0020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "trapuf" ,1,0x748F0020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "trapnc" ,1,0x74840020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "trapc" ,1,0x74810020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "trapnlv",1,0x74900020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "traplv" ,1,0x74910020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "trapnluf",1,0x74920020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "trapluf",1,0x74930020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "trapzuf",1,0x74940020,0, { IVector, 0, 0 }, Imm_None },
|
||||
{ "tstb" ,2,0x1A000000,AddressMode, { GAddr2, AllReg, 0 }, Imm_UInt },
|
||||
{ "tstb3" ,2,0x27800000,AddressMode, { TAddr1|AllReg, TAddr2|AllReg, 0 }, Imm_None },
|
||||
{ "xor" ,2,0x1A800000,AddressMode, { GAddr2, AllReg, 0 }, Imm_UInt },
|
||||
{ "xor3" ,3,0x28000000,AddressMode, { TAddr1|AllReg, TAddr2|AllReg, AllReg }, Imm_None },
|
||||
{ "" ,0,0x00000000,0, { 0, 0, 0 }, 0 }
|
||||
};
|
||||
|
||||
static const template *const tic30_optab_end =
|
||||
tic30_optab + sizeof(tic30_optab)/sizeof(tic30_optab[0]);
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
unsigned int operands_1;
|
||||
unsigned int operands_2;
|
||||
unsigned int base_opcode;
|
||||
unsigned int operand_types[2][3];
|
||||
/* Which operand fits into which part of the final opcode word. */
|
||||
int oporder;
|
||||
} partemplate;
|
||||
|
||||
/* oporder defines - not very descriptive. */
|
||||
#define OO_4op1 0
|
||||
#define OO_4op2 1
|
||||
#define OO_4op3 2
|
||||
#define OO_5op1 3
|
||||
#define OO_5op2 4
|
||||
#define OO_PField 5
|
||||
|
||||
static const partemplate tic30_paroptab[] = {
|
||||
{ "q_absf_stf", 2,2,0xC8000000, { { Indirect, Rn, 0 }, { Rn, Indirect, 0 } },
|
||||
OO_4op1 },
|
||||
{ "q_absi_sti", 2,2,0xCA000000, { { Indirect, Rn, 0 }, { Rn, Indirect, 0 } },
|
||||
OO_4op1 },
|
||||
{ "q_addf3_stf", 3,2,0xCC000000, { { Indirect, Rn, Rn }, { Rn, Indirect, 0 } },
|
||||
OO_5op1 },
|
||||
{ "q_addi3_sti", 3,2,0xCE000000, { { Indirect, Rn, Rn }, { Rn, Indirect, 0 } },
|
||||
OO_5op1 },
|
||||
{ "q_and3_sti", 3,2,0xD0000000, { { Indirect, Rn, Rn }, { Rn, Indirect, 0 } },
|
||||
OO_5op1 },
|
||||
{ "q_ash3_sti", 3,2,0xD2000000, { { Rn, Indirect, Rn }, { Rn, Indirect, 0 } },
|
||||
OO_5op2 },
|
||||
{ "q_fix_sti", 2,2,0xD4000000, { { Indirect, Rn, 0 }, { Rn, Indirect, 0 } },
|
||||
OO_4op1 },
|
||||
{ "q_float_stf", 2,2,0xD6000000, { { Indirect, Rn, 0 }, { Rn, Indirect, 0 } },
|
||||
OO_4op1 },
|
||||
{ "q_ldf_ldf", 2,2,0xC4000000, { { Indirect, Rn, 0 }, { Indirect, Rn, 0 } },
|
||||
OO_4op2 },
|
||||
{ "q_ldf_stf", 2,2,0xD8000000, { { Indirect, Rn, 0 }, { Rn, Indirect, 0 } },
|
||||
OO_4op1 },
|
||||
{ "q_ldi_ldi", 2,2,0xC6000000, { { Indirect, Rn, 0 }, { Indirect, Rn, 0 } },
|
||||
OO_4op2 },
|
||||
{ "q_ldi_sti", 2,2,0xDA000000, { { Indirect, Rn, 0 }, { Rn, Indirect, 0 } },
|
||||
OO_4op1 },
|
||||
{ "q_lsh3_sti", 3,2,0xDC000000, { { Rn, Indirect, Rn }, { Rn, Indirect, 0 } },
|
||||
OO_5op2 },
|
||||
{ "q_mpyf3_addf3",3,3,0x80000000, { { Rn | Indirect, Rn | Indirect, Rn },
|
||||
{ Rn | Indirect, Rn | Indirect, Rn } }, OO_PField },
|
||||
{ "q_mpyf3_stf", 3,2,0xDE000000, { { Indirect, Rn, Rn }, { Rn, Indirect, 0 } },
|
||||
OO_5op1 },
|
||||
{ "q_mpyf3_subf3",3,3,0x84000000, { { Rn | Indirect, Rn | Indirect, Rn },
|
||||
{ Rn | Indirect, Rn | Indirect, Rn } }, OO_PField },
|
||||
{ "q_mpyi3_addi3",3,3,0x88000000, { { Rn | Indirect, Rn | Indirect, Rn },
|
||||
{ Rn | Indirect, Rn | Indirect, Rn } }, OO_PField },
|
||||
{ "q_mpyi3_sti", 3,2,0xE0000000, { { Indirect, Rn, Rn }, { Rn, Indirect, 0 } },
|
||||
OO_5op1 },
|
||||
{ "q_mpyi3_subi3",3,3,0x8C000000, { { Rn | Indirect, Rn | Indirect, Rn },
|
||||
{ Rn | Indirect, Rn | Indirect, Rn } }, OO_PField },
|
||||
{ "q_negf_stf", 2,2,0xE2000000, { { Indirect, Rn, 0 }, { Rn, Indirect, 0 } },
|
||||
OO_4op1 },
|
||||
{ "q_negi_sti", 2,2,0xE4000000, { { Indirect, Rn, 0 }, { Rn, Indirect, 0 } },
|
||||
OO_4op1 },
|
||||
{ "q_not_sti", 2,2,0xE6000000, { { Indirect, Rn, 0 }, { Rn, Indirect, 0 } },
|
||||
OO_4op1 },
|
||||
{ "q_or3_sti", 3,2,0xE8000000, { { Indirect, Rn, Rn }, { Rn, Indirect, 0 } },
|
||||
OO_5op1 },
|
||||
{ "q_stf_stf", 2,2,0xC0000000, { { Rn, Indirect, 0 }, { Rn, Indirect, 0 } },
|
||||
OO_4op3 },
|
||||
{ "q_sti_sti", 2,2,0xC2000000, { { Rn, Indirect, 0 }, { Rn, Indirect, 0 } },
|
||||
OO_4op3 },
|
||||
{ "q_subf3_stf", 3,2,0xEA000000, { { Rn, Indirect, Rn }, { Rn, Indirect, 0 } },
|
||||
OO_5op2 },
|
||||
{ "q_subi3_sti", 3,2,0xEC000000, { { Rn, Indirect, Rn }, { Rn, Indirect, 0 } },
|
||||
OO_5op2 },
|
||||
{ "q_xor3_sti", 3,2,0xEE000000, { { Indirect, Rn, Rn }, { Rn, Indirect, 0 } },
|
||||
OO_5op1 },
|
||||
{ "", 0,0,0x00000000, { { 0, 0, 0 }, { 0, 0, 0 } }, 0 }
|
||||
};
|
||||
|
||||
static const partemplate *const tic30_paroptab_end =
|
||||
tic30_paroptab + sizeof(tic30_paroptab)/sizeof(tic30_paroptab[0]);
|
||||
|
||||
#endif
|
@ -1,165 +0,0 @@
|
||||
/* v850.h -- Header file for NEC V850 opcode table
|
||||
Copyright 1996, 1997, 2001 Free Software Foundation, Inc.
|
||||
Written by J.T. Conklin, Cygnus Support
|
||||
|
||||
This file is part of GDB, GAS, and the GNU binutils.
|
||||
|
||||
GDB, GAS, and the GNU binutils are free software; you can redistribute
|
||||
them and/or modify them under the terms of the GNU General Public
|
||||
License as published by the Free Software Foundation; either version
|
||||
1, or (at your option) any later version.
|
||||
|
||||
GDB, GAS, and the GNU binutils are distributed in the hope that they
|
||||
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 file; see the file COPYING. If not, write to the Free
|
||||
Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
#ifndef V850_H
|
||||
#define V850_H
|
||||
|
||||
/* The opcode table is an array of struct v850_opcode. */
|
||||
|
||||
struct v850_opcode
|
||||
{
|
||||
/* The opcode name. */
|
||||
const char *name;
|
||||
|
||||
/* The opcode itself. Those bits which will be filled in with
|
||||
operands are zeroes. */
|
||||
unsigned long opcode;
|
||||
|
||||
/* The opcode mask. This is used by the disassembler. This is a
|
||||
mask containing ones indicating those bits which must match the
|
||||
opcode field, and zeroes indicating those bits which need not
|
||||
match (and are presumably filled in by operands). */
|
||||
unsigned long mask;
|
||||
|
||||
/* An array of operand codes. Each code is an index into the
|
||||
operand table. They appear in the order which the operands must
|
||||
appear in assembly code, and are terminated by a zero. */
|
||||
unsigned char operands[8];
|
||||
|
||||
/* Which (if any) operand is a memory operand. */
|
||||
unsigned int memop;
|
||||
|
||||
/* Target processor(s). A bit field of processors which support
|
||||
this instruction. Note a bit field is used as some instructions
|
||||
are available on multiple, different processor types, whereas
|
||||
other instructions are only available on one specific type. */
|
||||
unsigned int processors;
|
||||
};
|
||||
|
||||
/* Values for the processors field in the v850_opcode structure. */
|
||||
#define PROCESSOR_V850 (1 << 0) /* Just the V850. */
|
||||
#define PROCESSOR_ALL -1 /* Any processor. */
|
||||
#define PROCESSOR_V850E (1 << 1) /* Just the V850E. */
|
||||
#define PROCESSOR_NOT_V850 (~ PROCESSOR_V850) /* Any processor except the V850. */
|
||||
#define PROCESSOR_V850EA (1 << 2) /* Just the V850EA. */
|
||||
|
||||
/* The table itself is sorted by major opcode number, and is otherwise
|
||||
in the order in which the disassembler should consider
|
||||
instructions. */
|
||||
extern const struct v850_opcode v850_opcodes[];
|
||||
extern const int v850_num_opcodes;
|
||||
|
||||
|
||||
/* The operands table is an array of struct v850_operand. */
|
||||
|
||||
struct v850_operand
|
||||
{
|
||||
/* The number of bits in the operand. */
|
||||
/* If this value is -1 then the operand's bits are in a discontinous distribution in the instruction. */
|
||||
int bits;
|
||||
|
||||
/* (bits >= 0): How far the operand is left shifted in the instruction. */
|
||||
/* (bits == -1): Bit mask of the bits in the operand. */
|
||||
int shift;
|
||||
|
||||
/* Insertion function. This is used by the assembler. To insert an
|
||||
operand value into an instruction, check this field.
|
||||
|
||||
If it is NULL, execute
|
||||
i |= (op & ((1 << o->bits) - 1)) << o->shift;
|
||||
(i is the instruction which we are filling in, o is a pointer to
|
||||
this structure, and op is the opcode value; this assumes twos
|
||||
complement arithmetic).
|
||||
|
||||
If this field is not NULL, then simply call it with the
|
||||
instruction and the operand value. It will return the new value
|
||||
of the instruction. If the ERRMSG argument is not NULL, then if
|
||||
the operand value is illegal, *ERRMSG will be set to a warning
|
||||
string (the operand will be inserted in any case). If the
|
||||
operand value is legal, *ERRMSG will be unchanged (most operands
|
||||
can accept any value). */
|
||||
unsigned long (* insert) PARAMS ((unsigned long instruction, long op,
|
||||
const char ** errmsg));
|
||||
|
||||
/* Extraction function. This is used by the disassembler. To
|
||||
extract this operand type from an instruction, check this field.
|
||||
|
||||
If it is NULL, compute
|
||||
op = o->bits == -1 ? ((i) & o->shift) : ((i) >> o->shift) & ((1 << o->bits) - 1);
|
||||
if (o->flags & V850_OPERAND_SIGNED)
|
||||
op = (op << (32 - o->bits)) >> (32 - o->bits);
|
||||
(i is the instruction, o is a pointer to this structure, and op
|
||||
is the result; this assumes twos complement arithmetic).
|
||||
|
||||
If this field is not NULL, then simply call it with the
|
||||
instruction value. It will return the value of the operand. If
|
||||
the INVALID argument is not NULL, *INVALID will be set to
|
||||
non-zero if this operand type can not actually be extracted from
|
||||
this operand (i.e., the instruction does not match). If the
|
||||
operand is valid, *INVALID will not be changed. */
|
||||
unsigned long (* extract) PARAMS ((unsigned long instruction, int * invalid));
|
||||
|
||||
/* One bit syntax flags. */
|
||||
int flags;
|
||||
};
|
||||
|
||||
/* Elements in the table are retrieved by indexing with values from
|
||||
the operands field of the v850_opcodes table. */
|
||||
|
||||
extern const struct v850_operand v850_operands[];
|
||||
|
||||
/* Values defined for the flags field of a struct v850_operand. */
|
||||
|
||||
/* This operand names a general purpose register */
|
||||
#define V850_OPERAND_REG 0x01
|
||||
|
||||
/* This operand names a system register */
|
||||
#define V850_OPERAND_SRG 0x02
|
||||
|
||||
/* This operand names a condition code used in the setf instruction */
|
||||
#define V850_OPERAND_CC 0x04
|
||||
|
||||
/* This operand takes signed values */
|
||||
#define V850_OPERAND_SIGNED 0x08
|
||||
|
||||
/* This operand is the ep register. */
|
||||
#define V850_OPERAND_EP 0x10
|
||||
|
||||
/* This operand is a PC displacement */
|
||||
#define V850_OPERAND_DISP 0x20
|
||||
|
||||
/* This is a relaxable operand. Only used for D9->D22 branch relaxing
|
||||
right now. We may need others in the future (or maybe handle them like
|
||||
promoted operands on the mn10300?) */
|
||||
#define V850_OPERAND_RELAX 0x40
|
||||
|
||||
/* The register specified must not be r0 */
|
||||
#define V850_NOT_R0 0x80
|
||||
|
||||
/* push/pop type instruction, V850E specific. */
|
||||
#define V850E_PUSH_POP 0x100
|
||||
|
||||
/* 16 bit immediate follows instruction, V850E specific. */
|
||||
#define V850E_IMMEDIATE16 0x200
|
||||
|
||||
/* 32 bit immediate follows instruction, V850E specific. */
|
||||
#define V850E_IMMEDIATE32 0x400
|
||||
|
||||
#endif /* V850_H */
|
@ -1,32 +0,0 @@
|
||||
# If you change this file, please also look at files which source this one:
|
||||
# shlelf.sh, shelf_nbsd.sh
|
||||
|
||||
SCRIPT_NAME=elf
|
||||
OUTPUT_FORMAT="elf32-sh"
|
||||
TEXT_START_ADDR=0x1000
|
||||
MAXPAGESIZE=128
|
||||
ARCH=sh
|
||||
MACHINE=
|
||||
TEMPLATE_NAME=elf32
|
||||
GENERATE_SHLIB_SCRIPT=yes
|
||||
EMBEDDED=yes
|
||||
|
||||
# These are for compatibility with the COFF toolchain.
|
||||
ENTRY=start
|
||||
CTOR_START='___ctors = .;'
|
||||
CTOR_END='___ctors_end = .;'
|
||||
DTOR_START='___dtors = .;'
|
||||
DTOR_END='___dtors_end = .;'
|
||||
# This is like setting STACK_ADDR to 0x30000, except that the setting can
|
||||
# be overridden, e.g. --defsym _stack=0x0f00, and that we put an extra
|
||||
# sentinal value at the bottom.
|
||||
# N.B. We can't use PROVIDE to set the default value in a symbol because
|
||||
# the address is needed to place the .stack section, which in turn is needed
|
||||
# to hold the sentinel value(s).
|
||||
OTHER_SECTIONS=" .stack ${RELOCATING-0}${RELOCATING+(DEFINED(_stack) ? _stack : 0x30000)} :
|
||||
{
|
||||
${RELOCATING+_stack = .;}
|
||||
*(.stack)
|
||||
LONG(0xdeaddead)
|
||||
}"
|
||||
|
@ -1,2 +0,0 @@
|
||||
. ${srcdir}/emulparams/shlelf_linux.sh
|
||||
OUTPUT_FORMAT="elf32-shbig-linux"
|
@ -1,7 +0,0 @@
|
||||
SCRIPT_NAME=tic30aout
|
||||
OUTPUT_FORMAT="a.out-tic30"
|
||||
OUTPUT_ARCH="tms320c30"
|
||||
TEXT_START_ADDR=0x0
|
||||
TARGET_PAGE_SIZE=128
|
||||
ARCH=tms320c30
|
||||
BIG=1
|
@ -1,7 +0,0 @@
|
||||
SCRIPT_NAME=tic30coff
|
||||
OUTPUT_FORMAT="coff-tic30"
|
||||
OUTPUT_ARCH="tms320c30"
|
||||
TEXT_START_ADDR=0x0
|
||||
TARGET_PAGE_SIZE=128
|
||||
ARCH=tms320c30
|
||||
BIG=1
|
@ -1,14 +0,0 @@
|
||||
MACHINE=
|
||||
SCRIPT_NAME=v850
|
||||
OUTPUT_FORMAT="elf32-v850"
|
||||
TEXT_START_ADDR=0x100000
|
||||
ZDATA_START_ADDR=0x160
|
||||
ROZDATA_START_ADDR="ALIGN (4)"
|
||||
SDATA_START_ADDR="ALIGN (4)"
|
||||
ROSDATA_START_ADDR="ALIGN (4)"
|
||||
TDATA_START_ADDR="ALIGN (4)"
|
||||
CALL_TABLE_START_ADDR="ALIGN (4)"
|
||||
ARCH=v850
|
||||
MAXPAGESIZE=256
|
||||
ENTRY=_start
|
||||
EMBEDDED=yes
|
@ -1,7 +0,0 @@
|
||||
SCRIPT_NAME=z8000
|
||||
OUTPUT_FORMAT="coff-z8k"
|
||||
OUTPUT_ARCH="z8001"
|
||||
TEXT_START_ADDR=0x0
|
||||
TARGET_PAGE_SIZE=128
|
||||
ARCH=z8k
|
||||
BIG=1
|
@ -1,6 +0,0 @@
|
||||
SCRIPT_NAME=z8000
|
||||
OUTPUT_FORMAT="coff-z8k"
|
||||
OUTPUT_ARCH="z8002"
|
||||
TEXT_START_ADDR=0x0
|
||||
TARGET_PAGE_SIZE=128
|
||||
ARCH=z8002
|
@ -1,34 +0,0 @@
|
||||
cat <<EOF
|
||||
OUTPUT_FORMAT("${OUTPUT_FORMAT}")
|
||||
OUTPUT_ARCH(${ARCH})
|
||||
|
||||
${STACKZERO+${RELOCATING+${STACKZERO}}}
|
||||
${RELOCATING+PROVIDE (__stack = 0);}
|
||||
SECTIONS
|
||||
{
|
||||
${RELOCATING+. = ${TEXT_START_ADDR};}
|
||||
.text :
|
||||
{
|
||||
CREATE_OBJECT_SYMBOLS
|
||||
*(.text)
|
||||
${RELOCATING+_etext = .;}
|
||||
${RELOCATING+__etext = .;}
|
||||
${PAD_TEXT+${RELOCATING+. = ${DATA_ALIGNMENT};}}
|
||||
}
|
||||
${RELOCATING+. = ${DATA_ALIGNMENT};}
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
${RELOCATING+_edata = .;}
|
||||
${RELOCATING+__edata = .;}
|
||||
}
|
||||
.bss :
|
||||
{
|
||||
${RELOCATING+ __bss_start = .};
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
${RELOCATING+_end = ALIGN(4) };
|
||||
${RELOCATING+__end = ALIGN(4) };
|
||||
}
|
||||
}
|
||||
EOF
|
@ -1,58 +0,0 @@
|
||||
cat <<EOF
|
||||
OUTPUT_FORMAT("${OUTPUT_FORMAT}")
|
||||
OUTPUT_ARCH("${OUTPUT_ARCH}")
|
||||
|
||||
MEMORY
|
||||
{
|
||||
rom : ORIGIN = 0x00000300, LENGTH = 16k
|
||||
ram : ORIGIN = 0x00000300 + 16k, LENGTH = 16k
|
||||
ramblk0 : ORIGIN = 0x02026000, LENGTH = 0x1000
|
||||
ramblk1 : ORIGIN = 0x02027000, LENGTH = 0x1000
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.vectors 0x00000000 :
|
||||
{
|
||||
*(vectors)
|
||||
}
|
||||
|
||||
.text :
|
||||
{
|
||||
*(.text)
|
||||
} > rom
|
||||
|
||||
.const :
|
||||
{
|
||||
*(.const)
|
||||
__etext = . ;
|
||||
} > rom
|
||||
|
||||
.mdata : AT( ADDR(.const) + SIZEOF(.const) )
|
||||
{
|
||||
__data = . ;
|
||||
*(.data);
|
||||
__edata = . ;
|
||||
} > ram
|
||||
|
||||
.bss :
|
||||
{
|
||||
__bss = . ;
|
||||
*(.bss);
|
||||
*(COMMON);
|
||||
__ebss = . ;
|
||||
} > ram
|
||||
|
||||
.ram0 :
|
||||
{
|
||||
*(ram0)
|
||||
} > ramblk0
|
||||
|
||||
.ram1 :
|
||||
{
|
||||
*(ram1)
|
||||
} > ramblk1
|
||||
|
||||
}
|
||||
|
||||
EOF
|
@ -1,230 +0,0 @@
|
||||
cat << EOF
|
||||
OUTPUT_FORMAT("elf32-v850", "elf32-v850",
|
||||
"elf32-v850")
|
||||
OUTPUT_ARCH(v850)
|
||||
ENTRY(_start)
|
||||
SEARCH_DIR(.);
|
||||
SECTIONS
|
||||
{
|
||||
/* This saves a little space in the ELF file, since the zda starts
|
||||
at a higher location that the ELF headers take up. */
|
||||
|
||||
.zdata ${ZDATA_START_ADDR} :
|
||||
{
|
||||
*(.zdata)
|
||||
*(.zbss)
|
||||
*(reszdata)
|
||||
*(.zcommon)
|
||||
}
|
||||
|
||||
/* This is the read only part of the zero data area.
|
||||
Having it as a seperate section prevents its
|
||||
attributes from being inherited by the zdata
|
||||
section. Specifically it prevents the zdata
|
||||
section from being marked READONLY. */
|
||||
|
||||
.rozdata ${ROZDATA_START_ADDR} :
|
||||
{
|
||||
*(.rozdata)
|
||||
*(romzdata)
|
||||
*(romzbss)
|
||||
}
|
||||
|
||||
/* Read-only sections, merged into text segment. */
|
||||
. = ${TEXT_START_ADDR};
|
||||
.interp : { *(.interp) }
|
||||
.hash : { *(.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.rel.text : { *(.rel.text) }
|
||||
.rela.text : { *(.rela.text) }
|
||||
.rel.data : { *(.rel.data) }
|
||||
.rela.data : { *(.rela.data) }
|
||||
.rel.rodata : { *(.rel.rodata) }
|
||||
.rela.rodata : { *(.rela.rodata) }
|
||||
.rel.gcc_except_table : { *(.rel.gcc_except_table) }
|
||||
.rela.gcc_except_table : { *(.rela.gcc_except_table) }
|
||||
.rel.got : { *(.rel.got) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rel.ctors : { *(.rel.ctors) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rel.dtors : { *(.rel.dtors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rel.init : { *(.rel.init) }
|
||||
.rela.init : { *(.rela.init) }
|
||||
.rel.fini : { *(.rel.fini) }
|
||||
.rela.fini : { *(.rela.fini) }
|
||||
.rel.bss : { *(.rel.bss) }
|
||||
.rela.bss : { *(.rela.bss) }
|
||||
.rel.plt : { *(.rel.plt) }
|
||||
.rela.plt : { *(.rela.plt) }
|
||||
.init : { KEEP (*(.init)) } =0
|
||||
.plt : { *(.plt) }
|
||||
|
||||
.text :
|
||||
{
|
||||
*(.text)
|
||||
${RELOCATING+*(.text.*)}
|
||||
|
||||
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||
*(.gnu.warning)
|
||||
*(.gnu.linkonce.t*)
|
||||
} =0
|
||||
|
||||
${RELOCATING+_etext = .;}
|
||||
${RELOCATING+PROVIDE (etext = .);}
|
||||
|
||||
/* This is special code area at the end of the normal text section.
|
||||
It contains a small lookup table at the start followed by the
|
||||
code pointed to by entries in the lookup table. */
|
||||
|
||||
.call_table_data ${CALL_TABLE_START_ADDR} :
|
||||
{
|
||||
${RELOCATING+PROVIDE(__ctbp = .);}
|
||||
*(.call_table_data)
|
||||
} = 0xff /* Fill gaps with 0xff. */
|
||||
|
||||
.call_table_text :
|
||||
{
|
||||
*(.call_table_text)
|
||||
}
|
||||
|
||||
.fini : { KEEP (*(.fini)) } =0
|
||||
.rodata : { *(.rodata) ${RELOCATING+*(.rodata.*)} *(.gnu.linkonce.r*) }
|
||||
.rodata1 : { *(.rodata1) }
|
||||
|
||||
.data :
|
||||
{
|
||||
*(.data)
|
||||
${RELOCATING+*(.data.*)}
|
||||
*(.gnu.linkonce.d*)
|
||||
CONSTRUCTORS
|
||||
}
|
||||
.data1 : { *(.data1) }
|
||||
.ctors :
|
||||
{
|
||||
${CONSTRUCTING+___ctors = .;}
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||
KEEP (*(SORT(.ctors.*)))
|
||||
KEEP (*crtend(.ctors))
|
||||
${CONSTRUCTING+___ctors_end = .;}
|
||||
}
|
||||
.dtors :
|
||||
{
|
||||
${CONSTRUCTING+___dtors = .;}
|
||||
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||
KEEP (*(SORT(.dtors.*)))
|
||||
KEEP (*crtend.o(.dtors))
|
||||
${CONSTRUCTING+___dtors_end = .;}
|
||||
}
|
||||
.jcr :
|
||||
{
|
||||
KEEP (*(.jcr))
|
||||
}
|
||||
|
||||
.gcc_except_table : { *(.gcc_except_table) }
|
||||
|
||||
.got : { *(.got.plt) *(.got) }
|
||||
.dynamic : { *(.dynamic) }
|
||||
|
||||
.tdata ${TDATA_START_ADDR} :
|
||||
{
|
||||
${RELOCATING+PROVIDE (__ep = .);}
|
||||
*(.tbyte)
|
||||
*(.tcommon_byte)
|
||||
*(.tdata)
|
||||
*(.tbss)
|
||||
*(.tcommon)
|
||||
}
|
||||
|
||||
/* We want the small data sections together, so single-instruction offsets
|
||||
can access them all, and initialized data all before uninitialized, so
|
||||
we can shorten the on-disk segment size. */
|
||||
|
||||
.sdata ${SDATA_START_ADDR} :
|
||||
{
|
||||
${RELOCATING+PROVIDE (__gp = . + 0x8000);}
|
||||
*(.sdata)
|
||||
}
|
||||
|
||||
/* See comment about .rozdata. */
|
||||
.rosdata ${ROSDATA_START_ADDR} :
|
||||
{
|
||||
*(.rosdata)
|
||||
}
|
||||
|
||||
/* We place the .sbss data section AFTER the .rosdata section, so that
|
||||
it can directly preceed the .bss section. This allows runtime startup
|
||||
code to initialise all the zero-data sections by simply taking the
|
||||
value of '_edata' and zeroing until it reaches '_end'. */
|
||||
|
||||
.sbss :
|
||||
{
|
||||
${RELOCATING+__sbss_start = .;}
|
||||
*(.sbss)
|
||||
*(.scommon)
|
||||
}
|
||||
|
||||
${RELOCATING+_edata = DEFINED (__sbss_start) ? __sbss_start : . ;}
|
||||
${RELOCATING+PROVIDE (edata = _edata);}
|
||||
|
||||
.bss :
|
||||
{
|
||||
${RELOCATING+__bss_start = DEFINED (__sbss_start) ? __sbss_start : . ;}
|
||||
${RELOCATING+__real_bss_start = . ;}
|
||||
*(.dynbss)
|
||||
*(.bss)
|
||||
*(COMMON)
|
||||
}
|
||||
|
||||
${RELOCATING+_end = . ;}
|
||||
${RELOCATING+PROVIDE (end = .);}
|
||||
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.comment 0 : { *(.comment) }
|
||||
|
||||
/* DWARF debug sections.
|
||||
Symbols in the DWARF debugging sections are relative to the beginning
|
||||
of the section so we begin them at 0. */
|
||||
|
||||
/* DWARF 1 */
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
|
||||
/* GNU DWARF 1 extensions */
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
|
||||
/* DWARF 1.1 and DWARF 2 */
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
|
||||
/* DWARF 2 */
|
||||
.debug_info 0 : { *(.debug_info) *(.gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
|
||||
/* SGI/MIPS DWARF 2 extensions. */
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
|
||||
/* User stack. */
|
||||
.stack 0x200000 :
|
||||
{
|
||||
${RELOCATING+__stack = .;}
|
||||
*(.stack)
|
||||
}
|
||||
}
|
||||
EOF
|
@ -1,57 +0,0 @@
|
||||
cat <<EOF
|
||||
OUTPUT_FORMAT("${OUTPUT_FORMAT}")
|
||||
OUTPUT_ARCH("${OUTPUT_ARCH}")
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text ${BIG+ ${RELOCATING+ 0x0000000}} :
|
||||
{
|
||||
*(.text)
|
||||
*(.strings)
|
||||
*(.rdata)
|
||||
}
|
||||
|
||||
.ctors ${BIG+ ${RELOCATING+ 0x2000000}} :
|
||||
{
|
||||
${CONSTRUCTING+ ___ctors = . ; }
|
||||
*(.ctors);
|
||||
${CONSTRUCTING+ ___ctors_end = . ; }
|
||||
___dtors = . ;
|
||||
*(.dtors);
|
||||
${CONSTRUCTING+ ___dtors_end = . ; }
|
||||
}
|
||||
|
||||
.data ${BIG+ ${RELOCATING+ 0x3000000}} :
|
||||
{
|
||||
*(.data)
|
||||
}
|
||||
|
||||
.bss ${BIG+ ${RELOCATING+ 0x4000000}} :
|
||||
{
|
||||
${RELOCATING+ __start_bss = . ; }
|
||||
*(.bss);
|
||||
*(COMMON);
|
||||
${RELOCATING+ __end_bss = . ; }
|
||||
}
|
||||
|
||||
.heap ${BIG+ ${RELOCATING+ 0x5000000}} :
|
||||
{
|
||||
${RELOCATING+ __start_heap = . ; }
|
||||
${RELOCATING+ . = . + 20k ; }
|
||||
${RELOCATING+ __end_heap = . ; }
|
||||
}
|
||||
|
||||
.stack ${RELOCATING+ 0xf000 } :
|
||||
{
|
||||
${RELOCATING+ _stack = . ; }
|
||||
*(.stack)
|
||||
${RELOCATING+ __stack_top = . ; }
|
||||
}
|
||||
|
||||
}
|
||||
EOF
|
||||
|
||||
|
||||
|
||||
|
@ -1,710 +0,0 @@
|
||||
/* Disassembly routines for TMS320C30 architecture
|
||||
Copyright 1998, 1999, 2000 Free Software Foundation, Inc.
|
||||
Contributed by Steven Haworth (steve@pm.cse.rmit.edu.au)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) 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. */
|
||||
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include "sysdep.h"
|
||||
#include "dis-asm.h"
|
||||
#include "opcode/tic30.h"
|
||||
|
||||
#define NORMAL_INSN 1
|
||||
#define PARALLEL_INSN 2
|
||||
|
||||
/* Gets the type of instruction based on the top 2 or 3 bits of the
|
||||
instruction word. */
|
||||
#define GET_TYPE(insn) (insn & 0x80000000 ? insn & 0xC0000000 : insn & 0xE0000000)
|
||||
|
||||
/* Instruction types. */
|
||||
#define TWO_OPERAND_1 0x00000000
|
||||
#define TWO_OPERAND_2 0x40000000
|
||||
#define THREE_OPERAND 0x20000000
|
||||
#define PAR_STORE 0xC0000000
|
||||
#define MUL_ADDS 0x80000000
|
||||
#define BRANCHES 0x60000000
|
||||
|
||||
/* Specific instruction id bits. */
|
||||
#define NORMAL_IDEN 0x1F800000
|
||||
#define PAR_STORE_IDEN 0x3E000000
|
||||
#define MUL_ADD_IDEN 0x2C000000
|
||||
#define BR_IMM_IDEN 0x1F000000
|
||||
#define BR_COND_IDEN 0x1C3F0000
|
||||
|
||||
/* Addressing modes. */
|
||||
#define AM_REGISTER 0x00000000
|
||||
#define AM_DIRECT 0x00200000
|
||||
#define AM_INDIRECT 0x00400000
|
||||
#define AM_IMM 0x00600000
|
||||
|
||||
#define P_FIELD 0x03000000
|
||||
|
||||
#define REG_AR0 0x08
|
||||
#define LDP_INSN 0x08700000
|
||||
|
||||
/* TMS320C30 program counter for current instruction. */
|
||||
static unsigned int _pc;
|
||||
|
||||
struct instruction
|
||||
{
|
||||
int type;
|
||||
template *tm;
|
||||
partemplate *ptm;
|
||||
};
|
||||
|
||||
int get_tic30_instruction PARAMS ((unsigned long, struct instruction *));
|
||||
int print_two_operand
|
||||
PARAMS ((disassemble_info *, unsigned long, struct instruction *));
|
||||
int print_three_operand
|
||||
PARAMS ((disassemble_info *, unsigned long, struct instruction *));
|
||||
int print_par_insn
|
||||
PARAMS ((disassemble_info *, unsigned long, struct instruction *));
|
||||
int print_branch
|
||||
PARAMS ((disassemble_info *, unsigned long, struct instruction *));
|
||||
int get_indirect_operand PARAMS ((unsigned short, int, char *));
|
||||
int get_register_operand PARAMS ((unsigned char, char *));
|
||||
int cnvt_tmsfloat_ieee PARAMS ((unsigned long, int, float *));
|
||||
|
||||
int
|
||||
print_insn_tic30 (pc, info)
|
||||
bfd_vma pc;
|
||||
disassemble_info *info;
|
||||
{
|
||||
unsigned long insn_word;
|
||||
struct instruction insn = { 0, NULL, NULL };
|
||||
bfd_vma bufaddr = pc - info->buffer_vma;
|
||||
/* Obtain the current instruction word from the buffer. */
|
||||
insn_word = (*(info->buffer + bufaddr) << 24) | (*(info->buffer + bufaddr + 1) << 16) |
|
||||
(*(info->buffer + bufaddr + 2) << 8) | *(info->buffer + bufaddr + 3);
|
||||
_pc = pc / 4;
|
||||
/* Get the instruction refered to by the current instruction word
|
||||
and print it out based on its type. */
|
||||
if (!get_tic30_instruction (insn_word, &insn))
|
||||
return -1;
|
||||
switch (GET_TYPE (insn_word))
|
||||
{
|
||||
case TWO_OPERAND_1:
|
||||
case TWO_OPERAND_2:
|
||||
if (!print_two_operand (info, insn_word, &insn))
|
||||
return -1;
|
||||
break;
|
||||
case THREE_OPERAND:
|
||||
if (!print_three_operand (info, insn_word, &insn))
|
||||
return -1;
|
||||
break;
|
||||
case PAR_STORE:
|
||||
case MUL_ADDS:
|
||||
if (!print_par_insn (info, insn_word, &insn))
|
||||
return -1;
|
||||
break;
|
||||
case BRANCHES:
|
||||
if (!print_branch (info, insn_word, &insn))
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
return 4;
|
||||
}
|
||||
|
||||
int
|
||||
get_tic30_instruction (insn_word, insn)
|
||||
unsigned long insn_word;
|
||||
struct instruction *insn;
|
||||
{
|
||||
switch (GET_TYPE (insn_word))
|
||||
{
|
||||
case TWO_OPERAND_1:
|
||||
case TWO_OPERAND_2:
|
||||
case THREE_OPERAND:
|
||||
insn->type = NORMAL_INSN;
|
||||
{
|
||||
template *current_optab = (template *) tic30_optab;
|
||||
for (; current_optab < tic30_optab_end; current_optab++)
|
||||
{
|
||||
if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
|
||||
{
|
||||
if (current_optab->operands == 0)
|
||||
{
|
||||
if (current_optab->base_opcode == insn_word)
|
||||
{
|
||||
insn->tm = current_optab;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ((current_optab->base_opcode & NORMAL_IDEN) == (insn_word & NORMAL_IDEN))
|
||||
{
|
||||
insn->tm = current_optab;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PAR_STORE:
|
||||
insn->type = PARALLEL_INSN;
|
||||
{
|
||||
partemplate *current_optab = (partemplate *) tic30_paroptab;
|
||||
for (; current_optab < tic30_paroptab_end; current_optab++)
|
||||
{
|
||||
if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
|
||||
{
|
||||
if ((current_optab->base_opcode & PAR_STORE_IDEN) == (insn_word & PAR_STORE_IDEN))
|
||||
{
|
||||
insn->ptm = current_optab;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MUL_ADDS:
|
||||
insn->type = PARALLEL_INSN;
|
||||
{
|
||||
partemplate *current_optab = (partemplate *) tic30_paroptab;
|
||||
for (; current_optab < tic30_paroptab_end; current_optab++)
|
||||
{
|
||||
if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
|
||||
{
|
||||
if ((current_optab->base_opcode & MUL_ADD_IDEN) == (insn_word & MUL_ADD_IDEN))
|
||||
{
|
||||
insn->ptm = current_optab;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BRANCHES:
|
||||
insn->type = NORMAL_INSN;
|
||||
{
|
||||
template *current_optab = (template *) tic30_optab;
|
||||
for (; current_optab < tic30_optab_end; current_optab++)
|
||||
{
|
||||
if (GET_TYPE (current_optab->base_opcode) == GET_TYPE (insn_word))
|
||||
{
|
||||
if (current_optab->operand_types[0] & Imm24)
|
||||
{
|
||||
if ((current_optab->base_opcode & BR_IMM_IDEN) == (insn_word & BR_IMM_IDEN))
|
||||
{
|
||||
insn->tm = current_optab;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (current_optab->operands > 0)
|
||||
{
|
||||
if ((current_optab->base_opcode & BR_COND_IDEN) == (insn_word & BR_COND_IDEN))
|
||||
{
|
||||
insn->tm = current_optab;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((current_optab->base_opcode & (BR_COND_IDEN | 0x00800000)) == (insn_word & (BR_COND_IDEN | 0x00800000)))
|
||||
{
|
||||
insn->tm = current_optab;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
print_two_operand (info, insn_word, insn)
|
||||
disassemble_info *info;
|
||||
unsigned long insn_word;
|
||||
struct instruction *insn;
|
||||
{
|
||||
char name[12];
|
||||
char operand[2][13] =
|
||||
{
|
||||
{0},
|
||||
{0}};
|
||||
float f_number;
|
||||
|
||||
if (insn->tm == NULL)
|
||||
return 0;
|
||||
strcpy (name, insn->tm->name);
|
||||
if (insn->tm->opcode_modifier == AddressMode)
|
||||
{
|
||||
int src_op, dest_op;
|
||||
/* Determine whether instruction is a store or a normal instruction. */
|
||||
if ((insn->tm->operand_types[1] & (Direct | Indirect)) == (Direct | Indirect))
|
||||
{
|
||||
src_op = 1;
|
||||
dest_op = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
src_op = 0;
|
||||
dest_op = 1;
|
||||
}
|
||||
/* Get the destination register. */
|
||||
if (insn->tm->operands == 2)
|
||||
get_register_operand ((insn_word & 0x001F0000) >> 16, operand[dest_op]);
|
||||
/* Get the source operand based on addressing mode. */
|
||||
switch (insn_word & AddressMode)
|
||||
{
|
||||
case AM_REGISTER:
|
||||
/* Check for the NOP instruction before getting the operand. */
|
||||
if ((insn->tm->operand_types[0] & NotReq) == 0)
|
||||
get_register_operand ((insn_word & 0x0000001F), operand[src_op]);
|
||||
break;
|
||||
case AM_DIRECT:
|
||||
sprintf (operand[src_op], "@0x%lX", (insn_word & 0x0000FFFF));
|
||||
break;
|
||||
case AM_INDIRECT:
|
||||
get_indirect_operand ((insn_word & 0x0000FFFF), 2, operand[src_op]);
|
||||
break;
|
||||
case AM_IMM:
|
||||
/* Get the value of the immediate operand based on variable type. */
|
||||
switch (insn->tm->imm_arg_type)
|
||||
{
|
||||
case Imm_Float:
|
||||
cnvt_tmsfloat_ieee ((insn_word & 0x0000FFFF), 2, &f_number);
|
||||
sprintf (operand[src_op], "%2.2f", f_number);
|
||||
break;
|
||||
case Imm_SInt:
|
||||
sprintf (operand[src_op], "%d", (short) (insn_word & 0x0000FFFF));
|
||||
break;
|
||||
case Imm_UInt:
|
||||
sprintf (operand[src_op], "%lu", (insn_word & 0x0000FFFF));
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
/* Handle special case for LDP instruction. */
|
||||
if ((insn_word & 0xFFFFFF00) == LDP_INSN)
|
||||
{
|
||||
strcpy (name, "ldp");
|
||||
sprintf (operand[0], "0x%06lX", (insn_word & 0x000000FF) << 16);
|
||||
operand[1][0] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Handle case for stack and rotate instructions. */
|
||||
else if (insn->tm->operands == 1)
|
||||
{
|
||||
if (insn->tm->opcode_modifier == StackOp)
|
||||
{
|
||||
get_register_operand ((insn_word & 0x001F0000) >> 16, operand[0]);
|
||||
}
|
||||
}
|
||||
/* Output instruction to stream. */
|
||||
info->fprintf_func (info->stream, " %s %s%c%s", name,
|
||||
operand[0][0] ? operand[0] : "",
|
||||
operand[1][0] ? ',' : ' ',
|
||||
operand[1][0] ? operand[1] : "");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
print_three_operand (info, insn_word, insn)
|
||||
disassemble_info *info;
|
||||
unsigned long insn_word;
|
||||
struct instruction *insn;
|
||||
{
|
||||
char operand[3][13] =
|
||||
{
|
||||
{0},
|
||||
{0},
|
||||
{0}};
|
||||
|
||||
if (insn->tm == NULL)
|
||||
return 0;
|
||||
switch (insn_word & AddressMode)
|
||||
{
|
||||
case AM_REGISTER:
|
||||
get_register_operand ((insn_word & 0x000000FF), operand[0]);
|
||||
get_register_operand ((insn_word & 0x0000FF00) >> 8, operand[1]);
|
||||
break;
|
||||
case AM_DIRECT:
|
||||
get_register_operand ((insn_word & 0x000000FF), operand[0]);
|
||||
get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1]);
|
||||
break;
|
||||
case AM_INDIRECT:
|
||||
get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0]);
|
||||
get_register_operand ((insn_word & 0x0000FF00) >> 8, operand[1]);
|
||||
break;
|
||||
case AM_IMM:
|
||||
get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0]);
|
||||
get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1]);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
if (insn->tm->operands == 3)
|
||||
get_register_operand ((insn_word & 0x001F0000) >> 16, operand[2]);
|
||||
info->fprintf_func (info->stream, " %s %s,%s%c%s", insn->tm->name,
|
||||
operand[0], operand[1],
|
||||
operand[2][0] ? ',' : ' ',
|
||||
operand[2][0] ? operand[2] : "");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
print_par_insn (info, insn_word, insn)
|
||||
disassemble_info *info;
|
||||
unsigned long insn_word;
|
||||
struct instruction *insn;
|
||||
{
|
||||
size_t i, len;
|
||||
char *name1, *name2;
|
||||
char operand[2][3][13] =
|
||||
{
|
||||
{
|
||||
{0},
|
||||
{0},
|
||||
{0}},
|
||||
{
|
||||
{0},
|
||||
{0},
|
||||
{0}}};
|
||||
|
||||
if (insn->ptm == NULL)
|
||||
return 0;
|
||||
/* Parse out the names of each of the parallel instructions from the
|
||||
q_insn1_insn2 format. */
|
||||
name1 = (char *) strdup (insn->ptm->name + 2);
|
||||
name2 = "";
|
||||
len = strlen (name1);
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if (name1[i] == '_')
|
||||
{
|
||||
name2 = &name1[i + 1];
|
||||
name1[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Get the operands of the instruction based on the operand order. */
|
||||
switch (insn->ptm->oporder)
|
||||
{
|
||||
case OO_4op1:
|
||||
get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
|
||||
get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
|
||||
get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
|
||||
get_register_operand ((insn_word >> 22) & 0x07, operand[0][1]);
|
||||
break;
|
||||
case OO_4op2:
|
||||
get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
|
||||
get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][0]);
|
||||
get_register_operand ((insn_word >> 19) & 0x07, operand[1][1]);
|
||||
get_register_operand ((insn_word >> 22) & 0x07, operand[0][1]);
|
||||
break;
|
||||
case OO_4op3:
|
||||
get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
|
||||
get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
|
||||
get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
|
||||
get_register_operand ((insn_word >> 22) & 0x07, operand[0][0]);
|
||||
break;
|
||||
case OO_5op1:
|
||||
get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][0]);
|
||||
get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
|
||||
get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
|
||||
get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
|
||||
get_register_operand ((insn_word >> 22) & 0x07, operand[0][2]);
|
||||
break;
|
||||
case OO_5op2:
|
||||
get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
|
||||
get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][1]);
|
||||
get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
|
||||
get_register_operand ((insn_word >> 19) & 0x07, operand[0][0]);
|
||||
get_register_operand ((insn_word >> 22) & 0x07, operand[0][2]);
|
||||
break;
|
||||
case OO_PField:
|
||||
if (insn_word & 0x00800000)
|
||||
get_register_operand (0x01, operand[0][2]);
|
||||
else
|
||||
get_register_operand (0x00, operand[0][2]);
|
||||
if (insn_word & 0x00400000)
|
||||
get_register_operand (0x03, operand[1][2]);
|
||||
else
|
||||
get_register_operand (0x02, operand[1][2]);
|
||||
switch (insn_word & P_FIELD)
|
||||
{
|
||||
case 0x00000000:
|
||||
get_indirect_operand ((insn_word & 0x000000FF), 1, operand[0][1]);
|
||||
get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
|
||||
get_register_operand ((insn_word >> 16) & 0x07, operand[1][1]);
|
||||
get_register_operand ((insn_word >> 19) & 0x07, operand[1][0]);
|
||||
break;
|
||||
case 0x01000000:
|
||||
get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][0]);
|
||||
get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
|
||||
get_register_operand ((insn_word >> 16) & 0x07, operand[1][1]);
|
||||
get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
|
||||
break;
|
||||
case 0x02000000:
|
||||
get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][1]);
|
||||
get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[1][0]);
|
||||
get_register_operand ((insn_word >> 16) & 0x07, operand[0][1]);
|
||||
get_register_operand ((insn_word >> 19) & 0x07, operand[0][0]);
|
||||
break;
|
||||
case 0x03000000:
|
||||
get_indirect_operand ((insn_word & 0x000000FF), 1, operand[1][1]);
|
||||
get_indirect_operand ((insn_word & 0x0000FF00) >> 8, 1, operand[0][0]);
|
||||
get_register_operand ((insn_word >> 16) & 0x07, operand[1][0]);
|
||||
get_register_operand ((insn_word >> 19) & 0x07, operand[0][1]);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
info->fprintf_func (info->stream, " %s %s,%s%c%s", name1,
|
||||
operand[0][0], operand[0][1],
|
||||
operand[0][2][0] ? ',' : ' ',
|
||||
operand[0][2][0] ? operand[0][2] : "");
|
||||
info->fprintf_func (info->stream, "\n\t\t\t|| %s %s,%s%c%s", name2,
|
||||
operand[1][0], operand[1][1],
|
||||
operand[1][2][0] ? ',' : ' ',
|
||||
operand[1][2][0] ? operand[1][2] : "");
|
||||
free (name1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
print_branch (info, insn_word, insn)
|
||||
disassemble_info *info;
|
||||
unsigned long insn_word;
|
||||
struct instruction *insn;
|
||||
{
|
||||
char operand[2][13] =
|
||||
{
|
||||
{0},
|
||||
{0}};
|
||||
unsigned long address;
|
||||
int print_label = 0;
|
||||
|
||||
if (insn->tm == NULL)
|
||||
return 0;
|
||||
/* Get the operands for 24-bit immediate jumps. */
|
||||
if (insn->tm->operand_types[0] & Imm24)
|
||||
{
|
||||
address = insn_word & 0x00FFFFFF;
|
||||
sprintf (operand[0], "0x%lX", address);
|
||||
print_label = 1;
|
||||
}
|
||||
/* Get the operand for the trap instruction. */
|
||||
else if (insn->tm->operand_types[0] & IVector)
|
||||
{
|
||||
address = insn_word & 0x0000001F;
|
||||
sprintf (operand[0], "0x%lX", address);
|
||||
}
|
||||
else
|
||||
{
|
||||
address = insn_word & 0x0000FFFF;
|
||||
/* Get the operands for the DB instructions. */
|
||||
if (insn->tm->operands == 2)
|
||||
{
|
||||
get_register_operand (((insn_word & 0x01C00000) >> 22) + REG_AR0, operand[0]);
|
||||
if (insn_word & PCRel)
|
||||
{
|
||||
sprintf (operand[1], "%d", (short) address);
|
||||
print_label = 1;
|
||||
}
|
||||
else
|
||||
get_register_operand (insn_word & 0x0000001F, operand[1]);
|
||||
}
|
||||
/* Get the operands for the standard branches. */
|
||||
else if (insn->tm->operands == 1)
|
||||
{
|
||||
if (insn_word & PCRel)
|
||||
{
|
||||
address = (short) address;
|
||||
sprintf (operand[0], "%ld", address);
|
||||
print_label = 1;
|
||||
}
|
||||
else
|
||||
get_register_operand (insn_word & 0x0000001F, operand[0]);
|
||||
}
|
||||
}
|
||||
info->fprintf_func (info->stream, " %s %s%c%s", insn->tm->name,
|
||||
operand[0][0] ? operand[0] : "",
|
||||
operand[1][0] ? ',' : ' ',
|
||||
operand[1][0] ? operand[1] : "");
|
||||
/* Print destination of branch in relation to current symbol. */
|
||||
if (print_label && info->symbols)
|
||||
{
|
||||
asymbol *sym = *info->symbols;
|
||||
|
||||
if ((insn->tm->opcode_modifier == PCRel) && (insn_word & PCRel))
|
||||
{
|
||||
address = (_pc + 1 + (short) address) - ((sym->section->vma + sym->value) / 4);
|
||||
/* Check for delayed instruction, if so adjust destination. */
|
||||
if (insn_word & 0x00200000)
|
||||
address += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
address -= ((sym->section->vma + sym->value) / 4);
|
||||
}
|
||||
if (address == 0)
|
||||
info->fprintf_func (info->stream, " <%s>", sym->name);
|
||||
else
|
||||
info->fprintf_func (info->stream, " <%s %c %d>", sym->name,
|
||||
((short) address < 0) ? '-' : '+',
|
||||
abs (address));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
get_indirect_operand (fragment, size, buffer)
|
||||
unsigned short fragment;
|
||||
int size;
|
||||
char *buffer;
|
||||
{
|
||||
unsigned char mod;
|
||||
unsigned arnum;
|
||||
unsigned char disp;
|
||||
|
||||
if (buffer == NULL)
|
||||
return 0;
|
||||
/* Determine which bits identify the sections of the indirect
|
||||
operand based on the size in bytes. */
|
||||
switch (size)
|
||||
{
|
||||
case 1:
|
||||
mod = (fragment & 0x00F8) >> 3;
|
||||
arnum = (fragment & 0x0007);
|
||||
disp = 0;
|
||||
break;
|
||||
case 2:
|
||||
mod = (fragment & 0xF800) >> 11;
|
||||
arnum = (fragment & 0x0700) >> 8;
|
||||
disp = (fragment & 0x00FF);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
{
|
||||
const ind_addr_type *current_ind = tic30_indaddr_tab;
|
||||
for (; current_ind < tic30_indaddrtab_end; current_ind++)
|
||||
{
|
||||
if (current_ind->modfield == mod)
|
||||
{
|
||||
if (current_ind->displacement == IMPLIED_DISP && size == 2)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t i, len;
|
||||
int bufcnt;
|
||||
|
||||
len = strlen (current_ind->syntax);
|
||||
for (i = 0, bufcnt = 0; i < len; i++, bufcnt++)
|
||||
{
|
||||
buffer[bufcnt] = current_ind->syntax[i];
|
||||
if (buffer[bufcnt - 1] == 'a' && buffer[bufcnt] == 'r')
|
||||
buffer[++bufcnt] = arnum + '0';
|
||||
if (buffer[bufcnt] == '('
|
||||
&& current_ind->displacement == DISP_REQUIRED)
|
||||
{
|
||||
sprintf (&buffer[bufcnt + 1], "%u", disp);
|
||||
bufcnt += strlen (&buffer[bufcnt + 1]);
|
||||
}
|
||||
}
|
||||
buffer[bufcnt + 1] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
get_register_operand (fragment, buffer)
|
||||
unsigned char fragment;
|
||||
char *buffer;
|
||||
{
|
||||
const reg *current_reg = tic30_regtab;
|
||||
|
||||
if (buffer == NULL)
|
||||
return 0;
|
||||
for (; current_reg < tic30_regtab_end; current_reg++)
|
||||
{
|
||||
if ((fragment & 0x1F) == current_reg->opcode)
|
||||
{
|
||||
strcpy (buffer, current_reg->name);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cnvt_tmsfloat_ieee (tmsfloat, size, ieeefloat)
|
||||
unsigned long tmsfloat;
|
||||
int size;
|
||||
float *ieeefloat;
|
||||
{
|
||||
unsigned long exp, sign, mant;
|
||||
|
||||
if (size == 2)
|
||||
{
|
||||
if ((tmsfloat & 0x0000F000) == 0x00008000)
|
||||
tmsfloat = 0x80000000;
|
||||
else
|
||||
{
|
||||
tmsfloat <<= 16;
|
||||
tmsfloat = (long) tmsfloat >> 4;
|
||||
}
|
||||
}
|
||||
exp = tmsfloat & 0xFF000000;
|
||||
if (exp == 0x80000000)
|
||||
{
|
||||
*ieeefloat = 0.0;
|
||||
return 1;
|
||||
}
|
||||
exp += 0x7F000000;
|
||||
sign = (tmsfloat & 0x00800000) << 8;
|
||||
mant = tmsfloat & 0x007FFFFF;
|
||||
if (exp == 0xFF000000)
|
||||
{
|
||||
if (mant == 0)
|
||||
*ieeefloat = ERANGE;
|
||||
if (sign == 0)
|
||||
*ieeefloat = 1.0 / 0.0;
|
||||
else
|
||||
*ieeefloat = -1.0 / 0.0;
|
||||
return 1;
|
||||
}
|
||||
exp >>= 1;
|
||||
if (sign)
|
||||
{
|
||||
mant = (~mant) & 0x007FFFFF;
|
||||
mant += 1;
|
||||
exp += mant & 0x00800000;
|
||||
exp &= 0x7F800000;
|
||||
mant &= 0x007FFFFF;
|
||||
}
|
||||
if (tmsfloat == 0x80000000)
|
||||
sign = mant = exp = 0;
|
||||
tmsfloat = sign | exp | mant;
|
||||
*ieeefloat = *((float *) &tmsfloat);
|
||||
return 1;
|
||||
}
|
@ -1,384 +0,0 @@
|
||||
/* Disassemble V850 instructions.
|
||||
Copyright 1996, 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) 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. */
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sysdep.h"
|
||||
#include "opcode/v850.h"
|
||||
#include "dis-asm.h"
|
||||
#include "opintl.h"
|
||||
|
||||
static const char *const v850_reg_names[] =
|
||||
{ "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7",
|
||||
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
|
||||
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
|
||||
"r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp" };
|
||||
|
||||
static const char *const v850_sreg_names[] =
|
||||
{ "eipc", "eipsw", "fepc", "fepsw", "ecr", "psw", "sr6", "sr7",
|
||||
"sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15",
|
||||
"ctpc", "ctpsw", "dbpc", "dbpsw", "ctbp", "sr21", "sr22", "sr23",
|
||||
"sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31",
|
||||
"sr16", "sr17", "sr18", "sr19", "sr20", "sr21", "sr22", "sr23",
|
||||
"sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31" };
|
||||
|
||||
static const char *const v850_cc_names[] =
|
||||
{ "v", "c/l", "z", "nh", "s/n", "t", "lt", "le",
|
||||
"nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt" };
|
||||
|
||||
static int disassemble
|
||||
PARAMS ((bfd_vma, struct disassemble_info *, unsigned long));
|
||||
|
||||
static int
|
||||
disassemble (memaddr, info, insn)
|
||||
bfd_vma memaddr;
|
||||
struct disassemble_info *info;
|
||||
unsigned long insn;
|
||||
{
|
||||
struct v850_opcode * op = (struct v850_opcode *)v850_opcodes;
|
||||
const struct v850_operand * operand;
|
||||
int match = 0;
|
||||
int short_op = ((insn & 0x0600) != 0x0600);
|
||||
int bytes_read;
|
||||
int target_processor;
|
||||
|
||||
/* Special case: 32 bit MOV */
|
||||
if ((insn & 0xffe0) == 0x0620)
|
||||
short_op = true;
|
||||
|
||||
bytes_read = short_op ? 2 : 4;
|
||||
|
||||
/* If this is a two byte insn, then mask off the high bits. */
|
||||
if (short_op)
|
||||
insn &= 0xffff;
|
||||
|
||||
switch (info->mach)
|
||||
{
|
||||
case 0:
|
||||
default:
|
||||
target_processor = PROCESSOR_V850;
|
||||
break;
|
||||
|
||||
case bfd_mach_v850e:
|
||||
target_processor = PROCESSOR_V850E;
|
||||
break;
|
||||
|
||||
case bfd_mach_v850ea:
|
||||
target_processor = PROCESSOR_V850EA;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Find the opcode. */
|
||||
while (op->name)
|
||||
{
|
||||
if ((op->mask & insn) == op->opcode
|
||||
&& (op->processors & target_processor))
|
||||
{
|
||||
const unsigned char * opindex_ptr;
|
||||
unsigned int opnum;
|
||||
unsigned int memop;
|
||||
|
||||
match = 1;
|
||||
(*info->fprintf_func) (info->stream, "%s\t", op->name);
|
||||
/*fprintf (stderr, "match: mask: %x insn: %x, opcode: %x, name: %s\n", op->mask, insn, op->opcode, op->name );*/
|
||||
|
||||
memop = op->memop;
|
||||
/* Now print the operands.
|
||||
|
||||
MEMOP is the operand number at which a memory
|
||||
address specification starts, or zero if this
|
||||
instruction has no memory addresses.
|
||||
|
||||
A memory address is always two arguments.
|
||||
|
||||
This information allows us to determine when to
|
||||
insert commas into the output stream as well as
|
||||
when to insert disp[reg] expressions onto the
|
||||
output stream. */
|
||||
|
||||
for (opindex_ptr = op->operands, opnum = 1;
|
||||
*opindex_ptr != 0;
|
||||
opindex_ptr++, opnum++)
|
||||
{
|
||||
long value;
|
||||
int flag;
|
||||
int status;
|
||||
bfd_byte buffer[ 4 ];
|
||||
|
||||
operand = &v850_operands[*opindex_ptr];
|
||||
|
||||
if (operand->extract)
|
||||
value = (operand->extract) (insn, 0);
|
||||
else
|
||||
{
|
||||
if (operand->bits == -1)
|
||||
value = (insn & operand->shift);
|
||||
else
|
||||
value = (insn >> operand->shift) & ((1 << operand->bits) - 1);
|
||||
|
||||
if (operand->flags & V850_OPERAND_SIGNED)
|
||||
value = ((long)(value << (32 - operand->bits))
|
||||
>> (32 - operand->bits));
|
||||
}
|
||||
|
||||
/* The first operand is always output without any
|
||||
special handling.
|
||||
|
||||
For the following arguments:
|
||||
|
||||
If memop && opnum == memop + 1, then we need '[' since
|
||||
we're about to output the register used in a memory
|
||||
reference.
|
||||
|
||||
If memop && opnum == memop + 2, then we need ']' since
|
||||
we just finished the register in a memory reference. We
|
||||
also need a ',' before this operand.
|
||||
|
||||
Else we just need a comma.
|
||||
|
||||
We may need to output a trailing ']' if the last operand
|
||||
in an instruction is the register for a memory address.
|
||||
|
||||
The exception (and there's always an exception) is the
|
||||
"jmp" insn which needs square brackets around it's only
|
||||
register argument. */
|
||||
|
||||
if (memop && opnum == memop + 1) info->fprintf_func (info->stream, "[");
|
||||
else if (memop && opnum == memop + 2) info->fprintf_func (info->stream, "],");
|
||||
else if (memop == 1 && opnum == 1
|
||||
&& (operand->flags & V850_OPERAND_REG))
|
||||
info->fprintf_func (info->stream, "[");
|
||||
else if (opnum > 1) info->fprintf_func (info->stream, ", ");
|
||||
|
||||
/* extract the flags, ignorng ones which do not effect disassembly output. */
|
||||
flag = operand->flags;
|
||||
flag &= ~ V850_OPERAND_SIGNED;
|
||||
flag &= ~ V850_OPERAND_RELAX;
|
||||
flag &= - flag;
|
||||
|
||||
switch (flag)
|
||||
{
|
||||
case V850_OPERAND_REG: info->fprintf_func (info->stream, "%s", v850_reg_names[value]); break;
|
||||
case V850_OPERAND_SRG: info->fprintf_func (info->stream, "%s", v850_sreg_names[value]); break;
|
||||
case V850_OPERAND_CC: info->fprintf_func (info->stream, "%s", v850_cc_names[value]); break;
|
||||
case V850_OPERAND_EP: info->fprintf_func (info->stream, "ep"); break;
|
||||
default: info->fprintf_func (info->stream, "%d", value); break;
|
||||
case V850_OPERAND_DISP:
|
||||
{
|
||||
bfd_vma addr = value + memaddr;
|
||||
|
||||
/* On the v850 the top 8 bits of an address are used by an overlay manager.
|
||||
Thus it may happen that when we are looking for a symbol to match
|
||||
against an address with some of its top bits set, the search fails to
|
||||
turn up an exact match. In this case we try to find an exact match
|
||||
against a symbol in the lower address space, and if we find one, we
|
||||
use that address. We only do this for JARL instructions however, as
|
||||
we do not want to misinterpret branch instructions. */
|
||||
if (operand->bits == 22)
|
||||
{
|
||||
if ( ! info->symbol_at_address_func (addr, info)
|
||||
&& ((addr & 0xFF000000) != 0)
|
||||
&& info->symbol_at_address_func (addr & 0x00FFFFFF, info))
|
||||
{
|
||||
addr &= 0x00FFFFFF;
|
||||
}
|
||||
}
|
||||
info->print_address_func (addr, info);
|
||||
break;
|
||||
}
|
||||
|
||||
case V850E_PUSH_POP:
|
||||
{
|
||||
static int list12_regs[32] = { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
|
||||
static int list18_h_regs[32] = { 19, 18, 17, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 30, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 };
|
||||
static int list18_l_regs[32] = { 3, 2, 1, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 14, 15, 13, 12, 7, 6, 5, 4, 11, 10, 9, 8 };
|
||||
int * regs;
|
||||
int i;
|
||||
unsigned long int mask = 0;
|
||||
int pc = false;
|
||||
int sr = false;
|
||||
|
||||
|
||||
switch (operand->shift)
|
||||
{
|
||||
case 0xffe00001: regs = list12_regs; break;
|
||||
case 0xfff8000f: regs = list18_h_regs; break;
|
||||
case 0xfff8001f: regs = list18_l_regs; value &= ~0x10; break; /* Do not include magic bit */
|
||||
default:
|
||||
/* xgettext:c-format */
|
||||
fprintf (stderr, _("unknown operand shift: %x\n"), operand->shift );
|
||||
abort();
|
||||
}
|
||||
|
||||
for (i = 0; i < 32; i++)
|
||||
{
|
||||
if (value & (1 << i))
|
||||
{
|
||||
switch (regs[ i ])
|
||||
{
|
||||
default: mask |= (1 << regs[ i ]); break;
|
||||
/* xgettext:c-format */
|
||||
case 0: fprintf (stderr, _("unknown pop reg: %d\n"), i ); abort();
|
||||
case -1: pc = true; break;
|
||||
case -2: sr = true; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
info->fprintf_func (info->stream, "{");
|
||||
|
||||
if (mask || pc || sr)
|
||||
{
|
||||
if (mask)
|
||||
{
|
||||
unsigned int bit;
|
||||
int shown_one = false;
|
||||
|
||||
for (bit = 0; bit < 32; bit++)
|
||||
if (mask & (1 << bit))
|
||||
{
|
||||
unsigned long int first = bit;
|
||||
unsigned long int last;
|
||||
|
||||
if (shown_one)
|
||||
info->fprintf_func (info->stream, ", ");
|
||||
else
|
||||
shown_one = true;
|
||||
|
||||
info->fprintf_func (info->stream, v850_reg_names[first]);
|
||||
|
||||
for (bit++; bit < 32; bit++)
|
||||
if ((mask & (1 << bit)) == 0)
|
||||
break;
|
||||
|
||||
last = bit;
|
||||
|
||||
if (last > first + 1)
|
||||
{
|
||||
info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pc)
|
||||
info->fprintf_func (info->stream, "%sPC", mask ? ", " : "");
|
||||
if (sr)
|
||||
info->fprintf_func (info->stream, "%sSR", (mask || pc) ? ", " : "");
|
||||
}
|
||||
|
||||
info->fprintf_func (info->stream, "}");
|
||||
}
|
||||
break;
|
||||
|
||||
case V850E_IMMEDIATE16:
|
||||
status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info);
|
||||
if (status == 0)
|
||||
{
|
||||
bytes_read += 2;
|
||||
value = bfd_getl16 (buffer);
|
||||
|
||||
/* If this is a DISPOSE instruction with ff set to 0x10, then shift value up by 16. */
|
||||
if ((insn & 0x001fffc0) == 0x00130780)
|
||||
value <<= 16;
|
||||
|
||||
info->fprintf_func (info->stream, "0x%x", value);
|
||||
}
|
||||
else
|
||||
{
|
||||
info->memory_error_func (status, memaddr + bytes_read, info);
|
||||
}
|
||||
break;
|
||||
|
||||
case V850E_IMMEDIATE32:
|
||||
status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info);
|
||||
if (status == 0)
|
||||
{
|
||||
bytes_read += 4;
|
||||
value = bfd_getl32 (buffer);
|
||||
info->fprintf_func (info->stream, "0x%lx", value);
|
||||
}
|
||||
else
|
||||
{
|
||||
info->memory_error_func (status, memaddr + bytes_read, info);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Handle jmp correctly. */
|
||||
if (memop == 1 && opnum == 1
|
||||
&& ((operand->flags & V850_OPERAND_REG) != 0))
|
||||
(*info->fprintf_func) (info->stream, "]");
|
||||
}
|
||||
|
||||
/* Close any square bracket we left open. */
|
||||
if (memop && opnum == memop + 2)
|
||||
(*info->fprintf_func) (info->stream, "]");
|
||||
|
||||
/* All done. */
|
||||
break;
|
||||
}
|
||||
op++;
|
||||
}
|
||||
|
||||
if (!match)
|
||||
{
|
||||
if (short_op)
|
||||
info->fprintf_func (info->stream, ".short\t0x%04x", insn);
|
||||
else
|
||||
info->fprintf_func (info->stream, ".long\t0x%08x", insn);
|
||||
}
|
||||
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
int
|
||||
print_insn_v850 (memaddr, info)
|
||||
bfd_vma memaddr;
|
||||
struct disassemble_info * info;
|
||||
{
|
||||
int status;
|
||||
bfd_byte buffer[ 4 ];
|
||||
unsigned long insn = 0;
|
||||
|
||||
/* First figure out how big the opcode is. */
|
||||
|
||||
status = info->read_memory_func (memaddr, buffer, 2, info);
|
||||
if (status == 0)
|
||||
{
|
||||
insn = bfd_getl16 (buffer);
|
||||
|
||||
if ( (insn & 0x0600) == 0x0600
|
||||
&& (insn & 0xffe0) != 0x0620)
|
||||
{
|
||||
/* If this is a 4 byte insn, read 4 bytes of stuff. */
|
||||
status = info->read_memory_func (memaddr, buffer, 4, info);
|
||||
|
||||
if (status == 0)
|
||||
insn = bfd_getl32 (buffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (status != 0)
|
||||
{
|
||||
info->memory_error_func (status, memaddr, info);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Make sure we tell our caller how many bytes we consumed. */
|
||||
return disassemble (memaddr, info, insn);
|
||||
}
|
@ -1,813 +0,0 @@
|
||||
/* Assemble V850 instructions.
|
||||
Copyright 1996, 1997, 1998, 2000, 2001 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) 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. */
|
||||
|
||||
#include "sysdep.h"
|
||||
#include "opcode/v850.h"
|
||||
#include <stdio.h>
|
||||
#include "opintl.h"
|
||||
|
||||
/* regular opcode */
|
||||
#define OP(x) ((x & 0x3f) << 5)
|
||||
#define OP_MASK OP (0x3f)
|
||||
|
||||
/* conditional branch opcode */
|
||||
#define BOP(x) ((0x0b << 7) | (x & 0x0f))
|
||||
#define BOP_MASK ((0x0f << 7) | 0x0f)
|
||||
|
||||
/* one-word opcodes */
|
||||
#define one(x) ((unsigned int) (x))
|
||||
|
||||
/* two-word opcodes */
|
||||
#define two(x,y) ((unsigned int) (x) | ((unsigned int) (y) << 16))
|
||||
|
||||
static long unsigned insert_d9 PARAMS ((long unsigned, long, const char **));
|
||||
static long unsigned extract_d9 PARAMS ((long unsigned, int *));
|
||||
static long unsigned insert_d22 PARAMS ((long unsigned, long, const char **));
|
||||
static long unsigned extract_d22 PARAMS ((long unsigned, int *));
|
||||
static long unsigned insert_d16_15 PARAMS ((long unsigned, long, const char **));
|
||||
static long unsigned extract_d16_15 PARAMS ((long unsigned, int *));
|
||||
static long unsigned insert_d8_7 PARAMS ((long unsigned, long, const char **));
|
||||
static long unsigned extract_d8_7 PARAMS ((long unsigned, int *));
|
||||
static long unsigned insert_d8_6 PARAMS ((long unsigned, long, const char **));
|
||||
static long unsigned extract_d8_6 PARAMS ((long unsigned, int *));
|
||||
static long unsigned insert_d5_4 PARAMS ((long unsigned, long, const char **));
|
||||
static long unsigned extract_d5_4 PARAMS ((long unsigned, int *));
|
||||
static long unsigned insert_d16_16 PARAMS ((long unsigned, long, const char **));
|
||||
static long unsigned extract_d16_16 PARAMS ((long unsigned, int *));
|
||||
static long unsigned insert_i9 PARAMS ((long unsigned, long, const char **));
|
||||
static long unsigned extract_i9 PARAMS ((long unsigned, int *));
|
||||
static long unsigned insert_u9 PARAMS ((long unsigned, long, const char **));
|
||||
static long unsigned extract_u9 PARAMS ((long unsigned, int *));
|
||||
static long unsigned insert_spe PARAMS ((long unsigned, long, const char **));
|
||||
static long unsigned extract_spe PARAMS ((long unsigned, int *));
|
||||
static long unsigned insert_i5div PARAMS ((long unsigned, long, const char **));
|
||||
static long unsigned extract_i5div PARAMS ((long unsigned, int *));
|
||||
|
||||
|
||||
/* The functions used to insert and extract complicated operands. */
|
||||
|
||||
/* Note: There is a conspiracy between these functions and
|
||||
v850_insert_operand() in gas/config/tc-v850.c. Error messages
|
||||
containing the string 'out of range' will be ignored unless a
|
||||
specific command line option is given to GAS. */
|
||||
|
||||
static const char * not_valid = N_ ("displacement value is not in range and is not aligned");
|
||||
static const char * out_of_range = N_ ("displacement value is out of range");
|
||||
static const char * not_aligned = N_ ("displacement value is not aligned");
|
||||
|
||||
static const char * immediate_out_of_range = N_ ("immediate value is out of range");
|
||||
|
||||
static unsigned long
|
||||
insert_d9 (insn, value, errmsg)
|
||||
unsigned long insn;
|
||||
long value;
|
||||
const char ** errmsg;
|
||||
{
|
||||
if (value > 0xff || value < -0x100)
|
||||
{
|
||||
if ((value % 2) != 0)
|
||||
* errmsg = _("branch value not in range and to odd offset");
|
||||
else
|
||||
* errmsg = _("branch value out of range");
|
||||
}
|
||||
else if ((value % 2) != 0)
|
||||
* errmsg = _("branch to odd offset");
|
||||
|
||||
return (insn | ((value & 0x1f0) << 7) | ((value & 0x0e) << 3));
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
extract_d9 (insn, invalid)
|
||||
unsigned long insn;
|
||||
int * invalid ATTRIBUTE_UNUSED;
|
||||
{
|
||||
unsigned long ret = ((insn & 0xf800) >> 7) | ((insn & 0x0070) >> 3);
|
||||
|
||||
if ((insn & 0x8000) != 0)
|
||||
ret -= 0x0200;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
insert_d22 (insn, value, errmsg)
|
||||
unsigned long insn;
|
||||
long value;
|
||||
const char ** errmsg;
|
||||
{
|
||||
if (value > 0x1fffff || value < -0x200000)
|
||||
{
|
||||
if ((value % 2) != 0)
|
||||
* errmsg = _("branch value not in range and to an odd offset");
|
||||
else
|
||||
* errmsg = _("branch value out of range");
|
||||
}
|
||||
else if ((value % 2) != 0)
|
||||
* errmsg = _("branch to odd offset");
|
||||
|
||||
return (insn | ((value & 0xfffe) << 16) | ((value & 0x3f0000) >> 16));
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
extract_d22 (insn, invalid)
|
||||
unsigned long insn;
|
||||
int * invalid ATTRIBUTE_UNUSED;
|
||||
{
|
||||
signed long ret = ((insn & 0xfffe0000) >> 16) | ((insn & 0x3f) << 16);
|
||||
|
||||
return (unsigned long) ((ret << 10) >> 10);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
insert_d16_15 (insn, value, errmsg)
|
||||
unsigned long insn;
|
||||
long value;
|
||||
const char ** errmsg;
|
||||
{
|
||||
if (value > 0x7fff || value < -0x8000)
|
||||
{
|
||||
if ((value % 2) != 0)
|
||||
* errmsg = _(not_valid);
|
||||
else
|
||||
* errmsg = _(out_of_range);
|
||||
}
|
||||
else if ((value % 2) != 0)
|
||||
* errmsg = _(not_aligned);
|
||||
|
||||
return insn | ((value & 0xfffe) << 16);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
extract_d16_15 (insn, invalid)
|
||||
unsigned long insn;
|
||||
int * invalid ATTRIBUTE_UNUSED;
|
||||
{
|
||||
signed long ret = (insn & 0xfffe0000);
|
||||
|
||||
return ret >> 16;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
insert_d8_7 (insn, value, errmsg)
|
||||
unsigned long insn;
|
||||
long value;
|
||||
const char ** errmsg;
|
||||
{
|
||||
if (value > 0xff || value < 0)
|
||||
{
|
||||
if ((value % 2) != 0)
|
||||
* errmsg = _(not_valid);
|
||||
else
|
||||
* errmsg = _(out_of_range);
|
||||
}
|
||||
else if ((value % 2) != 0)
|
||||
* errmsg = _(not_aligned);
|
||||
|
||||
value >>= 1;
|
||||
|
||||
return (insn | (value & 0x7f));
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
extract_d8_7 (insn, invalid)
|
||||
unsigned long insn;
|
||||
int * invalid ATTRIBUTE_UNUSED;
|
||||
{
|
||||
unsigned long ret = (insn & 0x7f);
|
||||
|
||||
return ret << 1;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
insert_d8_6 (insn, value, errmsg)
|
||||
unsigned long insn;
|
||||
long value;
|
||||
const char ** errmsg;
|
||||
{
|
||||
if (value > 0xff || value < 0)
|
||||
{
|
||||
if ((value % 4) != 0)
|
||||
*errmsg = _(not_valid);
|
||||
else
|
||||
* errmsg = _(out_of_range);
|
||||
}
|
||||
else if ((value % 4) != 0)
|
||||
* errmsg = _(not_aligned);
|
||||
|
||||
value >>= 1;
|
||||
|
||||
return (insn | (value & 0x7e));
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
extract_d8_6 (insn, invalid)
|
||||
unsigned long insn;
|
||||
int * invalid ATTRIBUTE_UNUSED;
|
||||
{
|
||||
unsigned long ret = (insn & 0x7e);
|
||||
|
||||
return ret << 1;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
insert_d5_4 (insn, value, errmsg)
|
||||
unsigned long insn;
|
||||
long value;
|
||||
const char ** errmsg;
|
||||
{
|
||||
if (value > 0x1f || value < 0)
|
||||
{
|
||||
if (value & 1)
|
||||
* errmsg = _(not_valid);
|
||||
else
|
||||
*errmsg = _(out_of_range);
|
||||
}
|
||||
else if (value & 1)
|
||||
* errmsg = _(not_aligned);
|
||||
|
||||
value >>= 1;
|
||||
|
||||
return (insn | (value & 0x0f));
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
extract_d5_4 (insn, invalid)
|
||||
unsigned long insn;
|
||||
int * invalid ATTRIBUTE_UNUSED;
|
||||
{
|
||||
unsigned long ret = (insn & 0x0f);
|
||||
|
||||
return ret << 1;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
insert_d16_16 (insn, value, errmsg)
|
||||
unsigned long insn;
|
||||
signed long value;
|
||||
const char ** errmsg;
|
||||
{
|
||||
if (value > 0x7fff || value < -0x8000)
|
||||
* errmsg = _(out_of_range);
|
||||
|
||||
return (insn | ((value & 0xfffe) << 16) | ((value & 1) << 5));
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
extract_d16_16 (insn, invalid)
|
||||
unsigned long insn;
|
||||
int * invalid ATTRIBUTE_UNUSED;
|
||||
{
|
||||
signed long ret = insn & 0xfffe0000;
|
||||
|
||||
ret >>= 16;
|
||||
|
||||
ret |= ((insn & 0x20) >> 5);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
insert_i9 (insn, value, errmsg)
|
||||
unsigned long insn;
|
||||
signed long value;
|
||||
const char ** errmsg;
|
||||
{
|
||||
if (value > 0xff || value < -0x100)
|
||||
* errmsg = _(immediate_out_of_range);
|
||||
|
||||
return insn | ((value & 0x1e0) << 13) | (value & 0x1f);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
extract_i9 (insn, invalid)
|
||||
unsigned long insn;
|
||||
int * invalid ATTRIBUTE_UNUSED;
|
||||
{
|
||||
signed long ret = insn & 0x003c0000;
|
||||
|
||||
ret <<= 10;
|
||||
ret >>= 23;
|
||||
|
||||
ret |= (insn & 0x1f);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
insert_u9 (insn, v, errmsg)
|
||||
unsigned long insn;
|
||||
long v;
|
||||
const char ** errmsg;
|
||||
{
|
||||
unsigned long value = (unsigned long) v;
|
||||
if (value > 0x1ff)
|
||||
* errmsg = _(immediate_out_of_range);
|
||||
|
||||
return insn | ((value & 0x1e0) << 13) | (value & 0x1f);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
extract_u9 (insn, invalid)
|
||||
unsigned long insn;
|
||||
int * invalid ATTRIBUTE_UNUSED;
|
||||
{
|
||||
unsigned long ret = insn & 0x003c0000;
|
||||
|
||||
ret >>= 13;
|
||||
|
||||
ret |= (insn & 0x1f);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
insert_spe (insn, v, errmsg)
|
||||
unsigned long insn;
|
||||
long v;
|
||||
const char ** errmsg;
|
||||
{
|
||||
unsigned long value = (unsigned long) v;
|
||||
|
||||
if (value != 3)
|
||||
* errmsg = _("invalid register for stack adjustment");
|
||||
|
||||
return insn & (~ 0x180000);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
extract_spe (insn, invalid)
|
||||
unsigned long insn ATTRIBUTE_UNUSED;
|
||||
int * invalid ATTRIBUTE_UNUSED;
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
insert_i5div (insn, v, errmsg)
|
||||
unsigned long insn;
|
||||
long v;
|
||||
const char ** errmsg;
|
||||
{
|
||||
unsigned long value = (unsigned long) v;
|
||||
|
||||
if (value > 0x1ff)
|
||||
{
|
||||
if (value & 1)
|
||||
* errmsg = _("immediate value not in range and not even");
|
||||
else
|
||||
* errmsg = _(immediate_out_of_range);
|
||||
}
|
||||
else if (value & 1)
|
||||
* errmsg = _("immediate value must be even");
|
||||
|
||||
value = 32 - value;
|
||||
|
||||
return insn | ((value & 0x1e) << 17);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
extract_i5div (insn, invalid)
|
||||
unsigned long insn;
|
||||
int * invalid ATTRIBUTE_UNUSED;
|
||||
{
|
||||
unsigned long ret = insn & 0x3c0000;
|
||||
|
||||
ret >>= 17;
|
||||
|
||||
ret = 32 - ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Warning: code in gas/config/tc-v850.c examines the contents of this array.
|
||||
If you change any of the values here, be sure to look for side effects in
|
||||
that code. */
|
||||
const struct v850_operand v850_operands[] =
|
||||
{
|
||||
#define UNUSED 0
|
||||
{ 0, 0, NULL, NULL, 0 },
|
||||
|
||||
/* The R1 field in a format 1, 6, 7, or 9 insn. */
|
||||
#define R1 (UNUSED + 1)
|
||||
{ 5, 0, NULL, NULL, V850_OPERAND_REG },
|
||||
|
||||
/* As above, but register 0 is not allowed. */
|
||||
#define R1_NOTR0 (R1 + 1)
|
||||
{ 5, 0, NULL, NULL, V850_OPERAND_REG | V850_NOT_R0 },
|
||||
|
||||
/* The R2 field in a format 1, 2, 4, 5, 6, 7, 9 insn. */
|
||||
#define R2 (R1_NOTR0 + 1)
|
||||
{ 5, 11, NULL, NULL, V850_OPERAND_REG },
|
||||
|
||||
/* As above, but register 0 is not allowed. */
|
||||
#define R2_NOTR0 (R2 + 1)
|
||||
{ 5, 11, NULL, NULL, V850_OPERAND_REG | V850_NOT_R0 },
|
||||
|
||||
/* The imm5 field in a format 2 insn. */
|
||||
#define I5 (R2_NOTR0 + 1)
|
||||
{ 5, 0, NULL, NULL, V850_OPERAND_SIGNED },
|
||||
|
||||
/* The unsigned imm5 field in a format 2 insn. */
|
||||
#define I5U (I5 + 1)
|
||||
{ 5, 0, NULL, NULL, 0 },
|
||||
|
||||
/* The imm16 field in a format 6 insn. */
|
||||
#define I16 (I5U + 1)
|
||||
{ 16, 16, NULL, NULL, V850_OPERAND_SIGNED },
|
||||
|
||||
/* The signed disp7 field in a format 4 insn. */
|
||||
#define D7 (I16 + 1)
|
||||
{ 7, 0, NULL, NULL, 0},
|
||||
|
||||
/* The disp16 field in a format 6 insn. */
|
||||
#define D16_15 (D7 + 1)
|
||||
{ 15, 17, insert_d16_15, extract_d16_15, V850_OPERAND_SIGNED },
|
||||
|
||||
/* The 3 bit immediate field in format 8 insn. */
|
||||
#define B3 (D16_15 + 1)
|
||||
{ 3, 11, NULL, NULL, 0 },
|
||||
|
||||
/* The 4 bit condition code in a setf instruction */
|
||||
#define CCCC (B3 + 1)
|
||||
{ 4, 0, NULL, NULL, V850_OPERAND_CC },
|
||||
|
||||
/* The unsigned DISP8 field in a format 4 insn. */
|
||||
#define D8_7 (CCCC + 1)
|
||||
{ 7, 0, insert_d8_7, extract_d8_7, 0 },
|
||||
|
||||
/* The unsigned DISP8 field in a format 4 insn. */
|
||||
#define D8_6 (D8_7 + 1)
|
||||
{ 6, 1, insert_d8_6, extract_d8_6, 0 },
|
||||
|
||||
/* System register operands. */
|
||||
#define SR1 (D8_6 + 1)
|
||||
{ 5, 0, NULL, NULL, V850_OPERAND_SRG },
|
||||
|
||||
/* EP Register. */
|
||||
#define EP (SR1 + 1)
|
||||
{ 0, 0, NULL, NULL, V850_OPERAND_EP },
|
||||
|
||||
/* The imm16 field (unsigned) in a format 6 insn. */
|
||||
#define I16U (EP + 1)
|
||||
{ 16, 16, NULL, NULL, 0},
|
||||
|
||||
/* The R2 field as a system register. */
|
||||
#define SR2 (I16U + 1)
|
||||
{ 5, 11, NULL, NULL, V850_OPERAND_SRG },
|
||||
|
||||
/* The disp16 field in a format 8 insn. */
|
||||
#define D16 (SR2 + 1)
|
||||
{ 16, 16, NULL, NULL, V850_OPERAND_SIGNED },
|
||||
|
||||
/* The DISP9 field in a format 3 insn, relaxable. */
|
||||
#define D9_RELAX (D16 + 1)
|
||||
{ 9, 0, insert_d9, extract_d9, V850_OPERAND_RELAX | V850_OPERAND_SIGNED | V850_OPERAND_DISP },
|
||||
|
||||
/* The DISP22 field in a format 4 insn, relaxable.
|
||||
This _must_ follow D9_RELAX; the assembler assumes that the longer
|
||||
version immediately follows the shorter version for relaxing. */
|
||||
#define D22 (D9_RELAX + 1)
|
||||
{ 22, 0, insert_d22, extract_d22, V850_OPERAND_SIGNED | V850_OPERAND_DISP },
|
||||
|
||||
/* The signed disp4 field in a format 4 insn. */
|
||||
#define D4 (D22 + 1)
|
||||
{ 4, 0, NULL, NULL, 0},
|
||||
|
||||
/* The unsigned disp5 field in a format 4 insn. */
|
||||
#define D5_4 (D4 + 1)
|
||||
{ 4, 0, insert_d5_4, extract_d5_4, 0 },
|
||||
|
||||
/* The disp16 field in an format 7 unsigned byte load insn. */
|
||||
#define D16_16 (D5_4 + 1)
|
||||
{ -1, 0xfffe0020, insert_d16_16, extract_d16_16, 0 },
|
||||
|
||||
/* Third register in conditional moves. */
|
||||
#define R3 (D16_16 + 1)
|
||||
{ 5, 27, NULL, NULL, V850_OPERAND_REG },
|
||||
|
||||
/* Condition code in conditional moves. */
|
||||
#define MOVCC (R3 + 1)
|
||||
{ 4, 17, NULL, NULL, V850_OPERAND_CC },
|
||||
|
||||
/* The imm9 field in a multiply word. */
|
||||
#define I9 (MOVCC + 1)
|
||||
{ 9, 0, insert_i9, extract_i9, V850_OPERAND_SIGNED },
|
||||
|
||||
/* The unsigned imm9 field in a multiply word. */
|
||||
#define U9 (I9 + 1)
|
||||
{ 9, 0, insert_u9, extract_u9, 0 },
|
||||
|
||||
/* A list of registers in a prepare/dispose instruction. */
|
||||
#define LIST12 (U9 + 1)
|
||||
{ -1, 0xffe00001, NULL, NULL, V850E_PUSH_POP },
|
||||
|
||||
/* The IMM6 field in a call instruction. */
|
||||
#define I6 (LIST12 + 1)
|
||||
{ 6, 0, NULL, NULL, 0 },
|
||||
|
||||
/* The 16 bit immediate following a 32 bit instruction. */
|
||||
#define IMM16 (I6 + 1)
|
||||
{ 16, 16, NULL, NULL, V850_OPERAND_SIGNED | V850E_IMMEDIATE16 },
|
||||
|
||||
/* The 32 bit immediate following a 32 bit instruction. */
|
||||
#define IMM32 (IMM16 + 1)
|
||||
{ 0, 0, NULL, NULL, V850E_IMMEDIATE32 },
|
||||
|
||||
/* The imm5 field in a push/pop instruction. */
|
||||
#define IMM5 (IMM32 + 1)
|
||||
{ 5, 1, NULL, NULL, 0 },
|
||||
|
||||
/* Reg2 in dispose instruction. */
|
||||
#define R2DISPOSE (IMM5 + 1)
|
||||
{ 5, 16, NULL, NULL, V850_OPERAND_REG | V850_NOT_R0 },
|
||||
|
||||
/* Stack pointer in prepare instruction. */
|
||||
#define SP (R2DISPOSE + 1)
|
||||
{ 2, 19, insert_spe, extract_spe, V850_OPERAND_REG },
|
||||
|
||||
/* The IMM5 field in a divide N step instruction. */
|
||||
#define I5DIV (SP + 1)
|
||||
{ 9, 0, insert_i5div, extract_i5div, V850_OPERAND_SIGNED },
|
||||
|
||||
/* The list of registers in a PUSHMH/POPMH instruction. */
|
||||
#define LIST18_H (I5DIV + 1)
|
||||
{ -1, 0xfff8000f, NULL, NULL, V850E_PUSH_POP },
|
||||
|
||||
/* The list of registers in a PUSHML/POPML instruction. */
|
||||
#define LIST18_L (LIST18_H + 1)
|
||||
{ -1, 0xfff8001f, NULL, NULL, V850E_PUSH_POP }, /* The setting of the 4th bit is a flag to disassmble() in v850-dis.c */
|
||||
} ;
|
||||
|
||||
|
||||
/* reg-reg instruction format (Format I) */
|
||||
#define IF1 {R1, R2}
|
||||
|
||||
/* imm-reg instruction format (Format II) */
|
||||
#define IF2 {I5, R2}
|
||||
|
||||
/* conditional branch instruction format (Format III) */
|
||||
#define IF3 {D9_RELAX}
|
||||
|
||||
/* 3 operand instruction (Format VI) */
|
||||
#define IF6 {I16, R1, R2}
|
||||
|
||||
/* 3 operand instruction (Format VI) */
|
||||
#define IF6U {I16U, R1, R2}
|
||||
|
||||
|
||||
|
||||
/* The opcode table.
|
||||
|
||||
The format of the opcode table is:
|
||||
|
||||
NAME OPCODE MASK { OPERANDS } MEMOP PROCESSOR
|
||||
|
||||
NAME is the name of the instruction.
|
||||
OPCODE is the instruction opcode.
|
||||
MASK is the opcode mask; this is used to tell the disassembler
|
||||
which bits in the actual opcode must match OPCODE.
|
||||
OPERANDS is the list of operands.
|
||||
MEMOP specifies which operand (if any) is a memory operand.
|
||||
PROCESSORS specifies which CPU(s) support the opcode.
|
||||
|
||||
The disassembler reads the table in order and prints the first
|
||||
instruction which matches, so this table is sorted to put more
|
||||
specific instructions before more general instructions. It is also
|
||||
sorted by major opcode.
|
||||
|
||||
The table is also sorted by name. This is used by the assembler.
|
||||
When parsing an instruction the assembler finds the first occurance
|
||||
of the name of the instruciton in this table and then attempts to
|
||||
match the instruction's arguments with description of the operands
|
||||
associated with the entry it has just found in this table. If the
|
||||
match fails the assembler looks at the next entry in this table.
|
||||
If that entry has the same name as the previous entry, then it
|
||||
tries to match the instruction against that entry and so on. This
|
||||
is how the assembler copes with multiple, different formats of the
|
||||
same instruction. */
|
||||
|
||||
const struct v850_opcode v850_opcodes[] =
|
||||
{
|
||||
{ "breakpoint", 0xffff, 0xffff, {UNUSED}, 0, PROCESSOR_ALL },
|
||||
|
||||
{ "jmp", one (0x0060), one (0xffe0), {R1}, 1, PROCESSOR_ALL },
|
||||
|
||||
/* load/store instructions */
|
||||
{ "sld.bu", one (0x0300), one (0x0780), {D7, EP, R2_NOTR0}, 1, PROCESSOR_V850EA },
|
||||
{ "sld.bu", one (0x0060), one (0x07f0), {D4, EP, R2_NOTR0}, 1, PROCESSOR_V850E },
|
||||
|
||||
{ "sld.hu", one (0x0400), one (0x0780), {D8_7, EP, R2_NOTR0}, 1, PROCESSOR_V850EA },
|
||||
{ "sld.hu", one (0x0070), one (0x07f0), {D5_4, EP, R2_NOTR0}, 1, PROCESSOR_V850E },
|
||||
|
||||
{ "sld.b", one (0x0060), one (0x07f0), {D4, EP, R2}, 1, PROCESSOR_V850EA },
|
||||
{ "sld.b", one (0x0300), one (0x0780), {D7, EP, R2}, 1, PROCESSOR_V850E },
|
||||
{ "sld.b", one (0x0300), one (0x0780), {D7, EP, R2}, 1, PROCESSOR_V850 },
|
||||
|
||||
{ "sld.h", one (0x0070), one (0x07f0), {D5_4, EP, R2}, 1, PROCESSOR_V850EA },
|
||||
{ "sld.h", one (0x0400), one (0x0780), {D8_7, EP, R2}, 1, PROCESSOR_V850E },
|
||||
{ "sld.h", one (0x0400), one (0x0780), {D8_7, EP, R2}, 1, PROCESSOR_V850 },
|
||||
{ "sld.w", one (0x0500), one (0x0781), {D8_6, EP, R2}, 1, PROCESSOR_ALL },
|
||||
{ "sst.b", one (0x0380), one (0x0780), {R2, D7, EP}, 2, PROCESSOR_ALL },
|
||||
{ "sst.h", one (0x0480), one (0x0780), {R2, D8_7, EP}, 2, PROCESSOR_ALL },
|
||||
{ "sst.w", one (0x0501), one (0x0781), {R2, D8_6, EP}, 2, PROCESSOR_ALL },
|
||||
|
||||
{ "pushml", two (0x07e0, 0x0001), two (0xfff0, 0x0007), {LIST18_L}, 0, PROCESSOR_V850EA },
|
||||
{ "pushmh", two (0x07e0, 0x0003), two (0xfff0, 0x0007), {LIST18_H}, 0, PROCESSOR_V850EA },
|
||||
{ "popml", two (0x07f0, 0x0001), two (0xfff0, 0x0007), {LIST18_L}, 0, PROCESSOR_V850EA },
|
||||
{ "popmh", two (0x07f0, 0x0003), two (0xfff0, 0x0007), {LIST18_H}, 0, PROCESSOR_V850EA },
|
||||
{ "prepare", two (0x0780, 0x0003), two (0xffc0, 0x001f), {LIST12, IMM5, SP}, 0, PROCESSOR_NOT_V850 },
|
||||
{ "prepare", two (0x0780, 0x000b), two (0xffc0, 0x001f), {LIST12, IMM5, IMM16}, 0, PROCESSOR_NOT_V850 },
|
||||
{ "prepare", two (0x0780, 0x0013), two (0xffc0, 0x001f), {LIST12, IMM5, IMM16}, 0, PROCESSOR_NOT_V850 },
|
||||
{ "prepare", two (0x0780, 0x001b), two (0xffc0, 0x001f), {LIST12, IMM5, IMM32}, 0, PROCESSOR_NOT_V850 },
|
||||
{ "prepare", two (0x0780, 0x0001), two (0xffc0, 0x001f), {LIST12, IMM5}, 0, PROCESSOR_NOT_V850 },
|
||||
{ "dispose", one (0x0640), one (0xffc0), {IMM5, LIST12, R2DISPOSE},0, PROCESSOR_NOT_V850 },
|
||||
{ "dispose", two (0x0640, 0x0000), two (0xffc0, 0x001f), {IMM5, LIST12}, 0, PROCESSOR_NOT_V850 },
|
||||
|
||||
{ "ld.b", two (0x0700, 0x0000), two (0x07e0, 0x0000), {D16, R1, R2}, 1, PROCESSOR_ALL },
|
||||
{ "ld.h", two (0x0720, 0x0000), two (0x07e0, 0x0001), {D16_15, R1, R2}, 1, PROCESSOR_ALL },
|
||||
{ "ld.w", two (0x0720, 0x0001), two (0x07e0, 0x0001), {D16_15, R1, R2}, 1, PROCESSOR_ALL },
|
||||
{ "ld.bu", two (0x0780, 0x0001), two (0x07c0, 0x0001), {D16_16, R1, R2_NOTR0}, 1, PROCESSOR_NOT_V850 },
|
||||
{ "ld.hu", two (0x07e0, 0x0001), two (0x07e0, 0x0001), {D16_15, R1, R2_NOTR0}, 1, PROCESSOR_NOT_V850 },
|
||||
{ "st.b", two (0x0740, 0x0000), two (0x07e0, 0x0000), {R2, D16, R1}, 2, PROCESSOR_ALL },
|
||||
{ "st.h", two (0x0760, 0x0000), two (0x07e0, 0x0001), {R2, D16_15, R1}, 2, PROCESSOR_ALL },
|
||||
{ "st.w", two (0x0760, 0x0001), two (0x07e0, 0x0001), {R2, D16_15, R1}, 2, PROCESSOR_ALL },
|
||||
|
||||
/* byte swap/extend instructions */
|
||||
{ "zxb", one (0x0080), one (0xffe0), {R1_NOTR0}, 0, PROCESSOR_NOT_V850 },
|
||||
{ "zxh", one (0x00c0), one (0xffe0), {R1_NOTR0}, 0, PROCESSOR_NOT_V850 },
|
||||
{ "sxb", one (0x00a0), one (0xffe0), {R1_NOTR0}, 0, PROCESSOR_NOT_V850 },
|
||||
{ "sxh", one (0x00e0), one (0xffe0), {R1_NOTR0}, 0, PROCESSOR_NOT_V850 },
|
||||
{ "bsh", two (0x07e0, 0x0342), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_NOT_V850 },
|
||||
{ "bsw", two (0x07e0, 0x0340), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_NOT_V850 },
|
||||
{ "hsw", two (0x07e0, 0x0344), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_NOT_V850 },
|
||||
|
||||
/* jump table instructions */
|
||||
{ "switch", one (0x0040), one (0xffe0), {R1}, 1, PROCESSOR_NOT_V850 },
|
||||
{ "callt", one (0x0200), one (0xffc0), {I6}, 0, PROCESSOR_NOT_V850 },
|
||||
{ "ctret", two (0x07e0, 0x0144), two (0xffff, 0xffff), {0}, 0, PROCESSOR_NOT_V850 },
|
||||
|
||||
/* arithmetic operation instructions */
|
||||
{ "setf", two (0x07e0, 0x0000), two (0x07f0, 0xffff), {CCCC, R2}, 0, PROCESSOR_ALL },
|
||||
{ "cmov", two (0x07e0, 0x0320), two (0x07e0, 0x07e1), {MOVCC, R1, R2, R3}, 0, PROCESSOR_NOT_V850 },
|
||||
{ "cmov", two (0x07e0, 0x0300), two (0x07e0, 0x07e1), {MOVCC, I5, R2, R3}, 0, PROCESSOR_NOT_V850 },
|
||||
|
||||
{ "mul", two (0x07e0, 0x0220), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 },
|
||||
{ "mul", two (0x07e0, 0x0240), two (0x07e0, 0x07c3), {I9, R2, R3}, 0, PROCESSOR_NOT_V850 },
|
||||
{ "mulu", two (0x07e0, 0x0222), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 },
|
||||
{ "mulu", two (0x07e0, 0x0242), two (0x07e0, 0x07c3), {U9, R2, R3}, 0, PROCESSOR_NOT_V850 },
|
||||
|
||||
{ "div", two (0x07e0, 0x02c0), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 },
|
||||
{ "divu", two (0x07e0, 0x02c2), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 },
|
||||
{ "divhu", two (0x07e0, 0x0282), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 },
|
||||
{ "divh", two (0x07e0, 0x0280), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 },
|
||||
{ "divh", OP (0x02), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL },
|
||||
|
||||
{ "divhn", two (0x07e0, 0x0280), two (0x07e0, 0x07c3), {I5DIV, R1, R2, R3}, 0, PROCESSOR_V850EA },
|
||||
{ "divhun", two (0x07e0, 0x0282), two (0x07e0, 0x07c3), {I5DIV, R1, R2, R3}, 0, PROCESSOR_V850EA },
|
||||
{ "divn", two (0x07e0, 0x02c0), two (0x07e0, 0x07c3), {I5DIV, R1, R2, R3}, 0, PROCESSOR_V850EA },
|
||||
{ "divun", two (0x07e0, 0x02c2), two (0x07e0, 0x07c3), {I5DIV, R1, R2, R3}, 0, PROCESSOR_V850EA },
|
||||
{ "sdivhn", two (0x07e0, 0x0180), two (0x07e0, 0x07c3), {I5DIV, R1, R2, R3}, 0, PROCESSOR_V850EA },
|
||||
{ "sdivhun", two (0x07e0, 0x0182), two (0x07e0, 0x07c3), {I5DIV, R1, R2, R3}, 0, PROCESSOR_V850EA },
|
||||
{ "sdivn", two (0x07e0, 0x01c0), two (0x07e0, 0x07c3), {I5DIV, R1, R2, R3}, 0, PROCESSOR_V850EA },
|
||||
{ "sdivun", two (0x07e0, 0x01c2), two (0x07e0, 0x07c3), {I5DIV, R1, R2, R3}, 0, PROCESSOR_V850EA },
|
||||
|
||||
{ "nop", one (0x00), one (0xffff), {0}, 0, PROCESSOR_ALL },
|
||||
{ "mov", OP (0x10), OP_MASK, {I5, R2_NOTR0}, 0, PROCESSOR_ALL },
|
||||
{ "mov", one (0x0620), one (0xffe0), {IMM32, R1_NOTR0}, 0, PROCESSOR_NOT_V850 },
|
||||
{ "mov", OP (0x00), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL },
|
||||
{ "movea", OP (0x31), OP_MASK, {I16, R1, R2_NOTR0}, 0, PROCESSOR_ALL },
|
||||
{ "movhi", OP (0x32), OP_MASK, {I16U, R1, R2_NOTR0}, 0, PROCESSOR_ALL },
|
||||
{ "add", OP (0x0e), OP_MASK, IF1, 0, PROCESSOR_ALL },
|
||||
{ "add", OP (0x12), OP_MASK, IF2, 0, PROCESSOR_ALL },
|
||||
{ "addi", OP (0x30), OP_MASK, IF6, 0, PROCESSOR_ALL },
|
||||
{ "sub", OP (0x0d), OP_MASK, IF1, 0, PROCESSOR_ALL },
|
||||
{ "subr", OP (0x0c), OP_MASK, IF1, 0, PROCESSOR_ALL },
|
||||
{ "mulh", OP (0x17), OP_MASK, {I5, R2_NOTR0}, 0, PROCESSOR_ALL },
|
||||
{ "mulh", OP (0x07), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL },
|
||||
{ "mulhi", OP (0x37), OP_MASK, {I16, R1, R2_NOTR0}, 0, PROCESSOR_ALL },
|
||||
{ "cmp", OP (0x0f), OP_MASK, IF1, 0, PROCESSOR_ALL },
|
||||
{ "cmp", OP (0x13), OP_MASK, IF2, 0, PROCESSOR_ALL },
|
||||
|
||||
/* saturated operation instructions */
|
||||
{ "satadd", OP (0x11), OP_MASK, {I5, R2_NOTR0}, 0, PROCESSOR_ALL },
|
||||
{ "satadd", OP (0x06), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL },
|
||||
{ "satsub", OP (0x05), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL },
|
||||
{ "satsubi", OP (0x33), OP_MASK, {I16, R1, R2_NOTR0}, 0, PROCESSOR_ALL },
|
||||
{ "satsubr", OP (0x04), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL },
|
||||
|
||||
/* logical operation instructions */
|
||||
{ "tst", OP (0x0b), OP_MASK, IF1, 0, PROCESSOR_ALL },
|
||||
{ "or", OP (0x08), OP_MASK, IF1, 0, PROCESSOR_ALL },
|
||||
{ "ori", OP (0x34), OP_MASK, IF6U, 0, PROCESSOR_ALL },
|
||||
{ "and", OP (0x0a), OP_MASK, IF1, 0, PROCESSOR_ALL },
|
||||
{ "andi", OP (0x36), OP_MASK, IF6U, 0, PROCESSOR_ALL },
|
||||
{ "xor", OP (0x09), OP_MASK, IF1, 0, PROCESSOR_ALL },
|
||||
{ "xori", OP (0x35), OP_MASK, IF6U, 0, PROCESSOR_ALL },
|
||||
{ "not", OP (0x01), OP_MASK, IF1, 0, PROCESSOR_ALL },
|
||||
{ "sar", OP (0x15), OP_MASK, {I5U, R2}, 0, PROCESSOR_ALL },
|
||||
{ "sar", two (0x07e0, 0x00a0), two (0x07e0, 0xffff), {R1, R2}, 0, PROCESSOR_ALL },
|
||||
{ "shl", OP (0x16), OP_MASK, {I5U, R2}, 0, PROCESSOR_ALL },
|
||||
{ "shl", two (0x07e0, 0x00c0), two (0x07e0, 0xffff), {R1, R2}, 0, PROCESSOR_ALL },
|
||||
{ "shr", OP (0x14), OP_MASK, {I5U, R2}, 0, PROCESSOR_ALL },
|
||||
{ "shr", two (0x07e0, 0x0080), two (0x07e0, 0xffff), {R1, R2}, 0, PROCESSOR_ALL },
|
||||
{ "sasf", two (0x07e0, 0x0200), two (0x07f0, 0xffff), {CCCC, R2}, 0, PROCESSOR_NOT_V850 },
|
||||
|
||||
/* branch instructions */
|
||||
/* signed integer */
|
||||
{ "bgt", BOP (0xf), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "bge", BOP (0xe), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "blt", BOP (0x6), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "ble", BOP (0x7), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
/* unsigned integer */
|
||||
{ "bh", BOP (0xb), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "bnh", BOP (0x3), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "bl", BOP (0x1), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "bnl", BOP (0x9), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
/* common */
|
||||
{ "be", BOP (0x2), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "bne", BOP (0xa), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
/* others */
|
||||
{ "bv", BOP (0x0), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "bnv", BOP (0x8), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "bn", BOP (0x4), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "bp", BOP (0xc), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "bc", BOP (0x1), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "bnc", BOP (0x9), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "bz", BOP (0x2), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "bnz", BOP (0xa), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "br", BOP (0x5), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "bsa", BOP (0xd), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
|
||||
/* Branch macros.
|
||||
|
||||
We use the short form in the opcode/mask fields. The assembler
|
||||
will twiddle bits as necessary if the long form is needed. */
|
||||
|
||||
/* signed integer */
|
||||
{ "jgt", BOP (0xf), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "jge", BOP (0xe), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "jlt", BOP (0x6), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "jle", BOP (0x7), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
/* unsigned integer */
|
||||
{ "jh", BOP (0xb), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "jnh", BOP (0x3), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "jl", BOP (0x1), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "jnl", BOP (0x9), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
/* common */
|
||||
{ "je", BOP (0x2), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "jne", BOP (0xa), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
/* others */
|
||||
{ "jv", BOP (0x0), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "jnv", BOP (0x8), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "jn", BOP (0x4), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "jp", BOP (0xc), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "jc", BOP (0x1), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "jnc", BOP (0x9), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "jz", BOP (0x2), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "jnz", BOP (0xa), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "jsa", BOP (0xd), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
{ "jbr", BOP (0x5), BOP_MASK, IF3, 0, PROCESSOR_ALL },
|
||||
|
||||
{ "jr", one (0x0780), two (0xffc0, 0x0001), {D22}, 0, PROCESSOR_ALL },
|
||||
{ "jarl", one (0x0780), two (0x07c0, 0x0001), {D22, R2}, 0, PROCESSOR_ALL},
|
||||
|
||||
/* bit manipulation instructions */
|
||||
{ "set1", two (0x07c0, 0x0000), two (0xc7e0, 0x0000), {B3, D16, R1}, 2, PROCESSOR_ALL },
|
||||
{ "set1", two (0x07e0, 0x00e0), two (0x07e0, 0xffff), {R2, R1}, 2, PROCESSOR_NOT_V850 },
|
||||
{ "not1", two (0x47c0, 0x0000), two (0xc7e0, 0x0000), {B3, D16, R1}, 2, PROCESSOR_ALL },
|
||||
{ "not1", two (0x07e0, 0x00e2), two (0x07e0, 0xffff), {R2, R1}, 2, PROCESSOR_NOT_V850 },
|
||||
{ "clr1", two (0x87c0, 0x0000), two (0xc7e0, 0x0000), {B3, D16, R1}, 2, PROCESSOR_ALL },
|
||||
{ "clr1", two (0x07e0, 0x00e4), two (0x07e0, 0xffff), {R2, R1}, 2, PROCESSOR_NOT_V850 },
|
||||
{ "tst1", two (0xc7c0, 0x0000), two (0xc7e0, 0x0000), {B3, D16, R1}, 2, PROCESSOR_ALL },
|
||||
{ "tst1", two (0x07e0, 0x00e6), two (0x07e0, 0xffff), {R2, R1}, 2, PROCESSOR_NOT_V850 },
|
||||
|
||||
/* special instructions */
|
||||
{ "di", two (0x07e0, 0x0160), two (0xffff, 0xffff), {0}, 0, PROCESSOR_ALL },
|
||||
{ "ei", two (0x87e0, 0x0160), two (0xffff, 0xffff), {0}, 0, PROCESSOR_ALL },
|
||||
{ "halt", two (0x07e0, 0x0120), two (0xffff, 0xffff), {0}, 0, PROCESSOR_ALL },
|
||||
{ "reti", two (0x07e0, 0x0140), two (0xffff, 0xffff), {0}, 0, PROCESSOR_ALL },
|
||||
{ "trap", two (0x07e0, 0x0100), two (0xffe0, 0xffff), {I5U}, 0, PROCESSOR_ALL },
|
||||
{ "ldsr", two (0x07e0, 0x0020), two (0x07e0, 0xffff), {R1, SR2}, 0, PROCESSOR_ALL },
|
||||
{ "stsr", two (0x07e0, 0x0040), two (0x07e0, 0xffff), {SR1, R2}, 0, PROCESSOR_ALL },
|
||||
{ 0, 0, 0, {0}, 0, 0 },
|
||||
|
||||
} ;
|
||||
|
||||
const int v850_num_opcodes =
|
||||
sizeof (v850_opcodes) / sizeof (v850_opcodes[0]);
|
||||
|
@ -1,587 +0,0 @@
|
||||
/* Disassemble z8000 code.
|
||||
Copyright 1992, 1993, 1998, 2000, 2001
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This file is part of GNU Binutils.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) 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. */
|
||||
|
||||
#include "sysdep.h"
|
||||
#include "dis-asm.h"
|
||||
|
||||
#define DEFINE_TABLE
|
||||
#include "z8k-opc.h"
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
typedef struct {
|
||||
/* These are all indexed by nibble number (i.e only every other entry
|
||||
of bytes is used, and every 4th entry of words). */
|
||||
unsigned char nibbles[24];
|
||||
unsigned char bytes[24];
|
||||
unsigned short words[24];
|
||||
|
||||
/* Nibble number of first word not yet fetched. */
|
||||
int max_fetched;
|
||||
bfd_vma insn_start;
|
||||
jmp_buf bailout;
|
||||
|
||||
long tabl_index;
|
||||
char instr_asmsrc[80];
|
||||
unsigned long arg_reg[0x0f];
|
||||
unsigned long immediate;
|
||||
unsigned long displacement;
|
||||
unsigned long address;
|
||||
unsigned long cond_code;
|
||||
unsigned long ctrl_code;
|
||||
unsigned long flags;
|
||||
unsigned long interrupts;
|
||||
} instr_data_s;
|
||||
|
||||
static int fetch_data PARAMS ((struct disassemble_info *, int));
|
||||
|
||||
|
||||
/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
|
||||
to ADDR (exclusive) are valid. Returns 1 for success, longjmps
|
||||
on error. */
|
||||
#define FETCH_DATA(info, nibble) \
|
||||
((nibble) < ((instr_data_s *) (info->private_data))->max_fetched \
|
||||
? 1 : fetch_data ((info), (nibble)))
|
||||
|
||||
static int
|
||||
fetch_data (info, nibble)
|
||||
struct disassemble_info *info;
|
||||
int nibble;
|
||||
{
|
||||
unsigned char mybuf[20];
|
||||
int status;
|
||||
instr_data_s *priv = (instr_data_s *) info->private_data;
|
||||
|
||||
if ((nibble % 4) != 0)
|
||||
abort ();
|
||||
|
||||
status = (*info->read_memory_func) (priv->insn_start,
|
||||
(bfd_byte *) mybuf,
|
||||
nibble / 2,
|
||||
info);
|
||||
if (status != 0)
|
||||
{
|
||||
(*info->memory_error_func) (status, priv->insn_start, info);
|
||||
longjmp (priv->bailout, 1);
|
||||
}
|
||||
|
||||
{
|
||||
int i;
|
||||
unsigned char *p = mybuf;
|
||||
|
||||
for (i = 0; i < nibble;)
|
||||
{
|
||||
priv->words[i] = (p[0] << 8) | p[1];
|
||||
|
||||
priv->bytes[i] = *p;
|
||||
priv->nibbles[i++] = *p >> 4;
|
||||
priv->nibbles[i++] = *p & 0xf;
|
||||
|
||||
++p;
|
||||
priv->bytes[i] = *p;
|
||||
priv->nibbles[i++] = *p >> 4;
|
||||
priv->nibbles[i++] = *p & 0xf;
|
||||
|
||||
++p;
|
||||
}
|
||||
}
|
||||
priv->max_fetched = nibble;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static char *codes[16] = {
|
||||
"f",
|
||||
"lt",
|
||||
"le",
|
||||
"ule",
|
||||
"ov/pe",
|
||||
"mi",
|
||||
"eq",
|
||||
"c/ult",
|
||||
"t",
|
||||
"ge",
|
||||
"gt",
|
||||
"ugt",
|
||||
"nov/po",
|
||||
"pl",
|
||||
"ne",
|
||||
"nc/uge"
|
||||
};
|
||||
|
||||
static char *ctrl_names[8] = {
|
||||
"<invld>",
|
||||
"flags",
|
||||
"fcw",
|
||||
"refresh",
|
||||
"psapseg",
|
||||
"psapoff",
|
||||
"nspseg",
|
||||
"nspoff"
|
||||
};
|
||||
|
||||
static int seg_length;
|
||||
static int print_insn_z8k PARAMS ((bfd_vma, disassemble_info *, int));
|
||||
int z8k_lookup_instr PARAMS ((unsigned char *, disassemble_info *));
|
||||
static void output_instr
|
||||
PARAMS ((instr_data_s *, unsigned long, disassemble_info *));
|
||||
static void unpack_instr PARAMS ((instr_data_s *, int, disassemble_info *));
|
||||
static void unparse_instr PARAMS ((instr_data_s *, int));
|
||||
|
||||
static int
|
||||
print_insn_z8k (addr, info, is_segmented)
|
||||
bfd_vma addr;
|
||||
disassemble_info *info;
|
||||
int is_segmented;
|
||||
{
|
||||
instr_data_s instr_data;
|
||||
|
||||
info->private_data = (PTR) &instr_data;
|
||||
instr_data.max_fetched = 0;
|
||||
instr_data.insn_start = addr;
|
||||
if (setjmp (instr_data.bailout) != 0)
|
||||
/* Error return. */
|
||||
return -1;
|
||||
|
||||
instr_data.tabl_index = z8k_lookup_instr (instr_data.nibbles, info);
|
||||
if (instr_data.tabl_index > 0)
|
||||
{
|
||||
unpack_instr (&instr_data, is_segmented, info);
|
||||
unparse_instr (&instr_data, is_segmented);
|
||||
output_instr (&instr_data, addr, info);
|
||||
return z8k_table[instr_data.tabl_index].length + seg_length;
|
||||
}
|
||||
else
|
||||
{
|
||||
FETCH_DATA (info, 4);
|
||||
(*info->fprintf_func) (info->stream, ".word %02x%02x",
|
||||
instr_data.bytes[0], instr_data.bytes[2]);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
print_insn_z8001 (addr, info)
|
||||
bfd_vma addr;
|
||||
disassemble_info *info;
|
||||
{
|
||||
return print_insn_z8k (addr, info, 1);
|
||||
}
|
||||
|
||||
int
|
||||
print_insn_z8002 (addr, info)
|
||||
bfd_vma addr;
|
||||
disassemble_info *info;
|
||||
{
|
||||
return print_insn_z8k (addr, info, 0);
|
||||
}
|
||||
|
||||
int
|
||||
z8k_lookup_instr (nibbles, info)
|
||||
unsigned char *nibbles;
|
||||
disassemble_info *info;
|
||||
{
|
||||
|
||||
int nibl_index, tabl_index;
|
||||
int nibl_matched;
|
||||
unsigned short instr_nibl;
|
||||
unsigned short tabl_datum, datum_class, datum_value;
|
||||
|
||||
nibl_matched = 0;
|
||||
tabl_index = 0;
|
||||
while (!nibl_matched && z8k_table[tabl_index].name)
|
||||
{
|
||||
nibl_matched = 1;
|
||||
for (nibl_index = 0;
|
||||
nibl_index < z8k_table[tabl_index].length * 2 && nibl_matched;
|
||||
nibl_index++)
|
||||
{
|
||||
if ((nibl_index % 4) == 0)
|
||||
/* Fetch one word at a time. */
|
||||
FETCH_DATA (info, nibl_index + 4);
|
||||
instr_nibl = nibbles[nibl_index];
|
||||
|
||||
tabl_datum = z8k_table[tabl_index].byte_info[nibl_index];
|
||||
datum_class = tabl_datum & CLASS_MASK;
|
||||
datum_value = ~CLASS_MASK & tabl_datum;
|
||||
|
||||
switch (datum_class)
|
||||
{
|
||||
case CLASS_BIT:
|
||||
if (datum_value != instr_nibl)
|
||||
nibl_matched = 0;
|
||||
break;
|
||||
case CLASS_00II:
|
||||
if (!((~instr_nibl) & 0x4))
|
||||
nibl_matched = 0;
|
||||
break;
|
||||
case CLASS_01II:
|
||||
if (!(instr_nibl & 0x4))
|
||||
nibl_matched = 0;
|
||||
break;
|
||||
case CLASS_0CCC:
|
||||
if (!((~instr_nibl) & 0x8))
|
||||
nibl_matched = 0;
|
||||
break;
|
||||
case CLASS_1CCC:
|
||||
if (!(instr_nibl & 0x8))
|
||||
nibl_matched = 0;
|
||||
break;
|
||||
case CLASS_0DISP7:
|
||||
if (!((~instr_nibl) & 0x8))
|
||||
nibl_matched = 0;
|
||||
nibl_index += 1;
|
||||
break;
|
||||
case CLASS_1DISP7:
|
||||
if (!(instr_nibl & 0x8))
|
||||
nibl_matched = 0;
|
||||
nibl_index += 1;
|
||||
break;
|
||||
case CLASS_REGN0:
|
||||
if (instr_nibl == 0)
|
||||
nibl_matched = 0;
|
||||
break;
|
||||
case CLASS_BIT_1OR2:
|
||||
if ((instr_nibl | 0x2) != (datum_value | 0x2))
|
||||
nibl_matched = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (nibl_matched)
|
||||
{
|
||||
return tabl_index;
|
||||
}
|
||||
|
||||
tabl_index++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void
|
||||
output_instr (instr_data, addr, info)
|
||||
instr_data_s *instr_data;
|
||||
unsigned long addr ATTRIBUTE_UNUSED;
|
||||
disassemble_info *info;
|
||||
{
|
||||
int loop, loop_limit;
|
||||
char tmp_str[20];
|
||||
char out_str[100];
|
||||
|
||||
strcpy (out_str, "\t");
|
||||
|
||||
loop_limit = (z8k_table[instr_data->tabl_index].length + seg_length) * 2;
|
||||
FETCH_DATA (info, loop_limit);
|
||||
for (loop = 0; loop < loop_limit; loop++)
|
||||
{
|
||||
sprintf (tmp_str, "%x", instr_data->nibbles[loop]);
|
||||
strcat (out_str, tmp_str);
|
||||
}
|
||||
|
||||
while (loop++ < 8)
|
||||
{
|
||||
strcat (out_str, " ");
|
||||
}
|
||||
|
||||
strcat (out_str, instr_data->instr_asmsrc);
|
||||
|
||||
(*info->fprintf_func) (info->stream, "%s", out_str);
|
||||
}
|
||||
|
||||
static void
|
||||
unpack_instr (instr_data, is_segmented, info)
|
||||
instr_data_s *instr_data;
|
||||
int is_segmented;
|
||||
disassemble_info *info;
|
||||
{
|
||||
int nibl_count, loop;
|
||||
unsigned short instr_nibl, instr_byte, instr_word;
|
||||
long instr_long;
|
||||
unsigned int tabl_datum, datum_class;
|
||||
unsigned short datum_value;
|
||||
|
||||
nibl_count = 0;
|
||||
loop = 0;
|
||||
seg_length = 0;
|
||||
while (z8k_table[instr_data->tabl_index].byte_info[loop] != 0)
|
||||
{
|
||||
FETCH_DATA (info, nibl_count + 4 - (nibl_count % 4));
|
||||
instr_nibl = instr_data->nibbles[nibl_count];
|
||||
instr_byte = instr_data->bytes[nibl_count & ~1];
|
||||
instr_word = instr_data->words[nibl_count & ~3];
|
||||
|
||||
tabl_datum = z8k_table[instr_data->tabl_index].byte_info[loop];
|
||||
datum_class = tabl_datum & CLASS_MASK;
|
||||
datum_value = tabl_datum & ~CLASS_MASK;
|
||||
|
||||
switch (datum_class)
|
||||
{
|
||||
case CLASS_DISP:
|
||||
switch (datum_value)
|
||||
{
|
||||
case ARG_DISP16:
|
||||
instr_data->displacement = instr_data->insn_start + 4
|
||||
+ (signed short) (instr_word & 0xffff);
|
||||
nibl_count += 3;
|
||||
break;
|
||||
case ARG_DISP12:
|
||||
if (instr_word & 0x800)
|
||||
{
|
||||
/* neg. 12 bit displacement */
|
||||
instr_data->displacement = instr_data->insn_start + 2
|
||||
- (signed short) ((instr_word & 0xfff) | 0xf000) * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
instr_data->displacement = instr_data->insn_start + 2
|
||||
- (instr_word & 0x0fff) * 2;
|
||||
}
|
||||
nibl_count += 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CLASS_IMM:
|
||||
switch (datum_value)
|
||||
{
|
||||
case ARG_IMM4:
|
||||
instr_data->immediate = instr_nibl;
|
||||
break;
|
||||
case ARG_NIM8:
|
||||
instr_data->immediate = (-instr_byte);
|
||||
nibl_count += 1;
|
||||
break;
|
||||
case ARG_IMM8:
|
||||
instr_data->immediate = instr_byte;
|
||||
nibl_count += 1;
|
||||
break;
|
||||
case ARG_IMM16:
|
||||
instr_data->immediate = instr_word;
|
||||
nibl_count += 3;
|
||||
break;
|
||||
case ARG_IMM32:
|
||||
FETCH_DATA (info, nibl_count + 8);
|
||||
instr_long = (instr_data->words[nibl_count] << 16)
|
||||
| (instr_data->words[nibl_count + 4]);
|
||||
instr_data->immediate = instr_long;
|
||||
nibl_count += 7;
|
||||
break;
|
||||
case ARG_IMMN:
|
||||
instr_data->immediate = instr_nibl - 1;
|
||||
break;
|
||||
case ARG_IMM4M1:
|
||||
instr_data->immediate = instr_nibl + 1;
|
||||
break;
|
||||
case ARG_IMM_1:
|
||||
instr_data->immediate = 1;
|
||||
break;
|
||||
case ARG_IMM_2:
|
||||
instr_data->immediate = 2;
|
||||
break;
|
||||
case ARG_IMM2:
|
||||
instr_data->immediate = instr_nibl & 0x3;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case CLASS_CC:
|
||||
instr_data->cond_code = instr_nibl;
|
||||
break;
|
||||
case CLASS_ADDRESS:
|
||||
if (is_segmented)
|
||||
{
|
||||
if (instr_nibl & 0x8)
|
||||
{
|
||||
FETCH_DATA (info, nibl_count + 8);
|
||||
instr_long = (instr_data->words[nibl_count] << 16)
|
||||
| (instr_data->words[nibl_count + 4]);
|
||||
instr_data->address = ((instr_word & 0x7f00) << 8)
|
||||
+ (instr_long & 0xffff);
|
||||
nibl_count += 7;
|
||||
seg_length = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
instr_data->address = ((instr_word & 0x7f00) << 8)
|
||||
+ (instr_word & 0x00ff);
|
||||
nibl_count += 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
instr_data->address = instr_word;
|
||||
nibl_count += 3;
|
||||
}
|
||||
break;
|
||||
case CLASS_0CCC:
|
||||
case CLASS_1CCC:
|
||||
instr_data->ctrl_code = instr_nibl & 0x7;
|
||||
break;
|
||||
case CLASS_0DISP7:
|
||||
instr_data->displacement =
|
||||
instr_data->insn_start + 2 - (instr_byte & 0x7f) * 2;
|
||||
nibl_count += 1;
|
||||
break;
|
||||
case CLASS_1DISP7:
|
||||
instr_data->displacement =
|
||||
instr_data->insn_start + 2 - (instr_byte & 0x7f) * 2;
|
||||
nibl_count += 1;
|
||||
break;
|
||||
case CLASS_01II:
|
||||
instr_data->interrupts = instr_nibl & 0x3;
|
||||
break;
|
||||
case CLASS_00II:
|
||||
instr_data->interrupts = instr_nibl & 0x3;
|
||||
break;
|
||||
case CLASS_BIT:
|
||||
instr_data->ctrl_code = instr_nibl & 0x7;
|
||||
break;
|
||||
case CLASS_FLAGS:
|
||||
instr_data->flags = instr_nibl;
|
||||
break;
|
||||
case CLASS_REG:
|
||||
instr_data->arg_reg[datum_value] = instr_nibl;
|
||||
break;
|
||||
case CLASS_REGN0:
|
||||
instr_data->arg_reg[datum_value] = instr_nibl;
|
||||
break;
|
||||
case CLASS_DISP8:
|
||||
instr_data->displacement =
|
||||
instr_data->insn_start + 2 + (signed char) instr_byte * 2;
|
||||
nibl_count += 1;
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
break;
|
||||
}
|
||||
|
||||
loop += 1;
|
||||
nibl_count += 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
unparse_instr (instr_data, is_segmented)
|
||||
instr_data_s *instr_data;
|
||||
int is_segmented;
|
||||
{
|
||||
unsigned short datum_value;
|
||||
unsigned int tabl_datum, datum_class;
|
||||
int loop, loop_limit;
|
||||
char out_str[80], tmp_str[25];
|
||||
|
||||
sprintf (out_str, "\t%s\t", z8k_table[instr_data->tabl_index].name);
|
||||
|
||||
loop_limit = z8k_table[instr_data->tabl_index].noperands;
|
||||
for (loop = 0; loop < loop_limit; loop++)
|
||||
{
|
||||
if (loop)
|
||||
strcat (out_str, ",");
|
||||
|
||||
tabl_datum = z8k_table[instr_data->tabl_index].arg_info[loop];
|
||||
datum_class = tabl_datum & CLASS_MASK;
|
||||
datum_value = tabl_datum & ~CLASS_MASK;
|
||||
|
||||
switch (datum_class)
|
||||
{
|
||||
case CLASS_X:
|
||||
sprintf (tmp_str, "0x%0lx(R%ld)", instr_data->address,
|
||||
instr_data->arg_reg[datum_value]);
|
||||
strcat (out_str, tmp_str);
|
||||
break;
|
||||
case CLASS_BA:
|
||||
sprintf (tmp_str, "r%ld(#%lx)", instr_data->arg_reg[datum_value],
|
||||
instr_data->immediate);
|
||||
strcat (out_str, tmp_str);
|
||||
break;
|
||||
case CLASS_BX:
|
||||
sprintf (tmp_str, "r%ld(R%ld)", instr_data->arg_reg[datum_value],
|
||||
instr_data->arg_reg[ARG_RX]);
|
||||
strcat (out_str, tmp_str);
|
||||
break;
|
||||
case CLASS_DISP:
|
||||
sprintf (tmp_str, "0x%0lx", instr_data->displacement);
|
||||
strcat (out_str, tmp_str);
|
||||
break;
|
||||
case CLASS_IMM:
|
||||
sprintf (tmp_str, "#0x%0lx", instr_data->immediate);
|
||||
strcat (out_str, tmp_str);
|
||||
break;
|
||||
case CLASS_CC:
|
||||
sprintf (tmp_str, "%s", codes[instr_data->cond_code]);
|
||||
strcat (out_str, tmp_str);
|
||||
break;
|
||||
case CLASS_CTRL:
|
||||
sprintf (tmp_str, "%s", ctrl_names[instr_data->ctrl_code]);
|
||||
strcat (out_str, tmp_str);
|
||||
break;
|
||||
case CLASS_DA:
|
||||
case CLASS_ADDRESS:
|
||||
sprintf (tmp_str, "0x%0lx", instr_data->address);
|
||||
strcat (out_str, tmp_str);
|
||||
break;
|
||||
case CLASS_IR:
|
||||
if (is_segmented)
|
||||
sprintf (tmp_str, "@rr%ld", instr_data->arg_reg[datum_value]);
|
||||
else
|
||||
sprintf (tmp_str, "@r%ld", instr_data->arg_reg[datum_value]);
|
||||
strcat (out_str, tmp_str);
|
||||
break;
|
||||
case CLASS_FLAGS:
|
||||
sprintf (tmp_str, "0x%0lx", instr_data->flags);
|
||||
strcat (out_str, tmp_str);
|
||||
break;
|
||||
case CLASS_REG_BYTE:
|
||||
if (instr_data->arg_reg[datum_value] >= 0x8)
|
||||
sprintf (tmp_str, "rl%ld",
|
||||
instr_data->arg_reg[datum_value] - 0x8);
|
||||
else
|
||||
sprintf (tmp_str, "rh%ld", instr_data->arg_reg[datum_value]);
|
||||
strcat (out_str, tmp_str);
|
||||
break;
|
||||
case CLASS_REG_WORD:
|
||||
sprintf (tmp_str, "r%ld", instr_data->arg_reg[datum_value]);
|
||||
strcat (out_str, tmp_str);
|
||||
break;
|
||||
case CLASS_REG_QUAD:
|
||||
sprintf (tmp_str, "rq%ld", instr_data->arg_reg[datum_value]);
|
||||
strcat (out_str, tmp_str);
|
||||
break;
|
||||
case CLASS_REG_LONG:
|
||||
sprintf (tmp_str, "rr%ld", instr_data->arg_reg[datum_value]);
|
||||
strcat (out_str, tmp_str);
|
||||
break;
|
||||
case CLASS_PR:
|
||||
if (is_segmented)
|
||||
sprintf (tmp_str, "rr%ld", instr_data->arg_reg[datum_value]);
|
||||
else
|
||||
sprintf (tmp_str, "r%ld", instr_data->arg_reg[datum_value]);
|
||||
strcat (out_str, tmp_str);
|
||||
break;
|
||||
default:
|
||||
abort ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
strcpy (instr_data->instr_asmsrc, out_str);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user