aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog10
-rw-r--r--bfd/bfd-in2.h3
-rw-r--r--bfd/elf32-cr16.c398
-rw-r--r--bfd/libbfd.h3
-rw-r--r--bfd/reloc.c6
-rw-r--r--gas/ChangeLog5
-rw-r--r--gas/config/tc-cr16.c802
-rw-r--r--include/elf/ChangeLog4
-rw-r--r--include/elf/cr16.h3
-rw-r--r--opcodes/ChangeLog5
-rw-r--r--opcodes/cr16-opc.c6
11 files changed, 750 insertions, 495 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 1445a2b..45180e3 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,13 @@
+2007-10-01 M R Swami Reddy <MR.Swami.Reddy@nsc.com>
+
+ * elf32-cr16.c: Fixed DISP8, DISP20 and IMM20 relocations at
+ final relocation phase.
+ Added the below relaxations: IMM32 -> IMM20/IM16 -> IMM4.
+ * reloc.c: Added 3 new relocations: R_CR16_SWITCH8,
+ R_CR16_SWITCH16, R_CR16_SWITCH32.
+ * libbfd.h: Regenerate.
+ * bfd-in2.h: Regenerate.
+
2007-09-30 Alan Modra <amodra@bigpond.net.au>
* elflink.c: Formatting.
diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 0943278..db9cd85 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -4148,6 +4148,9 @@ This is the 5 bits of a value. */
BFD_RELOC_CR16_DISP20,
BFD_RELOC_CR16_DISP24,
BFD_RELOC_CR16_DISP24a,
+ BFD_RELOC_CR16_SWITCH8,
+ BFD_RELOC_CR16_SWITCH16,
+ BFD_RELOC_CR16_SWITCH32,
/* NS CRX Relocations. */
BFD_RELOC_CRX_REL4,
diff --git a/bfd/elf32-cr16.c b/bfd/elf32-cr16.c
index 46664bc..d0f7fd1 100644
--- a/bfd/elf32-cr16.c
+++ b/bfd/elf32-cr16.c
@@ -61,7 +61,10 @@ static const struct cr16_reloc_map cr16_reloc_map[R_CR16_MAX] =
{BFD_RELOC_CR16_DISP8, R_CR16_DISP8},
{BFD_RELOC_CR16_DISP16, R_CR16_DISP16},
{BFD_RELOC_CR16_DISP24, R_CR16_DISP24},
- {BFD_RELOC_CR16_DISP24a, R_CR16_DISP24a}
+ {BFD_RELOC_CR16_DISP24a, R_CR16_DISP24a},
+ {BFD_RELOC_CR16_SWITCH8, R_CR16_SWITCH8},
+ {BFD_RELOC_CR16_SWITCH16, R_CR16_SWITCH16},
+ {BFD_RELOC_CR16_SWITCH32, R_CR16_SWITCH32}
};
static reloc_howto_type cr16_elf_howto_table[] =
@@ -429,7 +432,58 @@ static reloc_howto_type cr16_elf_howto_table[] =
FALSE, /* partial_inplace */
0xffffff, /* src_mask */
0xffffff, /* dst_mask */
- FALSE) /* pcrel_offset */
+ FALSE), /* pcrel_offset */
+
+ /* An 8 bit switch table entry. This is generated for an expression
+ such as ``.byte L1 - L2''. The offset holds the difference
+ between the reloc address and L2. */
+ HOWTO (R_CR16_SWITCH8, /* type */
+ 0, /* rightshift */
+ 0, /* size (0 = byte, 1 = short, 2 = long) */
+ 8, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_CR16_SWITCH8", /* name */
+ FALSE, /* partial_inplace */
+ 0xff, /* src_mask */
+ 0xff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ /* A 16 bit switch table entry. This is generated for an expression
+ such as ``.word L1 - L2''. The offset holds the difference
+ between the reloc address and L2. */
+ HOWTO (R_CR16_SWITCH16, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_CR16_SWITCH16", /* name */
+ FALSE, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ TRUE), /* pcrel_offset */
+
+ /* A 32 bit switch table entry. This is generated for an expression
+ such as ``.long L1 - L2''. The offset holds the difference
+ between the reloc address and L2. */
+ HOWTO (R_CR16_SWITCH32, /* type */
+ 0, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
+ FALSE, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_unsigned, /* complain_on_overflow */
+ bfd_elf_generic_reloc, /* special_function */
+ "R_CR16_SWITCH32", /* name */
+ FALSE, /* partial_inplace */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
+ TRUE) /* pcrel_offset */
};
/* Retrieve a howto ptr using a BFD reloc_code. */
@@ -478,13 +532,13 @@ elf_cr16_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, arelent *cache_ptr,
static bfd_reloc_status_type
cr16_elf_final_link_relocate (reloc_howto_type *howto,
- bfd *input_bfd,
+ bfd *input_bfd,
bfd *output_bfd ATTRIBUTE_UNUSED,
asection *input_section,
- bfd_byte *contents,
+ bfd_byte *contents,
bfd_vma offset,
- bfd_vma Rvalue,
- bfd_vma addend,
+ bfd_vma Rvalue,
+ bfd_vma addend,
struct bfd_link_info *info ATTRIBUTE_UNUSED,
asection *sec ATTRIBUTE_UNUSED,
int is_local ATTRIBUTE_UNUSED)
@@ -496,9 +550,12 @@ cr16_elf_final_link_relocate (reloc_howto_type *howto,
switch (r_type)
{
case R_CR16_IMM4:
+ case R_CR16_IMM20:
+ case R_CR16_ABS20:
+ break;
+
case R_CR16_IMM8:
case R_CR16_IMM16:
- case R_CR16_IMM20:
case R_CR16_IMM32:
case R_CR16_IMM32a:
case R_CR16_REGREL4:
@@ -507,7 +564,6 @@ cr16_elf_final_link_relocate (reloc_howto_type *howto,
case R_CR16_REGREL14a:
case R_CR16_REGREL16:
case R_CR16_REGREL20:
- case R_CR16_ABS20:
case R_CR16_ABS24:
case R_CR16_DISP16:
case R_CR16_DISP24:
@@ -521,11 +577,22 @@ cr16_elf_final_link_relocate (reloc_howto_type *howto,
break;
case R_CR16_DISP4:
+ if (is_local)
+ Rvalue += -1;
+ break;
+
case R_CR16_DISP8:
case R_CR16_DISP24a:
+ if (is_local)
+ Rvalue -= -1;
+ break;
+
+ case R_CR16_SWITCH8:
+ case R_CR16_SWITCH16:
+ case R_CR16_SWITCH32:
/* We only care about the addend, where the difference between
expressions is kept. */
- if (is_local) Rvalue -= -1;
+ Rvalue = 0;
default:
break;
@@ -563,7 +630,7 @@ cr16_elf_final_link_relocate (reloc_howto_type *howto,
{
check |= ((bfd_vma) - 1
& ~((bfd_vma) - 1
- >> howto->rightshift));
+ >> howto->rightshift));
if (((bfd_vma) check & ~reloc_bits)
!= (-(bfd_vma) 1 & ~reloc_bits))
@@ -582,14 +649,29 @@ cr16_elf_final_link_relocate (reloc_howto_type *howto,
switch (howto->size)
{
case 0:
- if ((r_type == R_CR16_IMM4)
- || (r_type == R_CR16_DISP4)
- || (r_type == R_CR16_DISP8))
+ if (r_type == R_CR16_DISP8)
{
Rvalue1 = bfd_get_16 (input_bfd, hit_data);
Rvalue = ((Rvalue1 & 0xf000) | ((Rvalue << 4) & 0xf00)
- | (Rvalue1 & 0x00f0) | (Rvalue & 0xf));
- bfd_put_16 (input_bfd, Rvalue, hit_data);
+ | (Rvalue1 & 0x00f0) | (Rvalue & 0xf));
+ bfd_put_16 (input_bfd, Rvalue, hit_data);
+ }
+ else if (r_type == R_CR16_IMM4)
+ {
+ Rvalue1 = bfd_get_16 (input_bfd, hit_data);
+ Rvalue = (((Rvalue1 & 0xff) << 8) | ((Rvalue << 4) & 0xf0)
+ | ((Rvalue1 & 0x0f00) >> 8));
+ bfd_put_16 (input_bfd, Rvalue, hit_data);
+ }
+ else if (r_type == R_CR16_DISP4)
+ {
+ Rvalue1 = bfd_get_16 (input_bfd, hit_data);
+ Rvalue = (Rvalue1 | ((Rvalue & 0xf) << 4));
+ bfd_put_16 (input_bfd, Rvalue, hit_data);
+ }
+ else
+ {
+ bfd_put_8 (input_bfd, (unsigned char) Rvalue, hit_data);
}
break;
@@ -598,65 +680,49 @@ cr16_elf_final_link_relocate (reloc_howto_type *howto,
{
Rvalue |= (bfd_get_16 (input_bfd, hit_data));
Rvalue = ((Rvalue & 0xfffe) | ((Rvalue >> 16) & 0x1));
-
- bfd_put_16 (input_bfd, Rvalue, hit_data);
}
+
+ bfd_put_16 (input_bfd, Rvalue, hit_data);
break;
case 2:
- if (r_type == R_CR16_ABS20)
+ if ((r_type == R_CR16_ABS20) || (r_type == R_CR16_IMM20))
{
- Rvalue |= (((bfd_get_16 (input_bfd, hit_data) << 16)
- | (bfd_get_16 (input_bfd, hit_data + 2)))
- & ~howto->dst_mask);
- Rvalue |= (bfd_get_16 (input_bfd, hit_data + 2) << 16);
-
- /* Relocation on INSTRUCTIONS is different : Instructions are
- word-addressable, that is, each word itself is arranged according
- to little-endian convention, whereas the words are arranged with
- respect to one another in BIG ENDIAN fashion.
- When there is an immediate value that spans a word boundary,
- it is split in a big-endian way with respect to the words. */
- bfd_put_16 (input_bfd, (Rvalue) & 0xffff, hit_data);
- bfd_put_16 (input_bfd, (Rvalue >> 16)& 0xffff, hit_data + 2);
- }
- else if (r_type == R_CR16_ABS24)
- {
- Rvalue = ((((Rvalue >> 20)& 0xf)
- | (((Rvalue >> 16) & 0xf) << 8)
- | (bfd_get_16 (input_bfd, hit_data)))
- | ((Rvalue & 0xffff) << 16));
-
- bfd_put_32 (input_bfd, Rvalue, hit_data);
+ bfd_put_16 (input_bfd, (bfd_get_16 (input_bfd, hit_data))
+ | ((Rvalue >> 16) & 0xf), hit_data);
+ bfd_put_16 (input_bfd, (Rvalue) & 0xffff, hit_data + 2);
}
- else if (r_type == R_CR16_DISP24)
+ else
{
- Rvalue = ((((Rvalue >> 20)& 0xf) | (((Rvalue >> 16) & 0xf)<<8)
- | (bfd_get_16 (input_bfd, hit_data)))
- | (((Rvalue & 0xfffE) | ((Rvalue >> 24) & 0x1)) << 16));
+ if (r_type == R_CR16_ABS24)
+ {
+ Rvalue = ((((Rvalue >> 20)& 0xf) | (((Rvalue >> 16) & 0xf) << 8)
+ | (bfd_get_16 (input_bfd, hit_data)))
+ | ((Rvalue & 0xffff) << 16));
+ }
+ if (r_type == R_CR16_DISP24)
+ {
+ Rvalue = ((((Rvalue >> 20)& 0xf) | (((Rvalue >>16) & 0xf) << 8)
+ | (bfd_get_16 (input_bfd, hit_data)))
+ | (((Rvalue & 0xfffe)
+ | ((Rvalue >> 24) & 0x1)) << 16));
+ }
+ else if ((r_type == R_CR16_IMM32) ||(r_type == R_CR16_IMM32a))
+ {
+ Rvalue = (((Rvalue >> 16)& 0xffff)
+ | (bfd_get_16 (input_bfd, hit_data)))
+ | ((Rvalue & 0xffff) << 16);
+ }
+ else if (r_type == R_CR16_DISP24a)
+ {
+ Rvalue = (((Rvalue & 0xfffffe) | (Rvalue >> 23)));
+ Rvalue = ((Rvalue >> 16) & 0xff) | ((Rvalue & 0xffff) << 16)
+ | (bfd_get_32 (input_bfd, hit_data));
+ }
bfd_put_32 (input_bfd, Rvalue, hit_data);
}
- else if ((r_type == R_CR16_IMM32) || (r_type == R_CR16_IMM32a))
- {
- Rvalue = (((Rvalue >> 16)& 0xffff)
- | (bfd_get_16 (input_bfd, hit_data)))
- | ((Rvalue & 0xffff) << 16);
- bfd_put_32 (input_bfd, Rvalue, hit_data);
- }
- else if (r_type == R_CR16_DISP24a)
- {
- Rvalue = (((Rvalue & 0xfffffe) | (Rvalue >> 23)));
- Rvalue = ((Rvalue >> 16) & 0xff) | ((Rvalue & 0xffff) << 16)
- | (bfd_get_32 (input_bfd, hit_data));
-
- bfd_put_32 (input_bfd, Rvalue, hit_data);
- }
- else if ((r_type == R_CR16_NUM32) || (r_type == R_CR16_NUM32a))
- {
- bfd_put_32 (input_bfd, Rvalue, hit_data);
- }
- break;
+ break;
default:
return bfd_reloc_notsupported;
@@ -705,7 +771,7 @@ elf32_cr16_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
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;
+ irel->r_offset -= count;
/* Adjust the local symbols defined in this section. */
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
@@ -724,6 +790,12 @@ elf32_cr16_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
Elf_Internal_Sym *rsym;
bfd_vma addsym, subsym;
+ /* Skip if not a SWITCH relocation. */
+ if (ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH8
+ && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH16
+ && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_SWITCH32)
+ continue;
+
r_symndx = ELF32_R_SYM (irel->r_info);
rsym = (Elf_Internal_Sym *) symtab_hdr->contents + r_symndx;
@@ -769,10 +841,10 @@ elf32_cr16_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
/* Loop only over the symbols whom been already checked. */
for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes;
cur_sym_hashes++)
- /* If the current symbol is identical to 'sym_hash', that means
- the symbol was already adjusted (or at least checked). */
- if (*cur_sym_hashes == sym_hash)
- break;
+ /* If the current symbol is identical to 'sym_hash', that means
+ the symbol was already adjusted (or at least checked). */
+ if (*cur_sym_hashes == sym_hash)
+ break;
/* Don't adjust the symbol again. */
if (cur_sym_hashes < sym_hashes)
@@ -794,10 +866,10 @@ elf32_cr16_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd,
static bfd_boolean
elf32_cr16_relocate_section (bfd *output_bfd, 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)
+ 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;
@@ -953,7 +1025,7 @@ elf32_cr16_get_relocated_section_contents (bfd *output_bfd,
bfd_size_type amt;
internal_relocs = _bfd_elf_link_read_relocs (input_bfd, input_section,
- NULL, NULL, FALSE);
+ NULL, NULL, FALSE);
if (internal_relocs == NULL)
goto error_return;
@@ -1024,8 +1096,9 @@ elf32_cr16_get_relocated_section_contents (bfd *output_bfd,
There's quite a few relaxing opportunites available on the CR16:
* bcond:24 -> bcond:16 2 bytes
- * bcond:16 -> bcond:8 2 bytes
- * arithmetic imm32 -> arithmetic imm16 2 bytes
+ * bcond:16 -> bcond:8 2 bytes
+ * arithmetic imm32 -> arithmetic imm20/imm16 2 bytes
+ * arithmetic imm20/imm16 -> arithmetic imm4 2 bytes
Symbol- and reloc-reading infrastructure copied from elf-m10200.c. */
@@ -1055,7 +1128,7 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
/* Get a copy of the native relocations. */
internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL,
- link_info->keep_memory);
+ link_info->keep_memory);
if (internal_relocs == NULL)
goto error_return;
@@ -1068,7 +1141,10 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
/* If this isn't something that can be relaxed, then ignore
this reloc. */
if (ELF32_R_TYPE (irel->r_info) != (int) R_CR16_DISP16
- && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_DISP24)
+ && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_DISP24
+ && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_IMM32
+ && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_IMM20
+ && ELF32_R_TYPE (irel->r_info) != (int) R_CR16_IMM16)
continue;
/* Get the section contents if we haven't done so already. */
@@ -1145,7 +1221,7 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
the linker is run. */
/* Try to turn a 24 branch/call into a 16bit relative
- * branch/call. */
+ branch/call. */
if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_DISP24)
{
bfd_vma value = symval;
@@ -1168,8 +1244,8 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
/* Verify it's a 'bcond' and fix the opcode. */
if ((code & 0xffff) == 0x0010)
{
- bfd_put_16 (abfd, 0x1800 | ((0xf & (code >>20))<<4), contents + irel->r_offset);
- bfd_put_16 (abfd, value, contents + irel->r_offset+2);
+ bfd_put_16 (abfd, 0x1800 | ((0xf & (code >> 20)) << 4), contents + irel->r_offset);
+ bfd_put_16 (abfd, value, contents + irel->r_offset + 2);
}
else
continue;
@@ -1194,8 +1270,8 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
}
}
- /* Try to turn a 16bit pc-relative branch into an
- 8bit pc-relative branch. */
+ /* Try to turn a 16-bit pc-relative branch into an
+ 8-bit pc-relative branch. */
if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_DISP16)
{
bfd_vma value = symval;
@@ -1218,8 +1294,8 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
/* Verify it's a 'bcond' opcode. */
if ((code & 0xff00) == 0x1800)
{
- bfd_put_8 (abfd, 0x1 | ((0xf & (code>>4))<<4), contents + irel->r_offset);
- bfd_put_8 (abfd, value, contents + irel->r_offset+2);
+ bfd_put_8 (abfd, 0x1 | ((0xf & (code >> 4)) << 4), contents + irel->r_offset);
+ bfd_put_8 (abfd, value, contents + irel->r_offset + 2);
}
else
continue;
@@ -1244,24 +1320,63 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
}
}
-#if 0 // REVISIT: To support IMM relaxation in CR16 target
/* Try to turn a 32bit immediate address into
- a 20bit immediate address. */
+ a 20/16bit immediate address. */
if (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM32)
{
bfd_vma value = symval;
+ unsigned short is_add_mov = 0;
/* See if the value will fit in 20 bits. */
- if ((long) value < 0x7ffff && (long) value > -0x80000)
+ if ((long) value < 0xfffff && (long) value > 0)
{
unsigned short code;
/* Get the opcode. */
code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
- /* Verify it's a 'arithmetic double'. */
- if ((code & 0xfff0) != 0x0070)
- continue;
+ /* Verify it's a arithmetic ADDD or MOVD instruction.
+ For ADDD and MOVD only, convert to IMM32 -> IMM20. */
+ if (((code & 0xfff0) != 0x0070) || ((code & 0xfff0) != 0x0020))
+ is_add_mov = 1;
+
+ if (is_add_mov)
+ {
+ /* 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 opcode. */
+ if ((code & 0xfff0) == 0x0070) /* For movd. */
+ bfd_put_8 (abfd, 0x05, contents + irel->r_offset + 1);
+ else /* code == 0x0020 for addd. */
+ bfd_put_8 (abfd, 0x04, contents + irel->r_offset + 1);
+
+ bfd_put_8 (abfd, (code & 0xf) << 4, contents + irel->r_offset);
+
+
+ /* Fix the relocation's type. */
+ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
+ R_CR16_IMM20);
+ /* Delete two bytes of data. */
+ if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
+ irel->r_offset + 2, 2))
+ goto error_return;
+
+ /* That will change things, so, we should relax again.
+ Note that this is not required, and it may be slow. */
+ *again = TRUE;
+ }
+ }
+ /* See if the value will fit in 16 bits. */
+ if ((!is_add_mov) && ((long) value < 0x7fff && (long) value > 0))
+ {
+ unsigned short code;
+
+ /* Get the opcode. */
+ code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
/* Note that we've changed the relocs, section contents, etc. */
elf_section_data (sec)->relocs = internal_relocs;
@@ -1269,40 +1384,46 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
symtab_hdr->contents = (unsigned char *) isymbuf;
/* Fix the opcode. */
- bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
+ if ((code & 0xf0) == 0x70) /* For movd. */
+ bfd_put_8 (abfd, 0x54, contents + irel->r_offset + 1);
+ else if ((code & 0xf0) == 0x20) /* For addd. */
+ bfd_put_8 (abfd, 0x60, contents + irel->r_offset + 1);
+ else if ((code & 0xf0) == 0x90) /* For cmpd. */
+ bfd_put_8 (abfd, 0x56, contents + irel->r_offset + 1);
+ else
+ continue;
+
+ bfd_put_8 (abfd, 0xb0 | (code & 0xf), contents + irel->r_offset);
/* Fix the relocation's type. */
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
- R_CR16_IMM20);
+ R_CR16_IMM16);
/* Delete two bytes of data. */
if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
- irel->r_offset + 2, 2))
- goto error_return;
+ irel->r_offset + 2, 2))
+ goto error_return;
/* That will change things, so, we should relax again.
Note that this is not required, and it may be slow. */
- *again = TRUE;
+ *again = TRUE;
}
}
- /* Try to turn a 20bit/16bit immediate address into
+
+ /* Try to turn a 20/16bit immediate address into
a 4bit immediate address. */
if ((ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM20)
- || (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM16))
+ || (ELF32_R_TYPE (irel->r_info) == (int) R_CR16_IMM16))
{
bfd_vma value = symval;
/* See if the value will fit in 4 bits. */
- if ((long) value < 0x7 && (long) value > -0x8)
+ if ((long) value < 0xf && (long) value > 0)
{
unsigned short code;
/* Get the opcode. */
- code = (unsigned short) bfd_get_8 (abfd, contents + irel->r_offset);
-
- /* Verify it's a 'arithmetic double'. */
- if (((code & 0xff) != 0x50) || ((code & 0xff) != 0x45))
- continue;
+ code = (unsigned short) bfd_get_16 (abfd, contents + irel->r_offset);
/* Note that we've changed the relocs, section contents, etc. */
elf_section_data (sec)->relocs = internal_relocs;
@@ -1310,7 +1431,45 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
symtab_hdr->contents = (unsigned char *) isymbuf;
/* Fix the opcode. */
- bfd_put_8 (abfd, (code & 0xff) - 0x10, contents + irel->r_offset);
+ if (((code & 0x0f00) == 0x0400) || ((code & 0x0f00) == 0x0500))
+ {
+ if ((code & 0x0f00) == 0x0400) /* For movd imm20. */
+ bfd_put_8 (abfd, 0x60, contents + irel->r_offset);
+ else /* For addd imm20. */
+ bfd_put_8 (abfd, 0x54, contents + irel->r_offset);
+ bfd_put_8 (abfd, (code & 0xf0) >> 4, contents + irel->r_offset + 1);
+ }
+ else
+ {
+ if ((code & 0xfff0) == 0x56b0) /* For cmpd imm16. */
+ bfd_put_8 (abfd, 0x56, contents + irel->r_offset);
+ else if ((code & 0xfff0) == 0x54b0) /* For movd imm16. */
+ bfd_put_8 (abfd, 0x54, contents + irel->r_offset);
+ else if ((code & 0xfff0) == 0x58b0) /* For movb imm16. */
+ bfd_put_8 (abfd, 0x58, contents + irel->r_offset);
+ else if ((code & 0xfff0) == 0x5Ab0) /* For movw imm16. */
+ bfd_put_8 (abfd, 0x5A, contents + irel->r_offset);
+ else if ((code & 0xfff0) == 0x60b0) /* For addd imm16. */
+ bfd_put_8 (abfd, 0x60, contents + irel->r_offset);
+ else if ((code & 0xfff0) == 0x30b0) /* For addb imm16. */
+ bfd_put_8 (abfd, 0x30, contents + irel->r_offset);
+ else if ((code & 0xfff0) == 0x2Cb0) /* For addub imm16. */
+ bfd_put_8 (abfd, 0x2C, contents + irel->r_offset);
+ else if ((code & 0xfff0) == 0x32b0) /* For adduw imm16. */
+ bfd_put_8 (abfd, 0x32, contents + irel->r_offset);
+ else if ((code & 0xfff0) == 0x38b0) /* For subb imm16. */
+ bfd_put_8 (abfd, 0x38, contents + irel->r_offset);
+ else if ((code & 0xfff0) == 0x3Ab0) /* For subw imm16. */
+ bfd_put_8 (abfd, 0x3A, contents + irel->r_offset);
+ else if ((code & 0xfff0) == 0x50b0) /* For cmpb imm16. */
+ bfd_put_8 (abfd, 0x50, contents + irel->r_offset);
+ else if ((code & 0xfff0) == 0x52b0) /* For cmpw imm16. */
+ bfd_put_8 (abfd, 0x52, contents + irel->r_offset);
+ else
+ continue;
+
+ bfd_put_8 (abfd, (code & 0xf), contents + irel->r_offset + 1);
+ }
/* Fix the relocation's type. */
irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info),
@@ -1318,7 +1477,7 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
/* Delete two bytes of data. */
if (!elf32_cr16_relax_delete_bytes (link_info, abfd, sec,
- irel->r_offset + 2, 2))
+ irel->r_offset + 2, 2))
goto error_return;
/* That will change things, so, we should relax again.
@@ -1326,7 +1485,6 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
*again = TRUE;
}
}
-#endif
}
if (isymbuf != NULL
@@ -1335,10 +1493,8 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
if (! link_info->keep_memory)
free (isymbuf);
else
- {
- /* Cache the symbols for elf_link_input_bfd. */
- symtab_hdr->contents = (unsigned char *) isymbuf;
- }
+ /* Cache the symbols for elf_link_input_bfd. */
+ symtab_hdr->contents = (unsigned char *) isymbuf;
}
if (contents != NULL
@@ -1347,10 +1503,8 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
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;
- }
+ /* Cache the section contents for elf_link_input_bfd. */
+ elf_section_data (sec)->this_hdr.contents = contents;
}
if (internal_relocs != NULL
@@ -1375,10 +1529,10 @@ elf32_cr16_relax_section (bfd *abfd, asection *sec,
static asection *
elf32_cr16_gc_mark_hook (asection *sec,
- struct bfd_link_info *info ATTRIBUTE_UNUSED,
- Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
- struct elf_link_hash_entry *h,
- Elf_Internal_Sym *sym)
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ Elf_Internal_Rela *rel ATTRIBUTE_UNUSED,
+ struct elf_link_hash_entry *h,
+ Elf_Internal_Sym *sym)
{
if (h == NULL)
return bfd_section_from_elf_index (sec->owner, sym->st_shndx);
@@ -1401,9 +1555,9 @@ elf32_cr16_gc_mark_hook (asection *sec,
static bfd_boolean
elf32_cr16_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)
+ struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ asection *sec ATTRIBUTE_UNUSED,
+ const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
{
/* We don't support garbage collection of GOT and PLT relocs yet. */
return TRUE;
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index 2d5b5b3d..7f10f46 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -1833,6 +1833,9 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_CR16_DISP20",
"BFD_RELOC_CR16_DISP24",
"BFD_RELOC_CR16_DISP24a",
+ "BFD_RELOC_CR16_SWITCH8",
+ "BFD_RELOC_CR16_SWITCH16",
+ "BFD_RELOC_CR16_SWITCH32",
"BFD_RELOC_CRX_REL4",
"BFD_RELOC_CRX_REL8",
"BFD_RELOC_CRX_REL8_CMP",
diff --git a/bfd/reloc.c b/bfd/reloc.c
index cb9269b..525fe35 100644
--- a/bfd/reloc.c
+++ b/bfd/reloc.c
@@ -4570,6 +4570,12 @@ ENUMX
BFD_RELOC_CR16_DISP24
ENUMX
BFD_RELOC_CR16_DISP24a
+ENUMX
+ BFD_RELOC_CR16_SWITCH8
+ENUMX
+ BFD_RELOC_CR16_SWITCH16
+ENUMX
+ BFD_RELOC_CR16_SWITCH32
ENUMDOC
NS CR16 Relocations.
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 3bee322..011d29b 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,8 @@
+2007-10-01 M R Swami Reddy <MR.Swami.Reddy@nsc.com>
+
+ * config/tc-cr16.c: Replaced 'tabs' with white spaces and
+ added R_CR16_DISP8 as default reloc type for b<cc> instructions.
+
2007-09-30 H.J. Lu <hongjiu.lu@intel.com>
PR gas/5080
diff --git a/gas/config/tc-cr16.c b/gas/config/tc-cr16.c
index 256feed..31c6215 100644
--- a/gas/config/tc-cr16.c
+++ b/gas/config/tc-cr16.c
@@ -141,92 +141,92 @@ l_cons (int nbytes)
expression (&exp);
if (*input_line_pointer == ':')
- {
- /* Bitfields. */
- long value = 0;
-
- for (;;)
- {
- unsigned long width;
-
- if (*input_line_pointer != ':')
- {
- input_line_pointer = hold;
- break;
- }
- if (exp.X_op == O_absent)
- {
- as_warn (_("using a bit field width of zero"));
- exp.X_add_number = 0;
- exp.X_op = O_constant;
- }
-
- if (exp.X_op != O_constant)
- {
- *input_line_pointer = '\0';
- as_bad (_("field width \"%s\" too complex for a bitfield"), hold);
- *input_line_pointer = ':';
- demand_empty_rest_of_line ();
- return;
- }
-
- if ((width = exp.X_add_number) >
- (unsigned int)(BITS_PER_CHAR * nbytes))
- {
- as_warn (_("field width %lu too big to fit in %d bytes: truncated to %d bits"), width, nbytes, (BITS_PER_CHAR * nbytes));
- width = BITS_PER_CHAR * nbytes;
- } /* Too big. */
-
-
- if (width > bits_available)
- {
- /* FIXME-SOMEDAY: backing up and reparsing is wasteful. */
- input_line_pointer = hold;
- exp.X_add_number = value;
- break;
- }
-
- /* Skip ':'. */
- hold = ++input_line_pointer;
-
- expression (&exp);
- if (exp.X_op != O_constant)
- {
- char cache = *input_line_pointer;
-
- *input_line_pointer = '\0';
- as_bad (_("field value \"%s\" too complex for a bitfield"), hold);
- *input_line_pointer = cache;
- demand_empty_rest_of_line ();
- return;
- }
-
- value |= ((~(-1 << width) & exp.X_add_number)
- << ((BITS_PER_CHAR * nbytes) - bits_available));
-
- if ((bits_available -= width) == 0
- || is_it_end_of_statement ()
- || *input_line_pointer != ',')
- break;
-
- hold = ++input_line_pointer;
- expression (&exp);
- }
-
- exp.X_add_number = value;
- exp.X_op = O_constant;
- exp.X_unsigned = 1;
- }
+ {
+ /* Bitfields. */
+ long value = 0;
+
+ for (;;)
+ {
+ unsigned long width;
+
+ if (*input_line_pointer != ':')
+ {
+ input_line_pointer = hold;
+ break;
+ }
+ if (exp.X_op == O_absent)
+ {
+ as_warn (_("using a bit field width of zero"));
+ exp.X_add_number = 0;
+ exp.X_op = O_constant;
+ }
+
+ if (exp.X_op != O_constant)
+ {
+ *input_line_pointer = '\0';
+ as_bad (_("field width \"%s\" too complex for a bitfield"), hold);
+ *input_line_pointer = ':';
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ if ((width = exp.X_add_number) >
+ (unsigned int)(BITS_PER_CHAR * nbytes))
+ {
+ as_warn (_("field width %lu too big to fit in %d bytes: truncated to %d bits"), width, nbytes, (BITS_PER_CHAR * nbytes));
+ width = BITS_PER_CHAR * nbytes;
+ } /* Too big. */
+
+
+ if (width > bits_available)
+ {
+ /* FIXME-SOMEDAY: backing up and reparsing is wasteful. */
+ input_line_pointer = hold;
+ exp.X_add_number = value;
+ break;
+ }
+
+ /* Skip ':'. */
+ hold = ++input_line_pointer;
+
+ expression (&exp);
+ if (exp.X_op != O_constant)
+ {
+ char cache = *input_line_pointer;
+
+ *input_line_pointer = '\0';
+ as_bad (_("field value \"%s\" too complex for a bitfield"), hold);
+ *input_line_pointer = cache;
+ demand_empty_rest_of_line ();
+ return;
+ }
+
+ value |= ((~(-1 << width) & exp.X_add_number)
+ << ((BITS_PER_CHAR * nbytes) - bits_available));
+
+ if ((bits_available -= width) == 0
+ || is_it_end_of_statement ()
+ || *input_line_pointer != ',')
+ break;
+
+ hold = ++input_line_pointer;
+ expression (&exp);
+ }
+
+ exp.X_add_number = value;
+ exp.X_op = O_constant;
+ exp.X_unsigned = 1;
+ }
if ((*(input_line_pointer) == '@') && (*(input_line_pointer +1) == 'c'))
- code_label = 1;
+ code_label = 1;
emit_expr (&exp, (unsigned int) nbytes);
++c;
if ((*(input_line_pointer) == '@') && (*(input_line_pointer +1) == 'c'))
- {
- input_line_pointer +=3;
- break;
- }
+ {
+ input_line_pointer +=3;
+ break;
+ }
}
while ((*input_line_pointer++ == ','));
@@ -373,8 +373,8 @@ get_index_register_pair (char *reg_name)
if (reg != NULL)
{
if ((reg->value.reg_val != 1) || (reg->value.reg_val != 7)
- || (reg->value.reg_val != 9) || (reg->value.reg_val > 10))
- return reg->value.reg_val;
+ || (reg->value.reg_val != 9) || (reg->value.reg_val > 10))
+ return reg->value.reg_val;
as_bad (_("Unknown register pair - index relative mode: `%d'"), reg->value.reg_val);
}
@@ -478,9 +478,7 @@ reset_vars (char *op)
int
cr16_force_relocation (fixS *fix)
{
- /* REVISIT: Check if the "SWITCH_TABLE (fix)" should be added
- if (generic_force_reloc (fix) || SWITCH_TABLE (fix)) */
- if (generic_force_reloc (fix))
+ if (generic_force_reloc (fix) || SWITCH_TABLE (fix))
return 1;
return 0;
@@ -499,12 +497,12 @@ cr16_cons_fix_new (fragS *frag, int offset, int len, expressionS *exp)
case 2: rtype = BFD_RELOC_CR16_NUM16; break;
case 4:
if (code_label)
- {
- rtype = BFD_RELOC_CR16_NUM32a;
- code_label = 0;
- }
+ {
+ rtype = BFD_RELOC_CR16_NUM32a;
+ code_label = 0;
+ }
else
- rtype = BFD_RELOC_CR16_NUM32;
+ rtype = BFD_RELOC_CR16_NUM32;
break;
}
@@ -534,21 +532,21 @@ tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS * fixP)
switch (fixP->fx_r_type)
{
- case BFD_RELOC_CR16_NUM8:
- fixP->fx_r_type = BFD_RELOC_CR16_NUM8;
- break;
- case BFD_RELOC_CR16_NUM16:
- fixP->fx_r_type = BFD_RELOC_CR16_NUM16;
- break;
- case BFD_RELOC_CR16_NUM32:
- fixP->fx_r_type = BFD_RELOC_CR16_NUM32;
- break;
- case BFD_RELOC_CR16_NUM32a:
- fixP->fx_r_type = BFD_RELOC_CR16_NUM32a;
- break;
- default:
- abort ();
- break;
+ case BFD_RELOC_CR16_NUM8:
+ fixP->fx_r_type = BFD_RELOC_CR16_SWITCH8;
+ break;
+ case BFD_RELOC_CR16_NUM16:
+ fixP->fx_r_type = BFD_RELOC_CR16_SWITCH16;
+ break;
+ case BFD_RELOC_CR16_NUM32:
+ fixP->fx_r_type = BFD_RELOC_CR16_SWITCH32;
+ break;
+ case BFD_RELOC_CR16_NUM32a:
+ fixP->fx_r_type = BFD_RELOC_CR16_NUM32a;
+ break;
+ default:
+ abort ();
+ break;
}
}
else
@@ -613,10 +611,41 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, fragS *fragP)
{
/* 'opcode' points to the start of the instruction, whether
we need to change the instruction's fixed encoding. */
- bfd_reloc_code_real_type reloc = BFD_RELOC_NONE;
+ char *opcode = fragP->fr_literal + fragP->fr_fix;
+ bfd_reloc_code_real_type reloc;
subseg_change (sec, 0);
+ switch (fragP->fr_subtype)
+ {
+ case 0:
+ reloc = BFD_RELOC_CR16_DISP8;
+ break;
+ case 1:
+ /* If the subtype is not changed due to :m operand qualifier,
+ then no need to update the opcode value. */
+ if ((int)opcode[1] != 0x18)
+ {
+ opcode[0] = (opcode[0] & 0xf0);
+ opcode[1] = 0x18;
+ }
+ reloc = BFD_RELOC_CR16_DISP16;
+ break;
+ case 2:
+ /* If the subtype is not changed due to :l operand qualifier,
+ then no need to update the opcode value. */
+ if ((int)opcode[1] != 0)
+ {
+ opcode[2] = opcode[0];
+ opcode[0] = opcode[1];
+ opcode[1] = 0x0;
+ }
+ reloc = BFD_RELOC_CR16_DISP24;
+ break;
+ default:
+ abort();
+ }
+
fix_new (fragP, fragP->fr_fix,
bfd_get_reloc_size (bfd_reloc_type_lookup (stdoutput, reloc)),
fragP->fr_symbol, fragP->fr_offset, 1, reloc);
@@ -752,8 +781,8 @@ md_pcrel_from (fixS *fixp)
static void
initialise_reg_hash_table (struct hash_control ** hash_table,
- const reg_entry * register_table,
- const unsigned int num_entries)
+ const reg_entry * register_table,
+ const unsigned int num_entries)
{
const reg_entry * reg;
const char *hashret;
@@ -767,8 +796,8 @@ initialise_reg_hash_table (struct hash_control ** hash_table,
{
hashret = hash_insert (* hash_table, reg->name, (char *) reg);
if (hashret)
- as_fatal (_("Internal Error: Can't hash %s: %s"),
- reg->name, hashret);
+ as_fatal (_("Internal Error: Can't hash %s: %s"),
+ reg->name, hashret);
}
}
@@ -790,7 +819,7 @@ md_begin (void)
const char *mnemonic = cr16_instruction[i].mnemonic;
hashret = hash_insert (cr16_inst_hash, mnemonic,
- (char *)(cr16_instruction + i));
+ (char *)(cr16_instruction + i));
if (hashret != NULL && *hashret != '\0')
as_fatal (_("Can't hash `%s': %s\n"), cr16_instruction[i].mnemonic,
@@ -845,7 +874,7 @@ process_label_constant (char *str, ins * cr16_ins)
case O_absent:
/* Missing or bad expr becomes absolute 0. */
as_bad (_("missing or invalid displacement expression `%s' taken as 0"),
- str);
+ str);
cr16_ins->exp.X_op = O_constant;
cr16_ins->exp.X_add_number = 0;
cr16_ins->exp.X_add_symbol = NULL;
@@ -865,105 +894,105 @@ process_label_constant (char *str, ins * cr16_ins)
relocatable = 1;
if (strneq (input_line_pointer, "@c", 2))
- symbol_with_at = 1;
+ symbol_with_at = 1;
if (strneq (input_line_pointer, "@l", 2)
- || strneq (input_line_pointer, ":l", 2))
- symbol_with_l = 1;
+ || strneq (input_line_pointer, ":l", 2))
+ symbol_with_l = 1;
if (strneq (input_line_pointer, "@m", 2)
- || strneq (input_line_pointer, ":m", 2))
- symbol_with_m = 1;
+ || strneq (input_line_pointer, ":m", 2))
+ symbol_with_m = 1;
if (strneq (input_line_pointer, "@s", 2)
- || strneq (input_line_pointer, ":s", 2))
- symbol_with_s = 1;
+ || strneq (input_line_pointer, ":s", 2))
+ symbol_with_s = 1;
switch (cur_arg->type)
{
- case arg_cr:
- if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (CSTBIT_INS))
- {
- if (cur_arg->size == 20)
- cr16_ins->rtype = BFD_RELOC_CR16_REGREL20;
- else
- cr16_ins->rtype = BFD_RELOC_CR16_REGREL20a;
- }
- break;
-
- case arg_crp:
- if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (CSTBIT_INS))
- switch (instruction->size)
- {
- case 1:
- switch (cur_arg->size)
- {
- case 0:
- cr16_ins->rtype = BFD_RELOC_CR16_REGREL0;
- break;
- case 4:
- if (IS_INSN_MNEMONIC ("loadb") || IS_INSN_MNEMONIC ("storb"))
- cr16_ins->rtype = BFD_RELOC_CR16_REGREL4;
- else
- cr16_ins->rtype = BFD_RELOC_CR16_REGREL4a;
- break;
- default: break;
- }
- break;
- case 2:
- cr16_ins->rtype = BFD_RELOC_CR16_REGREL16;
- break;
- case 3:
- if (cur_arg->size == 20)
- cr16_ins->rtype = BFD_RELOC_CR16_REGREL20;
- else
- cr16_ins->rtype = BFD_RELOC_CR16_REGREL20a;
- break;
- default:
- break;
- }
- break;
-
- case arg_idxr:
- if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (CSTBIT_INS))
- cr16_ins->rtype = BFD_RELOC_CR16_REGREL20;
- break;
-
- case arg_idxrp:
- if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (CSTBIT_INS))
- switch (instruction->size)
- {
- case 1: cr16_ins->rtype = BFD_RELOC_CR16_REGREL0; break;
- case 2: cr16_ins->rtype = BFD_RELOC_CR16_REGREL14; break;
- case 3: cr16_ins->rtype = BFD_RELOC_CR16_REGREL20; break;
- default: break;
- }
- break;
-
- case arg_c:
- if (IS_INSN_MNEMONIC ("bal"))
- cr16_ins->rtype = BFD_RELOC_CR16_DISP24;
- else if (IS_INSN_TYPE (BRANCH_INS))
- {
- if (symbol_with_s)
- cr16_ins->rtype = BFD_RELOC_CR16_DISP8;
- else if (symbol_with_m)
- cr16_ins->rtype = BFD_RELOC_CR16_DISP16;
- else
- cr16_ins->rtype = BFD_RELOC_CR16_DISP24;
- }
- else if (IS_INSN_TYPE (STOR_IMM_INS) || IS_INSN_TYPE (LD_STOR_INS)
- || IS_INSN_TYPE (CSTBIT_INS))
- {
- if (symbol_with_s)
- as_bad (_("operand %d: illegal use expression: `%s`"), cur_arg_num + 1, str);
- if (symbol_with_m)
- cr16_ins->rtype = BFD_RELOC_CR16_ABS20;
- else /* Default to (symbol_with_l) */
- cr16_ins->rtype = BFD_RELOC_CR16_ABS24;
- }
- else if (IS_INSN_TYPE (BRANCH_NEQ_INS))
- cr16_ins->rtype = BFD_RELOC_CR16_DISP4;
+ case arg_cr:
+ if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (CSTBIT_INS))
+ {
+ if (cur_arg->size == 20)
+ cr16_ins->rtype = BFD_RELOC_CR16_REGREL20;
+ else
+ cr16_ins->rtype = BFD_RELOC_CR16_REGREL20a;
+ }
+ break;
+
+ case arg_crp:
+ if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (CSTBIT_INS))
+ switch (instruction->size)
+ {
+ case 1:
+ switch (cur_arg->size)
+ {
+ case 0:
+ cr16_ins->rtype = BFD_RELOC_CR16_REGREL0;
+ break;
+ case 4:
+ if (IS_INSN_MNEMONIC ("loadb") || IS_INSN_MNEMONIC ("storb"))
+ cr16_ins->rtype = BFD_RELOC_CR16_REGREL4;
+ else
+ cr16_ins->rtype = BFD_RELOC_CR16_REGREL4a;
+ break;
+ default: break;
+ }
+ break;
+ case 2:
+ cr16_ins->rtype = BFD_RELOC_CR16_REGREL16;
+ break;
+ case 3:
+ if (cur_arg->size == 20)
+ cr16_ins->rtype = BFD_RELOC_CR16_REGREL20;
+ else
+ cr16_ins->rtype = BFD_RELOC_CR16_REGREL20a;
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case arg_idxr:
+ if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (CSTBIT_INS))
+ cr16_ins->rtype = BFD_RELOC_CR16_REGREL20;
+ break;
+
+ case arg_idxrp:
+ if (IS_INSN_TYPE (LD_STOR_INS) || IS_INSN_TYPE (CSTBIT_INS))
+ switch (instruction->size)
+ {
+ case 1: cr16_ins->rtype = BFD_RELOC_CR16_REGREL0; break;
+ case 2: cr16_ins->rtype = BFD_RELOC_CR16_REGREL14; break;
+ case 3: cr16_ins->rtype = BFD_RELOC_CR16_REGREL20; break;
+ default: break;
+ }
+ break;
+
+ case arg_c:
+ if (IS_INSN_MNEMONIC ("bal"))
+ cr16_ins->rtype = BFD_RELOC_CR16_DISP24;
+ else if (IS_INSN_TYPE (BRANCH_INS))
+ {
+ if (symbol_with_l)
+ cr16_ins->rtype = BFD_RELOC_CR16_DISP24;
+ else if (symbol_with_m)
+ cr16_ins->rtype = BFD_RELOC_CR16_DISP16;
+ else
+ cr16_ins->rtype = BFD_RELOC_CR16_DISP8;
+ }
+ else if (IS_INSN_TYPE (STOR_IMM_INS) || IS_INSN_TYPE (LD_STOR_INS)
+ || IS_INSN_TYPE (CSTBIT_INS))
+ {
+ if (symbol_with_s)
+ as_bad (_("operand %d: illegal use expression: `%s`"), cur_arg_num + 1, str);
+ if (symbol_with_m)
+ cr16_ins->rtype = BFD_RELOC_CR16_ABS20;
+ else /* Default to (symbol_with_l) */
+ cr16_ins->rtype = BFD_RELOC_CR16_ABS24;
+ }
+ else if (IS_INSN_TYPE (BRANCH_NEQ_INS))
+ cr16_ins->rtype = BFD_RELOC_CR16_DISP4;
break;
case arg_ic:
@@ -979,13 +1008,13 @@ process_label_constant (char *str, ins * cr16_ins)
cr16_ins->rtype = BFD_RELOC_CR16_IMM32;
}
else if (IS_INSN_TYPE (ARITH_BYTE_INS))
- {
- cr16_ins->rtype = BFD_RELOC_CR16_IMM16;
- }
+ {
+ cr16_ins->rtype = BFD_RELOC_CR16_IMM16;
+ }
break;
default:
break;
- }
+ }
break;
default:
@@ -1029,9 +1058,9 @@ getreg_image (reg r)
{
case CR16_R_REGTYPE:
if (! is_procreg)
- return reg->image;
+ return reg->image;
else
- IMAGE_ERR;
+ IMAGE_ERR;
case CR16_P_REGTYPE:
return reg->image;
@@ -1097,10 +1126,10 @@ set_operand (char *operand, ins * cr16_ins)
/* set the arg->rp, if reg is "r12" or "r13" or "14" or "15" */
if ((cur_arg->type != arg_rbase)
- && ((getreg_image (cur_arg->r) == 12)
- || (getreg_image (cur_arg->r) == 13)
- || (getreg_image (cur_arg->r) == 14)
- || (getreg_image (cur_arg->r) == 15)))
+ && ((getreg_image (cur_arg->r) == 12)
+ || (getreg_image (cur_arg->r) == 13)
+ || (getreg_image (cur_arg->r) == 14)
+ || (getreg_image (cur_arg->r) == 15)))
{
cur_arg->type = arg_crp;
cur_arg->rp = cur_arg->r;
@@ -1137,7 +1166,7 @@ set_operand (char *operand, ins * cr16_ins)
cur_arg->type = arg_idxrp;
}
else
- cur_arg->rp = -1;
+ cur_arg->rp = -1;
operandE = operandS;
/* Set displacement constant. */
@@ -1245,9 +1274,9 @@ parse_operand (char *operand, ins * cr16_ins)
{
case '$':
if (strchr (operand, '(') != NULL)
- cur_arg->type = arg_icr;
+ cur_arg->type = arg_icr;
else
- cur_arg->type = arg_ic;
+ cur_arg->type = arg_ic;
goto set_params;
break;
@@ -1439,7 +1468,7 @@ static int
is_bcc_insn (char * op)
{
if (!(streq (op, "bal") || streq (op, "beq0b") || streq (op, "bnq0b")
- || streq (op, "beq0w") || streq (op, "bnq0w")))
+ || streq (op, "beq0w") || streq (op, "bnq0w")))
if ((op[0] == 'b') && (get_b_cc (op) != NULL))
return 1;
return 0;
@@ -1540,18 +1569,18 @@ getidxregp_image (reg r)
if (reg->type == CR16_RP_REGTYPE)
{
switch (reg->image)
- {
- case 0: return 0; break;
- case 2: return 1; break;
- case 4: return 2; break;
- case 6: return 3; break;
- case 8: return 4; break;
- case 10: return 5; break;
- case 3: return 6; break;
- case 5: return 7; break;
- default:
- break;
- }
+ {
+ case 0: return 0; break;
+ case 2: return 1; break;
+ case 4: return 2; break;
+ case 6: return 3; break;
+ case 8: return 4; break;
+ case 10: return 5; break;
+ case 3: return 6; break;
+ case 5: return 7; break;
+ default:
+ break;
+ }
}
IDX_RPAIR_IMAGE_ERR;
@@ -1612,17 +1641,17 @@ getprocregp_image (reg r)
r = r - MAX_REG;
switch (r)
{
- case 4: pregptab_disp = 1; break;
- case 6: pregptab_disp = 2; break;
- case 8:
- case 9:
- case 10:
- pregptab_disp = 3; break;
- case 12:
- pregptab_disp = 4; break;
- case 14:
- pregptab_disp = 5; break;
- default: break;
+ case 4: pregptab_disp = 1; break;
+ case 6: pregptab_disp = 2; break;
+ case 8:
+ case 9:
+ case 10:
+ pregptab_disp = 3; break;
+ case 12:
+ pregptab_disp = 4; break;
+ case 14:
+ pregptab_disp = 5; break;
+ default: break;
}
reg = &cr16_pregptab[r - pregptab_disp];
}
@@ -1679,16 +1708,16 @@ print_constant (int nbits, int shift, argument *arg)
case 32:
case 28:
/* mask the upper part of the constant, that is, the bits
- going to the lowest byte of output_opcode[0].
- The upper part of output_opcode[1] is always filled,
- therefore it is always masked with 0xFFFF. */
+ going to the lowest byte of output_opcode[0].
+ The upper part of output_opcode[1] is always filled,
+ therefore it is always masked with 0xFFFF. */
mask = (1 << (nbits - 16)) - 1;
/* Divide the constant between two consecutive words :
- 0 1 2 3
- +---------+---------+---------+---------+
- | | X X X X | x X x X | |
- +---------+---------+---------+---------+
- output_opcode[0] output_opcode[1] */
+ 0 1 2 3
+ +---------+---------+---------+---------+
+ | | X X X X | x X x X | |
+ +---------+---------+---------+---------+
+ output_opcode[0] output_opcode[1] */
CR16_PRINT (0, (constant >> WORD_SHIFT) & mask, 0);
CR16_PRINT (1, (constant & 0xFFFF), WORD_SHIFT);
@@ -1700,70 +1729,70 @@ print_constant (int nbits, int shift, argument *arg)
case 22:
case 20:
/* mask the upper part of the constant, that is, the bits
- going to the lowest byte of output_opcode[0].
- The upper part of output_opcode[1] is always filled,
- therefore it is always masked with 0xFFFF. */
+ going to the lowest byte of output_opcode[0].
+ The upper part of output_opcode[1] is always filled,
+ therefore it is always masked with 0xFFFF. */
mask = (1 << (nbits - 16)) - 1;
/* Divide the constant between two consecutive words :
- 0 1 2 3
- +---------+---------+---------+---------+
- | | X X X X | - X - X | |
- +---------+---------+---------+---------+
- output_opcode[0] output_opcode[1] */
+ 0 1 2 3
+ +---------+---------+---------+---------+
+ | | X X X X | - X - X | |
+ +---------+---------+---------+---------+
+ output_opcode[0] output_opcode[1] */
if ((instruction->size > 2) && (shift == WORD_SHIFT))
- {
- if (arg->type == arg_idxrp)
- {
- CR16_PRINT (0, ((constant >> WORD_SHIFT) & mask) << 8, 0);
- CR16_PRINT (1, (constant & 0xFFFF), WORD_SHIFT);
- }
- else
- {
- CR16_PRINT (0, (((((constant >> WORD_SHIFT) & mask) << 8) & 0x0f00) | ((((constant >> WORD_SHIFT) & mask) >> 4) & 0xf)),0);
- CR16_PRINT (1, (constant & 0xFFFF), WORD_SHIFT);
- }
- }
+ {
+ if (arg->type == arg_idxrp)
+ {
+ CR16_PRINT (0, ((constant >> WORD_SHIFT) & mask) << 8, 0);
+ CR16_PRINT (1, (constant & 0xFFFF), WORD_SHIFT);
+ }
+ else
+ {
+ CR16_PRINT (0, (((((constant >> WORD_SHIFT) & mask) << 8) & 0x0f00) | ((((constant >> WORD_SHIFT) & mask) >> 4) & 0xf)),0);
+ CR16_PRINT (1, (constant & 0xFFFF), WORD_SHIFT);
+ }
+ }
else
- CR16_PRINT (0, constant, shift);
+ CR16_PRINT (0, constant, shift);
break;
case 14:
if (arg->type == arg_idxrp)
- {
- if (instruction->size == 2)
- {
- CR16_PRINT (0, ((constant)&0xf), shift); // 0-3 bits
- CR16_PRINT (0, ((constant>>4)&0x3), (shift+20)); // 4-5 bits
- CR16_PRINT (0, ((constant>>6)&0x3), (shift+14)); // 6-7 bits
- CR16_PRINT (0, ((constant>>8)&0x3f), (shift+8)); // 8-13 bits
- }
- else
- CR16_PRINT (0, constant, shift);
- }
+ {
+ if (instruction->size == 2)
+ {
+ CR16_PRINT (0, ((constant) & 0xf), shift); /* 0-3 bits. */
+ CR16_PRINT (0, ((constant >> 4) & 0x3), (shift + 20)); /* 4-5 bits. */
+ CR16_PRINT (0, ((constant >> 6) & 0x3), (shift + 14)); /* 6-7 bits. */
+ CR16_PRINT (0, ((constant >> 8) & 0x3f), (shift + 8)); /* 8-13 bits. */
+ }
+ else
+ CR16_PRINT (0, constant, shift);
+ }
break;
case 16:
case 12:
/* When instruction size is 3 and 'shift' is 16, a 16-bit constant is
- always filling the upper part of output_opcode[1]. If we mistakenly
- write it to output_opcode[0], the constant prefix (that is, 'match')
- will be overriden.
- 0 1 2 3
- +---------+---------+---------+---------+
- | 'match' | | X X X X | |
- +---------+---------+---------+---------+
- output_opcode[0] output_opcode[1] */
+ always filling the upper part of output_opcode[1]. If we mistakenly
+ write it to output_opcode[0], the constant prefix (that is, 'match')
+ will be overriden.
+ 0 1 2 3
+ +---------+---------+---------+---------+
+ | 'match' | | X X X X | |
+ +---------+---------+---------+---------+
+ output_opcode[0] output_opcode[1] */
if ((instruction->size > 2) && (shift == WORD_SHIFT))
- CR16_PRINT (1, constant, WORD_SHIFT);
+ CR16_PRINT (1, constant, WORD_SHIFT);
else
- CR16_PRINT (0, constant, shift);
+ CR16_PRINT (0, constant, shift);
break;
case 8:
- CR16_PRINT (0, ((constant/2)&0xf), shift);
- CR16_PRINT (0, ((constant/2)>>4), (shift+8));
+ CR16_PRINT (0, ((constant / 2) & 0xf), shift);
+ CR16_PRINT (0, ((constant / 2) >> 4), (shift + 8));
break;
default:
@@ -1810,35 +1839,35 @@ print_operand (int nbits, int shift, argument *arg)
+-----------------------------+ */
if (instruction->size == 3)
- {
- CR16_PRINT (0, getidxregp_image (arg->rp), 0);
- if (getreg_image (arg->i_r) == 12)
- CR16_PRINT (0, 0, 3);
- else
- CR16_PRINT (0, 1, 3);
- }
+ {
+ CR16_PRINT (0, getidxregp_image (arg->rp), 0);
+ if (getreg_image (arg->i_r) == 12)
+ CR16_PRINT (0, 0, 3);
+ else
+ CR16_PRINT (0, 1, 3);
+ }
else
- {
- CR16_PRINT (0, getidxregp_image (arg->rp), 16);
- if (getreg_image (arg->i_r) == 12)
- CR16_PRINT (0, 0, 19);
- else
- CR16_PRINT (0, 1, 19);
- }
+ {
+ CR16_PRINT (0, getidxregp_image (arg->rp), 16);
+ if (getreg_image (arg->i_r) == 12)
+ CR16_PRINT (0, 0, 19);
+ else
+ CR16_PRINT (0, 1, 19);
+ }
print_constant (nbits, shift, arg);
break;
case arg_idxr:
if (getreg_image (arg->i_r) == 12)
- if (IS_INSN_MNEMONIC ("cbitb") || IS_INSN_MNEMONIC ("sbitb")
- || IS_INSN_MNEMONIC ("tbitb"))
- CR16_PRINT (0, 0, 23);
- else CR16_PRINT (0, 0, 24);
+ if (IS_INSN_MNEMONIC ("cbitb") || IS_INSN_MNEMONIC ("sbitb")
+ || IS_INSN_MNEMONIC ("tbitb"))
+ CR16_PRINT (0, 0, 23);
+ else CR16_PRINT (0, 0, 24);
else
- if (IS_INSN_MNEMONIC ("cbitb") || IS_INSN_MNEMONIC ("sbitb")
- || IS_INSN_MNEMONIC ("tbitb"))
- CR16_PRINT (0, 1, 23);
- else CR16_PRINT (0, 1, 24);
+ if (IS_INSN_MNEMONIC ("cbitb") || IS_INSN_MNEMONIC ("sbitb")
+ || IS_INSN_MNEMONIC ("tbitb"))
+ CR16_PRINT (0, 1, 23);
+ else CR16_PRINT (0, 1, 24);
print_constant (nbits, shift, arg);
break;
@@ -1861,16 +1890,16 @@ print_operand (int nbits, int shift, argument *arg)
case arg_crp:
print_constant (nbits, shift , arg);
if (instruction->size > 1)
- CR16_PRINT (0, getregp_image (arg->rp), (shift + 16));
+ CR16_PRINT (0, getregp_image (arg->rp), (shift + 16));
else if (IS_INSN_TYPE (LD_STOR_INS) || (IS_INSN_TYPE (CSTBIT_INS)))
- {
- if (instruction->size == 2)
- CR16_PRINT (0, getregp_image (arg->rp), (shift - 8));
- else if (instruction->size == 1)
- CR16_PRINT (0, getregp_image (arg->rp), 16);
- }
+ {
+ if (instruction->size == 2)
+ CR16_PRINT (0, getregp_image (arg->rp), (shift - 8));
+ else if (instruction->size == 1)
+ CR16_PRINT (0, getregp_image (arg->rp), 16);
+ }
else
- CR16_PRINT (0, getregp_image (arg->rp), shift);
+ CR16_PRINT (0, getregp_image (arg->rp), shift);
break;
default:
@@ -1949,11 +1978,11 @@ check_range (long *num, int bits, int unsigned flags, int update)
if (value == 0xB || value == 0x9)
return OP_OUT_OF_RANGE;
else if (value == -1)
- {
- if (update)
- *num = 9;
- return retval;
- }
+ {
+ if (update)
+ *num = 9;
+ return retval;
+ }
}
if (flags & OP_ESC1)
@@ -1980,7 +2009,7 @@ check_range (long *num, int bits, int unsigned flags, int update)
else if (flags & OP_NEG)
{
max = - 1;
- min = - ((1 << (bits - 1))-1);
+ min = - ((1 << (bits - 1)) - 1);
if ((value > max) || (value < min))
retval = OP_OUT_OF_RANGE;
}
@@ -2011,17 +2040,17 @@ warn_if_needed (ins *insn)
unsigned int count = insn->arg[0].constant, reg_val;
/* Check if count operand caused to save/retrive the RA twice
- to generate warning message. */
+ to generate warning message. */
if (insn->nargs > 2)
{
reg_val = getreg_image (insn->arg[1].r);
if ( ((reg_val == 9) && (count > 7))
- || ((reg_val == 10) && (count > 6))
- || ((reg_val == 11) && (count > 5))
- || ((reg_val == 12) && (count > 4))
- || ((reg_val == 13) && (count > 2))
- || ((reg_val == 14) && (count > 0)))
+ || ((reg_val == 10) && (count > 6))
+ || ((reg_val == 11) && (count > 5))
+ || ((reg_val == 12) && (count > 4))
+ || ((reg_val == 13) && (count > 2))
+ || ((reg_val == 14) && (count > 0)))
as_warn (_("RA register is saved twice."));
/* Check if the third operand is "RA" or "ra" */
@@ -2036,10 +2065,10 @@ warn_if_needed (ins *insn)
/* If register is a register pair ie r12/r13/r14 in operand1, then
the count constant should be validated. */
if (((reg_val == 11) && (count > 7))
- || ((reg_val == 12) && (count > 6))
- || ((reg_val == 13) && (count > 4))
- || ((reg_val == 14) && (count > 2))
- || ((reg_val == 15) && (count > 0)))
+ || ((reg_val == 12) && (count > 6))
+ || ((reg_val == 13) && (count > 4))
+ || ((reg_val == 14) && (count > 2))
+ || ((reg_val == 15) && (count > 0)))
as_bad (_("`%s' Illegal count-register combination."), ins_parse);
}
else
@@ -2187,14 +2216,14 @@ assemble_insn (char *mnemonic, ins *insn)
/* If 'bal' instruction size is '2' and reg operand is not 'ra'
then goto next instruction. */
if (IS_INSN_MNEMONIC ("bal") && (i == 0)
- && (instruction->size == 2) && (insn->arg[i].rp != 14))
+ && (instruction->size == 2) && (insn->arg[i].rp != 14))
goto next_insn;
/* If 'storb' instruction with 'sp' reg and 16-bit disp of
* reg-pair, leads to undifined trap, so this should use
* 20-bit disp of reg-pair. */
if (IS_INSN_MNEMONIC ("storb") && (instruction->size == 2)
- && (insn->arg[i].r == 15) && (insn->arg[i + 1].type == arg_crp))
+ && (insn->arg[i].r == 15) && (insn->arg[i + 1].type == arg_crp))
goto next_insn;
/* Only check range - don't update the constant's value, since the
@@ -2216,7 +2245,7 @@ assemble_insn (char *mnemonic, ins *insn)
determined) is sufficient. */
else if ((insn->arg[i].X_op == O_symbol)
&& ((bfd_reloc_type_lookup (stdoutput, insn->rtype))->bitsize
- > cur_size[i]))
+ > cur_size[i]))
goto next_insn;
}
found_const_within_range = 1;
@@ -2241,15 +2270,15 @@ next_insn:
{
switch (const_err)
{
- case OP_OUT_OF_RANGE:
- as_bad (_("Operand out of range (arg %d)"), invalid_const);
- break;
- case OP_NOT_EVEN:
- as_bad (_("Operand has odd displacement (arg %d)"), invalid_const);
- break;
- default:
- as_bad (_("Illegal operand (arg %d)"), invalid_const);
- break;
+ case OP_OUT_OF_RANGE:
+ as_bad (_("Operand out of range (arg %d)"), invalid_const);
+ break;
+ case OP_NOT_EVEN:
+ as_bad (_("Operand has odd displacement (arg %d)"), invalid_const);
+ break;
+ default:
+ as_bad (_("Illegal operand (arg %d)"), invalid_const);
+ break;
}
}
@@ -2321,28 +2350,61 @@ print_insn (ins *insn)
words[j++] = output_opcode[i] & 0xFFFF;
}
- insn_size = instruction->size;
- this_frag = frag_more (insn_size * 2);
-
/* Handle relocation. */
- if ((relocatable) && (insn->rtype != BFD_RELOC_NONE))
+ if ((instruction->flags & RELAXABLE) && relocatable)
+ {
+ int relax_subtype;
+ /* Write the maximal instruction size supported. */
+ insn_size = INSN_MAX_SIZE;
+
+ if (IS_INSN_TYPE (BRANCH_INS))
+ {
+ switch (insn->rtype)
+ {
+ case BFD_RELOC_CR16_DISP24:
+ relax_subtype = 2;
+ break;
+ case BFD_RELOC_CR16_DISP16:
+ relax_subtype = 1;
+ break;
+ default:
+ relax_subtype = 0;
+ break;
+ }
+ }
+ else
+ abort ();
+
+ this_frag = frag_var (rs_machine_dependent, insn_size *2,
+ 4, relax_subtype,
+ insn->exp.X_add_symbol,
+ insn->exp.X_add_number,
+ 0);
+ }
+ else
{
- reloc_howto_type *reloc_howto;
- int size;
+ insn_size = instruction->size;
+ this_frag = frag_more (insn_size * 2);
- reloc_howto = bfd_reloc_type_lookup (stdoutput, insn->rtype);
+ if ((relocatable) && (insn->rtype != BFD_RELOC_NONE))
+ {
+ reloc_howto_type *reloc_howto;
+ int size;
- if (!reloc_howto)
- abort ();
+ reloc_howto = bfd_reloc_type_lookup (stdoutput, insn->rtype);
+
+ if (!reloc_howto)
+ abort ();
- size = bfd_get_reloc_size (reloc_howto);
+ size = bfd_get_reloc_size (reloc_howto);
- if (size < 1 || size > 4)
- abort ();
+ if (size < 1 || size > 4)
+ abort ();
- fix_new_exp (frag_now, this_frag - frag_now->fr_literal,
- size, &insn->exp, reloc_howto->pc_relative,
- insn->rtype);
+ fix_new_exp (frag_now, this_frag - frag_now->fr_literal,
+ size, &insn->exp, reloc_howto->pc_relative,
+ insn->rtype);
+ }
}
/* Verify a 2-byte code alignment. */
@@ -2410,14 +2472,14 @@ md_assemble (char *op)
instruction = (const inst *) hash_find (cr16_inst_hash, op);
parse_operands (&cr16_ins, param1);
if (((&cr16_ins)->arg[0].type == arg_ic)
- && ((&cr16_ins)->arg[0].constant >= 0))
+ && ((&cr16_ins)->arg[0].constant >= 0))
{
if (streq ("lshb", op))
- op = "ashub";
+ op = "ashub";
else if (streq ("lshd", op))
- op = "ashud";
- else
- op = "ashuw";
+ op = "ashud";
+ else
+ op = "ashuw";
}
}
diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog
index dd354e8..76449a2 100644
--- a/include/elf/ChangeLog
+++ b/include/elf/ChangeLog
@@ -1,3 +1,7 @@
+2007-10-01 M R Swami Reddy <MR.Swami.Reddy@nsc.com>
+
+ * cr16.h: Updated with new relocaction macros.
+
2007-09-17 H.J. Lu <hongjiu.lu@intel.com>
PR binutils/3281
diff --git a/include/elf/cr16.h b/include/elf/cr16.h
index e3f6c50..adb243d 100644
--- a/include/elf/cr16.h
+++ b/include/elf/cr16.h
@@ -51,6 +51,9 @@ START_RELOC_NUMBERS(elf_cr16_reloc_type)
RELOC_NUMBER (R_CR16_DISP16, 23)
RELOC_NUMBER (R_CR16_DISP24, 24)
RELOC_NUMBER (R_CR16_DISP24a, 25)
+ RELOC_NUMBER (R_CR16_SWITCH8, 26)
+ RELOC_NUMBER (R_CR16_SWITCH16, 27)
+ RELOC_NUMBER (R_CR16_SWITCH32, 28)
END_RELOC_NUMBERS(R_CR16_MAX)
#endif /* _ELF_CR16_H */
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index a12b90f..4bf8849 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -1,3 +1,8 @@
+2007-10-01 M R Swami Reddy <MR.Swami.Reddy@nsc.com>
+
+ * cr16-opc.c: Updated the branch on condition instructions with
+ RELAXABLE flag.
+
2007-09-30 H.J. Lu <hongjiu.lu@intel.com>
* 386-dis.c (prefix_table): Reformat comment.
diff --git a/opcodes/cr16-opc.c b/opcodes/cr16-opc.c
index 081c63d..55c0381 100644
--- a/opcodes/cr16-opc.c
+++ b/opcodes/cr16-opc.c
@@ -160,11 +160,11 @@ const inst cr16_instruction[] =
/* Create a conditional branch instruction. */
#define BRANCH_INST(NAME, OPC) \
/* opc4 c4 dispe9 */ \
- {NAME, 1, OPC, 28, BRANCH_INS, {{cc,20}, {dispe9,16}}}, \
+ {NAME, 1, OPC, 28, BRANCH_INS | RELAXABLE, {{cc,20}, {dispe9,16}}},\
/* opc4 c4 disps17 */ \
- {NAME, 2, ((OPC<<4)+0x8), 24, BRANCH_INS, {{cc,20}, {disps17,0}}}, \
+ {NAME, 2, ((OPC<<4)+0x8), 24, BRANCH_INS | RELAXABLE, {{cc,20}, {disps17,0}}},\
/* opc4 c4 disps25 */ \
- {NAME, 3, (OPC<<4), 16 , BRANCH_INS, {{cc,4}, {disps25,16}}}
+ {NAME, 3, (OPC<<4), 16 , BRANCH_INS | RELAXABLE, {{cc,4}, {disps25,16}}}
BRANCH_INST ("b", 0x1),