mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-02-17 13:10:12 +08:00
Apply Dmitry Diky's patches to add relaxation to msp430.
This commit is contained in:
parent
61f5d0545d
commit
b18c562e39
@ -1,3 +1,16 @@
|
||||
2004-08-25 Dmitry Diky <diwil@spec.ru>
|
||||
|
||||
* reloc.c (BFD_RELOC_MSP430_2X_PCREL,BFD_RELOC_MSP430_RL_PCREL):
|
||||
Add new relocations.
|
||||
* bfd-in2.h: Regenerate.
|
||||
* libbfd.h: Regenerate..
|
||||
* elf32-msp430.c: Clean-up code.
|
||||
(elf_msp430_howto_table): Add new relocation entries.
|
||||
(bfd_elf32_bfd_reloc_type_lookup): New relocation handlers.
|
||||
(msp430_elf_relax_section): New function.
|
||||
(msp430_elf_relax_delete_bytes): New function.
|
||||
(msp430_elf_symbol_address_p): New function.
|
||||
|
||||
2004-08-24 Kazuhiro Inaoka <inaoka.kazuhiro@renesas.com>
|
||||
|
||||
* elf32-m32r.c (m32r_elf_relocate_section): Handle
|
||||
|
@ -3587,6 +3587,8 @@ This is the 5 bits of a value. */
|
||||
BFD_RELOC_MSP430_16,
|
||||
BFD_RELOC_MSP430_16_PCREL_BYTE,
|
||||
BFD_RELOC_MSP430_16_BYTE,
|
||||
BFD_RELOC_MSP430_2X_PCREL,
|
||||
BFD_RELOC_MSP430_RL_PCREL,
|
||||
|
||||
/* IQ2000 Relocations. */
|
||||
BFD_RELOC_IQ2000_OFFSET_16,
|
||||
|
@ -25,41 +25,6 @@
|
||||
#include "elf-bfd.h"
|
||||
#include "elf/msp430.h"
|
||||
|
||||
static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup
|
||||
PARAMS ((bfd *, bfd_reloc_code_real_type));
|
||||
|
||||
static void msp430_info_to_howto_rela
|
||||
PARAMS ((bfd *, arelent *, Elf_Internal_Rela *));
|
||||
|
||||
static asection *elf32_msp430_gc_mark_hook
|
||||
PARAMS ((asection *, struct bfd_link_info *, Elf_Internal_Rela *,
|
||||
struct elf_link_hash_entry *, Elf_Internal_Sym *));
|
||||
|
||||
static bfd_boolean elf32_msp430_gc_sweep_hook
|
||||
PARAMS ((bfd *, struct bfd_link_info *, asection *,
|
||||
const Elf_Internal_Rela *));
|
||||
|
||||
static bfd_boolean elf32_msp430_check_relocs
|
||||
PARAMS ((bfd *, struct bfd_link_info *, asection *,
|
||||
const Elf_Internal_Rela *));
|
||||
|
||||
static bfd_reloc_status_type msp430_final_link_relocate
|
||||
PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *,
|
||||
Elf_Internal_Rela *, bfd_vma));
|
||||
|
||||
static bfd_boolean elf32_msp430_relocate_section
|
||||
PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *,
|
||||
Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));
|
||||
|
||||
static void bfd_elf_msp430_final_write_processing
|
||||
PARAMS ((bfd *, bfd_boolean));
|
||||
|
||||
static bfd_boolean elf32_msp430_object_p
|
||||
PARAMS ((bfd *));
|
||||
|
||||
static void elf32_msp430_post_process_headers
|
||||
PARAMS ((bfd *, struct bfd_link_info *));
|
||||
|
||||
/* Use RELA instead of REL. */
|
||||
#undef USE_REL
|
||||
|
||||
@ -71,7 +36,7 @@ static reloc_howto_type elf_msp430_howto_table[] =
|
||||
32, /* bitsize */
|
||||
FALSE, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_bitfield, /* complain_on_overflow */
|
||||
complain_overflow_bitfield,/* complain_on_overflow */
|
||||
bfd_elf_generic_reloc, /* special_function */
|
||||
"R_MSP430_NONE", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
@ -85,7 +50,7 @@ static reloc_howto_type elf_msp430_howto_table[] =
|
||||
32, /* bitsize */
|
||||
FALSE, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_bitfield, /* complain_on_overflow */
|
||||
complain_overflow_bitfield,/* complain_on_overflow */
|
||||
bfd_elf_generic_reloc, /* special_function */
|
||||
"R_MSP430_32", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
@ -100,7 +65,7 @@ static reloc_howto_type elf_msp430_howto_table[] =
|
||||
10, /* bitsize */
|
||||
TRUE, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_bitfield, /* complain_on_overflow */
|
||||
complain_overflow_bitfield,/* complain_on_overflow */
|
||||
bfd_elf_generic_reloc, /* special_function */
|
||||
"R_MSP430_13_PCREL", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
@ -119,7 +84,7 @@ static reloc_howto_type elf_msp430_howto_table[] =
|
||||
bfd_elf_generic_reloc, /* special_function */
|
||||
"R_MSP430_16", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
0xffff, /* src_mask */
|
||||
0, /* src_mask */
|
||||
0xffff, /* dst_mask */
|
||||
FALSE), /* pcrel_offset */
|
||||
|
||||
@ -134,7 +99,7 @@ static reloc_howto_type elf_msp430_howto_table[] =
|
||||
bfd_elf_generic_reloc, /* special_function */
|
||||
"R_MSP430_16_PCREL", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
0xffff, /* src_mask */
|
||||
0, /* src_mask */
|
||||
0xffff, /* dst_mask */
|
||||
TRUE), /* pcrel_offset */
|
||||
|
||||
@ -162,10 +127,40 @@ static reloc_howto_type elf_msp430_howto_table[] =
|
||||
0, /* bitpos */
|
||||
complain_overflow_dont,/* complain_on_overflow */
|
||||
bfd_elf_generic_reloc, /* special_function */
|
||||
"R_MSP430_16_PCREL_BYTE", /* name */
|
||||
"R_MSP430_16_PCREL_BYTE",/* name */
|
||||
FALSE, /* partial_inplace */
|
||||
0xffff, /* src_mask */
|
||||
0xffff, /* dst_mask */
|
||||
TRUE), /* pcrel_offset */
|
||||
|
||||
/* A 13 bit PC relative relocation for complicated polymorphs. */
|
||||
HOWTO (R_MSP430_2X_PCREL, /* type */
|
||||
1, /* rightshift */
|
||||
2, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
10, /* bitsize */
|
||||
TRUE, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_bitfield,/* complain_on_overflow */
|
||||
bfd_elf_generic_reloc, /* special_function */
|
||||
"R_MSP430_2X_PCREL", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
0xfff, /* src_mask */
|
||||
0xfff, /* dst_mask */
|
||||
TRUE), /* pcrel_offset */
|
||||
|
||||
/* A 16 bit relaxable relocation for command address. */
|
||||
HOWTO (R_MSP430_RL_PCREL, /* type */
|
||||
1, /* rightshift */
|
||||
1, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
16, /* bitsize */
|
||||
TRUE, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_dont,/* complain_on_overflow */
|
||||
bfd_elf_generic_reloc, /* special_function */
|
||||
"R_MSP430_RL_PCREL", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
0xffff, /* dst_mask */
|
||||
TRUE) /* pcrel_offset */
|
||||
};
|
||||
|
||||
@ -179,20 +174,21 @@ struct msp430_reloc_map
|
||||
|
||||
static const struct msp430_reloc_map msp430_reloc_map[] =
|
||||
{
|
||||
{BFD_RELOC_NONE, R_MSP430_NONE},
|
||||
{BFD_RELOC_32, R_MSP430_32},
|
||||
{BFD_RELOC_MSP430_10_PCREL, R_MSP430_10_PCREL},
|
||||
{BFD_RELOC_16, R_MSP430_16_BYTE},
|
||||
{BFD_RELOC_MSP430_16_PCREL, R_MSP430_16_PCREL},
|
||||
{BFD_RELOC_MSP430_16, R_MSP430_16},
|
||||
{BFD_RELOC_NONE, R_MSP430_NONE},
|
||||
{BFD_RELOC_32, R_MSP430_32},
|
||||
{BFD_RELOC_MSP430_10_PCREL, R_MSP430_10_PCREL},
|
||||
{BFD_RELOC_16, R_MSP430_16_BYTE},
|
||||
{BFD_RELOC_MSP430_16_PCREL, R_MSP430_16_PCREL},
|
||||
{BFD_RELOC_MSP430_16, R_MSP430_16},
|
||||
{BFD_RELOC_MSP430_16_PCREL_BYTE, R_MSP430_16_PCREL_BYTE},
|
||||
{BFD_RELOC_MSP430_16_BYTE, R_MSP430_16_BYTE}
|
||||
{BFD_RELOC_MSP430_16_BYTE, R_MSP430_16_BYTE},
|
||||
{BFD_RELOC_MSP430_2X_PCREL, R_MSP430_2X_PCREL},
|
||||
{BFD_RELOC_MSP430_RL_PCREL, R_MSP430_RL_PCREL}
|
||||
};
|
||||
|
||||
static reloc_howto_type *
|
||||
bfd_elf32_bfd_reloc_type_lookup (abfd, code)
|
||||
bfd *abfd ATTRIBUTE_UNUSED;
|
||||
bfd_reloc_code_real_type code;
|
||||
bfd_elf32_bfd_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED,
|
||||
bfd_reloc_code_real_type code)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
@ -206,10 +202,9 @@ bfd_elf32_bfd_reloc_type_lookup (abfd, code)
|
||||
/* Set the howto pointer for an MSP430 ELF reloc. */
|
||||
|
||||
static void
|
||||
msp430_info_to_howto_rela (abfd, cache_ptr, dst)
|
||||
bfd *abfd ATTRIBUTE_UNUSED;
|
||||
arelent *cache_ptr;
|
||||
Elf_Internal_Rela *dst;
|
||||
msp430_info_to_howto_rela (bfd * abfd ATTRIBUTE_UNUSED,
|
||||
arelent * cache_ptr,
|
||||
Elf_Internal_Rela * dst)
|
||||
{
|
||||
unsigned int r_type;
|
||||
|
||||
@ -219,12 +214,11 @@ msp430_info_to_howto_rela (abfd, cache_ptr, dst)
|
||||
}
|
||||
|
||||
static asection *
|
||||
elf32_msp430_gc_mark_hook (sec, info, rel, h, sym)
|
||||
asection *sec;
|
||||
struct bfd_link_info *info ATTRIBUTE_UNUSED;
|
||||
Elf_Internal_Rela *rel;
|
||||
struct elf_link_hash_entry *h;
|
||||
Elf_Internal_Sym *sym;
|
||||
elf32_msp430_gc_mark_hook (asection * sec,
|
||||
struct bfd_link_info * info ATTRIBUTE_UNUSED,
|
||||
Elf_Internal_Rela * rel,
|
||||
struct elf_link_hash_entry * h,
|
||||
Elf_Internal_Sym * sym)
|
||||
{
|
||||
if (h != NULL)
|
||||
{
|
||||
@ -252,11 +246,10 @@ elf32_msp430_gc_mark_hook (sec, info, rel, h, sym)
|
||||
}
|
||||
|
||||
static bfd_boolean
|
||||
elf32_msp430_gc_sweep_hook (abfd, info, sec, relocs)
|
||||
bfd *abfd ATTRIBUTE_UNUSED;
|
||||
struct bfd_link_info *info ATTRIBUTE_UNUSED;
|
||||
asection *sec ATTRIBUTE_UNUSED;
|
||||
const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;
|
||||
elf32_msp430_gc_sweep_hook (bfd * abfd ATTRIBUTE_UNUSED,
|
||||
struct bfd_link_info * info ATTRIBUTE_UNUSED,
|
||||
asection * sec ATTRIBUTE_UNUSED,
|
||||
const Elf_Internal_Rela * relocs ATTRIBUTE_UNUSED)
|
||||
{
|
||||
/* We don't use got and plt entries for msp430. */
|
||||
return TRUE;
|
||||
@ -267,11 +260,8 @@ elf32_msp430_gc_sweep_hook (abfd, info, sec, relocs)
|
||||
virtual table relocs for gc. */
|
||||
|
||||
static bfd_boolean
|
||||
elf32_msp430_check_relocs (abfd, info, sec, relocs)
|
||||
bfd *abfd;
|
||||
struct bfd_link_info *info;
|
||||
asection *sec;
|
||||
const Elf_Internal_Rela *relocs;
|
||||
elf32_msp430_check_relocs (bfd * abfd, struct bfd_link_info * info,
|
||||
asection * sec, const Elf_Internal_Rela * relocs)
|
||||
{
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
struct elf_link_hash_entry **sym_hashes, **sym_hashes_end;
|
||||
@ -308,14 +298,9 @@ elf32_msp430_check_relocs (abfd, info, sec, relocs)
|
||||
routines, but a few relocs, we have to do them ourselves. */
|
||||
|
||||
static bfd_reloc_status_type
|
||||
msp430_final_link_relocate (howto, input_bfd, input_section,
|
||||
contents, rel, relocation)
|
||||
reloc_howto_type *howto;
|
||||
bfd *input_bfd;
|
||||
asection *input_section;
|
||||
bfd_byte *contents;
|
||||
Elf_Internal_Rela *rel;
|
||||
bfd_vma relocation;
|
||||
msp430_final_link_relocate (reloc_howto_type * howto, bfd * input_bfd,
|
||||
asection * input_section, bfd_byte * contents,
|
||||
Elf_Internal_Rela * rel, bfd_vma relocation)
|
||||
{
|
||||
bfd_reloc_status_type r = bfd_reloc_ok;
|
||||
bfd_vma x;
|
||||
@ -347,7 +332,37 @@ msp430_final_link_relocate (howto, input_bfd, input_section,
|
||||
bfd_put_16 (input_bfd, x, contents);
|
||||
break;
|
||||
|
||||
case R_MSP430_2X_PCREL:
|
||||
contents += rel->r_offset;
|
||||
srel = (bfd_signed_vma) relocation;
|
||||
srel += rel->r_addend;
|
||||
srel -= rel->r_offset;
|
||||
srel -= 2; /* Branch instructions add 2 to the PC... */
|
||||
srel -= (input_section->output_section->vma +
|
||||
input_section->output_offset);
|
||||
|
||||
if (srel & 1)
|
||||
return bfd_reloc_outofrange;
|
||||
|
||||
/* MSP430 addresses commands as words. */
|
||||
srel >>= 1;
|
||||
|
||||
/* Check for an overflow. */
|
||||
if (srel < -512 || srel > 511)
|
||||
return bfd_reloc_overflow;
|
||||
|
||||
x = bfd_get_16 (input_bfd, contents);
|
||||
x = (x & 0xfc00) | (srel & 0x3ff);
|
||||
bfd_put_16 (input_bfd, x, contents);
|
||||
/* Handle second jump instruction. */
|
||||
x = bfd_get_16 (input_bfd, contents - 2);
|
||||
srel += 1;
|
||||
x = (x & 0xfc00) | (srel & 0x3ff);
|
||||
bfd_put_16 (input_bfd, x, contents - 2);
|
||||
break;
|
||||
|
||||
case R_MSP430_16_PCREL:
|
||||
case R_MSP430_RL_PCREL:
|
||||
contents += rel->r_offset;
|
||||
srel = (bfd_signed_vma) relocation;
|
||||
srel += rel->r_addend;
|
||||
@ -404,16 +419,14 @@ msp430_final_link_relocate (howto, input_bfd, input_section,
|
||||
/* Relocate an MSP430 ELF section. */
|
||||
|
||||
static bfd_boolean
|
||||
elf32_msp430_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
contents, relocs, local_syms, local_sections)
|
||||
bfd *output_bfd ATTRIBUTE_UNUSED;
|
||||
struct bfd_link_info *info;
|
||||
bfd *input_bfd;
|
||||
asection *input_section;
|
||||
bfd_byte *contents;
|
||||
Elf_Internal_Rela *relocs;
|
||||
Elf_Internal_Sym *local_syms;
|
||||
asection **local_sections;
|
||||
elf32_msp430_relocate_section (bfd * output_bfd ATTRIBUTE_UNUSED,
|
||||
struct bfd_link_info * info,
|
||||
bfd * input_bfd,
|
||||
asection * input_section,
|
||||
bfd_byte * contents,
|
||||
Elf_Internal_Rela * relocs,
|
||||
Elf_Internal_Sym * local_syms,
|
||||
asection ** local_sections)
|
||||
{
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
struct elf_link_hash_entry **sym_hashes;
|
||||
@ -520,9 +533,8 @@ elf32_msp430_relocate_section (output_bfd, info, input_bfd, input_section,
|
||||
number. */
|
||||
|
||||
static void
|
||||
bfd_elf_msp430_final_write_processing (abfd, linker)
|
||||
bfd *abfd;
|
||||
bfd_boolean linker ATTRIBUTE_UNUSED;
|
||||
bfd_elf_msp430_final_write_processing (bfd * abfd,
|
||||
bfd_boolean linker ATTRIBUTE_UNUSED)
|
||||
{
|
||||
unsigned long val;
|
||||
|
||||
@ -594,8 +606,7 @@ bfd_elf_msp430_final_write_processing (abfd, linker)
|
||||
/* Set the right machine number. */
|
||||
|
||||
static bfd_boolean
|
||||
elf32_msp430_object_p (abfd)
|
||||
bfd *abfd;
|
||||
elf32_msp430_object_p (bfd * abfd)
|
||||
{
|
||||
int e_set = bfd_mach_msp14;
|
||||
|
||||
@ -669,11 +680,10 @@ elf32_msp430_object_p (abfd)
|
||||
}
|
||||
|
||||
static void
|
||||
elf32_msp430_post_process_headers (abfd, link_info)
|
||||
bfd *abfd;
|
||||
struct bfd_link_info *link_info ATTRIBUTE_UNUSED;
|
||||
elf32_msp430_post_process_headers (bfd * abfd,
|
||||
struct bfd_link_info * link_info ATTRIBUTE_UNUSED)
|
||||
{
|
||||
Elf_Internal_Ehdr *i_ehdrp; /* ELF file header, internal form. */
|
||||
Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form. */
|
||||
|
||||
i_ehdrp = elf_elfheader (abfd);
|
||||
|
||||
@ -684,6 +694,466 @@ elf32_msp430_post_process_headers (abfd, link_info)
|
||||
i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_STANDALONE;
|
||||
}
|
||||
|
||||
/* These functions handle relaxing for the msp430.
|
||||
Relaxation required only in two cases:
|
||||
- Bad hand coding like jumps from one section to another or
|
||||
from file to file.
|
||||
- Sibling calls. This will affect onlu 'jump label' polymorph. Without
|
||||
relaxing this enlarges code by 2 bytes. Sibcalls implemented but
|
||||
do not work in gcc's port by the reason I do not know.
|
||||
Anyway, if a relaxation required, user should pass -relax option to the
|
||||
linker.
|
||||
|
||||
There are quite a few relaxing opportunities available on the msp430:
|
||||
|
||||
================================================================
|
||||
|
||||
1. 3 words -> 1 word
|
||||
|
||||
eq == jeq label jne +4; br lab
|
||||
ne != jne label jeq +4; br lab
|
||||
lt < jl label jge +4; br lab
|
||||
ltu < jlo label lhs +4; br lab
|
||||
ge >= jge label jl +4; br lab
|
||||
geu >= jhs label jlo +4; br lab
|
||||
|
||||
2. 4 words -> 1 word
|
||||
|
||||
ltn < jn jn +2; jmp +4; br lab
|
||||
|
||||
3. 4 words -> 2 words
|
||||
|
||||
gt > jeq +2; jge label jeq +6; jl +4; br label
|
||||
gtu > jeq +2; jhs label jeq +6; jlo +4; br label
|
||||
|
||||
4. 4 words -> 2 words and 2 labels
|
||||
|
||||
leu <= jeq label; jlo label jeq +2; jhs +4; br label
|
||||
le <= jeq label; jl label jeq +2; jge +4; br label
|
||||
=================================================================
|
||||
|
||||
codemap for first cases is (labels masked ):
|
||||
eq: 0x2002,0x4010,0x0000 -> 0x2400
|
||||
ne: 0x2402,0x4010,0x0000 -> 0x2000
|
||||
lt: 0x3402,0x4010,0x0000 -> 0x3800
|
||||
ltu: 0x2c02,0x4010,0x0000 -> 0x2800
|
||||
ge: 0x3802,0x4010,0x0000 -> 0x3400
|
||||
geu: 0x2802,0x4010,0x0000 -> 0x2c00
|
||||
|
||||
second case:
|
||||
ltn: 0x3001,0x3c02,0x4010,0x0000 -> 0x3000
|
||||
|
||||
third case:
|
||||
gt: 0x2403,0x3802,0x4010,0x0000 -> 0x2401,0x3400
|
||||
gtu: 0x2403,0x2802,0x4010,0x0000 -> 0x2401,0x2c00
|
||||
|
||||
fourth case:
|
||||
leu: 0x2401,0x2c02,0x4010,0x0000 -> 0x2400,0x2800
|
||||
le: 0x2401,0x3402,0x4010,0x0000 -> 0x2400,0x3800
|
||||
|
||||
Unspecified case :)
|
||||
jump: 0x4010,0x0000 -> 0x3c00. */
|
||||
|
||||
#define NUMB_RELAX_CODES 12
|
||||
static struct rcodes_s
|
||||
{
|
||||
int f0, f1; /* From code. */
|
||||
int t0, t1; /* To code. */
|
||||
int labels; /* Position of labels: 1 - one label at first
|
||||
word, 2 - one at second word, 3 - two
|
||||
labels at both. */
|
||||
int cdx; /* Words to match. */
|
||||
int bs; /* Shrink bytes. */
|
||||
int off; /* Offset from old label for new code. */
|
||||
int ncl; /* New code length. */
|
||||
} rcode[] =
|
||||
{/* lab,cdx,bs,off,ncl */
|
||||
{ 0x0000, 0x0000, 0x3c00, 0x0000, 1, 0, 2, 2, 2}, /* jump */
|
||||
{ 0x0000, 0x2002, 0x2400, 0x0000, 1, 1, 4, 4, 2}, /* eq */
|
||||
{ 0x0000, 0x2402, 0x2000, 0x0000, 1, 1, 4, 4, 2}, /* ne */
|
||||
{ 0x0000, 0x3402, 0x3800, 0x0000, 1, 1, 4, 4, 2}, /* lt */
|
||||
{ 0x0000, 0x2c02, 0x2800, 0x0000, 1, 1, 4, 4, 2}, /* ltu */
|
||||
{ 0x0000, 0x3802, 0x3400, 0x0000, 1, 1, 4, 4, 2}, /* ge */
|
||||
{ 0x0000, 0x2802, 0x2c00, 0x0000, 1, 1, 4, 4, 2}, /* geu */
|
||||
{ 0x3001, 0x3c02, 0x3000, 0x0000, 1, 2, 6, 6, 2}, /* ltn */
|
||||
{ 0x2403, 0x3802, 0x2401, 0x3400, 2, 2, 4, 6, 4}, /* gt */
|
||||
{ 0x2403, 0x2802, 0x2401, 0x2c00, 2, 2, 4, 6, 4}, /* gtu */
|
||||
{ 0x2401, 0x2c02, 0x2400, 0x2800, 3, 2, 4, 6, 4}, /* leu , 2 labels */
|
||||
{ 0x2401, 0x2c02, 0x2400, 0x2800, 3, 2, 4, 6, 4}, /* le , 2 labels */
|
||||
{ 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
|
||||
/* Return TRUE if a symbol exists at the given address. */
|
||||
|
||||
static bfd_boolean
|
||||
msp430_elf_symbol_address_p (bfd * abfd,
|
||||
asection * sec,
|
||||
Elf_Internal_Sym * isym,
|
||||
bfd_vma addr)
|
||||
{
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
unsigned int sec_shndx;
|
||||
Elf_Internal_Sym *isymend;
|
||||
struct elf_link_hash_entry **sym_hashes;
|
||||
struct elf_link_hash_entry **end_hashes;
|
||||
unsigned int symcount;
|
||||
|
||||
sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
|
||||
|
||||
/* Examine all the local symbols. */
|
||||
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
|
||||
for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
|
||||
if (isym->st_shndx == sec_shndx && isym->st_value == addr)
|
||||
return TRUE;
|
||||
|
||||
symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
|
||||
- symtab_hdr->sh_info);
|
||||
sym_hashes = elf_sym_hashes (abfd);
|
||||
end_hashes = sym_hashes + symcount;
|
||||
for (; sym_hashes < end_hashes; sym_hashes++)
|
||||
{
|
||||
struct elf_link_hash_entry *sym_hash = *sym_hashes;
|
||||
|
||||
if ((sym_hash->root.type == bfd_link_hash_defined
|
||||
|| sym_hash->root.type == bfd_link_hash_defweak)
|
||||
&& sym_hash->root.u.def.section == sec
|
||||
&& sym_hash->root.u.def.value == addr)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Delete some bytes from a section while relaxing. */
|
||||
|
||||
static bfd_boolean
|
||||
msp430_elf_relax_delete_bytes (bfd * abfd, asection * sec, bfd_vma addr,
|
||||
int count)
|
||||
{
|
||||
Elf_Internal_Shdr *symtab_hdr;
|
||||
unsigned int sec_shndx;
|
||||
bfd_byte *contents;
|
||||
Elf_Internal_Rela *irel;
|
||||
Elf_Internal_Rela *irelend;
|
||||
Elf_Internal_Rela *irelalign;
|
||||
bfd_vma toaddr;
|
||||
Elf_Internal_Sym *isym;
|
||||
Elf_Internal_Sym *isymend;
|
||||
struct elf_link_hash_entry **sym_hashes;
|
||||
struct elf_link_hash_entry **end_hashes;
|
||||
unsigned int symcount;
|
||||
|
||||
sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
|
||||
|
||||
contents = elf_section_data (sec)->this_hdr.contents;
|
||||
|
||||
/* The deletion must stop at the next ALIGN reloc for an aligment
|
||||
power larger than the number of bytes we are deleting. */
|
||||
|
||||
irelalign = NULL;
|
||||
toaddr = sec->size;
|
||||
|
||||
irel = elf_section_data (sec)->relocs;
|
||||
irelend = irel + sec->reloc_count;
|
||||
|
||||
/* Actually delete the bytes. */
|
||||
memmove (contents + addr, contents + addr + count,
|
||||
(size_t) (toaddr - addr - count));
|
||||
sec->size -= count;
|
||||
|
||||
/* Adjust all the relocs. */
|
||||
for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++)
|
||||
/* Get the new reloc address. */
|
||||
if ((irel->r_offset > addr && irel->r_offset < toaddr))
|
||||
irel->r_offset -= count;
|
||||
|
||||
/* Adjust the local symbols defined in this section. */
|
||||
symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
|
||||
isym = (Elf_Internal_Sym *) symtab_hdr->contents;
|
||||
for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++)
|
||||
if (isym->st_shndx == sec_shndx
|
||||
&& isym->st_value > addr && isym->st_value < toaddr)
|
||||
isym->st_value -= count;
|
||||
|
||||
/* Now adjust the global symbols defined in this section. */
|
||||
symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
|
||||
- symtab_hdr->sh_info);
|
||||
sym_hashes = elf_sym_hashes (abfd);
|
||||
end_hashes = sym_hashes + symcount;
|
||||
for (; sym_hashes < end_hashes; sym_hashes++)
|
||||
{
|
||||
struct elf_link_hash_entry *sym_hash = *sym_hashes;
|
||||
|
||||
if ((sym_hash->root.type == bfd_link_hash_defined
|
||||
|| sym_hash->root.type == bfd_link_hash_defweak)
|
||||
&& sym_hash->root.u.def.section == sec
|
||||
&& sym_hash->root.u.def.value > addr
|
||||
&& sym_hash->root.u.def.value < toaddr)
|
||||
sym_hash->root.u.def.value -= count;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static bfd_boolean
|
||||
msp430_elf_relax_section (bfd * abfd, asection * sec,
|
||||
struct bfd_link_info * link_info,
|
||||
bfd_boolean * again)
|
||||
{
|
||||
Elf_Internal_Shdr * symtab_hdr;
|
||||
Elf_Internal_Rela * internal_relocs;
|
||||
Elf_Internal_Rela * irel;
|
||||
Elf_Internal_Rela * irelend;
|
||||
bfd_byte * contents = NULL;
|
||||
Elf_Internal_Sym * isymbuf = NULL;
|
||||
|
||||
/* Assume nothing changes. */
|
||||
*again = FALSE;
|
||||
|
||||
/* We don't have to do anything for a relocatable link, if
|
||||
this section does not have relocs, or if this is not a
|
||||
code section. */
|
||||
if (link_info->relocatable
|
||||
|| (sec->flags & SEC_RELOC) == 0
|
||||
|| sec->reloc_count == 0 || (sec->flags & SEC_CODE) == 0)
|
||||
return TRUE;
|
||||
|
||||
symtab_hdr = & elf_tdata (abfd)->symtab_hdr;
|
||||
|
||||
/* Get a copy of the native relocations. */
|
||||
internal_relocs =
|
||||
_bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, link_info->keep_memory);
|
||||
if (internal_relocs == NULL)
|
||||
goto error_return;
|
||||
|
||||
/* Walk through them looking for relaxing opportunities. */
|
||||
irelend = internal_relocs + sec->reloc_count;
|
||||
for (irel = internal_relocs; irel < irelend; irel++)
|
||||
{
|
||||
bfd_vma symval;
|
||||
|
||||
/* If this isn't something that can be relaxed, then ignore
|
||||
this reloc. */
|
||||
if (ELF32_R_TYPE (irel->r_info) != (int) R_MSP430_RL_PCREL)
|
||||
continue;
|
||||
|
||||
/* Get the section contents if we haven't done so already. */
|
||||
if (contents == NULL)
|
||||
{
|
||||
/* Get cached copy if it exists. */
|
||||
if (elf_section_data (sec)->this_hdr.contents != NULL)
|
||||
contents = elf_section_data (sec)->this_hdr.contents;
|
||||
else if (! bfd_malloc_and_get_section (abfd, sec, &contents))
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
/* Read this BFD's local symbols if we haven't done so already. */
|
||||
if (isymbuf == NULL && symtab_hdr->sh_info != 0)
|
||||
{
|
||||
isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
|
||||
if (isymbuf == NULL)
|
||||
isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
|
||||
symtab_hdr->sh_info, 0,
|
||||
NULL, NULL, NULL);
|
||||
if (isymbuf == NULL)
|
||||
goto error_return;
|
||||
}
|
||||
|
||||
/* Get the value of the symbol referred to by the reloc. */
|
||||
if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
|
||||
{
|
||||
/* A local symbol. */
|
||||
Elf_Internal_Sym *isym;
|
||||
asection *sym_sec;
|
||||
|
||||
isym = isymbuf + ELF32_R_SYM (irel->r_info);
|
||||
if (isym->st_shndx == SHN_UNDEF)
|
||||
sym_sec = bfd_und_section_ptr;
|
||||
else if (isym->st_shndx == SHN_ABS)
|
||||
sym_sec = bfd_abs_section_ptr;
|
||||
else if (isym->st_shndx == SHN_COMMON)
|
||||
sym_sec = bfd_com_section_ptr;
|
||||
else
|
||||
sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
|
||||
symval = (isym->st_value
|
||||
+ sym_sec->output_section->vma + sym_sec->output_offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned long indx;
|
||||
struct elf_link_hash_entry *h;
|
||||
|
||||
/* An external symbol. */
|
||||
indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info;
|
||||
h = elf_sym_hashes (abfd)[indx];
|
||||
BFD_ASSERT (h != NULL);
|
||||
|
||||
if (h->root.type != bfd_link_hash_defined
|
||||
&& h->root.type != bfd_link_hash_defweak)
|
||||
/* This appears to be a reference to an undefined
|
||||
symbol. Just ignore it--it will be caught by the
|
||||
regular reloc processing. */
|
||||
continue;
|
||||
|
||||
symval = (h->root.u.def.value
|
||||
+ h->root.u.def.section->output_section->vma
|
||||
+ h->root.u.def.section->output_offset);
|
||||
}
|
||||
|
||||
/* For simplicity of coding, we are going to modify the section
|
||||
contents, the section relocs, and the BFD symbol table. We
|
||||
must tell the rest of the code not to free up this
|
||||
information. It would be possible to instead create a table
|
||||
of changes which have to be made, as is done in coff-mips.c;
|
||||
that would be more work, but would require less memory when
|
||||
the linker is run. */
|
||||
|
||||
/* Try to turn a 16bit pc-relative branch into a 10bit pc-relative
|
||||
branch. */
|
||||
/* Paranoia? paranoia... */
|
||||
if (ELF32_R_TYPE (irel->r_info) == (int) R_MSP430_RL_PCREL)
|
||||
{
|
||||
bfd_vma value = symval;
|
||||
|
||||
/* Deal with pc-relative gunk. */
|
||||
value -= (sec->output_section->vma + sec->output_offset);
|
||||
value -= irel->r_offset;
|
||||
value += irel->r_addend;
|
||||
|
||||
/* See if the value will fit in 10 bits, note the high value is
|
||||
1016 as the target will be two bytes closer if we are
|
||||
able to relax. */
|
||||
if ((long) value < 1016 && (long) value > -1016)
|
||||
{
|
||||
int code0 = 0, code1 = 0, code2 = 0;
|
||||
int i;
|
||||
struct rcodes_s *rx;
|
||||
|
||||
/* Get the opcode. */
|
||||
if (irel->r_offset >= 6)
|
||||
code0 = bfd_get_16 (abfd, contents + irel->r_offset - 6);
|
||||
|
||||
if (irel->r_offset >= 4)
|
||||
code1 = bfd_get_16 (abfd, contents + irel->r_offset - 4);
|
||||
|
||||
code2 = bfd_get_16 (abfd, contents + irel->r_offset - 2);
|
||||
|
||||
if (code2 != 0x4010)
|
||||
continue;
|
||||
|
||||
/* Check r4 and r3. */
|
||||
for (i = NUMB_RELAX_CODES - 1; i >= 0; i--)
|
||||
{
|
||||
rx = &rcode[i];
|
||||
if (rx->cdx == 2 && rx->f0 == code0 && rx->f1 == code1)
|
||||
break;
|
||||
else if (rx->cdx == 1 && rx->f1 == code1)
|
||||
break;
|
||||
else if (rx->cdx == 0) /* This is an unconditional jump. */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check labels:
|
||||
.Label0: ; we do not care about this label
|
||||
jeq +6
|
||||
.Label1: ; make sure there is no label here
|
||||
jl +4
|
||||
.Label2: ; make sure there is no label here
|
||||
br .Label_dst
|
||||
|
||||
So, if there is .Label1 or .Label2 we cannot relax this code.
|
||||
This actually should not happen, cause for relaxable
|
||||
instructions we use RL_PCREL reloc instead of 16_PCREL.
|
||||
Will change this in the future. */
|
||||
|
||||
if (rx->cdx > 0
|
||||
&& msp430_elf_symbol_address_p (abfd, sec, isymbuf,
|
||||
irel->r_offset - 2))
|
||||
continue;
|
||||
if (rx->cdx > 1
|
||||
&& msp430_elf_symbol_address_p (abfd, sec, isymbuf,
|
||||
irel->r_offset - 4))
|
||||
continue;
|
||||
|
||||
/* Note that we've changed the relocs, section contents, etc. */
|
||||
elf_section_data (sec)->relocs = internal_relocs;
|
||||
elf_section_data (sec)->this_hdr.contents = contents;
|
||||
symtab_hdr->contents = (unsigned char *) isymbuf;
|
||||
|
||||
/* Fix the relocation's type. */
|
||||
if (rx->labels == 3) /* Handle special cases. */
|
||||
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
|
||||
R_MSP430_2X_PCREL);
|
||||
else
|
||||
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
|
||||
R_MSP430_10_PCREL);
|
||||
|
||||
/* Fix the opcode right way. */
|
||||
bfd_put_16 (abfd, rx->t0, contents + irel->r_offset - rx->off);
|
||||
if (rx->t1)
|
||||
bfd_put_16 (abfd, rx->t1,
|
||||
contents + irel->r_offset - rx->off + 2);
|
||||
|
||||
/* Delete bytes. */
|
||||
if (!msp430_elf_relax_delete_bytes (abfd, sec,
|
||||
irel->r_offset - rx->off +
|
||||
rx->ncl, rx->bs))
|
||||
goto error_return;
|
||||
|
||||
/* Handle unconditional jumps. */
|
||||
if (rx->cdx == 0)
|
||||
irel->r_offset -= 2;
|
||||
|
||||
/* That will change things, so, we should relax again.
|
||||
Note that this is not required, and it may be slow. */
|
||||
*again = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
|
||||
{
|
||||
if (!link_info->keep_memory)
|
||||
free (isymbuf);
|
||||
else
|
||||
{
|
||||
/* Cache the symbols for elf_link_input_bfd. */
|
||||
symtab_hdr->contents = (unsigned char *) isymbuf;
|
||||
}
|
||||
}
|
||||
|
||||
if (contents != NULL
|
||||
&& elf_section_data (sec)->this_hdr.contents != contents)
|
||||
{
|
||||
if (!link_info->keep_memory)
|
||||
free (contents);
|
||||
else
|
||||
{
|
||||
/* Cache the section contents for elf_link_input_bfd. */
|
||||
elf_section_data (sec)->this_hdr.contents = contents;
|
||||
}
|
||||
}
|
||||
|
||||
if (internal_relocs != NULL
|
||||
&& elf_section_data (sec)->relocs != internal_relocs)
|
||||
free (internal_relocs);
|
||||
|
||||
return TRUE;
|
||||
|
||||
error_return:
|
||||
if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf)
|
||||
free (isymbuf);
|
||||
if (contents != NULL
|
||||
&& elf_section_data (sec)->this_hdr.contents != contents)
|
||||
free (contents);
|
||||
if (internal_relocs != NULL
|
||||
&& elf_section_data (sec)->relocs != internal_relocs)
|
||||
free (internal_relocs);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
#define ELF_ARCH bfd_arch_msp430
|
||||
#define ELF_MACHINE_CODE EM_MSP430
|
||||
@ -703,5 +1173,6 @@ elf32_msp430_post_process_headers (abfd, link_info)
|
||||
#define elf_backend_final_write_processing bfd_elf_msp430_final_write_processing
|
||||
#define elf_backend_object_p elf32_msp430_object_p
|
||||
#define elf_backend_post_process_headers elf32_msp430_post_process_headers
|
||||
#define bfd_elf32_bfd_relax_section msp430_elf_relax_section
|
||||
|
||||
#include "elf32-target.h"
|
||||
|
@ -1637,6 +1637,8 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
|
||||
"BFD_RELOC_MSP430_16",
|
||||
"BFD_RELOC_MSP430_16_PCREL_BYTE",
|
||||
"BFD_RELOC_MSP430_16_BYTE",
|
||||
"BFD_RELOC_MSP430_2X_PCREL",
|
||||
"BFD_RELOC_MSP430_RL_PCREL",
|
||||
"BFD_RELOC_IQ2000_OFFSET_16",
|
||||
"BFD_RELOC_IQ2000_OFFSET_21",
|
||||
"BFD_RELOC_IQ2000_UHI16",
|
||||
|
@ -4095,6 +4095,10 @@ ENUMX
|
||||
BFD_RELOC_MSP430_16_PCREL_BYTE
|
||||
ENUMX
|
||||
BFD_RELOC_MSP430_16_BYTE
|
||||
ENUMX
|
||||
BFD_RELOC_MSP430_2X_PCREL
|
||||
ENUMX
|
||||
BFD_RELOC_MSP430_RL_PCREL
|
||||
ENUMDOC
|
||||
msp430 specific relocation codes
|
||||
|
||||
|
@ -1,3 +1,20 @@
|
||||
2004-08-25 Dmitry Diky <diwil@spec.ru>
|
||||
|
||||
* config/tc-msp430.c: Clean-up the code.
|
||||
(md_relax_table): New relax table.
|
||||
(mcu_types): Sort MCU types.
|
||||
(md_pseudo_table): Add .profiler pseudo handler.
|
||||
(pow2value): New function.
|
||||
(msp430_profiler): New function.
|
||||
(msp430_operands): Add new insns handlers.
|
||||
(msp430_srcoperand): Add register operand handler, allow complex
|
||||
expressions.
|
||||
(md_estimate_size_before_relax): Rewritten.
|
||||
(md_convert_frag): Rewritten.
|
||||
(msp430_relax_frag): New function.
|
||||
* config/tc-msp430.h (md_relax_frag): define macro
|
||||
* doc/c-msp430.texi: Update information.
|
||||
|
||||
2004-08-24 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* as.c (std_shortopts): Allow -g to take an optional argument.
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/* This file is tc-msp430.h
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 2002, 2004 Free Software Foundation, Inc.
|
||||
|
||||
Contributed by Dmitry Diky <diwil@mail.ru>
|
||||
|
||||
@ -93,7 +93,7 @@
|
||||
of a PC relative instruction is the next instruction, so this
|
||||
macro would return the length of an instruction. */
|
||||
|
||||
extern long md_pcrel_from_section PARAMS ((struct fix *, segT));
|
||||
extern long md_pcrel_from_section (struct fix *, segT);
|
||||
|
||||
#define LISTING_WORD_SIZE 2
|
||||
/* The number of bytes to put into a word in a listing. This affects
|
||||
@ -112,3 +112,7 @@ extern long md_pcrel_from_section PARAMS ((struct fix *, segT));
|
||||
should do nothing. Some targets define a `.bss' directive that is
|
||||
also affected by this macro. The default definition will set
|
||||
P2VAR to the truncated power of two of sizes up to eight bytes. */
|
||||
|
||||
#define md_relax_frag(SEG, FRAGP, STRETCH) \
|
||||
msp430_relax_frag (SEG, FRAGP, STRETCH)
|
||||
extern long msp430_relax_frag (segT, fragS *, long);
|
||||
|
@ -1,4 +1,4 @@
|
||||
@c Copyright 2002 Free Software Foundation, Inc.
|
||||
@c Copyright 2002, 2004 Free Software Foundation, Inc.
|
||||
@c This is part of the GAS manual.
|
||||
@c For copying conditions, see the file as.texinfo.
|
||||
@ifset GENERIC
|
||||
@ -19,6 +19,7 @@
|
||||
* MSP430 Floating Point:: Floating Point
|
||||
* MSP430 Directives:: MSP 430 Machine Directives
|
||||
* MSP430 Opcodes:: Opcodes
|
||||
* MSP430 Profiling Capability:: Profiling Capability
|
||||
@end menu
|
||||
|
||||
@node MSP430 Options
|
||||
@ -116,6 +117,54 @@ Skips next N bytes followed by jump instruction and equivalent to
|
||||
|
||||
@end table
|
||||
|
||||
Also, there are some instructions, which cannot be found in other assemblers.
|
||||
These are branch instructions, which has different opcodes upon jump distance.
|
||||
They all got PC relative addressing mode.
|
||||
|
||||
@table @code
|
||||
@item beq label
|
||||
A polymorph instruction which is @samp{jeq label} in case if jump distance
|
||||
within allowed range for cpu's jump instruction. If not, this unrolls into
|
||||
a sequence of
|
||||
@smallexample
|
||||
jne $+6
|
||||
br label
|
||||
@end smallexample
|
||||
|
||||
@item bne label
|
||||
A polymorph instruction which is @samp{jne label} or @samp{jeq +4; br label}
|
||||
|
||||
@item blt label
|
||||
A polymorph instruction which is @samp{jl label} or @samp{jge +4; br label}
|
||||
|
||||
@item bltn label
|
||||
A polymorph instruction which is @samp{jn label} or @samp{jn +2; jmp +4; br label}
|
||||
|
||||
@item bltu label
|
||||
A polymorph instruction which is @samp{jlo label} or @samp{jhs +2; br label}
|
||||
|
||||
@item bge label
|
||||
A polymorph instruction which is @samp{jge label} or @samp{jl +4; br label}
|
||||
|
||||
@item bgeu label
|
||||
A polymorph instruction which is @samp{jhs label} or @samp{jlo +4; br label}
|
||||
|
||||
@item bgt label
|
||||
A polymorph instruction which is @samp{jeq +2; jge label} or @samp{jeq +6; jl +4; br label}
|
||||
|
||||
@item bgtu label
|
||||
A polymorph instruction which is @samp{jeq +2; jhs label} or @samp{jeq +6; jlo +4; br label}
|
||||
|
||||
@item bleu label
|
||||
A polymorph instruction which is @samp{jeq label; jlo label} or @samp{jeq +2; jhs +4; br label}
|
||||
|
||||
@item ble label
|
||||
A polymorph instruction which is @samp{jeq label; jl label} or @samp{jeq +2; jge +4; br label}
|
||||
|
||||
@item jump label
|
||||
A polymorph instruction which is @samp{jmp label} or @samp{br label}
|
||||
@end table
|
||||
|
||||
|
||||
@node MSP430 Floating Point
|
||||
@section Floating Point
|
||||
@ -150,6 +199,10 @@ MSP 430 assemblers.
|
||||
Currently this directive is ignored; it is accepted for compatibility with other
|
||||
MSP 430 assemblers.
|
||||
|
||||
@cindex @code{profiler} directive, MSP 430
|
||||
@item .profiler
|
||||
This directive instructs assembler to add new profile entry to the object file.
|
||||
|
||||
@end table
|
||||
|
||||
@node MSP430 Opcodes
|
||||
@ -162,3 +215,98 @@ additional pseudo-instructions are needed on this family.
|
||||
|
||||
For information on the 430 machine instruction set, see @cite{MSP430
|
||||
User's Manual, document slau049b}, Texas Instrument, Inc.
|
||||
|
||||
@node MSP430 Profiling Capability
|
||||
@section Profiling Capability
|
||||
|
||||
@cindex MSP 430 profiling capability
|
||||
@cindex profiling capability for MSP 430
|
||||
It is a performance hit to use gcc's profiling approach for this tiny target.
|
||||
Even more -- jtag hardware facility does not perform any profiling functions.
|
||||
However we've got gdb's built-in simulator where we can do anything.
|
||||
|
||||
We define new section @samp{.profiler} which holds all profiling information.
|
||||
We define new pseudo operation @samp{.profiler} which will instruct assembler to
|
||||
add new profile entry to the object file. Profile should take place at the
|
||||
present address.
|
||||
|
||||
Pseudo operation format:
|
||||
|
||||
@samp{.profiler flags,function_to_profile [, cycle_corrector, extra]}
|
||||
|
||||
|
||||
where:
|
||||
|
||||
@table @code
|
||||
|
||||
@table @code
|
||||
|
||||
@samp{flags} is a combination of the following characters:
|
||||
|
||||
@item s
|
||||
function entry
|
||||
@item x
|
||||
function exit
|
||||
@item i
|
||||
function is in init section
|
||||
@item f
|
||||
function is in fini section
|
||||
@item l
|
||||
library call
|
||||
@item c
|
||||
libc standard call
|
||||
@item d
|
||||
stack value demand
|
||||
@item I
|
||||
interrupt service routine
|
||||
@item P
|
||||
prologue start
|
||||
@item p
|
||||
prologue end
|
||||
@item E
|
||||
epilogue start
|
||||
@item e
|
||||
epilogue end
|
||||
@item j
|
||||
long jump / sjlj unwind
|
||||
@item a
|
||||
an arbitrary code fragment
|
||||
@item t
|
||||
extra parameter saved (a constant value like frame size)
|
||||
@end table
|
||||
|
||||
@item function_to_profile
|
||||
a function address
|
||||
@item cycle_corrector
|
||||
a value which should be added to the cycle counter, zero if omitted.
|
||||
@item extra
|
||||
any extra parameter, zero if omitted.
|
||||
|
||||
@end table
|
||||
|
||||
For example:
|
||||
@smallexample
|
||||
.global fxx
|
||||
.type fxx,@@function
|
||||
fxx:
|
||||
.LFrameOffset_fxx=0x08
|
||||
.profiler "scdP", fxx ; function entry.
|
||||
; we also demand stack value to be saved
|
||||
push r11
|
||||
push r10
|
||||
push r9
|
||||
push r8
|
||||
.profiler "cdpt",fxx,0, .LFrameOffset_fxx ; check stack value at this point
|
||||
; (this is a prologue end)
|
||||
; note, that spare var filled with
|
||||
; the farme size
|
||||
mov r15,r8
|
||||
...
|
||||
.profiler cdE,fxx ; check stack
|
||||
pop r8
|
||||
pop r9
|
||||
pop r10
|
||||
pop r11
|
||||
.profiler xcde,fxx,3 ; exit adds 3 to the cycle counter
|
||||
ret ; cause 'ret' insn takes 3 cycles
|
||||
@end smallexample
|
||||
|
@ -1,3 +1,7 @@
|
||||
2004-08-25 Dmitry Diky <diwil@spec.ru>
|
||||
|
||||
* msp430.h: Add new relocs.
|
||||
|
||||
2004-08-12 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* i386.h (R_386_USED_BY_INTEL_200): New.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* MSP430 ELF support for BFD.
|
||||
Copyright (C) 2002 Free Software Foundation, Inc.
|
||||
Copyright (C) 2002, 2004 Free Software Foundation, Inc.
|
||||
Contributed by Dmitry Diky <diwil@mail.ru>
|
||||
|
||||
This file is part of BFD, the Binary File Descriptor library.
|
||||
@ -50,6 +50,8 @@ START_RELOC_NUMBERS (elf_msp430_reloc_type)
|
||||
RELOC_NUMBER (R_MSP430_16_PCREL, 4)
|
||||
RELOC_NUMBER (R_MSP430_16_BYTE, 5)
|
||||
RELOC_NUMBER (R_MSP430_16_PCREL_BYTE, 6)
|
||||
RELOC_NUMBER (R_MSP430_2X_PCREL, 7)
|
||||
RELOC_NUMBER (R_MSP430_RL_PCREL, 8)
|
||||
|
||||
END_RELOC_NUMBERS (R_MSP430_max)
|
||||
|
||||
|
@ -1,3 +1,9 @@
|
||||
2004-08-24 Dmitry Diky <diwil@spec.ru>
|
||||
|
||||
* msp430.h (msp430_opc): Add new instructions.
|
||||
(msp430_rcodes): Declare new instructions.
|
||||
(msp430_hcodes): Likewise..
|
||||
|
||||
2004-08-13 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
PR/301
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* Opcode table for the TI MSP430 microcontrollers
|
||||
|
||||
Copyright 2002 Free Software Foundation, Inc.
|
||||
Copyright 2002, 2004 Free Software Foundation, Inc.
|
||||
Contributed by Dmitry Diky <diwil@mail.ru>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
@ -103,9 +103,114 @@ static struct msp430_opcode_s msp430_opcodes[] =
|
||||
MSP_INSN (rra, 2, 1, 0x1100, 0xff80),
|
||||
MSP_INSN (swpb, 2, 1, 0x1080, 0xffc0),
|
||||
MSP_INSN (rrc, 2, 1, 0x1000, 0xff80),
|
||||
/* Simple polymorphs. */
|
||||
MSP_INSN (beq, 4, 0, 0, 0xffff),
|
||||
MSP_INSN (bne, 4, 1, 0, 0xffff),
|
||||
MSP_INSN (blt, 4, 2, 0, 0xffff),
|
||||
MSP_INSN (bltu, 4, 3, 0, 0xffff),
|
||||
MSP_INSN (bge, 4, 4, 0, 0xffff),
|
||||
MSP_INSN (bgeu, 4, 5, 0, 0xffff),
|
||||
MSP_INSN (bltn, 4, 6, 0, 0xffff),
|
||||
MSP_INSN (jump, 4, 7, 0, 0xffff),
|
||||
/* Long polymorphs. */
|
||||
MSP_INSN (bgt, 5, 0, 0, 0xffff),
|
||||
MSP_INSN (bgtu, 5, 1, 0, 0xffff),
|
||||
MSP_INSN (bleu, 5, 2, 0, 0xffff),
|
||||
MSP_INSN (ble, 5, 3, 0, 0xffff),
|
||||
|
||||
/* End of instruction set. */
|
||||
{ NULL, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
/* GCC uses the some condition codes which we'll
|
||||
implement as new polymorph instructions.
|
||||
|
||||
COND EXPL SHORT JUMP LONG JUMP
|
||||
===============================================
|
||||
eq == jeq jne +4; br lab
|
||||
ne != jne jeq +4; br lab
|
||||
|
||||
ltn honours no-overflow flag
|
||||
ltn < jn jn +2; jmp +4; br lab
|
||||
|
||||
lt < jl jge +4; br lab
|
||||
ltu < jlo lhs +4; br lab
|
||||
le <= see below
|
||||
leu <= see below
|
||||
|
||||
gt > see below
|
||||
gtu > see below
|
||||
ge >= jge jl +4; br lab
|
||||
geu >= jhs jlo +4; br lab
|
||||
===============================================
|
||||
|
||||
Therefore, new opcodes are (BranchEQ -> beq; and so on...)
|
||||
beq,bne,blt,bltn,bltu,bge,bgeu
|
||||
'u' means unsigned compares
|
||||
|
||||
Also, we add 'jump' instruction:
|
||||
jump UNCOND -> jmp br lab
|
||||
|
||||
They will have fmt == 4, and insn_opnumb == number of instruction. */
|
||||
|
||||
struct rcodes_s
|
||||
{
|
||||
char * name;
|
||||
int index; /* Corresponding insn_opnumb. */
|
||||
int sop; /* Opcode if jump length is short. */
|
||||
long lpos; /* Label position. */
|
||||
long lop0; /* Opcode 1 _word_ (16 bits). */
|
||||
long lop1; /* Opcode second word. */
|
||||
long lop2; /* Opcode third word. */
|
||||
};
|
||||
|
||||
#define MSP430_RLC(n,i,sop,o1) \
|
||||
{#n, i, sop, 2, (o1 + 2), 0x4010, 0}
|
||||
|
||||
static struct rcodes_s msp430_rcodes[] =
|
||||
{
|
||||
MSP430_RLC (beq, 0, 0x2400, 0x2000),
|
||||
MSP430_RLC (bne, 1, 0x2000, 0x2400),
|
||||
MSP430_RLC (blt, 2, 0x3800, 0x3400),
|
||||
MSP430_RLC (bltu, 3, 0x2800, 0x2c00),
|
||||
MSP430_RLC (bge, 4, 0x3400, 0x3800),
|
||||
MSP430_RLC (bgeu, 5, 0x2c00, 0x2800),
|
||||
{"bltn", 6, 0x3000, 3, 0x3000 + 1, 0x3c00 + 2,0x4010},
|
||||
{"jump", 7, 0x3c00, 1, 0x4010, 0, 0},
|
||||
{0,0,0,0,0,0,0}
|
||||
};
|
||||
#undef MSP430_RLC
|
||||
|
||||
|
||||
/* More difficult than above and they have format 5.
|
||||
|
||||
COND EXPL SHORT LONG
|
||||
=================================================================
|
||||
gt > jeq +2; jge label jeq +6; jl +4; br label
|
||||
gtu > jeq +2; jhs label jeq +6; jlo +4; br label
|
||||
leu <= jeq label; jlo label jeq +2; jhs +4; br label
|
||||
le <= jeq label; jl label jeq +2; jge +4; br label
|
||||
================================================================= */
|
||||
|
||||
struct hcodes_s
|
||||
{
|
||||
char * name;
|
||||
int index; /* Corresponding insn_opnumb. */
|
||||
int tlab; /* Number of labels in short mode. */
|
||||
int op0; /* Opcode for first word of short jump. */
|
||||
int op1; /* Opcode for second word of short jump. */
|
||||
int lop0; /* Opcodes for long jump mode. */
|
||||
int lop1;
|
||||
int lop2;
|
||||
};
|
||||
|
||||
static struct hcodes_s msp430_hcodes[] =
|
||||
{
|
||||
{"bgt", 0, 1, 0x2401, 0x3400, 0x2403, 0x3802, 0x4010 },
|
||||
{"bgtu", 1, 1, 0x2401, 0x2c00, 0x2403, 0x2802, 0x4010 },
|
||||
{"bleu", 2, 2, 0x2400, 0x2800, 0x2401, 0x2c02, 0x4010 },
|
||||
{"ble", 3, 2, 0x2400, 0x3800, 0x2401, 0x3402, 0x4010 },
|
||||
{0,0,0,0,0,0,0,0}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,3 +1,8 @@
|
||||
2004-08-25 Dmitry Diky <diwil@spec.ru>
|
||||
|
||||
* emulparams/msp430all.sh: Fix RAM sizes for all targets.
|
||||
* scripttempl/elf32msp430.sc: Add .profiler section definition.
|
||||
|
||||
2004-08-24 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* ldlang.c (wildcardp): Defined as a macro with strpbrk.
|
||||
|
@ -288,7 +288,7 @@ TEMPLATE_NAME=generic
|
||||
ROM_START=0x4000
|
||||
ROM_SIZE=0xbfe0
|
||||
RAM_START=0x0200
|
||||
RAM_SIZE=0x07ff
|
||||
RAM_SIZE=0x0800
|
||||
|
||||
STACK=0xa00
|
||||
fi
|
||||
@ -305,7 +305,7 @@ TEMPLATE_NAME=generic
|
||||
ROM_START=0x1100
|
||||
ROM_SIZE=0xeee0
|
||||
RAM_START=0x0200
|
||||
RAM_SIZE=0x07ff
|
||||
RAM_SIZE=0x0800
|
||||
|
||||
STACK=0xa00
|
||||
fi
|
||||
@ -390,7 +390,7 @@ TEMPLATE_NAME=generic
|
||||
ROM_START=0x4000
|
||||
ROM_SIZE=0xbfe0
|
||||
RAM_START=0x0200
|
||||
RAM_SIZE=0x07ff
|
||||
RAM_SIZE=0x0800
|
||||
|
||||
STACK=0xa00
|
||||
fi
|
||||
@ -407,7 +407,7 @@ TEMPLATE_NAME=generic
|
||||
ROM_START=0x1100
|
||||
ROM_SIZE=0xeee0
|
||||
RAM_START=0x0200
|
||||
RAM_SIZE=0x07ff
|
||||
RAM_SIZE=0x0800
|
||||
|
||||
STACK=0xa00
|
||||
fi
|
||||
@ -424,9 +424,9 @@ TEMPLATE_NAME=generic
|
||||
ROM_START=0x8000
|
||||
ROM_SIZE=0x7fe0
|
||||
RAM_START=0x1100
|
||||
RAM_SIZE=0x13ff
|
||||
RAM_SIZE=0x1400
|
||||
|
||||
STACK=0x1400
|
||||
STACK=0x2500
|
||||
fi
|
||||
|
||||
if [ "${MSP430_NAME}" = "msp430x1611" ] ; then
|
||||
@ -441,9 +441,9 @@ TEMPLATE_NAME=generic
|
||||
ROM_START=0x4000
|
||||
ROM_SIZE=0xbfe0
|
||||
RAM_START=0x1100
|
||||
RAM_SIZE=0x27ff
|
||||
RAM_SIZE=0x2800
|
||||
|
||||
STACK=0x2800
|
||||
STACK=0x3900
|
||||
fi
|
||||
|
||||
if [ "${MSP430_NAME}" = "msp430x1612" ] ; then
|
||||
@ -455,12 +455,12 @@ MAXPAGESIZE=1
|
||||
EMBEDDED=yes
|
||||
TEMPLATE_NAME=generic
|
||||
|
||||
ROM_START=0x2800
|
||||
ROM_SIZE=0xd7e0
|
||||
ROM_START=0x2500
|
||||
ROM_SIZE=0xdae0
|
||||
RAM_START=0x1100
|
||||
RAM_SIZE=0x13ff
|
||||
RAM_SIZE=0x1400
|
||||
|
||||
STACK=0x1400
|
||||
STACK=0x2500
|
||||
fi
|
||||
|
||||
if [ "${MSP430_NAME}" = "msp430x311" ] ; then
|
||||
@ -764,7 +764,7 @@ TEMPLATE_NAME=generic
|
||||
ROM_START=0x4000
|
||||
ROM_SIZE=0xbfe0
|
||||
RAM_START=0x0200
|
||||
RAM_SIZE=0x07ff
|
||||
RAM_SIZE=0x0800
|
||||
|
||||
STACK=0xa00
|
||||
fi
|
||||
@ -781,7 +781,7 @@ TEMPLATE_NAME=generic
|
||||
ROM_START=0x1100
|
||||
ROM_SIZE=0xeee0
|
||||
RAM_START=0x0200
|
||||
RAM_SIZE=0x07ff
|
||||
RAM_SIZE=0x0800
|
||||
|
||||
STACK=0xa00
|
||||
fi
|
||||
@ -866,7 +866,7 @@ TEMPLATE_NAME=generic
|
||||
ROM_START=0x4000
|
||||
ROM_SIZE=0xbef0
|
||||
RAM_START=0x0200
|
||||
RAM_SIZE=0x07ff
|
||||
RAM_SIZE=0x0800
|
||||
|
||||
STACK=0xa00
|
||||
fi
|
||||
@ -883,7 +883,7 @@ TEMPLATE_NAME=generic
|
||||
ROM_START=0x1100
|
||||
ROM_SIZE=0xeee0
|
||||
RAM_START=0x0200
|
||||
RAM_SIZE=0x07ff
|
||||
RAM_SIZE=0x0800
|
||||
|
||||
STACK=0xa00
|
||||
fi
|
||||
@ -934,7 +934,7 @@ TEMPLATE_NAME=generic
|
||||
ROM_START=0x8000
|
||||
ROM_SIZE=0x7fe0
|
||||
RAM_START=0x0200
|
||||
RAM_SIZE=1K
|
||||
RAM_SIZE=0x400
|
||||
|
||||
STACK=0x600
|
||||
fi
|
||||
|
@ -202,6 +202,9 @@ SECTIONS
|
||||
|
||||
${HEAP_SECTION_MSP430}
|
||||
|
||||
/* Stabs for profiling information*/
|
||||
.profiler 0 : { *(.profiler) }
|
||||
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
|
Loading…
Reference in New Issue
Block a user