From 1cd986c58543909402a33d84b7821d0d7be17005 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Fri, 23 Jul 2010 14:52:54 +0000 Subject: [PATCH] Add support for v850E2 and v850E2V3 --- bfd/ChangeLog | 38 + bfd/archures.c | 4 +- bfd/bfd-in2.h | 68 + bfd/config.bfd | 8 +- bfd/cpu-v850.c | 10 +- bfd/elf32-v850.c | 766 +++++++++-- bfd/libbfd.h | 22 + bfd/reloc.c | 88 ++ binutils/ChangeLog | 5 + binutils/readelf.c | 10 +- configure | 10 +- configure.ac | 10 +- gas/ChangeLog | 47 + gas/NEWS | 2 + gas/config/tc-v850.c | 1986 +++++++++++++++++++-------- gas/configure.tgt | 4 +- gas/doc/c-v850.texi | 24 + gas/testsuite/ChangeLog | 7 + gas/testsuite/gas/all/byte.d | 3 + gas/testsuite/gas/rx/rx-asm-good.d | 4 +- gas/testsuite/gas/v850/split-lo16.d | 12 +- gas/testsuite/gas/v850/v850e1.d | 8 +- include/elf/ChangeLog | 6 + include/elf/v850.h | 28 + include/opcode/ChangeLog | 18 + include/opcode/v850.h | 94 +- ld/ChangeLog | 5 + ld/testsuite/ChangeLog | 6 + ld/testsuite/ld-v850/split-lo16.d | 14 +- opcodes/ChangeLog | 23 + opcodes/v850-dis.c | 609 +++++--- opcodes/v850-opc.c | 1246 ++++++++++++----- 32 files changed, 3900 insertions(+), 1285 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index cdbf3a04d88..47e98e79c1a 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,41 @@ +2010-07-23 Naveen.H.S + Ina Pandit + + * archures.c (DESCRIPTION): Define bfd_mach_v850e2 and + bfd_mach_v850e2v3. + * reloc.c (bfd_architecture): Define bfd_mach_v850e2 and + bfd_mach_v850e2v3. + (BFD_RELOC_V850_16_PCREL, BFD_RELOC_V850_17_PCREL, + BFD_RELOC_V850_22_PCREL, BFD_RELOC_V850_23, + BFD_RELOC_V850_32_PCREL, BFD_RELOC_V850_32_ABS, + BFD_RELOC_V850_16_SPLIT_OFFSET, BFD_RELOC_V850_16_S1, + BFD_RELOC_V850_LO16_SPLIT_OFFSET, BFD_RELOC_V850_SDA_15_16_OFFSET, + BFD_RELOC_V850_ZDA_16_16_OFFSET, BFD_RELOC_V850_CALLT_15_16_OFFSET, + BFD_RELOC_V850_32_GOTPCREL, BFD_RELOC_V850_16_GOT, + BFD_RELOC_V850_32_GOT, BFD_RELOC_V850_22_PLT_PCREL, + BFD_RELOC_V850_32_PLT_PCREL, BFD_RELOC_V850_COPY, + BFD_RELOC_V850_GLOB_DAT, BFD_RELOC_V850_JMP_SLOT, + BFD_RELOC_V850_RELATIVE, BFD_RELOC_V850_16_GOTOFF, + BFD_RELOC_V850_32_GOTOFF, BFD_RELOC_V850_CODE, + BFD_RELOC_V850_DATA): New relocations for V850 target. + * config.bfd: Match all v850 targets. + * cpu-v850.c (arch_info_struct): Define V850e2 and V850e2v3. + * elf32-v850.c (v850_elf_check_relocs): Check the newly added + relocations. + (v850_elf_perform_relocation ): Update the newly added + relocations. + (v850_elf_howto_t): Update the specifications of added + relocations. + (v850_elf_reloc_map): Update the relocation mappings. + (v850_elf_final_link_relocate): Maps added relocation into the + appropriate howto structure. + (v850_elf_object_p): Add support for V850E2 and V850E2V3. + (v850_elf_final_write_processing): Likewise. + (v850_elf_merge_private_bfd_data): Likewise. + (v850_elf_print_private_bfd_data): Likewise. + * libbfd.h: Regenerate. + * bfd-in2.h: Regenerate. + 2010-07-23 Alan Modra * archive.c (_bfd_archive_bsd44_construct_extended_name_table): diff --git a/bfd/archures.c b/bfd/archures.c index 0e085713b82..18671543821 100644 --- a/bfd/archures.c +++ b/bfd/archures.c @@ -310,7 +310,9 @@ DESCRIPTION . bfd_arch_v850, {* NEC V850 *} .#define bfd_mach_v850 1 .#define bfd_mach_v850e 'E' -.#define bfd_mach_v850e1 '1' +.#define bfd_mach_v850e1 '1' +.#define bfd_mach_v850e2 0x4532 +.#define bfd_mach_v850e2v3 0x45325633 . bfd_arch_arc, {* ARC Cores *} .#define bfd_mach_arc_5 5 .#define bfd_mach_arc_6 6 diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index f97c67fd132..277d4322d23 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -1977,6 +1977,8 @@ enum bfd_architecture #define bfd_mach_v850 1 #define bfd_mach_v850e 'E' #define bfd_mach_v850e1 '1' +#define bfd_mach_v850e2 0x4532 /* ('E'<<8|'2') */ +#define bfd_mach_v850e2v3 0x45325633 /* ('E'<<24|'2'<<16|'V'<<8|'3') */ bfd_arch_arc, /* ARC Cores */ #define bfd_mach_arc_5 5 #define bfd_mach_arc_6 6 @@ -3605,6 +3607,72 @@ bits placed non-contiguously in the instruction. */ instructions. */ BFD_RELOC_V850_LO16_SPLIT_OFFSET, +/* This is a 16-bit reloc. */ + BFD_RELOC_V850_16_PCREL, + +/* This is a 17-bit reloc. */ + BFD_RELOC_V850_17_PCREL, + +/* This is a 23-bit reloc. */ + BFD_RELOC_V850_23, + +/* This is a 32-bit reloc. */ + BFD_RELOC_V850_32_PCREL, + +/* This is a 32-bit reloc. */ + BFD_RELOC_V850_32_ABS, + +/* This is a 16-bit reloc. */ + BFD_RELOC_V850_16_SPLIT_OFFSET, + +/* This is a 16-bit reloc. */ + BFD_RELOC_V850_16_S1, + +/* Low 16 bits. 16 bit shifted by 1. */ + BFD_RELOC_V850_LO16_S1, + +/* This is a 16 bit offset from the call table base pointer. */ + BFD_RELOC_V850_CALLT_15_16_OFFSET, + +/* DSO relocations. */ + BFD_RELOC_V850_32_GOTPCREL, + +/* DSO relocations. */ + BFD_RELOC_V850_16_GOT, + +/* DSO relocations. */ + BFD_RELOC_V850_32_GOT, + +/* DSO relocations. */ + BFD_RELOC_V850_22_PLT_PCREL, + +/* DSO relocations. */ + BFD_RELOC_V850_32_PLT_PCREL, + +/* DSO relocations. */ + BFD_RELOC_V850_COPY, + +/* DSO relocations. */ + BFD_RELOC_V850_GLOB_DAT, + +/* DSO relocations. */ + BFD_RELOC_V850_JMP_SLOT, + +/* DSO relocations. */ + BFD_RELOC_V850_RELATIVE, + +/* DSO relocations. */ + BFD_RELOC_V850_16_GOTOFF, + +/* DSO relocations. */ + BFD_RELOC_V850_32_GOTOFF, + +/* start code. */ + BFD_RELOC_V850_CODE, + +/* start data in text. */ + BFD_RELOC_V850_DATA, + /* This is a 32bit pcrel reloc for the mn10300, offset by two bytes in the instruction. */ BFD_RELOC_MN10300_32_PCREL, diff --git a/bfd/config.bfd b/bfd/config.bfd index 1015f3cc445..960d4d4408c 100644 --- a/bfd/config.bfd +++ b/bfd/config.bfd @@ -1468,13 +1468,7 @@ case "${targ}" in targ_underscore=yes ;; - v850-*-*) - targ_defvec=bfd_elf32_v850_vec - ;; - v850e-*-*) - targ_defvec=bfd_elf32_v850_vec - ;; - v850ea-*-*) + v850*-*-*) targ_defvec=bfd_elf32_v850_vec ;; diff --git a/bfd/cpu-v850.c b/bfd/cpu-v850.c index 77ca519ccb4..6ebc96c8e82 100644 --- a/bfd/cpu-v850.c +++ b/bfd/cpu-v850.c @@ -1,6 +1,6 @@ /* BFD support for the NEC V850 processor - Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2007 - Free Software Foundation, Inc. + Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2007, + 2010 Free Software Foundation, Inc. This file is part of BFD, the Binary File Descriptor library. @@ -32,8 +32,10 @@ static const bfd_arch_info_type arch_info_struct[] = { - N (bfd_mach_v850e1, "v850e1", FALSE, & arch_info_struct[1]), - N (bfd_mach_v850e, "v850e", FALSE, NULL) + N (bfd_mach_v850e2v3, "v850e2v3", FALSE, & arch_info_struct[1]), + N (bfd_mach_v850e2, "v850e2", FALSE, & arch_info_struct[2]), + N (bfd_mach_v850e1, "v850e1", FALSE, & arch_info_struct[3]), + N (bfd_mach_v850e, "v850e", FALSE, NULL) }; #undef NEXT diff --git a/bfd/elf32-v850.c b/bfd/elf32-v850.c index 0ab7de8c10f..e153e8305a8 100644 --- a/bfd/elf32-v850.c +++ b/bfd/elf32-v850.c @@ -31,8 +31,11 @@ #include "elf/v850.h" #include "libiberty.h" -/* Sign-extend a 24-bit number. */ -#define SEXT24(x) ((((x) & 0xffffff) ^ 0x800000) - 0x800000) +/* Sign-extend a 17-bit number. */ +#define SEXT17(x) ((((x) & 0x1ffff) ^ 0x10000) - 0x10000) + +/* Sign-extend a 22-bit number. */ +#define SEXT22(x) ((((x) & 0x3fffff) ^ 0x200000) - 0x200000) static reloc_howto_type v850_elf_howto_table[]; @@ -89,16 +92,25 @@ v850_elf_check_relocs (bfd *abfd, default: case R_V850_NONE: case R_V850_9_PCREL: + case R_V850_16_PCREL: + case R_V850_17_PCREL: case R_V850_22_PCREL: - case R_V850_HI16_S: + case R_V850_32_PCREL: + case R_V850_32_ABS: case R_V850_HI16: + case R_V850_HI16_S: case R_V850_LO16: + case R_V850_LO16_S1: case R_V850_LO16_SPLIT_OFFSET: + case R_V850_23: case R_V850_ABS32: case R_V850_REL32: case R_V850_16: + case R_V850_16_S1: + case R_V850_16_SPLIT_OFFSET: case R_V850_8: case R_V850_CALLT_6_7_OFFSET: + case R_V850_CALLT_15_16_OFFSET: case R_V850_CALLT_16_16_OFFSET: break; @@ -132,11 +144,11 @@ v850_elf_check_relocs (bfd *abfd, common = ".zcommon"; goto small_data_common; - case R_V850_TDA_4_5_OFFSET: case R_V850_TDA_4_4_OFFSET: + case R_V850_TDA_4_5_OFFSET: + case R_V850_TDA_7_7_OFFSET: case R_V850_TDA_6_8_OFFSET: case R_V850_TDA_7_8_OFFSET: - case R_V850_TDA_7_7_OFFSET: case R_V850_TDA_16_16_OFFSET: other = V850_OTHER_TDA; common = ".tcommon"; @@ -315,15 +327,15 @@ find_remembered_hi16s_reloc (bfd_vma addend, bfd_boolean *already_found) will store 0 in the value fields for the MOVHI and MOVEA instructions and addend will be the address of fred, but for these instructions: - movhi hi( fred + 0x123456), r0, r1 - movea lo( fred + 0x123456), r1, r1 + movhi hi( fred + 0x123456 ), r0, r1 + movea lo( fred + 0x123456 ), r1, r1 the value stored in the MOVHI instruction will be 0x12 and the value stored in the MOVEA instruction will be 0x3456. If however the instructions were: - movhi hi( fred + 0x10ffff), r0, r1 - movea lo( fred + 0x10ffff), r1, r1 + movhi hi( fred + 0x10ffff ), r0, r1 + movea lo( fred + 0x10ffff ), r1, r1 then the value stored in the MOVHI instruction would be 0x11 (not 0x10) and the value stored in the MOVEA instruction would be 0xffff. @@ -332,8 +344,8 @@ find_remembered_hi16s_reloc (bfd_vma addend, bfd_boolean *already_found) adds 0xffffffff (sign extension!) producing 0x10ffff. Similarly if the instructions were: - movhi hi( fred - 1), r0, r1 - movea lo( fred - 1), r1, r1 + movhi hi( fred - 1 ), r0, r1 + movea lo( fred - 1 ), r1, r1 then 0 is stored in the MOVHI instruction and -1 is stored in the MOVEA instruction. @@ -345,8 +357,8 @@ find_remembered_hi16s_reloc (bfd_vma addend, bfd_boolean *already_found) clear, the assembler will not have added 1 to the previous HI16S reloc to compensate for this effect. For example: - movhi hi( fred + 0x123456), r0, r1 - movea lo( fred + 0x123456), r1, r1 + movhi hi( fred + 0x123456 ), r0, r1 + movea lo( fred + 0x123456 ), r1, r1 The value stored in HI16S reloc is 0x12, the value stored in the LO16 reloc is 0x3456. If we assume that the address of fred is 0x00007000 @@ -366,8 +378,8 @@ find_remembered_hi16s_reloc (bfd_vma addend, bfd_boolean *already_found) Note that if the 15th bit was set in the value stored in the LO16 reloc, then we do not have to do anything: - movhi hi( fred + 0x10ffff), r0, r1 - movea lo( fred + 0x10ffff), r1, r1 + movhi hi( fred + 0x10ffff ), r0, r1 + movea lo( fred + 0x10ffff ), r1, r1 HI16S: 0x0011 + (0x00007000 >> 16) = 0x11 LO16: 0xffff + (0x00007000 & 0xffff) = 0x6fff @@ -387,8 +399,8 @@ find_remembered_hi16s_reloc (bfd_vma addend, bfd_boolean *already_found) So, for example if fred is at address 0xf000: - movhi hi( fred + 0xffff), r0, r1 [bit 15 of the offset is set] - movea lo( fred + 0xffff), r1, r1 + movhi hi( fred + 0xffff ), r0, r1 [bit 15 of the offset is set] + movea lo( fred + 0xffff ), r1, r1 HI16S: 0x0001 + (0x0000f000 >> 16) = 0x0001 LO16: 0xffff + (0x0000f000 & 0xffff) = 0xefff (carry into bit 16 is lost) @@ -401,8 +413,8 @@ find_remembered_hi16s_reloc (bfd_vma addend, bfd_boolean *already_found) Similarly, if the 15th bit remains clear, but overflow occurs into the 16th bit then (assuming the address of fred is 0xf000): - movhi hi( fred + 0x7000), r0, r1 [bit 15 of the offset is clear] - movea lo( fred + 0x7000), r1, r1 + movhi hi( fred + 0x7000 ), r0, r1 [bit 15 of the offset is clear] + movea lo( fred + 0x7000 ), r1, r1 HI16S: 0x0000 + (0x0000f000 >> 16) = 0x0000 LO16: 0x7000 + (0x0000f000 & 0xffff) = 0x6fff (carry into bit 16 is lost) @@ -416,8 +428,8 @@ find_remembered_hi16s_reloc (bfd_vma addend, bfd_boolean *already_found) 15th bit changes its value from being set to being clear, as the HI16S reloc will have already added in 1 to the high part for us: - movhi hi( fred + 0xffff), r0, r1 [bit 15 of the offset is set] - movea lo( fred + 0xffff), r1, r1 + movhi hi( fred + 0xffff ), r0, r1 [bit 15 of the offset is set] + movea lo( fred + 0xffff ), r1, r1 HI16S: 0x0001 + (0x00007000 >> 16) LO16: 0xffff + (0x00007000 & 0xffff) = 0x6fff (carry into bit 16 is lost) @@ -430,8 +442,8 @@ find_remembered_hi16s_reloc (bfd_vma addend, bfd_boolean *already_found) but if the 15th bit goes from being clear to being set, then we must once again handle overflow: - movhi hi( fred + 0x7000), r0, r1 [bit 15 of the offset is clear] - movea lo( fred + 0x7000), r1, r1 + movhi hi( fred + 0x7000 ), r0, r1 [bit 15 of the offset is clear] + movea lo( fred + 0x7000 ), r1, r1 HI16S: 0x0000 + (0x0000ffff >> 16) LO16: 0x7000 + (0x0000ffff & 0xffff) = 0x6fff (carry into bit 16) @@ -504,6 +516,13 @@ v850_elf_perform_relocation (bfd *abfd, bfd_put_32 (abfd, addend, address); return bfd_reloc_ok; + case R_V850_23: + insn = bfd_get_32 (abfd, address); + insn &= ~((0x7f << 4) | (0x7fff80 << (16-7))); + insn |= ((addend & 0x7f) << 4) | ((addend & 0x7fff80) << (16-7)); + bfd_put_32 (abfd, (bfd_vma) insn, address); + return bfd_reloc_ok; + case R_V850_22_PCREL: if (saddend > 0x1fffff || saddend < -0x200000) return bfd_reloc_overflow; @@ -517,6 +536,30 @@ v850_elf_perform_relocation (bfd *abfd, bfd_put_32 (abfd, (bfd_vma) insn, address); return bfd_reloc_ok; + case R_V850_17_PCREL: + if (saddend > 0xffff || saddend < -0x10000) + return bfd_reloc_overflow; + + if ((addend % 2) != 0) + return bfd_reloc_dangerous; + + insn = bfd_get_32 (abfd, address); + insn &= ~ 0xfffe0010; + insn |= ((addend & 0xfffe) << 16) | ((addend & 0x10000) >> (16-4)); + break; + + case R_V850_16_PCREL: + if ((saddend < -0xffff) || (saddend > 0)) + return bfd_reloc_overflow; + + if ((addend % 2) != 0) + return bfd_reloc_dangerous; + + insn = bfd_get_16 (abfd, address); + insn &= ~0xfffe; + insn |= (-addend & 0xfffe); + break; + case R_V850_9_PCREL: if (saddend > 0xff || saddend < -0x100) return bfd_reloc_overflow; @@ -577,6 +620,36 @@ v850_elf_perform_relocation (bfd *abfd, insn = addend; break; + case R_V850_CALLT_15_16_OFFSET: + insn = bfd_get_16 (abfd, address); + + addend += insn & 0xfffe;; + + saddend = (bfd_signed_vma) addend; + + if (saddend > 0xffff || saddend < 0) + return bfd_reloc_overflow; + + insn = (0xfffe & addend) + | (insn & ~0xfffe); + break; + + case R_V850_CALLT_6_7_OFFSET: + insn = bfd_get_16 (abfd, address); + addend += ((insn & 0x3f) << 1); + + saddend = (bfd_signed_vma) addend; + + if (saddend > 0x7e || saddend < 0) + return bfd_reloc_overflow; + + if (addend & 1) + return bfd_reloc_dangerous; + + insn &= 0xff80; + insn |= (addend >> 1); + break; + case R_V850_16: case R_V850_SDA_16_16_OFFSET: case R_V850_ZDA_16_16_OFFSET: @@ -591,6 +664,7 @@ v850_elf_perform_relocation (bfd *abfd, insn = addend; break; + case R_V850_16_S1: case R_V850_SDA_15_16_OFFSET: case R_V850_ZDA_15_16_OFFSET: insn = bfd_get_16 (abfd, address); @@ -681,6 +755,18 @@ v850_elf_perform_relocation (bfd *abfd, insn |= addend; break; + case R_V850_LO16_S1: + insn = bfd_get_16 (abfd, address); + result = insn & 0xfffe; + if (! v850_elf_perform_lo16_relocation (abfd, &result, addend)) + return bfd_reloc_overflow; + if (result & 1) + return bfd_reloc_overflow; + insn = (result & 0xfffe) + | (insn & ~0xfffe); + bfd_put_16 (abfd, insn, address); + return bfd_reloc_ok; + case R_V850_LO16_SPLIT_OFFSET: insn = bfd_get_32 (abfd, address); result = ((insn & 0xfffe0000) >> 16) | ((insn & 0x20) >> 5); @@ -692,8 +778,9 @@ v850_elf_perform_relocation (bfd *abfd, bfd_put_32 (abfd, insn, address); return bfd_reloc_ok; - case R_V850_ZDA_16_16_SPLIT_OFFSET: + case R_V850_16_SPLIT_OFFSET: case R_V850_SDA_16_16_SPLIT_OFFSET: + case R_V850_ZDA_16_16_SPLIT_OFFSET: insn = bfd_get_32 (abfd, address); addend += ((insn & 0xfffe0000) >> 16) + ((insn & 0x20) >> 5); @@ -709,22 +796,6 @@ v850_elf_perform_relocation (bfd *abfd, bfd_put_32 (abfd, (bfd_vma) insn, address); return bfd_reloc_ok; - case R_V850_CALLT_6_7_OFFSET: - insn = bfd_get_16 (abfd, address); - addend += ((insn & 0x3f) << 1); - - saddend = (bfd_signed_vma) addend; - - if (saddend > 0x7e || saddend < 0) - return bfd_reloc_overflow; - - if (addend & 1) - return bfd_reloc_dangerous; - - insn &= 0xff80; - insn |= (addend >> 1); - break; - case R_V850_GNU_VTINHERIT: case R_V850_GNU_VTENTRY: return bfd_reloc_ok; @@ -813,7 +884,8 @@ v850_elf_ignore_reloc (bfd *abfd ATTRIBUTE_UNUSED, return bfd_reloc_ok; } /* Note: It is REQUIRED that the 'type' value of each entry - in this array match the index of the entry in the array. */ + in this array match the index of the entry in the array. + SeeAlso: RELOC_NUBMER in include/elf/v850.h */ static reloc_howto_type v850_elf_howto_table[] = { /* This reloc does nothing. */ @@ -833,9 +905,9 @@ static reloc_howto_type v850_elf_howto_table[] = /* A PC relative 9 bit branch. */ HOWTO (R_V850_9_PCREL, /* Type. */ - 2, /* Rightshift. */ - 2, /* Size (0 = byte, 1 = short, 2 = long). */ - 26, /* Bitsize. */ + 0, /* Rightshift. */ + 1, /* Size (0 = byte, 1 = short, 2 = long). */ + 9, /* Bitsize. */ TRUE, /* PC_relative. */ 0, /* Bitpos. */ complain_overflow_bitfield, /* Complain_on_overflow. */ @@ -848,11 +920,11 @@ static reloc_howto_type v850_elf_howto_table[] = /* A PC relative 22 bit branch. */ HOWTO (R_V850_22_PCREL, /* Type. */ - 2, /* Rightshift. */ + 0, /* Rightshift. */ 2, /* Size (0 = byte, 1 = short, 2 = long). */ 22, /* Bitsize. */ TRUE, /* PC_relative. */ - 7, /* Bitpos. */ + 0, /* Bitpos. */ complain_overflow_signed, /* Complain_on_overflow. */ v850_elf_reloc, /* Special_function. */ "R_V850_22_PCREL", /* Name. */ @@ -1161,82 +1233,83 @@ static reloc_howto_type v850_elf_howto_table[] = 0xffff, /* Dst_mask. */ FALSE), /* PCrel_offset. */ + /* GNU extension to record C++ vtable hierarchy */ HOWTO (R_V850_GNU_VTINHERIT, /* Type. */ - 0, /* Rightshift. */ - 2, /* Size (0 = byte, 1 = short, 2 = long). */ - 0, /* Bitsize. */ - FALSE, /* PC_relative. */ - 0, /* Bitpos. */ - complain_overflow_dont, /* Complain_on_overflow. */ - NULL, /* Special_function. */ - "R_V850_GNU_VTINHERIT", /* Name. */ - FALSE, /* Partial_inplace. */ - 0, /* Src_mask. */ - 0, /* Dst_mask. */ - FALSE), /* PCrel_offset. */ - - /* GNU extension to record C++ vtable member usage */ + 0, /* Rightshift. */ + 2, /* Size (0 = byte, 1 = short, 2 = long). */ + 0, /* Bitsize. */ + FALSE, /* PC_relative. */ + 0, /* Bitpos. */ + complain_overflow_dont, /* Complain_on_overflow. */ + NULL, /* Special_function. */ + "R_V850_GNU_VTINHERIT", /* Name. */ + FALSE, /* Partial_inplace. */ + 0, /* Src_mask. */ + 0, /* Dst_mask. */ + FALSE), /* PCrel_offset. */ + + /* GNU extension to record C++ vtable member usage. */ HOWTO (R_V850_GNU_VTENTRY, /* Type. */ - 0, /* Rightshift. */ - 2, /* Size (0 = byte, 1 = short, 2 = long). */ - 0, /* Bitsize. */ - FALSE, /* PC_relative. */ - 0, /* Bitpos. */ - complain_overflow_dont, /* Complain_on_overflow. */ - _bfd_elf_rel_vtable_reloc_fn, /* Special_function. */ - "R_V850_GNU_VTENTRY", /* Name. */ - FALSE, /* Partial_inplace. */ - 0, /* Src_mask. */ - 0, /* Dst_mask. */ - FALSE), /* PCrel_offset. */ + 0, /* Rightshift. */ + 2, /* Size (0 = byte, 1 = short, 2 = long). */ + 0, /* Bitsize. */ + FALSE, /* PC_relative. */ + 0, /* Bitpos. */ + complain_overflow_dont, /* Complain_on_overflow. */ + _bfd_elf_rel_vtable_reloc_fn, /* Special_function. */ + "R_V850_GNU_VTENTRY", /* Name. */ + FALSE, /* Partial_inplace. */ + 0, /* Src_mask. */ + 0, /* Dst_mask. */ + FALSE), /* PCrel_offset. */ /* Indicates a .longcall pseudo-op. The compiler will generate a .longcall pseudo-op when it finds a function call which can be relaxed. */ HOWTO (R_V850_LONGCALL, /* Type. */ - 0, /* Rightshift. */ - 2, /* Size (0 = byte, 1 = short, 2 = long). */ - 32, /* Bitsize. */ - TRUE, /* PC_relative. */ - 0, /* Bitpos. */ - complain_overflow_signed, /* Complain_on_overflow. */ - v850_elf_ignore_reloc, /* Special_function. */ - "R_V850_LONGCALL", /* Name. */ - FALSE, /* Partial_inplace. */ - 0, /* Src_mask. */ - 0, /* Dst_mask. */ - TRUE), /* PCrel_offset. */ + 0, /* Rightshift. */ + 2, /* Size (0 = byte, 1 = short, 2 = long). */ + 32, /* Bitsize. */ + TRUE, /* PC_relative. */ + 0, /* Bitpos. */ + complain_overflow_signed, /* Complain_on_overflow. */ + v850_elf_ignore_reloc, /* Special_function. */ + "R_V850_LONGCALL", /* Name. */ + FALSE, /* Partial_inplace. */ + 0, /* Src_mask. */ + 0, /* Dst_mask. */ + TRUE), /* PCrel_offset. */ /* Indicates a .longjump pseudo-op. The compiler will generate a .longjump pseudo-op when it finds a branch which can be relaxed. */ HOWTO (R_V850_LONGJUMP, /* Type. */ - 0, /* Rightshift. */ - 2, /* Size (0 = byte, 1 = short, 2 = long). */ - 32, /* Bitsize. */ - TRUE, /* PC_relative. */ - 0, /* Bitpos. */ - complain_overflow_signed, /* Complain_on_overflow. */ - v850_elf_ignore_reloc, /* Special_function. */ - "R_V850_LONGJUMP", /* Name. */ - FALSE, /* Partial_inplace. */ - 0, /* Src_mask. */ - 0, /* Dst_mask. */ - TRUE), /* PCrel_offset. */ + 0, /* Rightshift. */ + 2, /* Size (0 = byte, 1 = short, 2 = long). */ + 32, /* Bitsize. */ + TRUE, /* PC_relative. */ + 0, /* Bitpos. */ + complain_overflow_signed, /* Complain_on_overflow. */ + v850_elf_ignore_reloc, /* Special_function. */ + "R_V850_LONGJUMP", /* Name. */ + FALSE, /* Partial_inplace. */ + 0, /* Src_mask. */ + 0, /* Dst_mask. */ + TRUE), /* PCrel_offset. */ HOWTO (R_V850_ALIGN, /* Type. */ - 0, /* Rightshift. */ - 1, /* Size (0 = byte, 1 = short, 2 = long). */ - 0, /* Bitsize. */ - FALSE, /* PC_relative. */ - 0, /* Bitpos. */ - complain_overflow_unsigned, /* Complain_on_overflow. */ - v850_elf_ignore_reloc, /* Special_function. */ - "R_V850_ALIGN", /* Name. */ - FALSE, /* Partial_inplace. */ - 0, /* Src_mask. */ - 0, /* Dst_mask. */ - TRUE), /* PCrel_offset. */ - + 0, /* Rightshift. */ + 1, /* Size (0 = byte, 1 = short, 2 = long). */ + 0, /* Bitsize. */ + FALSE, /* PC_relative. */ + 0, /* Bitpos. */ + complain_overflow_unsigned, /* Complain_on_overflow. */ + v850_elf_ignore_reloc, /* Special_function. */ + "R_V850_ALIGN", /* Name. */ + FALSE, /* Partial_inplace. */ + 0, /* Src_mask. */ + 0, /* Dst_mask. */ + TRUE), /* PCrel_offset. */ + /* Simple pc-relative 32bit reloc. */ HOWTO (R_V850_REL32, /* Type. */ 0, /* Rightshift. */ @@ -1266,6 +1339,341 @@ static reloc_howto_type v850_elf_howto_table[] = 0xfffe0020, /* Src_mask. */ 0xfffe0020, /* Dst_mask. */ FALSE), /* PCrel_offset. */ + + /* A unsigned PC relative 16 bit loop. */ + HOWTO (R_V850_16_PCREL, /* Type. */ + 0, /* Rightshift. */ + 1, /* Size (0 = byte, 1 = short, 2 = long). */ + 16, /* Bitsize. */ + TRUE, /* PC_relative. */ + 0, /* Bitpos. */ + complain_overflow_bitfield, /* Complain_on_overflow. */ + v850_elf_reloc, /* Special_function. */ + "R_V850_16_PCREL", /* Name. */ + FALSE, /* Partial_inplace. */ + 0xfffe, /* Src_mask. */ + 0xfffe, /* Dst_mask. */ + TRUE), /* PCrel_offset. */ + + /* A PC relative 17 bit branch. */ + HOWTO (R_V850_17_PCREL, /* Type. */ + 0, /* Rightshift. */ + 2, /* Size (0 = byte, 1 = short, 2 = long). */ + 17, /* Bitsize. */ + TRUE, /* PC_relative. */ + 0, /* Bitpos. */ + complain_overflow_bitfield, /* Complain_on_overflow. */ + v850_elf_reloc, /* Special_function. */ + "R_V850_17_PCREL", /* Name. */ + FALSE, /* Partial_inplace. */ + 0x0010fffe, /* Src_mask. */ + 0x0010fffe, /* Dst_mask. */ + TRUE), /* PCrel_offset. */ + + /* A 23bit offset ld/st. */ + HOWTO (R_V850_23, /* type. */ + 0, /* rightshift. */ + 2, /* size (0 = byte, 1 = short, 2 = long). */ + 23, /* bitsize. */ + FALSE, /* pc_relative. */ + 0, /* bitpos. */ + complain_overflow_dont, /* complain_on_overflow. */ + v850_elf_reloc, /* special_function. */ + "R_V850_23", /* name. */ + FALSE, /* partial_inplace. */ + 0xffff07f0, /* src_mask. */ + 0xffff07f0, /* dst_mask. */ + FALSE), /* pcrel_offset. */ + + /* A PC relative 32 bit branch. */ + HOWTO (R_V850_32_PCREL, /* type. */ + 1, /* rightshift. */ + 2, /* size (0 = byte, 1 = short, 2 = long). */ + 32, /* bitsize. */ + TRUE, /* pc_relative. */ + 1, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ + v850_elf_reloc, /* special_function. */ + "R_V850_32_PCREL", /* name. */ + FALSE, /* partial_inplace. */ + 0xfffffffe, /* src_mask. */ + 0xfffffffe, /* dst_mask. */ + TRUE), /* pcrel_offset. */ + + /* A absolute 32 bit branch. */ + HOWTO (R_V850_32_ABS, /* type. */ + 1, /* rightshift. */ + 2, /* size (0 = byte, 1 = short, 2 = long). */ + 32, /* bitsize. */ + TRUE, /* pc_relative. */ + 1, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ + v850_elf_reloc, /* special_function. */ + "R_V850_32_ABS", /* name. */ + FALSE, /* partial_inplace. */ + 0xfffffffe, /* src_mask. */ + 0xfffffffe, /* dst_mask. */ + FALSE), /* pcrel_offset. */ + + /* High 16 bits of symbol value. */ + HOWTO (R_V850_HI16, /* Type. */ + 0, /* Rightshift. */ + 1, /* Size (0 = byte, 1 = short, 2 = long). */ + 16, /* Bitsize. */ + FALSE, /* PC_relative. */ + 0, /* Bitpos. */ + complain_overflow_dont, /* Complain_on_overflow. */ + v850_elf_reloc, /* Special_function. */ + "R_V850_HI16", /* Name. */ + FALSE, /* Partial_inplace. */ + 0xffff, /* Src_mask. */ + 0xffff, /* Dst_mask. */ + FALSE), /* PCrel_offset. */ + + /* Low 16 bits of symbol value. */ + HOWTO (R_V850_16_S1, /* type. */ + 1, /* rightshift. */ + 1, /* size (0 = byte, 1 = short, 2 = long). */ + 16, /* bitsize. */ + FALSE, /* pc_relative. */ + 1, /* bitpos. */ + complain_overflow_dont, /* complain_on_overflow. */ + v850_elf_reloc, /* special_function. */ + "R_V850_16_S1", /* name. */ + FALSE, /* partial_inplace. */ + 0xfffe, /* src_mask. */ + 0xfffe, /* dst_mask. */ + FALSE), /* pcrel_offset. */ + + /* Low 16 bits of symbol value. */ + HOWTO (R_V850_LO16_S1, /* type. */ + 1, /* rightshift. */ + 1, /* size (0 = byte, 1 = short, 2 = long). */ + 16, /* bitsize. */ + FALSE, /* pc_relative. */ + 1, /* bitpos. */ + complain_overflow_dont, /* complain_on_overflow. */ + v850_elf_reloc, /* special_function. */ + "R_V850_LO16_S1", /* name. */ + FALSE, /* partial_inplace. */ + 0xfffe, /* src_mask. */ + 0xfffe, /* dst_mask. */ + FALSE), /* pcrel_offset. */ + + /* 16 bit offset from the call table base pointer. */ + HOWTO (R_V850_CALLT_15_16_OFFSET, /* type. */ + 1, /* rightshift. */ + 1, /* size (0 = byte, 1 = short, 2 = long). */ + 16, /* bitsize. */ + FALSE, /* pc_relative. */ + 1, /* bitpos. */ + complain_overflow_dont, /* complain_on_overflow. */ + v850_elf_reloc, /* special_function. */ + "R_V850_CALLT_15_16_OFFSET", /* name. */ + FALSE, /* partial_inplace. */ + 0xfffe, /* src_mask. */ + 0xfffe, /* dst_mask. */ + FALSE), /* pcrel_offset. */ + + /* Like R_V850_32 PCREL, but referring to the GOT table entry for + the symbol. */ + HOWTO (R_V850_32_GOTPCREL, /* type. */ + 0, /* rightshift. */ + 2, /* size (0 = byte, 1 = short, 2 = long). */ + 32, /* bitsize. */ + TRUE, /* pc_relative. */ + 0, /* bitpos. */ + complain_overflow_unsigned, /* complain_on_overflow. */ + v850_elf_reloc, /* special_function. */ + "R_V850_32_GOTPCREL", /* name. */ + FALSE, /* partial_inplace. */ + 0xffffffff, /* src_mask. */ + 0xffffffff, /* dst_mask. */ + TRUE), /* pcrel_offset. */ + + /* Like R_V850_SDA_, but referring to the GOT table entry for + the symbol. */ + HOWTO (R_V850_16_GOT, /* type. */ + 0, /* rightshift. */ + 2, /* 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_V850_16_GOT", /* name. */ + FALSE, /* partial_inplace. */ + 0xffff, /* src_mask. */ + 0xffff, /* dst_mask. */ + FALSE), /* pcrel_offset. */ + + HOWTO (R_V850_32_GOT, /* 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_V850_32_GOT", /* name. */ + FALSE, /* partial_inplace. */ + 0xffffffff, /* src_mask. */ + 0xffffffff, /* dst_mask. */ + FALSE), /* pcrel_offset. */ + + /* Like R_V850_22_PCREL, but referring to the procedure linkage table + entry for the symbol. */ + HOWTO (R_V850_22_PLT, /* type. */ + 1, /* rightshift. */ + 2, /* size (0 = byte, 1 = short, 2 = long). */ + 22, /* bitsize. */ + TRUE, /* pc_relative. */ + 7, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_V850_22_PLT", /* name. */ + FALSE, /* partial_inplace. */ + 0x07ffff80, /* src_mask. */ + 0x07ffff80, /* dst_mask. */ + TRUE), /* pcrel_offset. */ + + HOWTO (R_V850_32_PLT, /* type. */ + 1, /* rightshift. */ + 2, /* size (0 = byte, 1 = short, 2 = long). */ + 32, /* bitsize. */ + TRUE, /* pc_relative. */ + 1, /* bitpos. */ + complain_overflow_signed, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_V850_32_PLT", /* name. */ + FALSE, /* partial_inplace. */ + 0xffffffff, /* src_mask. */ + 0xffffffff, /* dst_mask. */ + TRUE), /* pcrel_offset. */ + + /* This is used only by the dynamic linker. The symbol should exist + both in the object being run and in some shared library. The + dynamic linker copies the data addressed by the symbol from the + shared library into the object, because the object being + run has to have the data at some particular address. */ + HOWTO (R_V850_COPY, /* type. */ + 0, /* rightshift. */ + 2, /* size (0 = byte, 1 = short, 2 = long). */ + 32, /* bitsize. */ + FALSE, /* pc_relative. */ + 0, /* bitpos. */ + complain_overflow_bitfield, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_V850_COPY", /* name. */ + FALSE, /* partial_inplace. */ + 0xffffffff, /* src_mask. */ + 0xffffffff, /* dst_mask. */ + FALSE), /* pcrel_offset. */ + + /* Like R_M32R_24, but used when setting global offset table + entries. */ + HOWTO (R_V850_GLOB_DAT, /* type. */ + 0, /* rightshift. */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize. */ + FALSE, /* pc_relative. */ + 0, /* bitpos. */ + complain_overflow_bitfield, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_V850_GLOB_DAT", /* name. */ + FALSE, /* partial_inplace. */ + 0xffffffff, /* src_mask. */ + 0xffffffff, /* dst_mask. */ + FALSE), /* pcrel_offset. */ + + /* Marks a procedure linkage table entry for a symbol. */ + HOWTO (R_V850_JMP_SLOT, /* type. */ + 0, /* rightshift. */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize. */ + FALSE, /* pc_relative. */ + 0, /* bitpos. */ + complain_overflow_bitfield, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_V850_JMP_SLOT", /* name. */ + FALSE, /* partial_inplace. */ + 0xffffffff, /* src_mask. */ + 0xffffffff, /* dst_mask. */ + FALSE), /* pcrel_offset. */ + + /* Used only by the dynamic linker. When the object is run, this + longword is set to the load address of the object, plus the + addend. */ + HOWTO (R_V850_RELATIVE, /* type. */ + 0, /* rightshift. */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize. */ + FALSE, /* pc_relative. */ + 0, /* bitpos. */ + complain_overflow_bitfield, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_V850_RELATIVE", /* name. */ + FALSE, /* partial_inplace. */ + 0xffffffff, /* src_mask. */ + 0xffffffff, /* dst_mask. */ + FALSE), /* pcrel_offset. */ + + HOWTO (R_V850_16_GOTOFF, /* type. */ + 0, /* rightshift. */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize. */ + FALSE, /* pc_relative. */ + 0, /* bitpos. */ + complain_overflow_bitfield, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_V850_16_GOTOFF", /* name. */ + FALSE, /* partial_inplace. */ + 0xffff, /* src_mask. */ + 0xffff, /* dst_mask. */ + FALSE), /* pcrel_offset. */ + + HOWTO (R_V850_32_GOTOFF, /* type. */ + 0, /* rightshift. */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize. */ + FALSE, /* pc_relative. */ + 0, /* bitpos. */ + complain_overflow_bitfield, /* complain_on_overflow. */ + bfd_elf_generic_reloc, /* special_function. */ + "R_V850_32_GOTOFF", /* name. */ + FALSE, /* partial_inplace. */ + 0xffffffff, /* src_mask. */ + 0xffffffff, /* dst_mask. */ + FALSE), /* pcrel_offset. */ + + HOWTO (R_V850_CODE, /* type. */ + 0, /* rightshift. */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize. */ + FALSE, /* pc_relative. */ + 0, /* bitpos. */ + complain_overflow_unsigned, /* complain_on_overflow. */ + v850_elf_ignore_reloc, /* special_function. */ + "R_V850_CODE", /* name. */ + FALSE, /* partial_inplace. */ + 0, /* src_mask. */ + 0, /* dst_mask. */ + TRUE), /* pcrel_offset. */ + + HOWTO (R_V850_DATA, /* type. */ + 0, /* rightshift. */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize. */ + FALSE, /* pc_relative. */ + 0, /* bitpos. */ + complain_overflow_unsigned, /* complain_on_overflow. */ + v850_elf_ignore_reloc, /* special_function. */ + "R_V850_DATA", /* name. */ + FALSE, /* partial_inplace. */ + 0, /* src_mask. */ + 0, /* dst_mask. */ + TRUE), /* pcrel_offset. */ + }; /* Map BFD reloc types to V850 ELF reloc types. */ @@ -1280,16 +1688,16 @@ struct v850_elf_reloc_map static const struct v850_elf_reloc_map v850_elf_reloc_map[] = { - { BFD_RELOC_NONE, R_V850_NONE }, - { BFD_RELOC_V850_9_PCREL, R_V850_9_PCREL }, - { BFD_RELOC_V850_22_PCREL, R_V850_22_PCREL }, - { BFD_RELOC_HI16_S, R_V850_HI16_S }, - { BFD_RELOC_HI16, R_V850_HI16 }, - { BFD_RELOC_LO16, R_V850_LO16 }, - { BFD_RELOC_32, R_V850_ABS32 }, - { BFD_RELOC_32_PCREL, R_V850_REL32 }, - { BFD_RELOC_16, R_V850_16 }, - { BFD_RELOC_8, R_V850_8 }, + { BFD_RELOC_NONE, R_V850_NONE }, + { BFD_RELOC_V850_9_PCREL, R_V850_9_PCREL }, + { BFD_RELOC_V850_22_PCREL, R_V850_22_PCREL }, + { BFD_RELOC_HI16_S, R_V850_HI16_S }, + { BFD_RELOC_HI16, R_V850_HI16 }, + { BFD_RELOC_LO16, R_V850_LO16 }, + { BFD_RELOC_32, R_V850_ABS32 }, + { BFD_RELOC_32_PCREL, R_V850_REL32 }, + { BFD_RELOC_16, R_V850_16 }, + { BFD_RELOC_8, R_V850_8 }, { BFD_RELOC_V850_SDA_16_16_OFFSET, R_V850_SDA_16_16_OFFSET }, { BFD_RELOC_V850_SDA_15_16_OFFSET, R_V850_SDA_15_16_OFFSET }, { BFD_RELOC_V850_ZDA_16_16_OFFSET, R_V850_ZDA_16_16_OFFSET }, @@ -1310,7 +1718,28 @@ static const struct v850_elf_reloc_map v850_elf_reloc_map[] = { BFD_RELOC_V850_LONGCALL, R_V850_LONGCALL }, { BFD_RELOC_V850_LONGJUMP, R_V850_LONGJUMP }, { BFD_RELOC_V850_ALIGN, R_V850_ALIGN }, - + { BFD_RELOC_V850_16_PCREL, R_V850_16_PCREL }, + { BFD_RELOC_V850_17_PCREL, R_V850_17_PCREL }, + { BFD_RELOC_V850_23, R_V850_23 }, + { BFD_RELOC_V850_32_PCREL, R_V850_32_PCREL }, + { BFD_RELOC_V850_32_ABS, R_V850_32_ABS }, + { BFD_RELOC_V850_16_SPLIT_OFFSET, R_V850_HI16 }, + { BFD_RELOC_V850_16_S1, R_V850_16_S1 }, + { BFD_RELOC_V850_LO16_S1, R_V850_LO16_S1 }, + { BFD_RELOC_V850_CALLT_15_16_OFFSET, R_V850_CALLT_15_16_OFFSET }, + { BFD_RELOC_V850_32_GOTPCREL, R_V850_32_GOTPCREL }, + { BFD_RELOC_V850_16_GOT, R_V850_16_GOT }, + { BFD_RELOC_V850_32_GOT, R_V850_32_GOT }, + { BFD_RELOC_V850_22_PLT_PCREL, R_V850_22_PLT }, + { BFD_RELOC_V850_32_PLT_PCREL, R_V850_32_PLT }, + { BFD_RELOC_V850_COPY, R_V850_COPY }, + { BFD_RELOC_V850_GLOB_DAT, R_V850_GLOB_DAT }, + { BFD_RELOC_V850_JMP_SLOT, R_V850_JMP_SLOT }, + { BFD_RELOC_V850_RELATIVE, R_V850_RELATIVE }, + { BFD_RELOC_V850_16_GOTOFF, R_V850_16_GOTOFF }, + { BFD_RELOC_V850_32_GOTOFF, R_V850_32_GOTOFF }, + { BFD_RELOC_V850_CODE, R_V850_CODE }, + { BFD_RELOC_V850_DATA, R_V850_DATA }, }; /* Map a bfd relocation into the appropriate howto structure. */ @@ -1417,28 +1846,54 @@ v850_elf_final_link_relocate (reloc_howto_type *howto, value -= offset; break; + case R_V850_16_PCREL: + value -= (input_section->output_section->vma + + input_section->output_offset + + offset); + + /* If the sign extension will corrupt the value then we have overflowed. */ + if ((value & 0xffff0000) != 0xffff0000) + return bfd_reloc_overflow; + + break; + + case R_V850_17_PCREL: + value -= (input_section->output_section->vma + + input_section->output_offset + + offset); + + /* If the sign extension will corrupt the value then we have overflowed. */ + if (((value & 0xffff0000) != 0x0) && ((value & 0xffff0000) != 0xffff0000)) + return bfd_reloc_overflow; + + value = SEXT17 (value); + break; + case R_V850_22_PCREL: value -= (input_section->output_section->vma + input_section->output_offset + offset); /* If the sign extension will corrupt the value then we have overflowed. */ - if (((value & 0xff000000) != 0x0) && ((value & 0xff000000) != 0xff000000)) + if (((value & 0xffe00000) != 0x0) && ((value & 0xffe00000) != 0xffe00000)) return bfd_reloc_overflow; - /* Only the bottom 24 bits of the PC are valid. */ - value = SEXT24 (value); + /* Only the bottom 22 bits of the PC are valid. */ + value = SEXT22 (value); break; - case R_V850_REL32: + case R_V850_32_PCREL: value -= (input_section->output_section->vma + input_section->output_offset + offset); break; + case R_V850_32_ABS: + case R_V850_23: case R_V850_HI16_S: case R_V850_HI16: case R_V850_LO16: + case R_V850_LO16_S1: case R_V850_LO16_SPLIT_OFFSET: case R_V850_16: case R_V850_ABS32: @@ -1481,10 +1936,10 @@ v850_elf_final_link_relocate (reloc_howto_type *howto, case R_V850_TDA_4_4_OFFSET: case R_V850_TDA_4_5_OFFSET: - case R_V850_TDA_16_16_OFFSET: case R_V850_TDA_7_7_OFFSET: case R_V850_TDA_7_8_OFFSET: case R_V850_TDA_6_8_OFFSET: + case R_V850_TDA_16_16_OFFSET: { unsigned long ep; struct bfd_link_hash_entry * h; @@ -1521,6 +1976,7 @@ v850_elf_final_link_relocate (reloc_howto_type *howto, } break; + case R_V850_CALLT_15_16_OFFSET: case R_V850_CALLT_16_16_OFFSET: { unsigned long ctbp; @@ -1766,6 +2222,12 @@ v850_elf_object_p (bfd *abfd) case E_V850E1_ARCH: bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e1); break; + case E_V850E2_ARCH: + bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e2); + break; + case E_V850E2V3_ARCH: + bfd_default_set_arch_mach (abfd, bfd_arch_v850, bfd_mach_v850e2v3); + break; } return TRUE; } @@ -1784,6 +2246,8 @@ v850_elf_final_write_processing (bfd *abfd, case bfd_mach_v850: val = E_V850_ARCH; break; case bfd_mach_v850e: val = E_V850E_ARCH; break; case bfd_mach_v850e1: val = E_V850E1_ARCH; break; + case bfd_mach_v850e2: val = E_V850E2_ARCH; break; + case bfd_mach_v850e2v3: val = E_V850E2V3_ARCH; break; } elf_elfheader (abfd)->e_flags &=~ EF_V850_ARCH; @@ -1847,20 +2311,40 @@ v850_elf_merge_private_bfd_data (bfd *ibfd, bfd *obfd) if ((in_flags & EF_V850_ARCH) != (out_flags & EF_V850_ARCH) && (in_flags & EF_V850_ARCH) != E_V850_ARCH) { + /* Allow v850e1 binaries to be linked with v850e binaries. - Set the output binary to v850e. */ + Set the output binary to v850e. */ if ((in_flags & EF_V850_ARCH) == E_V850E1_ARCH - && (out_flags & EF_V850_ARCH) == E_V850E_ARCH) - return TRUE; + && (out_flags & EF_V850_ARCH) == E_V850E_ARCH) + return TRUE; - if ((in_flags & EF_V850_ARCH) == E_V850E_ARCH - && (out_flags & EF_V850_ARCH) == E_V850E1_ARCH) + if ((in_flags & EF_V850_ARCH) == E_V850_ARCH + && (out_flags & EF_V850_ARCH) == E_V850E_ARCH) { elf_elfheader (obfd)->e_flags = ((out_flags & ~ EF_V850_ARCH) | E_V850E_ARCH); return TRUE; } + if (((in_flags & EF_V850_ARCH) == E_V850_ARCH + || (in_flags & EF_V850_ARCH) == E_V850E_ARCH) + && (out_flags & EF_V850_ARCH) == E_V850E2_ARCH) + { + elf_elfheader (obfd)->e_flags = + ((out_flags & ~ EF_V850_ARCH) | E_V850E2_ARCH); + return TRUE; + } + + if (((in_flags & EF_V850_ARCH) == E_V850_ARCH + || (in_flags & EF_V850_ARCH) == E_V850E_ARCH + || (in_flags & EF_V850_ARCH) == E_V850E2_ARCH) + && (out_flags & EF_V850_ARCH) == E_V850E2V3_ARCH) + { + elf_elfheader (obfd)->e_flags = + ((out_flags & ~ EF_V850_ARCH) | E_V850E2V3_ARCH); + return TRUE; + } + _bfd_error_handler (_("%B: Architecture mismatch with previous modules"), ibfd); } @@ -1879,7 +2363,7 @@ v850_elf_print_private_bfd_data (bfd *abfd, void * ptr) _bfd_elf_print_private_bfd_data (abfd, ptr); - /* xgettext:c-format */ + /* xgettext:c-format. */ fprintf (file, _("private flags = %lx: "), elf_elfheader (abfd)->e_flags); switch (elf_elfheader (abfd)->e_flags & EF_V850_ARCH) @@ -1888,6 +2372,8 @@ v850_elf_print_private_bfd_data (bfd *abfd, void * ptr) case E_V850_ARCH: fprintf (file, _("v850 architecture")); break; case E_V850E_ARCH: fprintf (file, _("v850e architecture")); break; case E_V850E1_ARCH: fprintf (file, _("v850e1 architecture")); break; + case E_V850E2_ARCH: fprintf (file, _("v850e2 architecture")); break; + case E_V850E2V3_ARCH: fprintf (file, _("v850e2v3 architecture")); break; } fputc ('\n', file); @@ -1949,7 +2435,7 @@ v850_elf_symbol_processing (bfd *abfd, asymbol *asym) FIXME: Should we alter the st_shndx field as well ? */ if (indx < elf_numsections (abfd)) - switch (elf_elfsections(abfd)[indx]->sh_type) + switch (elf_elfsections (abfd)[indx]->sh_type) { case SHT_V850_SCOMMON: indx = SHN_V850_SCOMMON; @@ -2046,7 +2532,7 @@ v850_elf_add_symbol_hook (bfd *abfd, FIXME: Should we alter the st_shndx field as well ? */ if (indx < elf_numsections (abfd)) - switch (elf_elfsections(abfd)[indx]->sh_type) + switch (elf_elfsections (abfd)[indx]->sh_type) { case SHT_V850_SCOMMON: indx = SHN_V850_SCOMMON; @@ -2376,22 +2862,22 @@ v850_elf_relax_delete_bytes (bfd *abfd, } #define NOP_OPCODE (0x0000) -#define MOVHI 0x0640 /* 4byte */ +#define MOVHI 0x0640 /* 4byte. */ #define MOVHI_MASK 0x07e0 -#define MOVHI_R1(insn) ((insn) & 0x1f) /* 4byte */ +#define MOVHI_R1(insn) ((insn) & 0x1f) /* 4byte. */ #define MOVHI_R2(insn) ((insn) >> 11) -#define MOVEA 0x0620 /* 2byte */ +#define MOVEA 0x0620 /* 2byte. */ #define MOVEA_MASK 0x07e0 #define MOVEA_R1(insn) ((insn) & 0x1f) #define MOVEA_R2(insn) ((insn) >> 11) -#define JARL_4 0x00040780 /* 4byte */ +#define JARL_4 0x00040780 /* 4byte. */ #define JARL_4_MASK 0xFFFF07FF #define JARL_R2(insn) (int)(((insn) & (~JARL_4_MASK)) >> 11) -#define ADD_I 0x0240 /* 2byte */ +#define ADD_I 0x0240 /* 2byte. */ #define ADD_I_MASK 0x07e0 -#define ADD_I5(insn) ((((insn) & 0x001f) << 11) >> 11) /* 2byte */ +#define ADD_I5(insn) ((((insn) & 0x001f) << 11) >> 11) /* 2byte. */ #define ADD_R2(insn) ((insn) >> 11) -#define JMP_R 0x0060 /* 2byte */ +#define JMP_R 0x0060 /* 2byte. */ #define JMP_R_MASK 0xFFE0 #define JMP_R1(insn) ((insn) & 0x1f) diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 3da79d9ddec..94bbd8ef5cd 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1636,6 +1636,28 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_V850_LONGJUMP", "BFD_RELOC_V850_ALIGN", "BFD_RELOC_V850_LO16_SPLIT_OFFSET", + "BFD_RELOC_V850_16_PCREL", + "BFD_RELOC_V850_17_PCREL", + "BFD_RELOC_V850_23", + "BFD_RELOC_V850_32_PCREL", + "BFD_RELOC_V850_32_ABS", + "BFD_RELOC_V850_16_SPLIT_OFFSET", + "BFD_RELOC_V850_16_S1", + "BFD_RELOC_V850_LO16_S1", + "BFD_RELOC_V850_CALLT_15_16_OFFSET", + "BFD_RELOC_V850_32_GOTPCREL", + "BFD_RELOC_V850_16_GOT", + "BFD_RELOC_V850_32_GOT", + "BFD_RELOC_V850_22_PLT_PCREL", + "BFD_RELOC_V850_32_PLT_PCREL", + "BFD_RELOC_V850_COPY", + "BFD_RELOC_V850_GLOB_DAT", + "BFD_RELOC_V850_JMP_SLOT", + "BFD_RELOC_V850_RELATIVE", + "BFD_RELOC_V850_16_GOTOFF", + "BFD_RELOC_V850_32_GOTOFF", + "BFD_RELOC_V850_CODE", + "BFD_RELOC_V850_DATA", "BFD_RELOC_MN10300_32_PCREL", "BFD_RELOC_MN10300_16_PCREL", "BFD_RELOC_TIC30_LDP", diff --git a/bfd/reloc.c b/bfd/reloc.c index 7d16869263d..f8a39c9aa02 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -3722,6 +3722,94 @@ ENUM ENUMDOC This is a variation of BFD_RELOC_LO16 that can be used in v850e ld.bu instructions. +ENUM + BFD_RELOC_V850_16_PCREL +ENUMDOC + This is a 16-bit reloc. +ENUM + BFD_RELOC_V850_17_PCREL +ENUMDOC + This is a 17-bit reloc. +ENUM + BFD_RELOC_V850_23 +ENUMDOC + This is a 23-bit reloc. +ENUM + BFD_RELOC_V850_32_PCREL +ENUMDOC + This is a 32-bit reloc. +ENUM + BFD_RELOC_V850_32_ABS +ENUMDOC + This is a 32-bit reloc. +ENUM + BFD_RELOC_V850_16_SPLIT_OFFSET +ENUMDOC + This is a 16-bit reloc. +ENUM + BFD_RELOC_V850_16_S1 +ENUMDOC + This is a 16-bit reloc. +ENUM + BFD_RELOC_V850_LO16_S1 +ENUMDOC + Low 16 bits. 16 bit shifted by 1. +ENUM + BFD_RELOC_V850_CALLT_15_16_OFFSET +ENUMDOC + This is a 16 bit offset from the call table base pointer. +ENUM + BFD_RELOC_V850_32_GOTPCREL +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_16_GOT +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_32_GOT +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_22_PLT_PCREL +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_32_PLT_PCREL +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_COPY +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_GLOB_DAT +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_JMP_SLOT +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_RELATIVE +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_16_GOTOFF +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_32_GOTOFF +ENUMDOC + DSO relocations. +ENUM + BFD_RELOC_V850_CODE +ENUMDOC + start code. +ENUM + BFD_RELOC_V850_DATA +ENUMDOC + start data in text. ENUM BFD_RELOC_MN10300_32_PCREL ENUMDOC diff --git a/binutils/ChangeLog b/binutils/ChangeLog index 302d3165905..ae598c14d6a 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,8 @@ +2010-07-23 Naveen.H.S + Ina Pandit + + * binutils/readelf.c: Add support for V850E2 and V850E2V3. + 2010-07-22 Alan Modra * readelf.c: Add Moxie support. diff --git a/binutils/readelf.c b/binutils/readelf.c index fd81d2db12b..c2bb10de2f0 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -2352,8 +2352,14 @@ get_machine_flags (unsigned e_flags, unsigned e_machine) case EM_CYGNUS_V850: switch (e_flags & EF_V850_ARCH) { - case E_V850E1_ARCH: - strcat (buf, ", v850e1"); + case E_V850E2V3_ARCH: + strcat (buf, ", v850e2v3"); + break; + case E_V850E2_ARCH: + strcat (buf, ", v850e2"); + break; + case E_V850E1_ARCH: + strcat (buf, ", v850e1"); break; case E_V850E_ARCH: strcat (buf, ", v850e"); diff --git a/configure b/configure index 8edfde3da4d..0904ffb741b 100755 --- a/configure +++ b/configure @@ -3730,14 +3730,8 @@ case "${target}" in v810-*-*) noconfigdirs="$noconfigdirs bfd binutils gas gcc gdb ld target-libstdc++-v3 opcodes target-libgloss ${libgcj}" ;; - v850-*-*) - noconfigdirs="$noconfigdirs target-libgloss ${libgcj}" - ;; - v850e-*-*) - noconfigdirs="$noconfigdirs target-libgloss ${libgcj}" - ;; - v850ea-*-*) - noconfigdirs="$noconfigdirs target-libgloss ${libgcj}" + v850*-*-*) + noconfigdirs="$noconfigdirs ${libgcj}" ;; vax-*-vms) noconfigdirs="$noconfigdirs bfd binutils gdb ld target-newlib opcodes target-libgloss ${libgcj}" diff --git a/configure.ac b/configure.ac index f78c5273084..2d39219a619 100644 --- a/configure.ac +++ b/configure.ac @@ -967,14 +967,8 @@ case "${target}" in v810-*-*) noconfigdirs="$noconfigdirs bfd binutils gas gcc gdb ld target-libstdc++-v3 opcodes target-libgloss ${libgcj}" ;; - v850-*-*) - noconfigdirs="$noconfigdirs target-libgloss ${libgcj}" - ;; - v850e-*-*) - noconfigdirs="$noconfigdirs target-libgloss ${libgcj}" - ;; - v850ea-*-*) - noconfigdirs="$noconfigdirs target-libgloss ${libgcj}" + v850*-*-*) + noconfigdirs="$noconfigdirs ${libgcj}" ;; vax-*-vms) noconfigdirs="$noconfigdirs bfd binutils gdb ld target-newlib opcodes target-libgloss ${libgcj}" diff --git a/gas/ChangeLog b/gas/ChangeLog index a157d027683..5ad0269b30d 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,50 @@ +2010-07-23 Naveen.H.S + Ina Pandit + + * config/tc-v850.c: Update processor_mask. + (reg_name): Update the structure to use processors field. + (md_relax_table): Define SUBYPTE_COND_9_22, SUBYPTE_SA_9_22, + SUBYPTE_UNCOND_9_22, SUBYPTE_COND_9_22_32, SUBYPTE_SA_9_22_32, + SUBYPTE_UNCOND_9_22_32, SUBYPTE_COND_9_17_22, + SUBYPTE_SA_9_17_22, SUBYPTE_COND_9_17_22_32 and + SUBYPTE_SA_9_17_22_32. + (set_machine): Add support for V850E2 and V850E2V3. + (md_pseudo_table): Likewise. + (pre_defined_registers): Update pre defined registers suitable + for each family of registers. + (system_registers): Likewise. + (cc_names): Update the condition code. + (float_cc_names): Update the condition code for float. + (reg_name_search): Update based on current modifications. + (register_name): Likewise. + (system_register_name): Update to support new system registers + and supported families. + (cc_name): Update to support new condition codes. + (float_cc_name): New function to support float condition codes. + (parse_register_list): Update to support newly added registers. + (md_show_usage): Define support for V850E2 and V850E2V3 targets. + Also support added for disp-size-default-22, disp-size-default-32, + mextension, mno-bcond17 and mno-stld23. + (md_parse_option): Implement the support for above options defined + in md_show-usage. + (md_convert_frag): Implement support for subtypes defined in + md_relax_table to support branch operations. + (md_begin): Add support for V850E2 and V850E2V3. + (handle_hi016, handle_hi16): new relocation handling functions + (handle_lo16, handle_ctoff, handle_sdaoff, handle_zdaoff, + handle_tdaoff): Updated relocation handling functions for newly + added relocations. + (v850_reloc_prefix): Update the relocation handling functions. + (v850_insert_operand): Updated the functions with error message + parameter and modified the function to use it. + (md_assemble): Update according to the latest modifications. + (md_apply_fix): Updated the functions with error message parameter + and modified the function to use it. + (v850_force_relocation): Update with newly added relocations. + * configure.tgt: Match all v850 targets. + * doc/c-v850.texi: Document the newly added targets. + * NEWS: Likewise. + 2010-07-23 Alan Modra PR gas/11834 diff --git a/gas/NEWS b/gas/NEWS index db6b6d4d05c..c7280bb2231 100644 --- a/gas/NEWS +++ b/gas/NEWS @@ -16,6 +16,8 @@ Changes in 2.20: +* Added support for v850e2 and v850e2v3. + * GNU/Linux targets now supports "gnu_unique_object" as a value in the .type pseudo op. It marks the symbol as being globally unique in the entire process. diff --git a/gas/config/tc-v850.c b/gas/config/tc-v850.c index e0ac162279a..d792769f99c 100644 --- a/gas/config/tc-v850.c +++ b/gas/config/tc-v850.c @@ -1,6 +1,6 @@ /* tc-v850.c -- Assembler code for the NEC V850 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2009 Free Software Foundation, Inc. + 2006, 2007, 2009, 2010 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -39,13 +39,14 @@ static bfd_boolean warn_unsigned_overflows = FALSE; static int machine = -1; /* Indicates the target processor(s) for the assemble. */ -static int processor_mask = -1; +static int processor_mask = 0; /* Structure to hold information about predefined registers. */ struct reg_name { const char *name; int value; + unsigned int processors; }; /* Generic assembler global variables which must be defined by all @@ -71,15 +72,67 @@ const char FLT_CHARS[] = "dD"; const relax_typeS md_relax_table[] = { - /* Conditional branches. */ - {0xff, -0x100, 2, 1}, - {0x1fffff, -0x200000, 6, 0}, - /* Unconditional branches. */ - {0xff, -0x100, 2, 3}, - {0x1fffff, -0x200000, 4, 0}, + /* Conditional branches.(V850/V850E, max 22bit) */ +#define SUBYPTE_COND_9_22 0 + {0xfe, -0x100, 2, SUBYPTE_COND_9_22 + 1}, + {0x1ffffe + 2, -0x200000 + 2, 6, 0}, + /* Conditional branches.(V850/V850E, max 22bit) */ +#define SUBYPTE_SA_9_22 2 + {0xfe, -0x100, 2, SUBYPTE_SA_9_22 + 1}, + {0x1ffffe + 4, -0x200000 + 4, 8, 0}, + /* Unconditional branches.(V850/V850E, max 22bit) */ +#define SUBYPTE_UNCOND_9_22 4 + {0xfe, -0x100, 2, SUBYPTE_UNCOND_9_22 + 1}, + {0x1ffffe, -0x200000, 4, 0}, + /* Conditional branches.(V850E2, max 32bit) */ +#define SUBYPTE_COND_9_22_32 6 + {0xfe, -0x100, 2, SUBYPTE_COND_9_22_32 + 1}, + {0x1fffff + 2, -0x200000 + 2, 6, SUBYPTE_COND_9_22_32 + 2}, + {0x7ffffffe, -0x80000000, 8, 0}, + /* Conditional branches.(V850E2, max 32bit) */ +#define SUBYPTE_SA_9_22_32 9 + {0xfe, -0x100, 2, SUBYPTE_SA_9_22_32 + 1}, + {0x1ffffe + 4, -0x200000 + 4, 8, SUBYPTE_SA_9_22_32 + 2}, + {0x7ffffffe, -0x80000000, 10, 0}, + /* Unconditional branches.(V850E2, max 32bit) */ +#define SUBYPTE_UNCOND_9_22_32 12 + {0xfe, -0x100, 2, SUBYPTE_UNCOND_9_22_32 + 1}, + {0x1ffffe, -0x200000, 4, SUBYPTE_UNCOND_9_22_32 + 2}, + {0x7ffffffe, -0x80000000, 6, 0}, + /* Conditional branches.(V850E2R max 22bit) */ +#define SUBYPTE_COND_9_17_22 15 + {0xfe, -0x100, 2, SUBYPTE_COND_9_17_22 + 1}, + {0xfffe, -0x10000, 4, SUBYPTE_COND_9_17_22 + 2}, + {0x1ffffe + 2, -0x200000 + 2, 6, 0}, + /* Conditional branches.(V850E2R max 22bit) */ +#define SUBYPTE_SA_9_17_22 18 + {0xfe, -0x100, 2, SUBYPTE_SA_9_17_22 + 1}, + {0xfffe, -0x10000, 4, SUBYPTE_SA_9_17_22 + 2}, + {0x1ffffe + 4, -0x200000 + 4, 8, 0}, + /* Conditional branches.(V850E2R max 32bit) */ +#define SUBYPTE_COND_9_17_22_32 21 + {0xfe, -0x100, 2, SUBYPTE_COND_9_17_22_32 + 1}, + {0xfffe, -0x10000, 4, SUBYPTE_COND_9_17_22_32 + 2}, + {0x1ffffe + 2, -0x200000 + 2, 6, SUBYPTE_COND_9_17_22_32 + 3}, + {0x7ffffffe, -0x80000000, 8, 0}, + /* Conditional branches.(V850E2R max 32bit) */ +#define SUBYPTE_SA_9_17_22_32 25 + {0xfe, -0x100, 2, SUBYPTE_SA_9_17_22_32 + 1}, + {0xfffe, -0x10000, 4, SUBYPTE_SA_9_17_22_32 + 2}, + {0x1ffffe + 4, -0x200000 + 4, 8, SUBYPTE_SA_9_17_22_32 + 3}, + {0x7ffffffe, -0x80000000, 10, 0}, }; -static int v850_relax = 0; +static int v850_relax = 0; + +/* Default branch disp size 22 or 32. */ +static int default_disp_size = 22; + +/* Default no using bcond17. */ +static int no_bcond17 = 0; + +/* Default no using ld/st 23bit offset. */ +static int no_stld23 = 0; /* Fixups. */ #define MAX_INSN_FIXUPS 5 @@ -463,9 +516,12 @@ set_machine (int number) switch (machine) { - case 0: processor_mask = PROCESSOR_V850; break; - case bfd_mach_v850e: processor_mask = PROCESSOR_V850E; break; - case bfd_mach_v850e1: processor_mask = PROCESSOR_V850E; break; + case 0: SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850); break; + case bfd_mach_v850: SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850); break; + case bfd_mach_v850e: SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E); break; + case bfd_mach_v850e1: SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E); break; + case bfd_mach_v850e2: SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E2); break; + case bfd_mach_v850e2v3:SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E2V3); break; } } @@ -523,7 +579,9 @@ const pseudo_typeS md_pseudo_table[] = { "call_table_data", v850_seg, CALL_TABLE_DATA_SECTION }, { "call_table_text", v850_seg, CALL_TABLE_TEXT_SECTION }, { "v850e", set_machine, bfd_mach_v850e }, - { "v850e1", set_machine, bfd_mach_v850e1 }, + { "v850e1", set_machine, bfd_mach_v850e1 }, + { "v850e2", set_machine, bfd_mach_v850e2 }, + { "v850e2v3", set_machine, bfd_mach_v850e2v3 }, { "longcall", v850_longcode, 1 }, { "longjump", v850_longcode, 2 }, { NULL, NULL, 0 } @@ -535,45 +593,45 @@ static struct hash_control *v850_hash; /* This table is sorted. Suitable for searching by a binary search. */ static const struct reg_name pre_defined_registers[] = { - { "ep", 30 }, /* ep - element ptr. */ - { "gp", 4 }, /* gp - global ptr. */ - { "hp", 2 }, /* hp - handler stack ptr. */ - { "lp", 31 }, /* lp - link ptr. */ - { "r0", 0 }, - { "r1", 1 }, - { "r10", 10 }, - { "r11", 11 }, - { "r12", 12 }, - { "r13", 13 }, - { "r14", 14 }, - { "r15", 15 }, - { "r16", 16 }, - { "r17", 17 }, - { "r18", 18 }, - { "r19", 19 }, - { "r2", 2 }, - { "r20", 20 }, - { "r21", 21 }, - { "r22", 22 }, - { "r23", 23 }, - { "r24", 24 }, - { "r25", 25 }, - { "r26", 26 }, - { "r27", 27 }, - { "r28", 28 }, - { "r29", 29 }, - { "r3", 3 }, - { "r30", 30 }, - { "r31", 31 }, - { "r4", 4 }, - { "r5", 5 }, - { "r6", 6 }, - { "r7", 7 }, - { "r8", 8 }, - { "r9", 9 }, - { "sp", 3 }, /* sp - stack ptr. */ - { "tp", 5 }, /* tp - text ptr. */ - { "zero", 0 }, + { "ep", 30, PROCESSOR_ALL }, /* ep - element ptr. */ + { "gp", 4, PROCESSOR_ALL }, /* gp - global ptr. */ + { "hp", 2, PROCESSOR_ALL }, /* hp - handler stack ptr. */ + { "lp", 31, PROCESSOR_ALL }, /* lp - link ptr. */ + { "r0", 0, PROCESSOR_ALL }, + { "r1", 1, PROCESSOR_ALL }, + { "r10", 10, PROCESSOR_ALL }, + { "r11", 11, PROCESSOR_ALL }, + { "r12", 12, PROCESSOR_ALL }, + { "r13", 13, PROCESSOR_ALL }, + { "r14", 14, PROCESSOR_ALL }, + { "r15", 15, PROCESSOR_ALL }, + { "r16", 16, PROCESSOR_ALL }, + { "r17", 17, PROCESSOR_ALL }, + { "r18", 18, PROCESSOR_ALL }, + { "r19", 19, PROCESSOR_ALL }, + { "r2", 2, PROCESSOR_ALL }, + { "r20", 20, PROCESSOR_ALL }, + { "r21", 21, PROCESSOR_ALL }, + { "r22", 22, PROCESSOR_ALL }, + { "r23", 23, PROCESSOR_ALL }, + { "r24", 24, PROCESSOR_ALL }, + { "r25", 25, PROCESSOR_ALL }, + { "r26", 26, PROCESSOR_ALL }, + { "r27", 27, PROCESSOR_ALL }, + { "r28", 28, PROCESSOR_ALL }, + { "r29", 29, PROCESSOR_ALL }, + { "r3", 3, PROCESSOR_ALL }, + { "r30", 30, PROCESSOR_ALL }, + { "r31", 31, PROCESSOR_ALL }, + { "r4", 4, PROCESSOR_ALL }, + { "r5", 5, PROCESSOR_ALL }, + { "r6", 6, PROCESSOR_ALL }, + { "r7", 7, PROCESSOR_ALL }, + { "r8", 8, PROCESSOR_ALL }, + { "r9", 9, PROCESSOR_ALL }, + { "sp", 3, PROCESSOR_ALL }, /* sp - stack ptr. */ + { "tp", 5, PROCESSOR_ALL }, /* tp - text ptr. */ + { "zero", 0, PROCESSOR_ALL }, }; #define REG_NAME_CNT \ @@ -581,67 +639,220 @@ static const struct reg_name pre_defined_registers[] = static const struct reg_name system_registers[] = { - { "asid", 23 }, - { "bpc", 22 }, - { "bpav", 24 }, - { "bpam", 25 }, - { "bpdv", 26 }, - { "bpdm", 27 }, - { "ctbp", 20 }, - { "ctpc", 16 }, - { "ctpsw", 17 }, - { "dbpc", 18 }, - { "dbpsw", 19 }, - { "dir", 21 }, - { "ecr", 4 }, - { "eipc", 0 }, - { "eipsw", 1 }, - { "fepc", 2 }, - { "fepsw", 3 }, - { "psw", 5 }, + { "asid", 23, PROCESSOR_NOT_V850 }, + { "bpam", 25, PROCESSOR_NOT_V850 }, + { "bpav", 24, PROCESSOR_NOT_V850 }, + { "bpc", 22, PROCESSOR_NOT_V850 }, + { "bpdm", 27, PROCESSOR_NOT_V850 }, + { "bpdv", 26, PROCESSOR_NOT_V850 }, + { "bsel", 31, PROCESSOR_V850E2_ALL }, + { "cfg", 7, PROCESSOR_V850E2V3 }, + { "ctbp", 20, PROCESSOR_NOT_V850 }, + { "ctpc", 16, PROCESSOR_NOT_V850 }, + { "ctpsw", 17, PROCESSOR_NOT_V850 }, + { "dbic", 15, PROCESSOR_V850E2_ALL }, + { "dbpc", 18, PROCESSOR_NOT_V850 }, + { "dbpsw", 19, PROCESSOR_NOT_V850 }, + { "dbwr", 30, PROCESSOR_V850E2_ALL }, + { "dir", 21, PROCESSOR_NOT_V850 }, + { "dpa0l", 16, PROCESSOR_V850E2V3 }, + { "dpa0u", 17, PROCESSOR_V850E2V3 }, + { "dpa1l", 18, PROCESSOR_V850E2V3 }, + { "dpa1u", 19, PROCESSOR_V850E2V3 }, + { "dpa2l", 20, PROCESSOR_V850E2V3 }, + { "dpa2u", 21, PROCESSOR_V850E2V3 }, + { "dpa3l", 22, PROCESSOR_V850E2V3 }, + { "dpa3u", 23, PROCESSOR_V850E2V3 }, + { "dpa4l", 24, PROCESSOR_V850E2V3 }, + { "dpa4u", 25, PROCESSOR_V850E2V3 }, + { "dpa5l", 26, PROCESSOR_V850E2V3 }, + { "dpa5u", 27, PROCESSOR_V850E2V3 }, + { "ecr", 4, PROCESSOR_ALL }, + { "eh_base", 3, PROCESSOR_V850E2V3 }, + { "eh_cfg", 1, PROCESSOR_V850E2V3 }, + { "eh_reset", 2, PROCESSOR_V850E2V3 }, + { "eiic", 13, PROCESSOR_V850E2_ALL }, + { "eipc", 0, PROCESSOR_ALL }, + { "eipsw", 1, PROCESSOR_ALL }, + { "eiwr", 28, PROCESSOR_V850E2_ALL }, + { "feic", 14, PROCESSOR_V850E2_ALL }, + { "fepc", 2, PROCESSOR_ALL }, + { "fepsw", 3, PROCESSOR_ALL }, + { "fewr", 29, PROCESSOR_V850E2_ALL }, + { "fpcc", 9, PROCESSOR_V850E2V3 }, + { "fpcfg", 10, PROCESSOR_V850E2V3 }, + { "fpec", 11, PROCESSOR_V850E2V3 }, + { "fpepc", 7, PROCESSOR_V850E2V3 }, + { "fpspc", 27, PROCESSOR_V850E2V3 }, + { "fpsr", 6, PROCESSOR_V850E2V3 }, + { "fpst", 8, PROCESSOR_V850E2V3 }, + { "ipa0l", 6, PROCESSOR_V850E2V3 }, + { "ipa0u", 7, PROCESSOR_V850E2V3 }, + { "ipa1l", 8, PROCESSOR_V850E2V3 }, + { "ipa1u", 9, PROCESSOR_V850E2V3 }, + { "ipa2l", 10, PROCESSOR_V850E2V3 }, + { "ipa2u", 11, PROCESSOR_V850E2V3 }, + { "ipa3l", 12, PROCESSOR_V850E2V3 }, + { "ipa3u", 13, PROCESSOR_V850E2V3 }, + { "ipa4l", 14, PROCESSOR_V850E2V3 }, + { "ipa4u", 15, PROCESSOR_V850E2V3 }, + { "mca", 24, PROCESSOR_V850E2V3 }, + { "mcc", 26, PROCESSOR_V850E2V3 }, + { "mcr", 27, PROCESSOR_V850E2V3 }, + { "mcs", 25, PROCESSOR_V850E2V3 }, + { "mpc", 1, PROCESSOR_V850E2V3 }, + { "mpm", 0, PROCESSOR_V850E2V3 }, + { "mpu10_dpa0l", 16, PROCESSOR_V850E2V3 }, + { "mpu10_dpa0u", 17, PROCESSOR_V850E2V3 }, + { "mpu10_dpa1l", 18, PROCESSOR_V850E2V3 }, + { "mpu10_dpa1u", 19, PROCESSOR_V850E2V3 }, + { "mpu10_dpa2l", 20, PROCESSOR_V850E2V3 }, + { "mpu10_dpa2u", 21, PROCESSOR_V850E2V3 }, + { "mpu10_dpa3l", 22, PROCESSOR_V850E2V3 }, + { "mpu10_dpa3u", 23, PROCESSOR_V850E2V3 }, + { "mpu10_dpa4l", 24, PROCESSOR_V850E2V3 }, + { "mpu10_dpa4u", 25, PROCESSOR_V850E2V3 }, + { "mpu10_dpa5l", 26, PROCESSOR_V850E2V3 }, + { "mpu10_dpa5u", 27, PROCESSOR_V850E2V3 }, + { "mpu10_ipa0l", 6, PROCESSOR_V850E2V3 }, + { "mpu10_ipa0u", 7, PROCESSOR_V850E2V3 }, + { "mpu10_ipa1l", 8, PROCESSOR_V850E2V3 }, + { "mpu10_ipa1u", 9, PROCESSOR_V850E2V3 }, + { "mpu10_ipa2l", 10, PROCESSOR_V850E2V3 }, + { "mpu10_ipa2u", 11, PROCESSOR_V850E2V3 }, + { "mpu10_ipa3l", 12, PROCESSOR_V850E2V3 }, + { "mpu10_ipa3u", 13, PROCESSOR_V850E2V3 }, + { "mpu10_ipa4l", 14, PROCESSOR_V850E2V3 }, + { "mpu10_ipa4u", 15, PROCESSOR_V850E2V3 }, + { "mpu10_mpc", 1, PROCESSOR_V850E2V3 }, + { "mpu10_mpm", 0, PROCESSOR_V850E2V3 }, + { "mpu10_tid", 2, PROCESSOR_V850E2V3 }, + { "mpu10_vmadr", 5, PROCESSOR_V850E2V3 }, + { "mpu10_vmecr", 3, PROCESSOR_V850E2V3 }, + { "mpu10_vmtid", 4, PROCESSOR_V850E2V3 }, + { "pid", 6, PROCESSOR_V850E2V3 }, + { "pmcr0", 4, PROCESSOR_V850E2V3 }, + { "pmis2", 14, PROCESSOR_V850E2V3 }, + { "psw", 5, PROCESSOR_ALL }, + { "scbp", 12, PROCESSOR_V850E2V3 }, + { "sccfg", 11, PROCESSOR_V850E2V3 }, + { "sr0", 0, PROCESSOR_ALL }, + { "sr1", 1, PROCESSOR_ALL }, + { "sr10", 10, PROCESSOR_ALL }, + { "sr11", 11, PROCESSOR_ALL }, + { "sr12", 12, PROCESSOR_ALL }, + { "sr13", 13, PROCESSOR_ALL }, + { "sr14", 14, PROCESSOR_ALL }, + { "sr15", 15, PROCESSOR_ALL }, + { "sr16", 16, PROCESSOR_ALL }, + { "sr17", 17, PROCESSOR_ALL }, + { "sr18", 18, PROCESSOR_ALL }, + { "sr19", 19, PROCESSOR_ALL }, + { "sr2", 2, PROCESSOR_ALL }, + { "sr20", 20, PROCESSOR_ALL }, + { "sr21", 21, PROCESSOR_ALL }, + { "sr22", 22, PROCESSOR_ALL }, + { "sr23", 23, PROCESSOR_ALL }, + { "sr24", 24, PROCESSOR_ALL }, + { "sr25", 25, PROCESSOR_ALL }, + { "sr26", 26, PROCESSOR_ALL }, + { "sr27", 27, PROCESSOR_ALL }, + { "sr28", 28, PROCESSOR_ALL }, + { "sr29", 29, PROCESSOR_ALL }, + { "sr3", 3, PROCESSOR_ALL }, + { "sr30", 30, PROCESSOR_ALL }, + { "sr31", 31, PROCESSOR_ALL }, + { "sr4", 4, PROCESSOR_ALL }, + { "sr5", 5, PROCESSOR_ALL }, + { "sr6", 6, PROCESSOR_ALL }, + { "sr7", 7, PROCESSOR_ALL }, + { "sr8", 8, PROCESSOR_ALL }, + { "sr9", 9, PROCESSOR_ALL }, + { "sw_base", 3, PROCESSOR_V850E2V3 }, + { "sw_cfg", 1, PROCESSOR_V850E2V3 }, + { "sw_ctl", 0, PROCESSOR_V850E2V3 }, + { "tid", 2, PROCESSOR_V850E2V3 }, + { "vmadr", 6, PROCESSOR_V850E2V3 }, + { "vmecr", 4, PROCESSOR_V850E2V3 }, + { "vmtid", 5, PROCESSOR_V850E2V3 }, + { "vsadr", 2, PROCESSOR_V850E2V3 }, + { "vsecr", 0, PROCESSOR_V850E2V3 }, + { "vstid", 1, PROCESSOR_V850E2V3 }, }; #define SYSREG_NAME_CNT \ (sizeof (system_registers) / sizeof (struct reg_name)) -static const struct reg_name system_list_registers[] = -{ - {"PS", 5 }, - {"SR", 0 + 1} -}; - -#define SYSREGLIST_NAME_CNT \ - (sizeof (system_list_registers) / sizeof (struct reg_name)) static const struct reg_name cc_names[] = { - { "c", 0x1 }, - { "e", 0x2 }, - { "ge", 0xe }, - { "gt", 0xf }, - { "h", 0xb }, - { "l", 0x1 }, - { "le", 0x7 }, - { "lt", 0x6 }, - { "n", 0x4 }, - { "nc", 0x9 }, - { "ne", 0xa }, - { "nh", 0x3 }, - { "nl", 0x9 }, - { "ns", 0xc }, - { "nv", 0x8 }, - { "nz", 0xa }, - { "p", 0xc }, - { "s", 0x4 }, - { "sa", 0xd }, - { "t", 0x5 }, - { "v", 0x0 }, - { "z", 0x2 }, + { "c", 0x1, PROCESSOR_ALL }, + { "e", 0x2, PROCESSOR_ALL }, + { "ge", 0xe, PROCESSOR_ALL }, + { "gt", 0xf, PROCESSOR_ALL }, + { "h", 0xb, PROCESSOR_ALL }, + { "l", 0x1, PROCESSOR_ALL }, + { "le", 0x7, PROCESSOR_ALL }, + { "lt", 0x6, PROCESSOR_ALL }, + { "n", 0x4, PROCESSOR_ALL }, + { "nc", 0x9, PROCESSOR_ALL }, + { "ne", 0xa, PROCESSOR_ALL }, + { "nh", 0x3, PROCESSOR_ALL }, + { "nl", 0x9, PROCESSOR_ALL }, + { "ns", 0xc, PROCESSOR_ALL }, + { "nv", 0x8, PROCESSOR_ALL }, + { "nz", 0xa, PROCESSOR_ALL }, + { "p", 0xc, PROCESSOR_ALL }, + { "s", 0x4, PROCESSOR_ALL }, +#define COND_SA_NUM 0xd + { "sa", COND_SA_NUM, PROCESSOR_ALL }, + { "t", 0x5, PROCESSOR_ALL }, + { "v", 0x0, PROCESSOR_ALL }, + { "z", 0x2, PROCESSOR_ALL }, }; #define CC_NAME_CNT \ (sizeof (cc_names) / sizeof (struct reg_name)) +static const struct reg_name float_cc_names[] = +{ + { "eq", 0x2, PROCESSOR_V850E2V3 }, /* true. */ + { "f", 0x0, PROCESSOR_V850E2V3 }, /* true. */ + { "ge", 0xd, PROCESSOR_V850E2V3 }, /* false. */ + { "gl", 0xb, PROCESSOR_V850E2V3 }, /* false. */ + { "gle", 0x9, PROCESSOR_V850E2V3 }, /* false. */ + { "gt", 0xf, PROCESSOR_V850E2V3 }, /* false. */ + { "le", 0xe, PROCESSOR_V850E2V3 }, /* true. */ + { "lt", 0xc, PROCESSOR_V850E2V3 }, /* true. */ + { "neq", 0x2, PROCESSOR_V850E2V3 }, /* false. */ + { "nge", 0xd, PROCESSOR_V850E2V3 }, /* true. */ + { "ngl", 0xb, PROCESSOR_V850E2V3 }, /* true. */ + { "ngle",0x9, PROCESSOR_V850E2V3 }, /* true. */ + { "ngt", 0xf, PROCESSOR_V850E2V3 }, /* true. */ + { "nle", 0xe, PROCESSOR_V850E2V3 }, /* false. */ + { "nlt", 0xc, PROCESSOR_V850E2V3 }, /* false. */ + { "oge", 0x5, PROCESSOR_V850E2V3 }, /* false. */ + { "ogl", 0x3, PROCESSOR_V850E2V3 }, /* false. */ + { "ogt", 0x7, PROCESSOR_V850E2V3 }, /* false. */ + { "ole", 0x6, PROCESSOR_V850E2V3 }, /* true. */ + { "olt", 0x4, PROCESSOR_V850E2V3 }, /* true. */ + { "or", 0x1, PROCESSOR_V850E2V3 }, /* false. */ + { "seq", 0xa, PROCESSOR_V850E2V3 }, /* true. */ + { "sf", 0x8, PROCESSOR_V850E2V3 }, /* true. */ + { "sne", 0xa, PROCESSOR_V850E2V3 }, /* false. */ + { "st", 0x8, PROCESSOR_V850E2V3 }, /* false. */ + { "t", 0x0, PROCESSOR_V850E2V3 }, /* false. */ + { "ueq", 0x3, PROCESSOR_V850E2V3 }, /* true. */ + { "uge", 0x4, PROCESSOR_V850E2V3 }, /* false. */ + { "ugt", 0x6, PROCESSOR_V850E2V3 }, /* false. */ + { "ule", 0x7, PROCESSOR_V850E2V3 }, /* true. */ + { "ult", 0x5, PROCESSOR_V850E2V3 }, /* true. */ + { "un", 0x1, PROCESSOR_V850E2V3 }, /* true. */ +}; + +#define FLOAT_CC_NAME_CNT \ + (sizeof (float_cc_names) / sizeof (struct reg_name)) + /* Do a binary search of the given register table to see if NAME is a valid regiter name. Return the register number from the array on success, or -1 on failure. */ @@ -667,9 +878,7 @@ reg_name_search (const struct reg_name *regs, else if (accept_numbers) { int reg = S_GET_VALUE (symbolP); - - if (reg >= 0 && reg <= 31) - return reg; + return reg; } /* Otherwise drop through and try parsing name normally. */ @@ -687,7 +896,9 @@ reg_name_search (const struct reg_name *regs, else if (cmp > 0) low = middle + 1; else - return regs[middle].value; + return ((regs[middle].processors & processor_mask) + ? regs[middle].value + : -1); } while (low <= high); return -1; @@ -722,25 +933,24 @@ register_name (expressionS *expressionP) /* Put back the delimiting char. */ *input_line_pointer = c; + expressionP->X_add_symbol = NULL; + expressionP->X_op_symbol = NULL; + /* Look to see if it's in the register table. */ if (reg_number >= 0) { expressionP->X_op = O_register; expressionP->X_add_number = reg_number; - /* Make the rest nice. */ - expressionP->X_add_symbol = NULL; - expressionP->X_op_symbol = NULL; - return TRUE; } - else - { - /* Reset the line as if we had not done anything. */ - input_line_pointer = start; - return FALSE; - } + /* Reset the line as if we had not done anything. */ + input_line_pointer = start; + + expressionP->X_op = O_illegal; + + return FALSE; } /* Summary of system_register_name(). @@ -748,8 +958,6 @@ register_name (expressionS *expressionP) in: INPUT_LINE_POINTER points to 1st char of operand. EXPRESSIONP points to an expression structure to be filled in. ACCEPT_NUMBERS is true iff numerical register names may be used. - ACCEPT_LIST_NAMES is true iff the special names PS and SR may be - accepted. out: An expressionS structure in expressionP. The operand may have been a register: in this case, X_op == O_register, @@ -759,8 +967,7 @@ register_name (expressionS *expressionP) static bfd_boolean system_register_name (expressionS *expressionP, - bfd_boolean accept_numbers, - bfd_boolean accept_list_names) + bfd_boolean accept_numbers) { int reg_number; char *name; @@ -785,44 +992,28 @@ system_register_name (expressionS *expressionP, if (ISDIGIT (*input_line_pointer)) { - reg_number = strtol (input_line_pointer, &input_line_pointer, 10); - - /* Make sure that the register number is allowable. */ - if (reg_number < 0 - || (reg_number > 5 && reg_number < 16) - || reg_number > 27) - reg_number = -1; - } - else if (accept_list_names) - { - c = get_symbol_end (); - reg_number = reg_name_search (system_list_registers, - SYSREGLIST_NAME_CNT, name, FALSE); - - /* Put back the delimiting char. */ - *input_line_pointer = c; + reg_number = strtol (input_line_pointer, &input_line_pointer, 0); } } + expressionP->X_add_symbol = NULL; + expressionP->X_op_symbol = NULL; + /* Look to see if it's in the register table. */ if (reg_number >= 0) { expressionP->X_op = O_register; expressionP->X_add_number = reg_number; - /* Make the rest nice. */ - expressionP->X_add_symbol = NULL; - expressionP->X_op_symbol = NULL; - return TRUE; } - else - { - /* Reset the line as if we had not done anything. */ - input_line_pointer = start; - return FALSE; - } + /* Reset the line as if we had not done anything. */ + input_line_pointer = start; + + expressionP->X_op = O_illegal; + + return FALSE; } /* Summary of cc_name(). @@ -836,7 +1027,8 @@ system_register_name (expressionS *expressionP, its original state. */ static bfd_boolean -cc_name (expressionS *expressionP) +cc_name (expressionS *expressionP, + bfd_boolean accept_numbers) { int reg_number; char *name; @@ -847,30 +1039,93 @@ cc_name (expressionS *expressionP) start = name = input_line_pointer; c = get_symbol_end (); - reg_number = reg_name_search (cc_names, CC_NAME_CNT, name, FALSE); + reg_number = reg_name_search (cc_names, CC_NAME_CNT, name, accept_numbers); /* Put back the delimiting char. */ *input_line_pointer = c; + if (reg_number < 0 + && accept_numbers) + { + /* Reset input_line pointer. */ + input_line_pointer = start; + + if (ISDIGIT (*input_line_pointer)) + { + reg_number = strtol (input_line_pointer, &input_line_pointer, 0); + } + } + + expressionP->X_add_symbol = NULL; + expressionP->X_op_symbol = NULL; + /* Look to see if it's in the register table. */ if (reg_number >= 0) { expressionP->X_op = O_constant; expressionP->X_add_number = reg_number; - /* Make the rest nice. */ - expressionP->X_add_symbol = NULL; - expressionP->X_op_symbol = NULL; - return TRUE; } - else + + /* Reset the line as if we had not done anything. */ + input_line_pointer = start; + + expressionP->X_op = O_illegal; + expressionP->X_add_number = 0; + + return FALSE; +} + +static bfd_boolean +float_cc_name (expressionS *expressionP, + bfd_boolean accept_numbers) +{ + int reg_number; + char *name; + char *start; + char c; + + /* Find the spelling of the operand. */ + start = name = input_line_pointer; + + c = get_symbol_end (); + reg_number = reg_name_search (float_cc_names, FLOAT_CC_NAME_CNT, name, accept_numbers); + + /* Put back the delimiting char. */ + *input_line_pointer = c; + + if (reg_number < 0 + && accept_numbers) { - /* Reset the line as if we had not done anything. */ + /* Reset input_line pointer. */ input_line_pointer = start; - return FALSE; + if (ISDIGIT (*input_line_pointer)) + { + reg_number = strtol (input_line_pointer, &input_line_pointer, 0); + } + } + + expressionP->X_add_symbol = NULL; + expressionP->X_op_symbol = NULL; + + /* Look to see if it's in the register table. */ + if (reg_number >= 0) + { + expressionP->X_op = O_constant; + expressionP->X_add_number = reg_number; + + return TRUE; } + + /* Reset the line as if we had not done anything. */ + input_line_pointer = start; + + expressionP->X_op = O_illegal; + expressionP->X_add_number = 0; + + return FALSE; } static void @@ -915,16 +1170,7 @@ parse_register_list (unsigned long *insn, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 }; - static int type2_regs[32] = - { - 19, 18, 17, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 30, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 - }; - static int type3_regs[32] = - { - 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 14, 15, 13, 12, 7, 6, 5, 4, 11, 10, 9, 8 - }; + int *regs; expressionS exp; @@ -932,8 +1178,6 @@ parse_register_list (unsigned long *insn, switch (operand->shift) { case 0xffe00001: regs = type1_regs; break; - case 0xfff8000f: regs = type2_regs; break; - case 0xfff8001f: regs = type3_regs; break; default: as_bad (_("unknown operand shift: %x\n"), operand->shift); return _("internal failure in parse_register_list"); @@ -967,41 +1211,6 @@ parse_register_list (unsigned long *insn, *insn |= (1 << i); } } - else if (regs == type2_regs) - { - if (exp.X_add_number & 0xFFFE0000) - return _("high bits set in register list expression"); - - for (reg = 1; reg < 16; reg++) - if (exp.X_add_number & (1 << (reg - 1))) - { - for (i = 0; i < 32; i++) - if (regs[i] == reg) - *insn |= (1 << i); - } - - if (exp.X_add_number & (1 << 15)) - *insn |= (1 << 3); - - if (exp.X_add_number & (1 << 16)) - *insn |= (1 << 19); - } - else /* regs == type3_regs */ - { - if (exp.X_add_number & 0xFFFE0000) - return _("high bits set in register list expression"); - - for (reg = 16; reg < 32; reg++) - if (exp.X_add_number & (1 << (reg - 16))) - { - for (i = 0; i < 32; i++) - if (regs[i] == reg) - *insn |= (1 << i); - } - - if (exp.X_add_number & (1 << 16)) - *insn |= (1 << 19); - } return NULL; } @@ -1012,6 +1221,8 @@ parse_register_list (unsigned long *insn, new-line) is found. */ for (;;) { + skip_white_space (); + if (register_name (&exp)) { int i; @@ -1030,25 +1241,15 @@ parse_register_list (unsigned long *insn, if (i == 32) return _("illegal register included in list"); } - else if (system_register_name (&exp, TRUE, TRUE)) + else if (system_register_name (&exp, TRUE)) { if (regs == type1_regs) { return _("system registers cannot be included in list"); } - else if (exp.X_add_number == 5) - { - if (regs == type2_regs) - return _("PSW cannot be included in list"); - else - *insn |= 0x8; - } - else if (exp.X_add_number < 4) - *insn |= 0x80000; - else - return _("High value system registers cannot be included in list"); } - else if (*input_line_pointer == '}') + + if (*input_line_pointer == '}') { input_line_pointer++; break; @@ -1071,7 +1272,11 @@ parse_register_list (unsigned long *insn, if (! register_name (&exp2)) { return _("second register should follow dash in register list"); - exp2.X_add_number = exp.X_add_number; + } + + if (exp.X_add_number > exp2.X_add_number) + { + return _("second register should greater tahn first register"); } /* Add the rest of the registers in the range. */ @@ -1093,11 +1298,11 @@ parse_register_list (unsigned long *insn, if (i == 32) return _("illegal register included in list"); } + + exp = exp2; } else break; - - skip_white_space (); } return NULL; @@ -1107,6 +1312,10 @@ const char *md_shortopts = "m:"; struct option md_longopts[] = { +#define OPTION_DISP_SIZE_DEFAULT_22 (OPTION_MD_BASE) + {"disp-size-default-22", no_argument, NULL, OPTION_DISP_SIZE_DEFAULT_22}, +#define OPTION_DISP_SIZE_DEFAULT_32 (OPTION_MD_BASE + 1) + {"disp-size-default-32", no_argument, NULL, OPTION_DISP_SIZE_DEFAULT_32}, {NULL, no_argument, NULL, 0} }; @@ -1121,15 +1330,33 @@ md_show_usage (FILE *stream) fprintf (stream, _(" -mv850 The code is targeted at the v850\n")); fprintf (stream, _(" -mv850e The code is targeted at the v850e\n")); fprintf (stream, _(" -mv850e1 The code is targeted at the v850e1\n")); - fprintf (stream, _(" -mv850any The code is generic, despite any processor specific instructions\n")); + fprintf (stream, _(" -mv850e2 The code is targeted at the v850e2\n")); + fprintf (stream, _(" -mv850e2v3 The code is targeted at the v850e2v3\n")); fprintf (stream, _(" -mrelax Enable relaxation\n")); + fprintf (stream, _(" --disp-size-default-22 branch displacement with unknown size is 22 bits (default)\n")); + fprintf (stream, _(" --disp-size-default-32 branch displacement with unknown size is 32 bits\n")); + fprintf (stream, _(" -mextension enable extension opcode support\n")); + fprintf (stream, _(" -mno-bcond17 disable b disp17 instruction\n")); + fprintf (stream, _(" -mno-stld23 disable st/ld offset23 instruction\n")); } int md_parse_option (int c, char *arg) { if (c != 'm') - return 0; + { + switch (c) + { + case OPTION_DISP_SIZE_DEFAULT_22: + default_disp_size = 22; + return 1; + + case OPTION_DISP_SIZE_DEFAULT_32: + default_disp_size = 32; + return 1; + } + return 0; + } if (strcmp (arg, "warn-signed-overflow") == 0) warn_signed_overflows = TRUE; @@ -1140,26 +1367,39 @@ md_parse_option (int c, char *arg) else if (strcmp (arg, "v850") == 0) { machine = 0; - processor_mask = PROCESSOR_V850; + SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850); } else if (strcmp (arg, "v850e") == 0) { machine = bfd_mach_v850e; - processor_mask = PROCESSOR_V850E; + SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E); } else if (strcmp (arg, "v850e1") == 0) { machine = bfd_mach_v850e1; - processor_mask = PROCESSOR_V850E1; + SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E1); } - else if (strcmp (arg, "v850any") == 0) + else if (strcmp (arg, "v850e2") == 0) { - /* Tell the world that this is for any v850 chip. */ - machine = 0; - - /* But support instructions for the extended versions. */ - processor_mask = PROCESSOR_V850E; - processor_mask |= PROCESSOR_V850E1; + machine = bfd_mach_v850e2; + SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E2); + } + else if (strcmp (arg, "v850e2v3") == 0) + { + machine = bfd_mach_v850e2v3; + SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E2V3); + } + else if (strcmp (arg, "extension") == 0) + { + processor_mask |= PROCESSOR_OPTION_EXTENSION | PROCESSOR_OPTION_ALIAS;; + } + else if (strcmp (arg, "no-bcond17") == 0) + { + no_bcond17 = 1; + } + else if (strcmp (arg, "no-stld23") == 0) + { + no_stld23 = 1; } else if (strcmp (arg, "relax") == 0) v850_relax = 1; @@ -1188,13 +1428,6 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, fragS *fragP) { - /* This code performs some nasty type punning between the - fr_opcode field of the frag structure (a char *) and the - fx_r_type field of the fix structure (a bfd_reloc_code_real_type) - On a 64bit host this causes problems because these two fields - are not the same size, but since we know that we are only - ever storing small integers in the fields, it is safe to use - a union to convert between them. */ union u { bfd_reloc_code_real_type fx_r_type; @@ -1204,17 +1437,52 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, subseg_change (sec, 0); opcode_converter.fr_opcode = fragP->fr_opcode; - + + subseg_change (sec, 0); + /* In range conditional or unconditional branch. */ - if (fragP->fr_subtype == 0 || fragP->fr_subtype == 2) + if (fragP->fr_subtype == SUBYPTE_COND_9_22 + || fragP->fr_subtype == SUBYPTE_UNCOND_9_22 + || fragP->fr_subtype == SUBYPTE_COND_9_22_32 + || fragP->fr_subtype == SUBYPTE_UNCOND_9_22_32 + || fragP->fr_subtype == SUBYPTE_COND_9_17_22 + || fragP->fr_subtype == SUBYPTE_COND_9_17_22_32 + || fragP->fr_subtype == SUBYPTE_SA_9_22 + || fragP->fr_subtype == SUBYPTE_SA_9_22_32 + || fragP->fr_subtype == SUBYPTE_SA_9_17_22 + || fragP->fr_subtype == SUBYPTE_SA_9_17_22_32) + { fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset, 1, BFD_RELOC_UNUSED + opcode_converter.fx_r_type); fragP->fr_fix += 2; } - /* Out of range conditional branch. Emit a branch around a jump. */ - else if (fragP->fr_subtype == 1) + /* V850e2r-v3 17bit conditional branch. */ + else if (fragP->fr_subtype == SUBYPTE_COND_9_17_22 + 1 + || fragP->fr_subtype == SUBYPTE_COND_9_17_22_32 + 1 + || fragP->fr_subtype == SUBYPTE_SA_9_17_22 + 1 + || fragP->fr_subtype == SUBYPTE_SA_9_17_22_32 + 1) + { + unsigned char *buffer = + (unsigned char *) (fragP->fr_fix + fragP->fr_literal); + + buffer[0] &= 0x0f; /* Use condition. */ + buffer[0] |= 0xe0; + buffer[1] = 0x07; + + /* Now create the unconditional branch + fixup to the final + target. */ + md_number_to_chars ((char *) buffer + 2, 0x0001, 2); + fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, + fragP->fr_offset, 1, BFD_RELOC_V850_17_PCREL); + fragP->fr_fix += 4; + } + /* Out of range conditional branch. Emit a branch around a 22bit jump. */ + else if (fragP->fr_subtype == SUBYPTE_COND_9_22 + 1 + || fragP->fr_subtype == SUBYPTE_COND_9_22_32 + 1 + || fragP->fr_subtype == SUBYPTE_COND_9_17_22 + 2 + || fragP->fr_subtype == SUBYPTE_COND_9_17_22_32 + 2) { unsigned char *buffer = (unsigned char *) (fragP->fr_fix + fragP->fr_literal); @@ -1232,19 +1500,99 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, target. */ md_number_to_chars ((char *) buffer + 2, 0x00000780, 4); fix_new (fragP, fragP->fr_fix + 2, 4, fragP->fr_symbol, - fragP->fr_offset, 1, - BFD_RELOC_UNUSED + opcode_converter.fx_r_type + 1); + fragP->fr_offset, 1, BFD_RELOC_V850_22_PCREL); fragP->fr_fix += 6; } - /* Out of range unconditional branch. Emit a jump. */ - else if (fragP->fr_subtype == 3) + /* Out of range conditional branch. Emit a branch around a 32bit jump. */ + else if (fragP->fr_subtype == SUBYPTE_COND_9_22_32 + 2 + || fragP->fr_subtype == SUBYPTE_COND_9_17_22_32 + 3) + { + unsigned char *buffer = + (unsigned char *) (fragP->fr_fix + fragP->fr_literal); + + /* Reverse the condition of the first branch. */ + buffer[0] ^= 0x08; + /* Mask off all the displacement bits. */ + buffer[0] &= 0x8f; + buffer[1] &= 0x07; + /* Now set the displacement bits so that we branch + around the unconditional branch. */ + buffer[0] |= 0x40; + + /* Now create the unconditional branch + fixup to the final + target. */ + md_number_to_chars ((char *) buffer + 2, 0x02e0, 2); + fix_new (fragP, fragP->fr_fix + 4, 4, fragP->fr_symbol, + fragP->fr_offset + 2, 1, BFD_RELOC_V850_32_PCREL); + fragP->fr_fix += 8; + } + /* Out of range unconditional branch. Emit a 22bit jump. */ + else if (fragP->fr_subtype == SUBYPTE_UNCOND_9_22 + 1 + || fragP->fr_subtype == SUBYPTE_UNCOND_9_22_32 + 1) { md_number_to_chars (fragP->fr_fix + fragP->fr_literal, 0x00000780, 4); fix_new (fragP, fragP->fr_fix, 4, fragP->fr_symbol, - fragP->fr_offset, 1, - BFD_RELOC_UNUSED + opcode_converter.fx_r_type + 1); + fragP->fr_offset, 1, BFD_RELOC_V850_22_PCREL); fragP->fr_fix += 4; } + /* Out of range unconditional branch. Emit a 32bit jump. */ + else if (fragP->fr_subtype == SUBYPTE_UNCOND_9_22_32 + 2) + { + md_number_to_chars (fragP->fr_fix + fragP->fr_literal, 0x02e0, 2); + fix_new (fragP, fragP->fr_fix + 4, 4, fragP->fr_symbol, + fragP->fr_offset + 2, 1, BFD_RELOC_V850_32_PCREL); + fragP->fr_fix += 6; + } + /* Out of range SA conditional branch. Emit a branch to a 22bit jump. */ + else if (fragP->fr_subtype == SUBYPTE_SA_9_22 + 1 + || fragP->fr_subtype == SUBYPTE_SA_9_22_32 + 1 + || fragP->fr_subtype == SUBYPTE_SA_9_17_22 + 2 + || fragP->fr_subtype == SUBYPTE_SA_9_17_22_32 + 2) + { + unsigned char *buffer = + (unsigned char *) (fragP->fr_fix + fragP->fr_literal); + + /* bsa .+4 */ + buffer[0] &= 0x8f; + buffer[0] |= 0x20; + buffer[1] &= 0x07; + + /* br .+6 */ + md_number_to_chars ((char *) buffer + 2, 0x05b5, 2); + + /* Now create the unconditional branch + fixup to the final + target. */ + /* jr SYM */ + md_number_to_chars ((char *) buffer + 4, 0x00000780, 4); + fix_new (fragP, fragP->fr_fix + 4, 4, fragP->fr_symbol, + fragP->fr_offset, 1, + BFD_RELOC_V850_22_PCREL); + fragP->fr_fix += 8; + } + /* Out of range SA conditional branch. Emit a branch around a 32bit jump. */ + else if (fragP->fr_subtype == SUBYPTE_SA_9_22_32 + 2 + || fragP->fr_subtype == SUBYPTE_SA_9_17_22_32 + 3) + { + unsigned char *buffer = + (unsigned char *) (fragP->fr_fix + fragP->fr_literal); + + /* bsa .+2 */ + buffer[0] &= 0x8f; + buffer[0] |= 0x20; + buffer[1] &= 0x07; + + /* br .+8 */ + md_number_to_chars ((char *) buffer + 2, 0x05c5, 2); + + /* Now create the unconditional branch + fixup to the final + target. */ + /* jr SYM */ + md_number_to_chars ((char *) buffer + 4, 0x02e0, 2); + fix_new (fragP, fragP->fr_fix + 6, 4, fragP->fr_symbol, + fragP->fr_offset + 2, 1, BFD_RELOC_V850_32_PCREL); + + fragP->fr_fix += 10; + } else abort (); } @@ -1262,29 +1610,45 @@ md_begin (void) char *prev_name = ""; const struct v850_opcode *op; - if (strncmp (TARGET_CPU, "v850e1", 6) == 0) + if (strncmp (TARGET_CPU, "v850e2v3", 8) == 0) + { + if (machine == -1) + machine = bfd_mach_v850e2v3; + + if (!processor_mask) + SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E2V3); + } + else if (strncmp (TARGET_CPU, "v850e2", 6) == 0) + { + if (machine == -1) + machine = bfd_mach_v850e2; + + if (!processor_mask) + SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E2); + } + else if (strncmp (TARGET_CPU, "v850e1", 6) == 0) { if (machine == -1) - machine = bfd_mach_v850e1; + machine = bfd_mach_v850e1; - if (processor_mask == -1) - processor_mask = PROCESSOR_V850E1; + if (!processor_mask) + SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E1); } else if (strncmp (TARGET_CPU, "v850e", 5) == 0) { if (machine == -1) machine = bfd_mach_v850e; - if (processor_mask == -1) - processor_mask = PROCESSOR_V850E; + if (!processor_mask) + SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850E); } else if (strncmp (TARGET_CPU, "v850", 4) == 0) { if (machine == -1) machine = 0; - if (processor_mask == -1) - processor_mask = PROCESSOR_V850; + if (!processor_mask) + SET_PROCESSOR_MASK (processor_mask, PROCESSOR_V850); } else /* xgettext:c-format */ @@ -1312,152 +1676,192 @@ md_begin (void) bfd_set_arch_mach (stdoutput, TARGET_ARCH, machine); } + static bfd_reloc_code_real_type -handle_lo16 (const struct v850_operand *operand) +handle_hi016 (const struct v850_operand *operand, const char **errmsg) { - if (operand != NULL) - { - if (operand->bits == -1) - return BFD_RELOC_V850_LO16_SPLIT_OFFSET; + if (operand == NULL) + return BFD_RELOC_HI16; - if (!(operand->bits == 16 && operand->shift == 16) - && !(operand->bits == 15 && operand->shift == 17)) - { - as_bad (_("lo() relocation used on an instruction which does " - "not support it")); - return BFD_RELOC_64; /* Used to indicate an error condition. */ - } - } - return BFD_RELOC_LO16; + if (operand->default_reloc == BFD_RELOC_HI16) + return BFD_RELOC_HI16; + + if (operand->default_reloc == BFD_RELOC_HI16_S) + return BFD_RELOC_HI16; + + if (operand->default_reloc == BFD_RELOC_16) + return BFD_RELOC_HI16; + + *errmsg = _("hi0() relocation used on an instruction which does " + "not support it"); + return BFD_RELOC_64; /* Used to indicate an error condition. */ } static bfd_reloc_code_real_type -handle_ctoff (const struct v850_operand *operand) +handle_hi16 (const struct v850_operand *operand, const char **errmsg) { if (operand == NULL) - return BFD_RELOC_V850_CALLT_16_16_OFFSET; + return BFD_RELOC_HI16_S; - if (operand->bits != 6 - || operand->shift != 0) - { - as_bad (_("ctoff() relocation used on an instruction which does not support it")); - return BFD_RELOC_64; /* Used to indicate an error condition. */ - } + if (operand->default_reloc == BFD_RELOC_HI16_S) + return BFD_RELOC_HI16_S; + + if (operand->default_reloc == BFD_RELOC_HI16) + return BFD_RELOC_HI16_S; + + if (operand->default_reloc == BFD_RELOC_16) + return BFD_RELOC_HI16_S; - return BFD_RELOC_V850_CALLT_6_7_OFFSET; + *errmsg = _("hi() relocation used on an instruction which does " + "not support it"); + return BFD_RELOC_64; /* Used to indicate an error condition. */ } static bfd_reloc_code_real_type -handle_sdaoff (const struct v850_operand *operand) +handle_lo16 (const struct v850_operand *operand, const char **errmsg) { if (operand == NULL) - return BFD_RELOC_V850_SDA_16_16_OFFSET; + return BFD_RELOC_LO16; - if (operand->bits == 15 && operand->shift == 17) - return BFD_RELOC_V850_SDA_15_16_OFFSET; + if (operand->default_reloc == BFD_RELOC_LO16) + return BFD_RELOC_LO16; - if (operand->bits == -1) - return BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET; + if (operand->default_reloc == BFD_RELOC_V850_16_SPLIT_OFFSET) + return BFD_RELOC_V850_LO16_SPLIT_OFFSET; - if (operand->bits != 16 - || operand->shift != 16) - { - as_bad (_("sdaoff() relocation used on an instruction which does not support it")); - return BFD_RELOC_64; /* Used to indicate an error condition. */ - } + if (operand->default_reloc == BFD_RELOC_V850_16_S1) + return BFD_RELOC_V850_LO16_S1; + + if (operand->default_reloc == BFD_RELOC_16) + return BFD_RELOC_LO16; - return BFD_RELOC_V850_SDA_16_16_OFFSET; + *errmsg = _("lo() relocation used on an instruction which does " + "not support it"); + return BFD_RELOC_64; /* Used to indicate an error condition. */ } static bfd_reloc_code_real_type -handle_zdaoff (const struct v850_operand *operand) +handle_ctoff (const struct v850_operand *operand, const char **errmsg) { if (operand == NULL) - return BFD_RELOC_V850_ZDA_16_16_OFFSET; + return BFD_RELOC_V850_CALLT_16_16_OFFSET; - if (operand->bits == 15 && operand->shift == 17) - return BFD_RELOC_V850_ZDA_15_16_OFFSET; + if (operand->default_reloc == BFD_RELOC_V850_CALLT_6_7_OFFSET) + return operand->default_reloc; - if (operand->bits == -1) - return BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET; + if (operand->default_reloc == BFD_RELOC_V850_16_S1) + return BFD_RELOC_V850_CALLT_15_16_OFFSET; - if (operand->bits != 16 - || operand->shift != 16) - { - as_bad (_("zdaoff() relocation used on an instruction which does not support it")); - /* Used to indicate an error condition. */ - return BFD_RELOC_64; - } + if (operand->default_reloc == BFD_RELOC_16) + return BFD_RELOC_V850_CALLT_16_16_OFFSET; - return BFD_RELOC_V850_ZDA_16_16_OFFSET; + *errmsg = _("ctoff() relocation used on an instruction which does not support it"); + return BFD_RELOC_64; /* Used to indicate an error condition. */ } static bfd_reloc_code_real_type -handle_tdaoff (const struct v850_operand *operand) +handle_sdaoff (const struct v850_operand *operand, const char **errmsg) { if (operand == NULL) - /* Data item, not an instruction. */ - return BFD_RELOC_V850_TDA_7_7_OFFSET; - - if (operand->bits == 6 && operand->shift == 1) - /* sld.w/sst.w, operand: D8_6. */ - return BFD_RELOC_V850_TDA_6_8_OFFSET; - - if (operand->bits == 4 && operand->insert != NULL) - /* sld.hu, operand: D5-4. */ - return BFD_RELOC_V850_TDA_4_5_OFFSET; + return BFD_RELOC_V850_SDA_16_16_OFFSET; - if (operand->bits == 4 && operand->insert == NULL) - /* sld.bu, operand: D4. */ - return BFD_RELOC_V850_TDA_4_4_OFFSET; + if (operand->default_reloc == BFD_RELOC_V850_16_SPLIT_OFFSET) + return BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET; - if (operand->bits == 16 && operand->shift == 16) - /* set1 & chums, operands: D16. */ - return BFD_RELOC_V850_TDA_16_16_OFFSET; + if (operand->default_reloc == BFD_RELOC_16) + return BFD_RELOC_V850_SDA_16_16_OFFSET; - if (operand->bits != 7) - { - as_bad (_("tdaoff() relocation used on an instruction which does not support it")); - /* Used to indicate an error condition. */ - return BFD_RELOC_64; - } + if (operand->default_reloc == BFD_RELOC_V850_16_S1) + return BFD_RELOC_V850_SDA_15_16_OFFSET; - return operand->insert != NULL - ? BFD_RELOC_V850_TDA_7_8_OFFSET /* sld.h/sst.h, operand: D8_7. */ - : BFD_RELOC_V850_TDA_7_7_OFFSET; /* sld.b/sst.b, operand: D7. */ + *errmsg = _("sdaoff() relocation used on an instruction which does not support it"); + return BFD_RELOC_64; /* Used to indicate an error condition. */ } -/* Warning: The code in this function relies upon the definitions - in the v850_operands[] array (defined in opcodes/v850-opc.c) - matching the hard coded values contained herein. */ - static bfd_reloc_code_real_type -v850_reloc_prefix (const struct v850_operand *operand) +handle_zdaoff (const struct v850_operand *operand, const char **errmsg) { - bfd_boolean paren_skipped = FALSE; + if (operand == NULL) + return BFD_RELOC_V850_ZDA_16_16_OFFSET; - /* Skip leading opening parenthesis. */ - if (*input_line_pointer == '(') - { - ++input_line_pointer; - paren_skipped = TRUE; - } + if (operand->default_reloc == BFD_RELOC_V850_16_SPLIT_OFFSET) + return BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET; -#define CHECK_(name, reloc) \ + if (operand->default_reloc == BFD_RELOC_16) + return BFD_RELOC_V850_ZDA_16_16_OFFSET; + + if (operand->default_reloc == BFD_RELOC_V850_16_S1) + return BFD_RELOC_V850_ZDA_15_16_OFFSET; + + *errmsg = _("zdaoff() relocation used on an instruction which does not support it"); + return BFD_RELOC_64; /* Used to indicate an error condition. */ +} + +static bfd_reloc_code_real_type +handle_tdaoff (const struct v850_operand *operand, const char **errmsg) +{ + if (operand == NULL) + /* Data item, not an instruction. */ + return BFD_RELOC_V850_TDA_16_16_OFFSET; + + switch (operand->default_reloc) + { + /* sld.hu, operand: D5-4. */ + case BFD_RELOC_V850_TDA_4_5_OFFSET: + /* sld.bu, operand: D4. */ + case BFD_RELOC_V850_TDA_4_4_OFFSET: + /* sld.w/sst.w, operand: D8_6. */ + case BFD_RELOC_V850_TDA_6_8_OFFSET: + /* sld.h/sst.h, operand: D8_7. */ + case BFD_RELOC_V850_TDA_7_8_OFFSET: + /* sld.b/sst.b, operand: D7. */ + case BFD_RELOC_V850_TDA_7_7_OFFSET: + return operand->default_reloc; + default: + break; + } + + if (operand->default_reloc == BFD_RELOC_16 && operand->shift == 16) + /* set1 & chums, operands: D16. */ + return BFD_RELOC_V850_TDA_16_16_OFFSET; + + *errmsg = _("tdaoff() relocation used on an instruction which does not support it"); + /* Used to indicate an error condition. */ + return BFD_RELOC_64; +} + +/* Warning: The code in this function relies upon the definitions + in the v850_operands[] array (defined in opcodes/v850-opc.c) + matching the hard coded values contained herein. */ + +static bfd_reloc_code_real_type +v850_reloc_prefix (const struct v850_operand *operand, const char **errmsg) +{ + bfd_boolean paren_skipped = FALSE; + + /* Skip leading opening parenthesis. */ + if (*input_line_pointer == '(') + { + ++input_line_pointer; + paren_skipped = TRUE; + } + +#define CHECK_(name, reloc) \ if (strncmp (input_line_pointer, name "(", strlen (name) + 1) == 0) \ { \ input_line_pointer += strlen (name); \ return reloc; \ } - CHECK_ ("hi0", BFD_RELOC_HI16 ); - CHECK_ ("hi", BFD_RELOC_HI16_S ); - CHECK_ ("lo", handle_lo16 (operand) ); - CHECK_ ("sdaoff", handle_sdaoff (operand)); - CHECK_ ("zdaoff", handle_zdaoff (operand)); - CHECK_ ("tdaoff", handle_tdaoff (operand)); - CHECK_ ("hilo", BFD_RELOC_32 ); - CHECK_ ("ctoff", handle_ctoff (operand) ); + CHECK_ ("hi0", handle_hi016(operand, errmsg) ); + CHECK_ ("hi", handle_hi16(operand, errmsg) ); + CHECK_ ("lo", handle_lo16 (operand, errmsg) ); + CHECK_ ("sdaoff", handle_sdaoff (operand, errmsg)); + CHECK_ ("zdaoff", handle_zdaoff (operand, errmsg)); + CHECK_ ("tdaoff", handle_tdaoff (operand, errmsg)); + CHECK_ ("hilo", BFD_RELOC_32); + CHECK_ ("lo23", BFD_RELOC_V850_23); + CHECK_ ("ctoff", handle_ctoff (operand, errmsg) ); /* Restore skipped parenthesis. */ if (paren_skipped) @@ -1472,9 +1876,7 @@ static unsigned long v850_insert_operand (unsigned long insn, const struct v850_operand *operand, offsetT val, - char *file, - unsigned int line, - char *str) + const char **errmsg) { if (operand->insert) { @@ -1485,35 +1887,33 @@ v850_insert_operand (unsigned long insn, { if ((operand->flags & V850_OPERAND_SIGNED) && ! warn_signed_overflows - && strstr (message, "out of range") != NULL) + && v850_msg_is_out_of_range (message)) { /* Skip warning... */ } else if ((operand->flags & V850_OPERAND_SIGNED) == 0 && ! warn_unsigned_overflows - && strstr (message, "out of range") != NULL) + && v850_msg_is_out_of_range (message)) { /* Skip warning... */ } - else if (str) - { - if (file == (char *) NULL) - as_warn ("%s: %s", str, message); - else - as_warn_where (file, line, "%s: %s", str, message); - } else { - if (file == (char *) NULL) - as_warn ("%s", message); - else - as_warn_where (file, line, "%s", message); + if (errmsg != NULL) + *errmsg = message; } } } + else if (operand->bits == -1 + || operand->flags & V850E_IMMEDIATE16 + || operand->flags & V850E_IMMEDIATE23 + || operand->flags & V850E_IMMEDIATE32) + { + abort (); + } else { - if (operand->bits != 32) + if (operand->bits < 32) { long min, max; @@ -1566,17 +1966,17 @@ v850_insert_operand (unsigned long insn, && ! warn_unsigned_overflows) min = 0; - if (str) - sprintf (buf, "%s: ", str); - else - buf[0] = 0; - strcat (buf, _("operand")); - - as_bad_value_out_of_range (buf, val, (offsetT) min, (offsetT) max, file, line); + sprintf (buf, _("operand out of range (%d is not between %d and %d)"), + (int) val, (int) min, (int) max); + *errmsg = buf; } - } - insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift); + insn |= (((long) val & ((1 << operand->bits) - 1)) << operand->shift); + } + else + { + insn |= (((long) val) << operand->shift); + } } return insn; @@ -1603,8 +2003,11 @@ md_assemble (char *str) unsigned extra_data_len = 0; unsigned long extra_data = 0; char *saved_input_line_pointer; + char most_match_errmsg[1024]; + int most_match_count = -1; strncpy (copy_of_instruction, str, sizeof (copy_of_instruction) - 1); + most_match_errmsg[0] = 0; /* Get the opcode. */ for (s = str; *s != '\0' && ! ISSPACE (*s); s++) @@ -1634,10 +2037,26 @@ md_assemble (char *str) for (;;) { const char *errmsg = NULL; + const char *warningmsg = NULL; match = 0; + opindex_ptr = opcode->operands; - if ((opcode->processors & processor_mask) == 0) + if (no_stld23) + { + if ((strncmp (opcode->name, "st.", 3) == 0 + && v850_operands[opcode->operands[1]].bits == 23) + || (strncmp (opcode->name, "ld.", 3) == 0 + && v850_operands[opcode->operands[0]].bits == 23)) + { + errmsg = _("st/ld offset 23 instruction was disabled ."); + goto error; + } + } + + if ((opcode->processors & processor_mask & PROCESSOR_MASK) == 0 + || (((opcode->processors & ~PROCESSOR_MASK) != 0) + && ((opcode->processors & processor_mask & ~PROCESSOR_MASK) == 0))) { errmsg = _("Target processor does not support this instruction."); goto error; @@ -1647,6 +2066,7 @@ md_assemble (char *str) fc = 0; next_opindex = 0; insn = opcode->opcode; + extra_data_len = 0; extra_data_after_insn = FALSE; input_line_pointer = str = start_of_operands; @@ -1668,7 +2088,20 @@ md_assemble (char *str) errmsg = NULL; - while (*str == ' ' || *str == ',' || *str == '[' || *str == ']') + while (*str == ' ') + ++str; + + if (operand->flags & V850_OPERAND_BANG + && *str == '!') + ++str; + else if (operand->flags & V850_OPERAND_PERCENT + && *str == '%') + ++str; + + if (*str == ',' || *str == '[' || *str == ']') + ++str; + + while (*str == ' ') ++str; if (operand->flags & V850_OPERAND_RELAX) @@ -1679,12 +2112,12 @@ md_assemble (char *str) input_line_pointer = str; /* lo(), hi(), hi0(), etc... */ - if ((reloc = v850_reloc_prefix (operand)) != BFD_RELOC_UNUSED) + if ((reloc = v850_reloc_prefix (operand, &errmsg)) != BFD_RELOC_UNUSED) { /* This is a fake reloc, used to indicate an error condition. */ if (reloc == BFD_RELOC_64) { - match = 1; + /* match = 1; */ goto error; } @@ -1695,11 +2128,14 @@ md_assemble (char *str) switch (reloc) { case BFD_RELOC_V850_ZDA_16_16_OFFSET: + case BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET: + case BFD_RELOC_V850_ZDA_15_16_OFFSET: /* To cope with "not1 7, zdaoff(0xfffff006)[r0]" and the like. */ /* Fall through. */ case BFD_RELOC_LO16: + case BFD_RELOC_V850_LO16_S1: case BFD_RELOC_V850_LO16_SPLIT_OFFSET: { /* Truncate, then sign extend the value. */ @@ -1725,16 +2161,23 @@ md_assemble (char *str) break; } + case BFD_RELOC_V850_23: + if ((operand->flags & V850E_IMMEDIATE23) == 0) + { + errmsg = _("immediate operand is too large"); + goto error; + } + break; + case BFD_RELOC_32: + case BFD_RELOC_V850_32_ABS: + case BFD_RELOC_V850_32_PCREL: if ((operand->flags & V850E_IMMEDIATE32) == 0) { errmsg = _("immediate operand is too large"); goto error; } - extra_data_after_insn = TRUE; - extra_data_len = 4; - extra_data = 0; break; default: @@ -1743,6 +2186,45 @@ md_assemble (char *str) break; } + if (operand->flags & V850E_IMMEDIATE32) + { + extra_data_after_insn = TRUE; + extra_data_len = 4; + extra_data = 0; + } + else if (operand->flags & V850E_IMMEDIATE23) + { + if (reloc != BFD_RELOC_V850_23) + { + errmsg = _("immediate operand is too large"); + goto error; + } + extra_data_after_insn = TRUE; + extra_data_len = 2; + extra_data = 0; + } + else if ((operand->flags & V850E_IMMEDIATE16) + || (operand->flags & V850E_IMMEDIATE16HI)) + { + if (operand->flags & V850E_IMMEDIATE16HI + && reloc != BFD_RELOC_HI16 + && reloc != BFD_RELOC_HI16_S) + { + errmsg = _("immediate operand is too large"); + goto error; + } + else if (operand->flags & V850E_IMMEDIATE16 + && reloc != BFD_RELOC_LO16) + { + errmsg = _("immediate operand is too large"); + goto error; + } + + extra_data_after_insn = TRUE; + extra_data_len = 2; + extra_data = 0; + } + if (fc > MAX_INSN_FIXUPS) as_fatal (_("too many fixups")); @@ -1751,19 +2233,67 @@ md_assemble (char *str) fixups[fc].reloc = reloc; fc++; } - else + else /* ex.X_op != O_constant. */ { - if (reloc == BFD_RELOC_32) + if ((reloc == BFD_RELOC_32 + || reloc == BFD_RELOC_V850_32_ABS + || reloc == BFD_RELOC_V850_32_PCREL) + && operand->bits < 32) { - if ((operand->flags & V850E_IMMEDIATE32) == 0) + errmsg = _("immediate operand is too large"); + goto error; + } + else if (reloc == BFD_RELOC_V850_23 + && (operand->flags & V850E_IMMEDIATE23) == 0) + { + errmsg = _("immediate operand is too large"); + goto error; + } + else if ((reloc == BFD_RELOC_HI16 + || reloc == BFD_RELOC_HI16_S) + && operand->bits < 16) + { + errmsg = _("immediate operand is too large"); + goto error; + } + + if (operand->flags & V850E_IMMEDIATE32) + { + extra_data_after_insn = TRUE; + extra_data_len = 4; + extra_data = 0; + } + else if (operand->flags & V850E_IMMEDIATE23) + { + if (reloc != BFD_RELOC_V850_23) + { + errmsg = _("immediate operand is too large"); + goto error; + } + extra_data_after_insn = TRUE; + extra_data_len = 2; + extra_data = 0; + } + else if ((operand->flags & V850E_IMMEDIATE16) + || (operand->flags & V850E_IMMEDIATE16HI)) + { + if (operand->flags & V850E_IMMEDIATE16HI + && reloc != BFD_RELOC_HI16 + && reloc != BFD_RELOC_HI16_S) + { + errmsg = _("immediate operand is too large"); + goto error; + } + else if (operand->flags & V850E_IMMEDIATE16 + && reloc != BFD_RELOC_LO16) { errmsg = _("immediate operand is too large"); goto error; } extra_data_after_insn = TRUE; - extra_data_len = 4; - extra_data = ex.X_add_number; + extra_data_len = 2; + extra_data = 0; } if (fc > MAX_INSN_FIXUPS) @@ -1775,6 +2305,140 @@ md_assemble (char *str) fc++; } } + else if (operand->flags & V850E_IMMEDIATE16 + || operand->flags & V850E_IMMEDIATE16HI) + { + expression (&ex); + + switch (ex.X_op) + { + case O_constant: + if (operand->flags & V850E_IMMEDIATE16HI) + { + if (ex.X_add_number & 0xffff) + { + errmsg = _("constant too big to fit into instruction"); + goto error; + } + + ex.X_add_number >>= 16; + } + if (operand->flags & V850E_IMMEDIATE16) + { + if (ex.X_add_number & 0xffff0000) + { + errmsg = _("constant too big to fit into instruction"); + goto error; + } + } + break; + + case O_illegal: + errmsg = _("illegal operand"); + goto error; + + case O_absent: + errmsg = _("missing operand"); + goto error; + + default: + if (fc >= MAX_INSN_FIXUPS) + as_fatal (_("too many fixups")); + + fixups[fc].exp = ex; + fixups[fc].opindex = *opindex_ptr; + fixups[fc].reloc = operand->default_reloc; + ++fc; + + ex.X_add_number = 0; + break; + } + + extra_data_after_insn = TRUE; + extra_data_len = 2; + extra_data = ex.X_add_number; + } + else if (operand->flags & V850E_IMMEDIATE23) + { + expression (&ex); + + switch (ex.X_op) + { + case O_constant: + break; + + case O_illegal: + errmsg = _("illegal operand"); + goto error; + + case O_absent: + errmsg = _("missing operand"); + goto error; + + default: + break; + } + + if (fc >= MAX_INSN_FIXUPS) + as_fatal (_("too many fixups")); + + fixups[fc].exp = ex; + fixups[fc].opindex = *opindex_ptr; + fixups[fc].reloc = operand->default_reloc; + ++fc; + + extra_data_after_insn = TRUE; + extra_data_len = 2; + extra_data = 0; + } + else if (operand->flags & V850E_IMMEDIATE32) + { + expression (&ex); + + switch (ex.X_op) + { + case O_constant: + if ((operand->default_reloc == BFD_RELOC_V850_32_ABS + || operand->default_reloc == BFD_RELOC_V850_32_PCREL) + && (ex.X_add_number & 1)) + { + errmsg = _("odd number cannot be used here"); + goto error; + } + break; + + case O_illegal: + errmsg = _("illegal operand"); + goto error; + + case O_absent: + errmsg = _("missing operand"); + goto error; + + default: + if (fc >= MAX_INSN_FIXUPS) + as_fatal (_("too many fixups")); + + fixups[fc].exp = ex; + fixups[fc].opindex = *opindex_ptr; + fixups[fc].reloc = operand->default_reloc; + ++fc; + + ex.X_add_number = 0; + break; + } + + extra_data_after_insn = TRUE; + extra_data_len = 4; + extra_data = ex.X_add_number; + } + else if (operand->flags & V850E_OPERAND_REG_LIST) + { + errmsg = parse_register_list (&insn, operand); + + if (errmsg) + goto error; + } else { errmsg = NULL; @@ -1782,22 +2446,30 @@ md_assemble (char *str) if ((operand->flags & V850_OPERAND_REG) != 0) { if (!register_name (&ex)) - errmsg = _("invalid register name"); - else if ((operand->flags & V850_NOT_R0) + { + errmsg = _("invalid register name"); + } + + if ((operand->flags & V850_NOT_R0) && ex.X_add_number == 0) { errmsg = _("register r0 cannot be used here"); + } - /* Force an error message to be generated by - skipping over any following potential matches - for this opcode. */ - opcode += 3; + if (operand->flags & V850_REG_EVEN) + { + if (ex.X_add_number % 2) + errmsg = _("odd register cannot be used here"); + ex.X_add_number = ex.X_add_number / 2; } + } else if ((operand->flags & V850_OPERAND_SRG) != 0) { - if (!system_register_name (&ex, TRUE, FALSE)) - errmsg = _("invalid system register name"); + if (!system_register_name (&ex, TRUE)) + { + errmsg = _("invalid system register name"); + } } else if ((operand->flags & V850_OPERAND_EP) != 0) { @@ -1824,53 +2496,26 @@ md_assemble (char *str) } else if ((operand->flags & V850_OPERAND_CC) != 0) { - if (!cc_name (&ex)) - errmsg = _("invalid condition code name"); - } - else if (operand->flags & V850E_PUSH_POP) - { - errmsg = parse_register_list (&insn, operand); - - /* The parse_register_list() function has already done - everything, so fake a dummy expression. */ - ex.X_op = O_constant; - ex.X_add_number = 0; - } - else if (operand->flags & V850E_IMMEDIATE16) - { - expression (&ex); - - if (ex.X_op != O_constant) - errmsg = _("constant expression expected"); - else if (ex.X_add_number & 0xffff0000) + if (!cc_name (&ex, TRUE)) { - if (ex.X_add_number & 0xffff) - errmsg = _("constant too big to fit into instruction"); - else if ((insn & 0x001fffc0) == 0x00130780) - ex.X_add_number >>= 16; - else - errmsg = _("constant too big to fit into instruction"); + errmsg = _("invalid condition code name"); } - extra_data_after_insn = TRUE; - extra_data_len = 2; - extra_data = ex.X_add_number; - ex.X_add_number = 0; + if ((operand->flags & V850_NOT_SA) + && ex.X_add_number == COND_SA_NUM) + { + errmsg = _("condition sa cannot be used here"); + } } - else if (operand->flags & V850E_IMMEDIATE32) + else if ((operand->flags & V850_OPERAND_FLOAT_CC) != 0) { - expression (&ex); - - if (ex.X_op != O_constant) - errmsg = _("constant expression expected"); - - extra_data_after_insn = TRUE; - extra_data_len = 4; - extra_data = ex.X_add_number; - ex.X_add_number = 0; + if (!float_cc_name (&ex, TRUE)) + { + errmsg = _("invalid condition code name"); + } } - else if (register_name (&ex) - && (operand->flags & V850_OPERAND_REG) == 0) + else if ((register_name (&ex) + && (operand->flags & V850_OPERAND_REG) == 0)) { char c; int exists = 0; @@ -1900,8 +2545,10 @@ md_assemble (char *str) the parsing of the instruction, (because another field is missing) then report this. */ if (opindex_ptr[1] != 0 - && (v850_operands[opindex_ptr[1]].flags - & V850_OPERAND_REG)) + && ((v850_operands[opindex_ptr[1]].flags + & V850_OPERAND_REG) + ||(v850_operands[opindex_ptr[1]].flags + & V850_OPERAND_VREG))) errmsg = _("syntax error: value is missing before the register name"); else errmsg = _("syntax error: register not expected"); @@ -1915,29 +2562,55 @@ md_assemble (char *str) &symbol_rootP, &symbol_lastP); } } - else if (system_register_name (&ex, FALSE, FALSE) + else if (system_register_name (&ex, FALSE) && (operand->flags & V850_OPERAND_SRG) == 0) - errmsg = _("syntax error: system register not expected"); - - else if (cc_name (&ex) + { + errmsg = _("syntax error: system register not expected"); + } + else if (cc_name (&ex, FALSE) && (operand->flags & V850_OPERAND_CC) == 0) - errmsg = _("syntax error: condition code not expected"); - + { + errmsg = _("syntax error: condition code not expected"); + } + else if (float_cc_name (&ex, FALSE) + && (operand->flags & V850_OPERAND_FLOAT_CC) == 0) + { + errmsg = _("syntax error: condition code not expected"); + } else { expression (&ex); + + if ((operand->flags & V850_NOT_IMM0) + && ex.X_op == O_constant + && ex.X_add_number == 0) + { + errmsg = _("immediate 0 cannot be used here"); + } + /* Special case: - If we are assembling a MOV instruction and the immediate + If we are assembling a MOV/JARL/JR instruction and the immediate value does not fit into the bits available then create a - fake error so that the next MOV instruction will be + fake error so that the next MOV/JARL/JR instruction will be selected. This one has a 32 bit immediate field. */ - if (((insn & 0x07e0) == 0x0200) - && operand->bits == 5 /* Do not match the CALLT instruction. */ + if ((strcmp (opcode->name, "mov") == 0 + || strcmp (opcode->name, "jarl") == 0 + || strcmp (opcode->name, "jr") == 0) && ex.X_op == O_constant && (ex.X_add_number < (-(1 << (operand->bits - 1))) || ex.X_add_number > ((1 << (operand->bits - 1)) - 1))) - errmsg = _("immediate operand is too large"); + { + errmsg = _("immediate operand is too large"); + } + + if ((strcmp (opcode->name, "jarl") == 0 + || strcmp (opcode->name, "jr") == 0) + && ex.X_op != O_constant + && operand->bits != default_disp_size) + { + errmsg = _("immediate operand is not match"); + } } if (errmsg) @@ -1953,18 +2626,21 @@ md_assemble (char *str) goto error; case O_register: if ((operand->flags - & (V850_OPERAND_REG | V850_OPERAND_SRG)) == 0) + & (V850_OPERAND_REG | V850_OPERAND_SRG | V850_OPERAND_VREG)) == 0) { errmsg = _("invalid operand"); goto error; } - insn = v850_insert_operand (insn, operand, ex.X_add_number, - NULL, 0, copy_of_instruction); + + insn = v850_insert_operand (insn, operand, + ex.X_add_number, + &warningmsg); + break; case O_constant: insn = v850_insert_operand (insn, operand, ex.X_add_number, - NULL, 0, copy_of_instruction); + &warningmsg); break; default: @@ -1987,11 +2663,23 @@ md_assemble (char *str) || *str == ')') ++str; } - match = 1; + + while (ISSPACE (*str)) + ++str; + + if (*str == '\0') + match = 1; error: if (match == 0) { + if ((opindex_ptr - opcode->operands) >= most_match_count) + { + most_match_count = opindex_ptr - opcode->operands; + if (errmsg != NULL) + strncpy (most_match_errmsg, errmsg, sizeof (most_match_errmsg)-1); + } + next_opcode = opcode + 1; if (next_opcode->name != NULL && strcmp (next_opcode->name, opcode->name) == 0) @@ -2006,7 +2694,11 @@ md_assemble (char *str) continue; } - as_bad ("%s: %s", copy_of_instruction, errmsg); + if (most_match_errmsg[0] == 0) + /* xgettext:c-format. */ + as_bad (_("junk at end of line: `%s'"), str); + else + as_bad ("%s: %s", copy_of_instruction, most_match_errmsg); if (*input_line_pointer == ']') ++input_line_pointer; @@ -2015,16 +2707,12 @@ md_assemble (char *str) input_line_pointer = saved_input_line_pointer; return; } + + if (warningmsg != NULL) + as_warn (warningmsg); break; } - while (ISSPACE (*str)) - ++str; - - if (*str != '\0') - /* xgettext:c-format */ - as_bad (_("junk at end of line: `%s'"), str); - input_line_pointer = str; /* Tie dwarf2 debug info to the address at the start of the insn. @@ -2036,40 +2724,124 @@ md_assemble (char *str) if (relaxable && fc > 0) { - /* On a 64-bit host the size of an 'int' is not the same - as the size of a pointer, so we need a union to convert - the opindex field of the fr_cgen structure into a char * - so that it can be stored in the frag. We do not have - to worry about loosing accuracy as we are not going to - be even close to the 32bit limit of the int. */ - union - { - int opindex; - char * ptr; - } - opindex_converter; - - opindex_converter.opindex = fixups[0].opindex; insn_size = 2; fc = 0; - if (!strcmp (opcode->name, "br")) + if (strcmp (opcode->name, "br") == 0 + || strcmp (opcode->name, "jbr") == 0) { - f = frag_var (rs_machine_dependent, 4, 2, 2, - fixups[0].exp.X_add_symbol, - fixups[0].exp.X_add_number, - opindex_converter.ptr); - md_number_to_chars (f, insn, insn_size); - md_number_to_chars (f + 2, 0, 2); + if ((processor_mask & PROCESSOR_V850E2_ALL) == 0 || default_disp_size == 22) + { + f = frag_var (rs_machine_dependent, 4, 2, SUBYPTE_UNCOND_9_22, + fixups[0].exp.X_add_symbol, + fixups[0].exp.X_add_number, + (char *)(size_t) fixups[0].opindex); + md_number_to_chars (f, insn, insn_size); + md_number_to_chars (f + 2, 0, 2); + } + else + { + f = frag_var (rs_machine_dependent, 6, 4, SUBYPTE_UNCOND_9_22_32, + fixups[0].exp.X_add_symbol, + fixups[0].exp.X_add_number, + (char *)(size_t) fixups[0].opindex); + md_number_to_chars (f, insn, insn_size); + md_number_to_chars (f + 2, 0, 4); + } } - else + else /* b, j. */ { - f = frag_var (rs_machine_dependent, 6, 4, 0, - fixups[0].exp.X_add_symbol, - fixups[0].exp.X_add_number, - opindex_converter.ptr); - md_number_to_chars (f, insn, insn_size); - md_number_to_chars (f + 2, 0, 4); + if (default_disp_size == 22 + || (processor_mask & PROCESSOR_V850E2_ALL) == 0) + { + if (processor_mask & PROCESSOR_V850E2V3 && !no_bcond17) + { + if (strcmp (opcode->name, "bsa") == 0) + { + f = frag_var (rs_machine_dependent, 8, 6, SUBYPTE_SA_9_17_22, + fixups[0].exp.X_add_symbol, + fixups[0].exp.X_add_number, + (char *)(size_t) fixups[0].opindex); + md_number_to_chars (f, insn, insn_size); + md_number_to_chars (f + 2, 0, 6); + } + else + { + f = frag_var (rs_machine_dependent, 6, 4, SUBYPTE_COND_9_17_22, + fixups[0].exp.X_add_symbol, + fixups[0].exp.X_add_number, + (char *)(size_t) fixups[0].opindex); + md_number_to_chars (f, insn, insn_size); + md_number_to_chars (f + 2, 0, 4); + } + } + else + { + if (strcmp (opcode->name, "bsa") == 0) + { + f = frag_var (rs_machine_dependent, 8, 6, SUBYPTE_SA_9_22, + fixups[0].exp.X_add_symbol, + fixups[0].exp.X_add_number, + (char *)(size_t) fixups[0].opindex); + md_number_to_chars (f, insn, insn_size); + md_number_to_chars (f + 2, 0, 6); + } + else + { + f = frag_var (rs_machine_dependent, 6, 4, SUBYPTE_COND_9_22, + fixups[0].exp.X_add_symbol, + fixups[0].exp.X_add_number, + (char *)(size_t) fixups[0].opindex); + md_number_to_chars (f, insn, insn_size); + md_number_to_chars (f + 2, 0, 4); + } + } + } + else + { + if (processor_mask & PROCESSOR_V850E2V3 && !no_bcond17) + { + if (strcmp (opcode->name, "bsa") == 0) + { + f = frag_var (rs_machine_dependent, 10, 8, SUBYPTE_SA_9_17_22_32, + fixups[0].exp.X_add_symbol, + fixups[0].exp.X_add_number, + (char *)(size_t) fixups[0].opindex); + md_number_to_chars (f, insn, insn_size); + md_number_to_chars (f + 2, 0, 8); + } + else + { + f = frag_var (rs_machine_dependent, 8, 6, SUBYPTE_COND_9_17_22_32, + fixups[0].exp.X_add_symbol, + fixups[0].exp.X_add_number, + (char *)(size_t) fixups[0].opindex); + md_number_to_chars (f, insn, insn_size); + md_number_to_chars (f + 2, 0, 6); + } + } + else + { + if (strcmp (opcode->name, "bsa") == 0) + { + f = frag_var (rs_machine_dependent, 10, 8, SUBYPTE_SA_9_22_32, + fixups[0].exp.X_add_symbol, + fixups[0].exp.X_add_number, + (char *)(size_t) fixups[0].opindex); + md_number_to_chars (f, insn, insn_size); + md_number_to_chars (f + 2, 0, 8); + } + else + { + f = frag_var (rs_machine_dependent, 8, 6, SUBYPTE_COND_9_22_32, + fixups[0].exp.X_add_symbol, + fixups[0].exp.X_add_number, + (char *)(size_t) fixups[0].opindex); + md_number_to_chars (f, insn, insn_size); + md_number_to_chars (f + 2, 0, 6); + } + } + } } } else @@ -2084,6 +2856,12 @@ md_assemble (char *str) if ((insn & 0xffe0) == 0x0620) insn_size = 2; + /* Special case: 32 bit JARL,JMP,JR. */ + if ((insn & 0x1ffe0) == 0x2e0 /* JARL. */ + || (insn & 0x1ffe0) == 0x6e0 /* JMP. */ + || (insn & 0x1ffff) == 0x2e0) /* JR. */ + insn_size = 2; + f = frag_more (insn_size); md_number_to_chars (f, insn, insn_size); @@ -2129,11 +2907,26 @@ md_assemble (char *str) if (size != 2 && size != 4) abort (); - address = (f - frag_now->fr_literal) + insn_size - size; + if (extra_data_len == 0) + { + address = (f - frag_now->fr_literal) + insn_size - size; + } + else + { + address = (f - frag_now->fr_literal) + extra_data_len - size; + } - if (reloc == BFD_RELOC_32) - address += 2; + if ((operand->flags & V850E_IMMEDIATE32) && (operand->flags & V850_PCREL)) + { + fixups[i].exp.X_add_number += 2; + } + else if (operand->default_reloc == BFD_RELOC_V850_16_PCREL) + { + fixups[i].exp.X_add_number += 2; + address += 2; + } + /* fprintf (stderr, "0x%x %d %ld\n", address, size, fixups[i].exp.X_add_number); */ fixP = fix_new_exp (frag_now, address, size, &fixups[i].exp, reloc_howto->pc_relative, @@ -2144,6 +2937,7 @@ md_assemble (char *str) switch (reloc) { case BFD_RELOC_LO16: + case BFD_RELOC_V850_LO16_S1: case BFD_RELOC_V850_LO16_SPLIT_OFFSET: case BFD_RELOC_HI16: case BFD_RELOC_HI16_S: @@ -2158,7 +2952,7 @@ md_assemble (char *str) fix_new_exp (frag_now, f - frag_now->fr_literal, 4, & fixups[i].exp, - (operand->flags & V850_OPERAND_DISP) != 0, + (operand->flags & V850_PCREL) != 0, (bfd_reloc_code_real_type) (fixups[i].opindex + (int) BFD_RELOC_UNUSED)); } @@ -2188,9 +2982,11 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp) reloc->addend = fixp->fx_offset; else { +#if 0 if (fixp->fx_r_type == BFD_RELOC_32 && fixp->fx_pcrel) fixp->fx_r_type = BFD_RELOC_32_PCREL; +#endif reloc->addend = fixp->fx_addnumber; } @@ -2295,6 +3091,7 @@ md_apply_fix (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED) int opindex; const struct v850_operand *operand; unsigned long insn; + const char *errmsg = NULL; opindex = (int) fixP->fx_r_type - (int) BFD_RELOC_UNUSED; operand = &v850_operands[opindex]; @@ -2306,10 +3103,20 @@ md_apply_fix (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED) format! */ where = fixP->fx_frag->fr_literal + fixP->fx_where; - insn = bfd_getl32 ((unsigned char *) where); + if (fixP->fx_size > 2) + insn = bfd_getl32 ((unsigned char *) where); + else + insn = bfd_getl16 ((unsigned char *) where); + insn = v850_insert_operand (insn, operand, (offsetT) value, - fixP->fx_file, fixP->fx_line, NULL); - bfd_putl32 ((bfd_vma) insn, (unsigned char *) where); + &errmsg); + if (errmsg) + as_warn_where (fixP->fx_file, fixP->fx_line, errmsg); + + if (fixP->fx_size > 2) + bfd_putl32 ((bfd_vma) insn, (unsigned char *) where); + else + bfd_putl16 ((bfd_vma) insn, (unsigned char *) where); if (fixP->fx_done) /* Nothing else to do here. */ @@ -2318,17 +3125,23 @@ md_apply_fix (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED) /* Determine a BFD reloc value based on the operand information. We are only prepared to turn a few of the operands into relocs. */ - if (operand->bits == 22) - fixP->fx_r_type = BFD_RELOC_V850_22_PCREL; - else if (operand->bits == 9) - fixP->fx_r_type = BFD_RELOC_V850_9_PCREL; - else + if (operand->default_reloc == BFD_RELOC_NONE) { as_bad_where (fixP->fx_file, fixP->fx_line, _("unresolved expression that must be resolved")); fixP->fx_done = 1; return; } + + { + fixP->fx_r_type = operand->default_reloc; + if (operand->default_reloc == BFD_RELOC_V850_16_PCREL) + { + fixP->fx_where += 2; + fixP->fx_size = 2; + fixP->fx_addnumber += 2; + } + } } else if (fixP->fx_done) { @@ -2336,54 +3149,140 @@ md_apply_fix (fixS *fixP, valueT *valueP, segT seg ATTRIBUTE_UNUSED) where = fixP->fx_frag->fr_literal + fixP->fx_where; if (fixP->tc_fix_data != NULL - && ((struct v850_operand *) fixP->tc_fix_data)->insert != NULL) - { - const char * message = NULL; - struct v850_operand * operand = (struct v850_operand *) fixP->tc_fix_data; - unsigned long insn; - - /* The variable "where" currently points at the exact point inside - the insn where we need to insert the value. But we need to - extract the entire insn so we probably need to move "where" - back a few bytes. */ - if (fixP->fx_size == 2) - where -= 2; - else if (fixP->fx_size == 1) - where -= 3; - - insn = bfd_getl32 ((unsigned char *) where); - - /* Use the operand's insertion procedure, if present, in order to - make sure that the value is correctly stored in the insn. */ - insn = operand->insert (insn, (offsetT) value, & message); - /* Ignore message even if it is set. */ - - bfd_putl32 ((bfd_vma) insn, (unsigned char *) where); - } + && ((struct v850_operand *) fixP->tc_fix_data)->insert != NULL) + { + const char * message = NULL; + struct v850_operand * operand = (struct v850_operand *) fixP->tc_fix_data; + unsigned long insn; + + /* The variable "where" currently points at the exact point inside + the insn where we need to insert the value. But we need to + extract the entire insn so we probably need to move "where" + back a few bytes. */ + + if (fixP->fx_size == 2) + where -= 2; + else if (fixP->fx_size == 1) + where -= 3; + + insn = bfd_getl32 ((unsigned char *) where); + + /* Use the operand's insertion procedure, if present, in order to + make sure that the value is correctly stored in the insn. */ + insn = operand->insert (insn, (offsetT) value, & message); + /* Ignore message even if it is set. */ + + bfd_putl32 ((bfd_vma) insn, (unsigned char *) where); + } else - { - if (fixP->fx_r_type == BFD_RELOC_V850_LO16_SPLIT_OFFSET) - bfd_putl32 (((value << 16) & 0xfffe0000) - | ((value << 5) & 0x20) - | (bfd_getl32 (where) & ~0xfffe0020), where); - else if (fixP->fx_size == 1) - *where = value & 0xff; - else if (fixP->fx_size == 2) - bfd_putl16 (value & 0xffff, (unsigned char *) where); - else if (fixP->fx_size == 4) - bfd_putl32 (value, (unsigned char *) where); - } + { + switch (fixP->fx_r_type) + { + case BFD_RELOC_V850_32_ABS: + case BFD_RELOC_V850_32_PCREL: + bfd_putl32 (value & 0xfffffffe, (unsigned char *) where); + break; + + case BFD_RELOC_32: + bfd_putl32 (value, (unsigned char *) where); + break; + + case BFD_RELOC_V850_23: + bfd_putl32 (((value & 0x7f) << 4) | ((value & 0x7fff80) << (16-7)) + | (bfd_getl32 (where) & ~((0x7f << 4) | (0xffff << 16))), + (unsigned char *) where); + break; + + case BFD_RELOC_16: + case BFD_RELOC_HI16: + case BFD_RELOC_HI16_S: + case BFD_RELOC_LO16: + case BFD_RELOC_V850_ZDA_16_16_OFFSET: + case BFD_RELOC_V850_SDA_16_16_OFFSET: + case BFD_RELOC_V850_TDA_16_16_OFFSET: + case BFD_RELOC_V850_CALLT_16_16_OFFSET: + bfd_putl16 (value & 0xffff, (unsigned char *) where); + break; + + case BFD_RELOC_8: + *where = value & 0xff; + break; + + case BFD_RELOC_V850_9_PCREL: + bfd_putl16 (((value & 0x1f0) << 7) | ((value & 0x0e) << 3) + | (bfd_getl16 (where) & ~((0x1f0 << 7) | (0x0e << 3))), where); + break; + + case BFD_RELOC_V850_17_PCREL: + bfd_putl32 (((value & 0x10000) >> (16 - 4)) | ((value & 0xfffe) << 16) + | (bfd_getl32 (where) & ~((0x10000 >> (16 - 4)) | (0xfffe << 16))), where); + break; + + case BFD_RELOC_V850_16_PCREL: + bfd_putl16 (-value & 0xfffe, (unsigned char *) where); + break; + + case BFD_RELOC_V850_22_PCREL: + bfd_putl32 (((value & 0xfffe) << 16) | ((value & 0x3f0000) >> 16) + | (bfd_getl32 (where) & ~((0xfffe << 16) | (0x3f0000 >> 16))), where); + break; + + case BFD_RELOC_V850_16_S1: + case BFD_RELOC_V850_LO16_S1: + case BFD_RELOC_V850_ZDA_15_16_OFFSET: + case BFD_RELOC_V850_SDA_15_16_OFFSET: + bfd_putl16 (value & 0xfffe, (unsigned char *) where); + break; + + case BFD_RELOC_V850_16_SPLIT_OFFSET: + case BFD_RELOC_V850_LO16_SPLIT_OFFSET: + case BFD_RELOC_V850_ZDA_16_16_SPLIT_OFFSET: + case BFD_RELOC_V850_SDA_16_16_SPLIT_OFFSET: + bfd_putl32 (((value << 16) & 0xfffe0000) + | ((value << 5) & 0x20) + | (bfd_getl32 (where) & ~0xfffe0020), where); + break; + + case BFD_RELOC_V850_TDA_6_8_OFFSET: + *where = (*where & ~0x7e) | ((value >> 1) & 0x7e); + break; + + case BFD_RELOC_V850_TDA_7_8_OFFSET: + *where = (*where & ~0x7f) | ((value >> 1) & 0x7f); + break; + + case BFD_RELOC_V850_TDA_7_7_OFFSET: + *where = (*where & ~0x7f) | (value & 0x7f); + break; + + case BFD_RELOC_V850_TDA_4_5_OFFSET: + *where = (*where & ~0xf) | ((value >> 1) & 0xf); + break; + + case BFD_RELOC_V850_TDA_4_4_OFFSET: + *where = (*where & ~0xf) | (value & 0xf); + break; + + case BFD_RELOC_V850_CALLT_6_7_OFFSET: + *where = (*where & ~0x3f) | (value & 0x3f); + break; + + default: + abort (); + } + } } } - + /* Parse a cons expression. We have to handle hi(), lo(), etc on the v850. */ void parse_cons_expression_v850 (expressionS *exp) { + const char *errmsg; /* See if there's a reloc prefix like hi() we have to handle. */ - hold_cons_reloc = v850_reloc_prefix (NULL); + hold_cons_reloc = v850_reloc_prefix (NULL, &errmsg); /* Do normal expression parsing. */ expression (exp); @@ -2445,8 +3344,11 @@ v850_force_relocation (struct fix *fixP) if (v850_relax && (fixP->fx_pcrel || fixP->fx_r_type == BFD_RELOC_V850_ALIGN - || fixP->fx_r_type == BFD_RELOC_V850_22_PCREL || fixP->fx_r_type == BFD_RELOC_V850_9_PCREL + || fixP->fx_r_type == BFD_RELOC_V850_16_PCREL + || fixP->fx_r_type == BFD_RELOC_V850_17_PCREL + || fixP->fx_r_type == BFD_RELOC_V850_22_PCREL + || fixP->fx_r_type == BFD_RELOC_V850_32_PCREL || fixP->fx_r_type >= BFD_RELOC_UNUSED)) return 1; diff --git a/gas/configure.tgt b/gas/configure.tgt index 55be314c6b4..1909160e299 100644 --- a/gas/configure.tgt +++ b/gas/configure.tgt @@ -400,9 +400,7 @@ case ${generic_target} in tic54x-*-* | c54x*-*-*) fmt=coff bfd_gas=yes need_libm=yes;; tic6x-*-*) fmt=elf ;; - v850-*-*) fmt=elf ;; - v850e-*-*) fmt=elf ;; - v850ea-*-*) fmt=elf ;; + v850*-*-*) fmt=elf ;; vax-*-netbsdelf*) fmt=elf em=nbsd ;; vax-*-linux-*) fmt=elf em=linux ;; diff --git a/gas/doc/c-v850.texi b/gas/doc/c-v850.texi index b641f8e11cc..e92fbed527d 100644 --- a/gas/doc/c-v850.texi +++ b/gas/doc/c-v850.texi @@ -68,6 +68,18 @@ routines used by the code produced by GCC for all versions of the v850 architecture, together with support routines only used by the V850E architecture. +@cindex @code{-mv850e2} command line option, V850 +@item -mv850e2 +Specifies that the assembled code should be marked as being targeted at +the V850E2 processor. This allows the linker to detect attempts to link +such code with code assembled for other processors. + +@cindex @code{-mv850e2v3} command line option, V850 +@item -mv850e2v3 +Specifies that the assembled code should be marked as being targeted at +the V850E2V3 processor. This allows the linker to detect attempts to link +such code with code assembled for other processors. + @cindex @code{-mrelax} command line option, V850 @item -mrelax Enables relaxation. This allows the .longcall and .longjump pseudo @@ -245,6 +257,18 @@ Specifies that the assembled code should be marked as being targeted at the V850E1 processor. This allows the linker to detect attempts to link such code with code assembled for other processors. +@cindex @code{.v850e2} directive, V850 +@item .v850e2 +Specifies that the assembled code should be marked as being targeted at +the V850E2 processor. This allows the linker to detect attempts to link +such code with code assembled for other processors. + +@cindex @code{.v850e2v3} directive, V850 +@item .v850e2v3 +Specifies that the assembled code should be marked as being targeted at +the V850E2V3 processor. This allows the linker to detect attempts to link +such code with code assembled for other processors. + @end table @node V850 Opcodes diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 63058013c37..70973c93cb4 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2010-07-23 Naveen.H.S + Ina Pandit + + * gas/v850/split-lo16.d: Update the "ld" instructions with a space + for second operand. + * gas/v850/v850e1.d: Likewise. + 2010-07-22 Alan Modra * gas/arm/mapdir.s: Don't specify attr/type for .fini_array. diff --git a/gas/testsuite/gas/all/byte.d b/gas/testsuite/gas/all/byte.d index 739b9ceadb2..9e23feaae57 100644 --- a/gas/testsuite/gas/all/byte.d +++ b/gas/testsuite/gas/all/byte.d @@ -1,2 +1,5 @@ #name: bad byte directive #error-output: byte.l +# The RX target allows quoted ASCII strings inside .byte directives +# for compatibily with the Renesas assembler. +#skip: rx-*-* diff --git a/gas/testsuite/gas/rx/rx-asm-good.d b/gas/testsuite/gas/rx/rx-asm-good.d index d515f24f753..6733bbf423e 100644 --- a/gas/testsuite/gas/rx/rx-asm-good.d +++ b/gas/testsuite/gas/rx/rx-asm-good.d @@ -10,8 +10,8 @@ Disassembly of section .text: 0+0108 66 20[ ]+mov.l[ ]+#2, r0 0+010a 66 10[ ]+mov.l[ ]+#1, r0 0+010c 66 00[ ]+mov.l[ ]+#0, r0 -0+010e 05 f2 fe ff[ ]+bsr.a[ ]+0+0000 -0+0112 05 ee fe ff[ ]+bsr.a[ ]+0+0000 +0+010e 05 .. .. ..[ ]+bsr.a[ ]+[0-9a-f]+ +0+0112 05 .. .. ..[ ]+bsr.a[ ]+[0-9a-f]+ 0+0116 62 65[ ]+add[ ]+#6, r5 0+0118 72 74 0b 2e[ ]+add[ ]+#0x2e0b, r7, r4 0+011c ff 2e 00[ ]+add[ ]+r0, r0, r14 diff --git a/gas/testsuite/gas/v850/split-lo16.d b/gas/testsuite/gas/v850/split-lo16.d index 5ed195cb087..617dfd8ffb1 100644 --- a/gas/testsuite/gas/v850/split-lo16.d +++ b/gas/testsuite/gas/v850/split-lo16.d @@ -7,12 +7,12 @@ 2: R_V850_HI16_S foo 4: 01 16 00 00 addi 0, r1, r2 6: R_V850_LO16 foo - 8: 01 17 00 00 ld\.b 0\[r1\],r2 + 8: 01 17 00 00 ld\.b 0\[r1\], r2 a: R_V850_LO16 foo - c: 81 17 01 00 ld\.bu 0\[r1\],r2 + c: 81 17 01 00 ld\.bu 0\[r1\], r2 c: R_V850_LO16_SPLIT_OFFSET foo - 10: a1 17 45 23 ld\.bu 9029\[r1\],r2 - 14: 81 17 57 34 ld\.bu 13398\[r1\],r2 - 18: 20 57 01 00 ld.w 0\[r0\],r10 - 1c: 20 57 79 56 ld.w 22136\[r0\],r10 + 10: a1 17 45 23 ld\.bu 9029\[r1\], r2 + 14: 81 17 57 34 ld\.bu 13398\[r1\], r2 + 18: 20 57 01 00 ld.w 0\[r0\], r10 + 1c: 20 57 79 56 ld.w 22136\[r0\], r10 #pass diff --git a/gas/testsuite/gas/v850/v850e1.d b/gas/testsuite/gas/v850/v850e1.d index 9fb689b5d3c..8172b09747e 100644 --- a/gas/testsuite/gas/v850/v850e1.d +++ b/gas/testsuite/gas/v850/v850e1.d @@ -23,8 +23,8 @@ Disassembly of section .text: 0x0+30 e7 47 82 4a [ ]*divhu r7, r8, r9 0x0+34 ea 5f c2 62 [ ]*divu r10, r11, r12 0x0+38 e0 6f 44 73 [ ]*hsw r13, r14 -0x0+3c a1 17 0d 00 [ ]*ld.bu 13\[r1\],r2 -0x0+40 e3 27 11 00 [ ]*ld.hu 16\[sp\],gp +0x0+3c a1 17 0d 00 [ ]*ld.bu 13\[r1\], r2 +0x0+40 e3 27 11 00 [ ]*ld.hu 16\[sp\], gp 0x0+44 21 06 78 56 34 12 [ ]*mov 0x12345678, r1 0x0+4a e5 17 40 1a [ ]*mul 5, r2, sp 0x0+4e e1 17 20 1a [ ]*mul r1, r2, sp @@ -35,8 +35,8 @@ Disassembly of section .text: 0x0+62 a8 07 03 70 [ ]*prepare {r25 - r27}, 20, sp 0x0+66 e1 4f e0 00 [ ]*set1 r9, r1 0x0+6a ea 47 00 02 [ ]*sasf nz, r8 -0x0+6e 60 20 [ ]*sld.bu 0\[ep\],gp -0x0+70 77 28 [ ]*sld.hu 14\[ep\],r5 +0x0+6e 60 20 [ ]*sld.bu 0\[ep\], gp +0x0+70 77 28 [ ]*sld.hu 14\[ep\], r5 0x0+72 a1 00 [ ]*sxb r1 0x0+74 e2 00 [ ]*sxh r2 0x0+76 ff 07 e6 00 [ ]*tst1 r0, lp diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog index edd9b48b003..61bbf81db1d 100644 --- a/include/elf/ChangeLog +++ b/include/elf/ChangeLog @@ -1,3 +1,9 @@ +2010-07-23 Naveen.H.S + Ina Pandit + + * v850.h: Add support for V850E2 and V850E2V3. + (v850_reloc_type): Update the newly added relocations + 2010-07-20 Alan Modra * internal.h (ELF_TBSS_SPECIAL): New macro, extracted from.. diff --git a/include/elf/v850.h b/include/elf/v850.h index 71ae1db4b49..2a0e03ef822 100644 --- a/include/elf/v850.h +++ b/include/elf/v850.h @@ -40,6 +40,11 @@ /* v850e1 code. */ #define E_V850E1_ARCH 0x20000000 +/* v850e2 code. */ +#define E_V850E2_ARCH 0x30000000 + +/* v850e2v3 code. */ +#define E_V850E2V3_ARCH 0x40000000 /* Flags for the st_other field. */ #define V850_OTHER_SDA 0x10 /* Symbol had SDA relocations. */ @@ -81,6 +86,29 @@ START_RELOC_NUMBERS (v850_reloc_type) RELOC_NUMBER (R_V850_ALIGN, 27) RELOC_NUMBER (R_V850_REL32, 28) RELOC_NUMBER (R_V850_LO16_SPLIT_OFFSET, 29) /* For ld.bu */ + RELOC_NUMBER (R_V850_16_PCREL, 30) /* For loop */ + RELOC_NUMBER (R_V850_17_PCREL, 31) /* For br */ + RELOC_NUMBER (R_V850_23, 32) /* For 23bit ld.[w,h,hu,b,bu],st.[w,h,b] */ + RELOC_NUMBER (R_V850_32_PCREL, 33) /* For jr32, jarl32 */ + RELOC_NUMBER (R_V850_32_ABS, 34) /* For jmp32 */ + RELOC_NUMBER (R_V850_16_SPLIT_OFFSET, 35) /* For ld.bu */ + RELOC_NUMBER (R_V850_16_S1, 36) /* For ld.w, ld.h st.w st.h */ + RELOC_NUMBER (R_V850_LO16_S1, 37) /* For ld.w, ld.h st.w st.h */ + RELOC_NUMBER (R_V850_CALLT_15_16_OFFSET, 38) /* For ld.w, ld.h, ld.hu, st.w, st.h */ + RELOC_NUMBER (R_V850_32_GOTPCREL, 39) /* GLOBAL_OFFSET_TABLE from pc */ + RELOC_NUMBER (R_V850_16_GOT, 40) /* GOT ENTRY from gp */ + RELOC_NUMBER (R_V850_32_GOT, 41) + RELOC_NUMBER (R_V850_22_PLT, 42) /* For jr */ + RELOC_NUMBER (R_V850_32_PLT, 43) /* For jr32 */ + RELOC_NUMBER (R_V850_COPY, 44) + RELOC_NUMBER (R_V850_GLOB_DAT, 45) + RELOC_NUMBER (R_V850_JMP_SLOT, 46) + RELOC_NUMBER (R_V850_RELATIVE, 47) + RELOC_NUMBER (R_V850_16_GOTOFF, 48) /* From gp */ + RELOC_NUMBER (R_V850_32_GOTOFF, 49) + RELOC_NUMBER (R_V850_CODE, 50) + RELOC_NUMBER (R_V850_DATA, 51) /* For loop */ + END_RELOC_NUMBERS (R_V850_max) diff --git a/include/opcode/ChangeLog b/include/opcode/ChangeLog index aa09a3a48ec..f2e13459359 100644 --- a/include/opcode/ChangeLog +++ b/include/opcode/ChangeLog @@ -1,3 +1,21 @@ +2010-07-23 Naveen.H.S + Ina Pandit + + * v850.h: Define PROCESSOR_MASK, PROCESSOR_OPTION_EXTENSION, + PROCESSOR_OPTION_ALIAS, PROCESSOR_V850E2, PROCESSOR_V850E2V3 and + PROCESSOR_V850E2_ALL. + Remove PROCESSOR_V850EA support. + (v850_operand): Define V850_OPERAND_EP, V850_OPERAND_FLOAT_CC, + V850_OPERAND_VREG, V850E_IMMEDIATE16, V850E_IMMEDIATE16HI, + V850E_IMMEDIATE23, V850E_IMMEDIATE32, V850_OPERAND_SIGNED, + V850_OPERAND_DISP, V850_PCREL, V850_REG_EVEN, V850E_PUSH_POP, + V850_NOT_IMM0, V850_NOT_SA, V850_OPERAND_BANG and + V850_OPERAND_PERCENT. + Update V850_OPERAND_SRG, V850_OPERAND_CC, V850_OPERAND_RELAX and + V850_NOT_R0. + Remove V850_OPERAND_SIGNED, V850_OPERAND_EP, V850_OPERAND_DISP + and V850E_PUSH_POP + 2010-07-06 Maciej W. Rozycki * mips.h (MIPS16_INSN_UNCOND_BRANCH): New macro. diff --git a/include/opcode/v850.h b/include/opcode/v850.h index fcf96310fc6..59033059179 100644 --- a/include/opcode/v850.h +++ b/include/opcode/v850.h @@ -55,12 +55,18 @@ struct v850_opcode }; /* Values for the processors field in the v850_opcode structure. */ +#define PROCESSOR_MASK 0x1f +#define PROCESSOR_OPTION_EXTENSION (1 << 5) /* Enable extension opcodes. */ +#define PROCESSOR_OPTION_ALIAS (1 << 6) /* Enable alias opcodes. */ #define PROCESSOR_V850 (1 << 0) /* Just the V850. */ -#define PROCESSOR_ALL -1 /* Any processor. */ -#define PROCESSOR_V850E (1 << 1) /* Just the V850E. */ -#define PROCESSOR_NOT_V850 (~ PROCESSOR_V850) /* Any processor except the V850. */ -#define PROCESSOR_V850EA (1 << 2) /* Just the V850EA. */ -#define PROCESSOR_V850E1 (1 << 3) /* Just the V850E1. */ +#define PROCESSOR_ALL PROCESSOR_MASK /* Any processor. */ +#define PROCESSOR_V850E (1 << 1) /* Just the V850E. */ +#define PROCESSOR_NOT_V850 (PROCESSOR_ALL & (~ PROCESSOR_V850)) /* Any processor except the V850. */ +#define PROCESSOR_V850E1 (1 << 2) /* Just the V850E1. */ +#define PROCESSOR_V850E2 (1 << 3) /* Just the V850E2. */ +#define PROCESSOR_V850E2V3 (1 << 4) /* Just the V850E2V3. */ +#define PROCESSOR_V850E2_ALL (PROCESSOR_V850E2 | PROCESSOR_V850E2V3) /* V850E2 & V850E2V3. */ +#define SET_PROCESSOR_MASK(mask,set) ((mask) = ((mask) & ~PROCESSOR_MASK) | (set)) /* The table itself is sorted by major opcode number, and is otherwise in the order in which the disassembler should consider @@ -74,7 +80,8 @@ extern const int v850_num_opcodes; struct v850_operand { /* The number of bits in the operand. */ - /* If this value is -1 then the operand's bits are in a discontinous distribution in the instruction. */ + /* If this value is -1 then the operand's bits are in a discontinous + distribution in the instruction. */ int bits; /* (bits >= 0): How far the operand is left shifted in the instruction. */ @@ -120,6 +127,8 @@ struct v850_operand /* One bit syntax flags. */ int flags; + + int default_reloc; }; /* Elements in the table are retrieved by indexing with values from @@ -129,39 +138,70 @@ extern const struct v850_operand v850_operands[]; /* Values defined for the flags field of a struct v850_operand. */ -/* This operand names a general purpose register */ +/* This operand names a general purpose register. */ #define V850_OPERAND_REG 0x01 -/* This operand names a system register */ -#define V850_OPERAND_SRG 0x02 +/* This operand is the ep register. */ +#define V850_OPERAND_EP 0x02 -/* This operand names a condition code used in the setf instruction */ -#define V850_OPERAND_CC 0x04 +/* This operand names a system register. */ +#define V850_OPERAND_SRG 0x04 -/* This operand takes signed values */ -#define V850_OPERAND_SIGNED 0x08 +/* Prologue eilogue type instruction, V850E specific. */ +#define V850E_OPERAND_REG_LIST 0x08 -/* This operand is the ep register. */ -#define V850_OPERAND_EP 0x10 +/* This operand names a condition code used in the setf instruction. */ +#define V850_OPERAND_CC 0x10 -/* This operand is a PC displacement */ -#define V850_OPERAND_DISP 0x20 +#define V850_OPERAND_FLOAT_CC 0x20 -/* This is a relaxable operand. Only used for D9->D22 branch relaxing - right now. We may need others in the future (or maybe handle them like - promoted operands on the mn10300?) */ -#define V850_OPERAND_RELAX 0x40 +/* This operand names a vector purpose register. */ +#define V850_OPERAND_VREG 0x40 -/* The register specified must not be r0 */ -#define V850_NOT_R0 0x80 +/* 16 bit immediate follows instruction, V850E specific. */ +#define V850E_IMMEDIATE16 0x80 -/* push/pop type instruction, V850E specific. */ -#define V850E_PUSH_POP 0x100 +/* hi16 bit immediate follows instruction, V850E specific. */ +#define V850E_IMMEDIATE16HI 0x100 -/* 16 bit immediate follows instruction, V850E specific. */ -#define V850E_IMMEDIATE16 0x200 +/* 23 bit immediate follows instruction, V850E specific. */ +#define V850E_IMMEDIATE23 0x200 /* 32 bit immediate follows instruction, V850E specific. */ #define V850E_IMMEDIATE32 0x400 +/* This is a relaxable operand. Only used for D9->D22 branch relaxing + right now. We may need others in the future (or maybe handle them like + promoted operands on the mn10300?). */ +#define V850_OPERAND_RELAX 0x800 + +/* This operand takes signed values. */ +#define V850_OPERAND_SIGNED 0x1000 + +/* This operand is a displacement. */ +#define V850_OPERAND_DISP 0x2000 + +/* This operand is a PC displacement. */ +#define V850_PCREL 0x4000 + +/* The register specified must be even number. */ +#define V850_REG_EVEN 0x8000 + +/* The register specified must not be r0. */ +#define V850_NOT_R0 0x20000 + +/* The register specified must not be 0. */ +#define V850_NOT_IMM0 0x40000 + +/* The condition code must not be SA CONDITION. */ +#define V850_NOT_SA 0x80000 + +/* The operand has '!' prefix. */ +#define V850_OPERAND_BANG 0x100000 + +/* The operand has '%' prefix. */ +#define V850_OPERAND_PERCENT 0x200000 + +extern int v850_msg_is_out_of_range (const char * msg); + #endif /* V850_H */ diff --git a/ld/ChangeLog b/ld/ChangeLog index 24d2cfd74a9..7635da40d92 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,8 @@ +2010-07-23 Naveen.H.S + Ina Pandit + + * configure.tgt: Match all v850 targets. + 2010-07-20 Mike Frysinger * ld.texinfo (VERSION): Remove "int" from example script and add ";". diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 6ec6d55f44d..b407ab66f18 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2010-07-23 Naveen.H.S + Ina Pandit + + * ld-v850/split-lo16.d: Update the "ld" instructions with a space + for second operand. + 2010-07-20 Alan Modra * ld-powerpc/tlsexe.r: Update. diff --git a/ld/testsuite/ld-v850/split-lo16.d b/ld/testsuite/ld-v850/split-lo16.d index c5668ffaf73..fbc325cb748 100644 --- a/ld/testsuite/ld-v850/split-lo16.d +++ b/ld/testsuite/ld-v850/split-lo16.d @@ -5,22 +5,22 @@ 00010000 <.*>: 10000: 40 0e 34 12 movhi 4660, r0, r1 10004: 01 16 78 56 addi 22136, r1, r2 - 10008: 81 17 79 56 ld\.bu 22136\[r1\],r2 + 10008: 81 17 79 56 ld\.bu 22136\[r1\], r2 1000c: 40 0e 36 12 movhi 4662, r0, r1 10010: 01 16 78 d8 addi -10120, r1, r2 - 10014: 81 17 79 d8 ld\.bu -10120\[r1\],r2 + 10014: 81 17 79 d8 ld\.bu -10120\[r1\], r2 10018: 40 0e 12 00 movhi 18, r0, r1 - 1001c: 81 17 57 34 ld\.bu 13398\[r1\],r2 + 1001c: 81 17 57 34 ld\.bu 13398\[r1\], r2 10020: 01 16 56 34 addi 13398, r1, r2 10024: 40 0e 14 00 movhi 20, r0, r1 - 10028: 81 17 57 b6 ld\.bu -18858\[r1\],r2 + 10028: 81 17 57 b6 ld\.bu -18858\[r1\], r2 1002c: 01 16 56 b6 addi -18858, r1, r2 10030: 40 0e 79 56 movhi 22137, r0, r1 10034: 01 16 bc 9a addi -25924, r1, r2 - 10038: 81 17 bd 9a ld\.bu -25924\[r1\],r2 + 10038: 81 17 bd 9a ld\.bu -25924\[r1\], r2 1003c: 40 0e 9b 78 movhi 30875, r0, r1 - 10040: 81 17 df bc ld\.bu -17186\[r1\],r2 + 10040: 81 17 df bc ld\.bu -17186\[r1\], r2 10044: 01 16 de bc addi -17186, r1, r2 10048: 40 0e 45 23 movhi 9029, r0, r1 - 1004c: a1 17 89 67 ld\.bu 26505\[r1\],r2 + 1004c: a1 17 89 67 ld\.bu 26505\[r1\], r2 #pass diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index c0c9835c106..b47aa3ddc70 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,26 @@ +2010-07-23 Naveen.H.S + Ina Pandit + + * v850-dis.c (v850_sreg_names): Updated structure for system + registers. + (float_cc_names): new structure for condition codes. + (print_value): Update the function that prints value. + (get_operand_value): New function to get the operand value. + (disassemble): Updated to handle the disassembly of instructions. + (print_insn_v850): Updated function to print instruction for different + families. + * opcodes/v850-opc.c (v850_msg_is_out_of_range, insert_i5div1, + extract_i5div1, insert_i5div2, extract_i5div2, insert_i5div3, + extract_i5div3, insert_d5_4, extract_d5_4, extract_d8_6, + insert_d8_7, extract_d8_7, insert_v8, extract_v8, insert_u16_loop, + extract_u16_loop, insert_d16_15, extract_d16_15, insert_d16_16, + extract_d16_16, nsert_d17_16, extract_d17_16, insert_d22, + extract_d22, insert_d23, extract_d23, insert_i9, extract_i9, + insert_u9, extract_u9, extract_spe, insert_r4, extract_r4): New. + (insert_d8_7, insert_d5_4, insert_i5div): Remove. + (v850_operands): Update with the relocation name. Also update + the instructions with specific set of processors. + 2010-07-08 Tejas Belagod * arm-dis.c (print_insn_arm): Add cases for printing more diff --git a/opcodes/v850-dis.c b/opcodes/v850-dis.c index 6cf90296658..c3624b21f4b 100644 --- a/opcodes/v850-dis.c +++ b/opcodes/v850-dis.c @@ -1,5 +1,5 @@ /* Disassemble V850 instructions. - Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2007 + Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2007, 2010 Free Software Foundation, Inc. This file is part of the GNU opcodes library. @@ -28,44 +28,169 @@ #include "opintl.h" static const char *const v850_reg_names[] = -{ "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7", +{ + "r0", "r1", "r2", "sp", "gp", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", - "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp" }; + "r24", "r25", "r26", "r27", "r28", "r29", "ep", "lp" +}; static const char *const v850_sreg_names[] = -{ "eipc", "eipsw", "fepc", "fepsw", "ecr", "psw", "sr6", "sr7", - "sr8", "sr9", "sr10", "sr11", "sr12", "sr13", "sr14", "sr15", - "ctpc", "ctpsw", "dbpc", "dbpsw", "ctbp", "sr21", "sr22", "sr23", - "sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31", - "sr16", "sr17", "sr18", "sr19", "sr20", "sr21", "sr22", "sr23", - "sr24", "sr25", "sr26", "sr27", "sr28", "sr29", "sr30", "sr31" }; +{ + "eipc/vip/mpm", "eipsw/mpc", "fepc/tid", "fepsw/ppa", "ecr/vmecr", "psw/vmtid", + "sr6/fpsr/vmadr/dcc", "sr7/fpepc/dc0", + "sr8/fpst/vpecr/dcv1", "sr9/fpcc/vptid", "sr10/fpcfg/vpadr/spal", "sr11/spau", + "sr12/vdecr/ipa0l", "eiic/vdtid/ipa0u", "feic/ipa1l", "dbic/ipa1u", + "ctpc/ipa2l", "ctpsw/ipa2u", "dbpc/ipa3l", "dbpsw/ipa3u", "ctbp/dpa0l", + "dir/dpa0u", "bpc/dpa0u", "asid/dpa1l", + "bpav/dpa1u", "bpam/dpa2l", "bpdv/dpa2u", "bpdm/dpa3l", "eiwr/dpa3u", + "fewr", "dbwr", "bsel" +}; static const char *const v850_cc_names[] = -{ "v", "c/l", "z", "nh", "s/n", "t", "lt", "le", - "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt" }; +{ + "v", "c/l", "z", "nh", "s/n", "t", "lt", "le", + "nv", "nc/nl", "nz", "h", "ns/p", "sa", "ge", "gt" +}; -static int -disassemble (bfd_vma memaddr, - struct disassemble_info * info, - unsigned long insn) +static const char *const v850_float_cc_names[] = { - struct v850_opcode * op = (struct v850_opcode *) v850_opcodes; - const struct v850_operand * operand; - int match = 0; - int short_op = ((insn & 0x0600) != 0x0600); - int bytes_read; - int target_processor; + "f/t", "un/or", "eq/neq", "ueq/ogl", "olt/uge", "ult/oge", "ole/ugt", "ule/ogt", + "sf/st", "ngle/gle", "seq/sne", "ngl/gl", "lt/nlt", "nge/ge", "le/nle", "ngt/gt" +}; - /* Special case: 32 bit MOV. */ - if ((insn & 0xffe0) == 0x0620) - short_op = 1; - bytes_read = short_op ? 2 : 4; +static void +print_value (int flags, bfd_vma memaddr, struct disassemble_info *info, long value) +{ + if (flags & V850_PCREL) + { + bfd_vma addr = value + memaddr; + info->print_address_func (addr, info); + } + else if (flags & V850_OPERAND_DISP) + { + if (flags & V850_OPERAND_SIGNED) + { + info->fprintf_func (info->stream, "%ld", value); + } + else + { + info->fprintf_func (info->stream, "%lu", value); + } + } + else if (flags & V850E_IMMEDIATE32) + { + info->fprintf_func (info->stream, "0x%lx", value); + } + else + { + if (flags & V850_OPERAND_SIGNED) + { + info->fprintf_func (info->stream, "%ld", value); + } + else + { + info->fprintf_func (info->stream, "%lu", value); + } + } +} - /* If this is a two byte insn, then mask off the high bits. */ - if (short_op) - insn &= 0xffff; +static long +get_operand_value (const struct v850_operand *operand, + unsigned long insn, + int bytes_read, + bfd_vma memaddr, + struct disassemble_info * info, + bfd_boolean noerror, + int *invalid) +{ + long value; + bfd_byte buffer[4]; + + if ((operand->flags & V850E_IMMEDIATE16) + || (operand->flags & V850E_IMMEDIATE16HI)) + { + int status = info->read_memory_func (memaddr + bytes_read, buffer, 2, info); + + if (status == 0) + { + value = bfd_getl16 (buffer); + + if (operand->flags & V850E_IMMEDIATE16HI) + value <<= 16; + + return value; + } + + if (!noerror) + info->memory_error_func (status, memaddr + bytes_read, info); + + return 0; + } + + if (operand->flags & V850E_IMMEDIATE23) + { + int status = info->read_memory_func (memaddr + 2, buffer, 4, info); + + if (status == 0) + { + value = bfd_getl32 (buffer); + + value = (operand->extract) (value, invalid); + + return value; + } + + if (!noerror) + info->memory_error_func (status, memaddr + bytes_read, info); + + return 0; + } + + if (operand->flags & V850E_IMMEDIATE32) + { + int status = info->read_memory_func (memaddr + bytes_read, buffer, 4, info); + + if (status == 0) + { + bytes_read += 4; + value = bfd_getl32 (buffer); + + return value; + } + + if (!noerror) + info->memory_error_func (status, memaddr + bytes_read, info); + + return 0; + } + + if (operand->extract) + value = (operand->extract) (insn, invalid); + else + { + if (operand->bits == -1) + value = (insn & operand->shift); + else + value = (insn >> operand->shift) & ((1 << operand->bits) - 1); + + if (operand->flags & V850_OPERAND_SIGNED) + value = ((long)(value << (sizeof (long)*8 - operand->bits)) + >> (sizeof (long)*8 - operand->bits)); + } + + return value; +} + + +static int +disassemble (bfd_vma memaddr, struct disassemble_info *info, int bytes_read, unsigned long insn) +{ + struct v850_opcode *op = (struct v850_opcode *)v850_opcodes; + const struct v850_operand *operand; + int match = 0; + int target_processor; switch (info->mach) { @@ -79,22 +204,66 @@ disassemble (bfd_vma memaddr, break; case bfd_mach_v850e1: - target_processor = PROCESSOR_V850E1; + target_processor = PROCESSOR_V850E; + break; + + case bfd_mach_v850e2: + target_processor = PROCESSOR_V850E2; + break; + + case bfd_mach_v850e2v3: + target_processor = PROCESSOR_V850E2V3; break; } + /* If this is a two byte insn, then mask off the high bits. */ + if (bytes_read == 2) + insn &= 0xffff; + /* Find the opcode. */ while (op->name) { if ((op->mask & insn) == op->opcode - && (op->processors & target_processor)) + && (op->processors & target_processor) + && !(op->processors & PROCESSOR_OPTION_ALIAS)) { + /* Code check start. */ const unsigned char *opindex_ptr; unsigned int opnum; unsigned int memop; + for (opindex_ptr = op->operands, opnum = 1; + *opindex_ptr != 0; + opindex_ptr++, opnum++) + { + int invalid = 0; + long value; + + operand = &v850_operands[*opindex_ptr]; + + value = get_operand_value (operand, insn, bytes_read, memaddr, info, 1, &invalid); + + if (invalid) + goto next_opcode; + + if ((operand->flags & V850_NOT_R0) && value == 0 && (op->memop) <=2) + goto next_opcode; + + if ((operand->flags & V850_NOT_SA) && value == 0xd) + goto next_opcode; + + if ((operand->flags & V850_NOT_IMM0) && value == 0) + goto next_opcode; + } + + /* Code check end. */ + match = 1; (*info->fprintf_func) (info->stream, "%s\t", op->name); +#if 0 + fprintf (stderr, "match: insn: %lx, mask: %lx, opcode: %lx, name: %s\n", + insn, op->mask, op->opcode, op->name ); +#endif memop = op->memop; /* Now print the operands. @@ -116,24 +285,11 @@ disassemble (bfd_vma memaddr, { long value; int flag; - int status; - bfd_byte buffer[4]; + char *prefix; operand = &v850_operands[*opindex_ptr]; - if (operand->extract) - value = (operand->extract) (insn, 0); - else - { - if (operand->bits == -1) - value = (insn & operand->shift); - else - value = (insn >> operand->shift) & ((1 << operand->bits) - 1); - - if (operand->flags & V850_OPERAND_SIGNED) - value = ((long)(value << (32 - operand->bits)) - >> (32 - operand->bits)); - } + value = get_operand_value (operand, insn, bytes_read, memaddr, info, 0, 0); /* The first operand is always output without any special handling. @@ -156,88 +312,57 @@ disassemble (bfd_vma memaddr, The exception (and there's always an exception) is the "jmp" insn which needs square brackets around it's only register argument. */ + prefix = ""; + if (operand->flags & V850_OPERAND_BANG) + { + prefix = "!"; + } + else if (operand->flags & V850_OPERAND_PERCENT) + { + prefix = "%"; + } - if (memop && opnum == memop + 1) - info->fprintf_func (info->stream, "["); - else if (memop && opnum == memop + 2) - info->fprintf_func (info->stream, "],"); - else if (memop == 1 && opnum == 1 - && (operand->flags & V850_OPERAND_REG)) - info->fprintf_func (info->stream, "["); - else if (opnum > 1) - info->fprintf_func (info->stream, ", "); - - /* Extract the flags, ignorng ones which - do not effect disassembly output. */ - flag = operand->flags; - flag &= ~ V850_OPERAND_SIGNED; - flag &= ~ V850_OPERAND_RELAX; - flag &= - flag; + if (opnum == 1 && opnum == memop) + info->fprintf_func (info->stream, "%s[", prefix); + else if (opnum > 1 + && (v850_operands[*(opindex_ptr - 1)].flags & V850_OPERAND_DISP) != 0 + && opnum == memop) + info->fprintf_func (info->stream, "%s[", prefix); + else if (opnum > 1) + info->fprintf_func (info->stream, ", %s", prefix); + + /* Extract the flags, ignoring ones which do not effect disassembly output. */ + flag = operand->flags & (V850_OPERAND_REG + | V850_REG_EVEN + | V850_OPERAND_EP + | V850_OPERAND_SRG + | V850E_OPERAND_REG_LIST + | V850_OPERAND_CC + | V850_OPERAND_FLOAT_CC); switch (flag) { - case V850_OPERAND_REG: - info->fprintf_func (info->stream, "%s", v850_reg_names[value]); - break; - case V850_OPERAND_SRG: - info->fprintf_func (info->stream, "%s", v850_sreg_names[value]); - break; - case V850_OPERAND_CC: - info->fprintf_func (info->stream, "%s", v850_cc_names[value]); - break; - case V850_OPERAND_EP: - info->fprintf_func (info->stream, "ep"); - break; - default: - info->fprintf_func (info->stream, "%ld", value); - break; - case V850_OPERAND_DISP: - { - bfd_vma addr = value + memaddr; - - /* On the v850 the top 8 bits of an address are used by an - overlay manager. Thus it may happen that when we are - looking for a symbol to match against an address with - some of its top bits set, the search fails to turn up an - exact match. In this case we try to find an exact match - against a symbol in the lower address space, and if we - find one, we use that address. We only do this for - JARL instructions however, as we do not want to - misinterpret branch instructions. */ - if (operand->bits == 22) - { - if ( ! info->symbol_at_address_func (addr, info) - && ((addr & 0xFF000000) != 0) - && info->symbol_at_address_func (addr & 0x00FFFFFF, info)) - addr &= 0x00FFFFFF; - } - info->print_address_func (addr, info); - break; - } + case V850_OPERAND_REG: info->fprintf_func (info->stream, "%s", v850_reg_names[value]); break; + case (V850_OPERAND_REG|V850_REG_EVEN): info->fprintf_func (info->stream, "%s", v850_reg_names[value*2]); break; + case V850_OPERAND_EP: info->fprintf_func (info->stream, "ep"); break; + case V850_OPERAND_SRG: info->fprintf_func (info->stream, "%s", v850_sreg_names[value]); break; - case V850E_PUSH_POP: + case V850E_OPERAND_REG_LIST: { - static int list12_regs[32] = { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 }; - static int list18_h_regs[32] = { 19, 18, 17, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 30, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 }; - static int list18_l_regs[32] = { 3, 2, 1, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, 14, 15, 13, 12, 7, 6, 5, 4, 11, 10, 9, 8 }; + static int list12_regs[32] = { 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 31, 29, 28, 23, 22, 21, 20, 27, 26, 25, 24 }; int *regs; int i; unsigned long int mask = 0; int pc = 0; - int sr = 0; + switch (operand->shift) { case 0xffe00001: regs = list12_regs; break; - case 0xfff8000f: regs = list18_h_regs; break; - case 0xfff8001f: - regs = list18_l_regs; - value &= ~0x10; /* Do not include magic bit. */ - break; default: /* xgettext:c-format */ - fprintf (stderr, _("unknown operand shift: %x\n"), - operand->shift); + fprintf (stderr, _("unknown operand shift: %x\n"), operand->shift ); abort (); } @@ -249,18 +374,15 @@ disassemble (bfd_vma memaddr, { default: mask |= (1 << regs[ i ]); break; /* xgettext:c-format */ - case 0: - fprintf (stderr, _("unknown pop reg: %d\n"), i ); - abort (); + case 0: fprintf (stderr, _("unknown reg: %d\n"), i ); abort (); case -1: pc = 1; break; - case -2: sr = 1; break; } } } info->fprintf_func (info->stream, "{"); - if (mask || pc || sr) + if (mask || pc) { if (mask) { @@ -278,8 +400,7 @@ disassemble (bfd_vma memaddr, else shown_one = 1; - info->fprintf_func (info->stream, - v850_reg_names[first]); + info->fprintf_func (info->stream, v850_reg_names[first]); for (bit++; bit < 32; bit++) if ((mask & (1 << bit)) == 0) @@ -288,113 +409,227 @@ disassemble (bfd_vma memaddr, last = bit; if (last > first + 1) - info->fprintf_func (info->stream, " - %s", - v850_reg_names[last - 1]); + { + info->fprintf_func (info->stream, " - %s", v850_reg_names[ last - 1 ]); + } } } if (pc) info->fprintf_func (info->stream, "%sPC", mask ? ", " : ""); - if (sr) - info->fprintf_func (info->stream, "%sSR", (mask || pc) ? ", " : ""); } info->fprintf_func (info->stream, "}"); } - break; - - case V850E_IMMEDIATE16: - status = info->read_memory_func (memaddr + bytes_read, - buffer, 2, info); - if (status == 0) - { - bytes_read += 2; - value = bfd_getl16 (buffer); - - /* If this is a DISPOSE instruction with ff - set to 0x10, then shift value up by 16. */ - if ((insn & 0x001fffc0) == 0x00130780) - value <<= 16; - - info->fprintf_func (info->stream, "0x%lx", value); - } - else - info->memory_error_func (status, memaddr + bytes_read, - info); break; - case V850E_IMMEDIATE32: - status = info->read_memory_func (memaddr + bytes_read, - buffer, 4, info); - if (status == 0) - { - bytes_read += 4; - value = bfd_getl32 (buffer); - info->fprintf_func (info->stream, "0x%lx", value); - } - else - info->memory_error_func (status, memaddr + bytes_read, - info); + case V850_OPERAND_CC: info->fprintf_func (info->stream, "%s", v850_cc_names[value]); break; + case V850_OPERAND_FLOAT_CC: info->fprintf_func (info->stream, "%s", v850_float_cc_names[value]); break; + + default: + print_value (operand->flags, memaddr, info, value); break; } - /* Handle jmp correctly. */ - if (memop == 1 && opnum == 1 - && ((operand->flags & V850_OPERAND_REG) != 0)) + if (opnum == 2 && opnum == memop) (*info->fprintf_func) (info->stream, "]"); } - /* Close any square bracket we left open. */ - if (memop && opnum == memop + 2) - (*info->fprintf_func) (info->stream, "]"); - /* All done. */ break; } + next_opcode: op++; } - if (!match) - { - if (short_op) - info->fprintf_func (info->stream, ".short\t0x%04lx", insn); - else - info->fprintf_func (info->stream, ".long\t0x%08lx", insn); - } - - return bytes_read; + return match; } int print_insn_v850 (bfd_vma memaddr, struct disassemble_info * info) { - int status; - bfd_byte buffer[4]; - unsigned long insn = 0; + int status, status2, match; + bfd_byte buffer[8]; + int length = 0, code_length = 0; + unsigned long insn = 0, insn2 = 0; + int target_processor; + + switch (info->mach) + { + case 0: + default: + target_processor = PROCESSOR_V850; + break; + + case bfd_mach_v850e: + target_processor = PROCESSOR_V850E; + break; + + case bfd_mach_v850e1: + target_processor = PROCESSOR_V850E; + break; + + case bfd_mach_v850e2: + target_processor = PROCESSOR_V850E2; + break; + + case bfd_mach_v850e2v3: + target_processor = PROCESSOR_V850E2V3; + break; + } - /* First figure out how big the opcode is. */ status = info->read_memory_func (memaddr, buffer, 2, info); - if (status == 0) + + if (status) + { + info->memory_error_func (status, memaddr, info); + return -1; + } + + insn = bfd_getl16 (buffer); + + status2 = info->read_memory_func (memaddr+2, buffer, 2 , info); + + if (!status2) { - insn = bfd_getl16 (buffer); + insn2 = bfd_getl16 (buffer); + /* fprintf (stderr, "insn2 0x%08lx\n", insn2); */ + } - if ( (insn & 0x0600) == 0x0600 - && (insn & 0xffe0) != 0x0620) + /* Special case. */ + if (length == 0 + && (target_processor == PROCESSOR_V850E2 + || target_processor == PROCESSOR_V850E2V3)) + { + if ((insn & 0xffff) == 0x02e0 /* jr 32bit */ + && !status2 && (insn2 & 0x1) == 0) + { + length = 2; + code_length = 6; + } + else if ((insn & 0xffe0) == 0x02e0 /* jarl 32bit */ + && !status2 && (insn2 & 0x1) == 0) + { + length = 2; + code_length = 6; + } + else if ((insn & 0xffe0) == 0x06e0 /* jmp 32bit */ + && !status2 && (insn2 & 0x1) == 0) { - /* If this is a 4 byte insn, read 4 bytes of stuff. */ - status = info->read_memory_func (memaddr, buffer, 4, info); + length = 2; + code_length = 6; + } + } - if (status == 0) - insn = bfd_getl32 (buffer); + if (length == 0 + && target_processor == PROCESSOR_V850E2V3) + { + if (((insn & 0xffe0) == 0x0780 /* ld.b 23bit */ + && !status2 && (insn2 & 0x000f) == 0x0005) + || ((insn & 0xffe0) == 0x07a0 /* ld.bu 23bit */ + && !status2 && (insn2 & 0x000f) == 0x0005) + || ((insn & 0xffe0) == 0x0780 /* ld.h 23bit */ + && !status2 && (insn2 & 0x000f) == 0x0007) + || ((insn & 0xffe0) == 0x07a0 /* ld.hu 23bit */ + && !status2 && (insn2 & 0x000f) == 0x0007) + || ((insn & 0xffe0) == 0x0780 /* ld.w 23bit */ + && !status2 && (insn2 & 0x000f) == 0x0009)) + { + length = 4; + code_length = 6; + } + else if (((insn & 0xffe0) == 0x0780 /* st.b 23bit */ + && !status2 && (insn2 & 0x000f) == 0x000d) + || ((insn & 0xffe0) == 0x07a0 /* st.h 23bit */ + && !status2 && (insn2 & 0x000f) == 0x000d) + || ((insn & 0xffe0) == 0x0780 /* st.w 23bit */ + && !status2 && (insn2 & 0x000f) == 0x000f)) + { + length = 4; + code_length = 6; } } - if (status != 0) + if (length == 0 + && target_processor != PROCESSOR_V850) { - info->memory_error_func (status, memaddr, info); - return -1; + if ((insn & 0xffe0) == 0x0620) /* 32 bit MOV */ + { + length = 2; + code_length = 6; + } + else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16<<16 */ + && !status2 && (insn2 & 0x001f) == 0x0013) + { + length = 4; + code_length = 6; + } + else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm16 */ + && !status2 && (insn2 & 0x001f) == 0x000b) + { + length = 4; + code_length = 6; + } + else if ((insn & 0xffc0) == 0x0780 /* prepare {list}, imm5, imm32 */ + && !status2 && (insn2 & 0x001f) == 0x001b) + { + length = 4; + code_length = 8; + } + } + + if (length == 4 + || (length == 0 + && (insn & 0x0600) == 0x0600)) + { + /* This is a 4 byte insn. */ + status = info->read_memory_func (memaddr, buffer, 4, info); + if (!status) + { + insn = bfd_getl32 (buffer); + + if (!length) + length = code_length = 4; + } + } + + if (code_length > length) + { + status = info->read_memory_func (memaddr + length, buffer, code_length - length, info); + if (status) + length = 0; + } + + if (length == 0 && !status) + length = code_length = 2; + + if (length == 2) + insn &= 0xffff; + + match = disassemble (memaddr, info, length, insn); + + if (!match) + { + int l = 0; + + status = info->read_memory_func (memaddr, buffer, code_length, info); + + while (l < code_length) + { + if (code_length - l == 2) + { + insn = bfd_getl16 (buffer + l) & 0xffff; + info->fprintf_func (info->stream, ".short\t0x%04lx", insn); + l += 2; + } + else + { + insn = bfd_getl32 (buffer + l); + info->fprintf_func (info->stream, ".long\t0x%08lx", insn); + l += 4; + } + } } - /* Make sure we tell our caller how many bytes we consumed. */ - return disassemble (memaddr, info, insn); + return code_length; } diff --git a/opcodes/v850-opc.c b/opcodes/v850-opc.c index 99c168b5d78..eea427c881f 100644 --- a/opcodes/v850-opc.c +++ b/opcodes/v850-opc.c @@ -1,5 +1,5 @@ /* Assemble V850 instructions. - Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2007 + Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2005, 2007, 2010 Free Software Foundation, Inc. This file is part of the GNU opcodes library. @@ -19,24 +19,31 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ +#include #include "sysdep.h" #include "opcode/v850.h" -#include +#include "bfd.h" #include "opintl.h" + /* Regular opcodes. */ #define OP(x) ((x & 0x3f) << 5) #define OP_MASK OP (0x3f) -/* Conditional branch opcodes. */ -#define BOP(x) ((0x0b << 7) | (x & 0x0f)) -#define BOP_MASK ((0x0f << 7) | 0x0f) +/* Conditional branch opcodes (Format III). */ +#define BOP(x) ((0x58 << 4) | (x & 0x0f)) +#define BOP_MASK ((0x78 << 4) | 0x0f) + +/* Conditional branch opcodes (Format VII). */ +#define BOP7(x) (0x107e0 | (x & 0xf)) +#define BOP7_MASK (0x1ffe0 | 0xf) /* One-word opcodes. */ #define one(x) ((unsigned int) (x)) /* Two-word opcodes. */ #define two(x,y) ((unsigned int) (x) | ((unsigned int) (y) << 16)) + /* The functions used to insert and extract complicated operands. */ @@ -50,106 +57,134 @@ static const char * out_of_range = N_ ("displacement value is out of range"); static const char * not_aligned = N_ ("displacement value is not aligned"); static const char * immediate_out_of_range = N_ ("immediate value is out of range"); +static const char * branch_out_of_range = N_ ("branch value out of range"); +static const char * branch_out_of_range_and_odd_offset = N_ ("branch value not in range and to odd offset"); +static const char * branch_to_odd_offset = N_ ("branch to odd offset"); + + +int +v850_msg_is_out_of_range (const char* msg) +{ + return msg == out_of_range + || msg == immediate_out_of_range + || msg == branch_out_of_range; +} static unsigned long -insert_d9 (unsigned long insn, long value, const char ** errmsg) +insert_i5div1 (unsigned long insn, long value, const char ** errmsg) { - if (value > 0xff || value < -0x100) + if (value > 30 || value < 2) { - if ((value % 2) != 0) - * errmsg = _("branch value not in range and to odd offset"); + if (value & 1) + * errmsg = _(not_valid); else - * errmsg = _("branch value out of range"); + * errmsg = _(out_of_range); } - else if ((value % 2) != 0) - * errmsg = _("branch to odd offset"); + else if (value & 1) + * errmsg = _(not_aligned); - return insn | ((value & 0x1f0) << 7) | ((value & 0x0e) << 3); + value = (32 - value)/2; + + return (insn | ((value << (2+16)) & 0x3c0000)); } static unsigned long -extract_d9 (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) +extract_i5div1 (unsigned long insn, int * invalid) { - unsigned long ret = ((insn & 0xf800) >> 7) | ((insn & 0x0070) >> 3); - - if ((insn & 0x8000) != 0) - ret -= 0x0200; + unsigned long ret = (insn & 0x003c0000) >> (16+2); + ret = 32 - (ret * 2); + if (invalid != 0) + *invalid = (ret > 30 || ret < 2) ? 1 : 0; return ret; } static unsigned long -insert_d22 (unsigned long insn, long value, const char ** errmsg) +insert_i5div2 (unsigned long insn, long value, const char ** errmsg) { - if (value > 0x1fffff || value < -0x200000) + if (value > 30 || value < 4) { - if ((value % 2) != 0) - * errmsg = _("branch value not in range and to an odd offset"); + if (value & 1) + * errmsg = _(not_valid); else - * errmsg = _("branch value out of range"); + * errmsg = _(out_of_range); } - else if ((value % 2) != 0) - * errmsg = _("branch to odd offset"); + else if (value & 1) + * errmsg = _(not_aligned); - return insn | ((value & 0xfffe) << 16) | ((value & 0x3f0000) >> 16); + value = (32 - value)/2; + + return (insn | ((value << (2+16)) & 0x3c0000)); } static unsigned long -extract_d22 (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) +extract_i5div2 (unsigned long insn, int * invalid) { - signed long ret = ((insn & 0xfffe0000) >> 16) | ((insn & 0x3f) << 16); + unsigned long ret = (insn & 0x003c0000) >> (16+2); + ret = 32 - (ret * 2); - return (unsigned long) ((ret << 10) >> 10); + if (invalid != 0) + *invalid = (ret > 30 || ret < 4) ? 1 : 0; + return ret; } static unsigned long -insert_d16_15 (unsigned long insn, long value, const char ** errmsg) +insert_i5div3 (unsigned long insn, long value, const char ** errmsg) { - if (value > 0x7fff || value < -0x8000) + if (value > 32 || value < 2) { - if ((value % 2) != 0) + if (value & 1) * errmsg = _(not_valid); else * errmsg = _(out_of_range); } - else if ((value % 2) != 0) + else if (value & 1) * errmsg = _(not_aligned); - return insn | ((value & 0xfffe) << 16); + value = (32 - value)/2; + + return (insn | ((value << (2+16)) & 0x3c0000)); } static unsigned long -extract_d16_15 (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) +extract_i5div3 (unsigned long insn, int * invalid) { - signed long ret = (insn & 0xfffe0000); + unsigned long ret = (insn & 0x003c0000) >> (16+2); + ret = 32 - (ret * 2); - return ret >> 16; + if (invalid != 0) + *invalid = (ret > 32 || ret < 2) ? 1 : 0; + return ret; } static unsigned long -insert_d8_7 (unsigned long insn, long value, const char ** errmsg) +insert_d5_4 (unsigned long insn, long value, const char ** errmsg) { - if (value > 0xff || value < 0) + if (value > 0x1f || value < 0) { - if ((value % 2) != 0) + if (value & 1) * errmsg = _(not_valid); else * errmsg = _(out_of_range); } - else if ((value % 2) != 0) + else if (value & 1) * errmsg = _(not_aligned); value >>= 1; - return insn | (value & 0x7f); + return insn | (value & 0x0f); } static unsigned long -extract_d8_7 (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) +extract_d5_4 (unsigned long insn, int * invalid) { - unsigned long ret = (insn & 0x7f); + unsigned long ret = (insn & 0x0f); + + ret <<= 1; - return ret << 1; + if (invalid != 0) + *invalid = 0; + return ret; } static unsigned long @@ -158,7 +193,7 @@ insert_d8_6 (unsigned long insn, long value, const char ** errmsg) if (value > 0xff || value < 0) { if ((value % 4) != 0) - *errmsg = _(not_valid); + * errmsg = _(not_valid); else * errmsg = _(out_of_range); } @@ -171,37 +206,147 @@ insert_d8_6 (unsigned long insn, long value, const char ** errmsg) } static unsigned long -extract_d8_6 (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) +extract_d8_6 (unsigned long insn, int * invalid) { unsigned long ret = (insn & 0x7e); - return ret << 1; + ret <<= 1; + + if (invalid != 0) + *invalid = 0; + return ret; } static unsigned long -insert_d5_4 (unsigned long insn, long value, const char ** errmsg) +insert_d8_7 (unsigned long insn, long value, const char ** errmsg) { - if (value > 0x1f || value < 0) + if (value > 0xff || value < 0) { - if (value & 1) + if ((value % 2) != 0) * errmsg = _(not_valid); else - *errmsg = _(out_of_range); + * errmsg = _(out_of_range); } - else if (value & 1) + else if ((value % 2) != 0) * errmsg = _(not_aligned); value >>= 1; - return insn | (value & 0x0f); + return insn | (value & 0x7f); } static unsigned long -extract_d5_4 (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) +extract_d8_7 (unsigned long insn, int * invalid) { - unsigned long ret = (insn & 0x0f); + unsigned long ret = (insn & 0x7f); + + ret <<= 1; + + if (invalid != 0) + *invalid = 0; + return ret; +} + +static unsigned long +insert_v8 (unsigned long insn, long value, const char ** errmsg) +{ + if (value > 0xff || value < 0) + * errmsg = _(immediate_out_of_range); + + return insn | (value & 0x1f) | ((value & 0xe0) << (27-5)); +} + +static unsigned long +extract_v8 (unsigned long insn, int * invalid) +{ + unsigned long ret = (insn & 0x1f) | ((insn & 0x38000000) >> (27-5)); + + if (invalid != 0) + *invalid = 0; + return ret; +} + +static unsigned long +insert_d9 (unsigned long insn, long value, const char ** errmsg) +{ + if (value > 0xff || value < -0x100) + { + if ((value % 2) != 0) + * errmsg = branch_out_of_range_and_odd_offset; + else + * errmsg = branch_out_of_range; + } + else if ((value % 2) != 0) + * errmsg = branch_to_odd_offset; + + return insn | ((value & 0x1f0) << 7) | ((value & 0x0e) << 3); +} + +static unsigned long +extract_d9 (unsigned long insn, int * invalid) +{ + unsigned long ret = ((insn & 0xf800) >> 7) | ((insn & 0x0070) >> 3); + + if ((insn & 0x8000) != 0) + ret -= 0x0200; + + if (invalid != 0) + *invalid = 0; + return ret; +} + +static unsigned long +insert_u16_loop (unsigned long insn, long value, const char ** errmsg) +{ + if (value < -0xffff || value > 0) + { + if ((value % 2) != 0) + * errmsg = branch_out_of_range_and_odd_offset; + else + * errmsg = branch_out_of_range; + } + else if ((value % 2) != 0) + * errmsg = branch_to_odd_offset; + + return insn | ((-value & 0xfffe) << 16); +} + +static unsigned long +extract_u16_loop (unsigned long insn, int * invalid) +{ + long ret = (insn >> 16) & 0xfffe; + ret = -ret; + + if (invalid != 0) + *invalid = 0; + return ret; +} + +static unsigned long +insert_d16_15 (unsigned long insn, long value, const char ** errmsg) +{ + if (value > 0x7fff || value < -0x8000) + { + if ((value % 2) != 0) + * errmsg = _(not_valid); + else + * errmsg = _(out_of_range); + } + else if ((value % 2) != 0) + * errmsg = _(not_aligned); + + return insn | ((value & 0xfffe) << 16); +} + +static unsigned long +extract_d16_15 (unsigned long insn, int * invalid) +{ + signed long ret = (insn & 0xfffe0000); + ret >>= 16; - return ret << 1; + if (invalid != 0) + *invalid = 0; + return ret; } static unsigned long @@ -214,17 +359,87 @@ insert_d16_16 (unsigned long insn, signed long value, const char ** errmsg) } static unsigned long -extract_d16_16 (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) +extract_d16_16 (unsigned long insn, int * invalid) { signed long ret = insn & 0xfffe0000; - ret >>= 16; - ret |= ((insn & 0x20) >> 5); + if (invalid != 0) + *invalid = 0; return ret; } +static unsigned long +insert_d17_16 (unsigned long insn, long value, const char ** errmsg) +{ + if (value > 0xffff || value < -0x10000) + * errmsg = _(out_of_range); + + return insn | ((value & 0xfffe) << 16) | ((value & 0x10000) >> (16 - 4)); +} + +static unsigned long +extract_d17_16 (unsigned long insn, int * invalid) +{ + signed long ret = (insn >> 16) & 0xfffe; + ret |= (insn << (16 - 4)) & 0x10000; + ret = (ret << ((sizeof ret)*8 - 17)) >> ((sizeof ret)*8 - 17); + + if (invalid != 0) + *invalid = 0; + return (unsigned long)ret; +} + +static unsigned long +insert_d22 (unsigned long insn, long value, const char ** errmsg) +{ + if (value > 0x1fffff || value < -0x200000) + { + if ((value % 2) != 0) + * errmsg = branch_out_of_range_and_odd_offset; + else + * errmsg = branch_out_of_range; + } + else if ((value % 2) != 0) + * errmsg = branch_to_odd_offset; + + return insn | ((value & 0xfffe) << 16) | ((value & 0x3f0000) >> 16); +} + +static unsigned long +extract_d22 (unsigned long insn, int * invalid) +{ + signed long ret = ((insn & 0xfffe0000) >> 16) | ((insn & 0x3f) << 16); + + ret = (ret << ((sizeof ret)*8 - 22)) >> ((sizeof ret)*8 - 22); + + if (invalid != 0) + *invalid = 0; + return (unsigned long) ret; +} + +static unsigned long +insert_d23 (unsigned long insn, long value, const char ** errmsg) +{ + if (value > 0x3fffff || value < -0x400000) + * errmsg = out_of_range; + + return insn | ((value & 0x7f) << 4) | ((value & 0x7fff80) << (16-7)); +} + +static unsigned long +extract_d23 (unsigned long insn, int * invalid) +{ + signed long ret = ((insn >> 4) & 0x7f) | ((insn >> (16-7)) & 0x7fffff80); + + ret = ((ret << ((sizeof ret)*8 - 23)) >> ((sizeof ret)*8 - 23)); + + if (invalid != 0) + *invalid = 0; + return (unsigned long) ret; +} + static unsigned long insert_i9 (unsigned long insn, signed long value, const char ** errmsg) { @@ -235,15 +450,16 @@ insert_i9 (unsigned long insn, signed long value, const char ** errmsg) } static unsigned long -extract_i9 (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) +extract_i9 (unsigned long insn, int * invalid) { signed long ret = insn & 0x003c0000; ret <<= 10; ret >>= 23; - ret |= (insn & 0x1f); + if (invalid != 0) + *invalid = 0; return ret; } @@ -259,7 +475,7 @@ insert_u9 (unsigned long insn, long v, const char ** errmsg) } static unsigned long -extract_u9 (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) +extract_u9 (unsigned long insn, int * invalid) { unsigned long ret = insn & 0x003c0000; @@ -267,6 +483,8 @@ extract_u9 (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) ret |= (insn & 0x1f); + if (invalid != 0) + *invalid = 0; return ret; } @@ -282,44 +500,38 @@ insert_spe (unsigned long insn, long v, const char ** errmsg) } static unsigned long -extract_spe (unsigned long insn ATTRIBUTE_UNUSED, - int * invalid ATTRIBUTE_UNUSED) +extract_spe (unsigned long insn ATTRIBUTE_UNUSED, int * invalid) { + if (invalid != 0) + *invalid = 0; + return 3; } static unsigned long -insert_i5div (unsigned long insn, long v, const char ** errmsg) +insert_r4 (unsigned long insn, long v, const char ** errmsg) { unsigned long value = (unsigned long) v; - if (value > 0x1ff) + if (value >= 32) { - if (value & 1) - * errmsg = _("immediate value not in range and not even"); - else - * errmsg = _(immediate_out_of_range); + * errmsg = _("invalid register name"); } - else if (value & 1) - * errmsg = _("immediate value must be even"); - - value = 32 - value; - return insn | ((value & 0x1e) << 17); + return insn | ((value & 0x10) << (23-4)) | ((value & 0x0f) << (17)); } static unsigned long -extract_i5div (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) +extract_r4 (unsigned long insn, int * invalid) { - unsigned long ret = insn & 0x3c0000; - - ret >>= 17; - - ret = 32 - ret; + unsigned long ret; + ret = (insn >> 17) & 0xf; + ret |= (insn >> (23-4)) & 0x10; + if (invalid != 0) + *invalid = 0; return ret; } - /* Warning: code in gas/config/tc-v850.c examines the contents of this array. If you change any of the values here, be sure to look for side effects in @@ -327,169 +539,284 @@ extract_i5div (unsigned long insn, int * invalid ATTRIBUTE_UNUSED) const struct v850_operand v850_operands[] = { #define UNUSED 0 - { 0, 0, NULL, NULL, 0 }, + { 0, 0, NULL, NULL, 0, BFD_RELOC_NONE }, -/* The R1 field in a format 1, 6, 7, or 9 insn. */ +/* The R1 field in a format 1, 6, 7, 9, C insn. */ #define R1 (UNUSED + 1) - { 5, 0, NULL, NULL, V850_OPERAND_REG }, + { 5, 0, NULL, NULL, V850_OPERAND_REG, BFD_RELOC_NONE }, /* As above, but register 0 is not allowed. */ #define R1_NOTR0 (R1 + 1) - { 5, 0, NULL, NULL, V850_OPERAND_REG | V850_NOT_R0 }, + { 5, 0, NULL, NULL, V850_OPERAND_REG | V850_NOT_R0, BFD_RELOC_NONE }, + +/* Even register is allowed. */ +#define R1_EVEN (R1_NOTR0 + 1) + { 4, 1, NULL, NULL, V850_OPERAND_REG | V850_REG_EVEN, BFD_RELOC_NONE }, + +/* Bang (bit reverse). */ +#define R1_BANG (R1_EVEN + 1) + { 5, 0, NULL, NULL, V850_OPERAND_REG | V850_OPERAND_BANG, BFD_RELOC_NONE }, + +/* Percent (modulo). */ +#define R1_PERCENT (R1_BANG + 1) + { 5, 0, NULL, NULL, V850_OPERAND_REG | V850_OPERAND_PERCENT, BFD_RELOC_NONE }, -/* The R2 field in a format 1, 2, 4, 5, 6, 7, 9 insn. */ -#define R2 (R1_NOTR0 + 1) - { 5, 11, NULL, NULL, V850_OPERAND_REG }, +/* The R2 field in a format 1, 2, 4, 5, 6, 7, 9, C insn. */ +#define R2 (R1_PERCENT + 1) + { 5, 11, NULL, NULL, V850_OPERAND_REG, BFD_RELOC_NONE }, /* As above, but register 0 is not allowed. */ #define R2_NOTR0 (R2 + 1) - { 5, 11, NULL, NULL, V850_OPERAND_REG | V850_NOT_R0 }, + { 5, 11, NULL, NULL, V850_OPERAND_REG | V850_NOT_R0, BFD_RELOC_NONE }, -/* The imm5 field in a format 2 insn. */ -#define I5 (R2_NOTR0 + 1) - { 5, 0, NULL, NULL, V850_OPERAND_SIGNED }, - -/* The unsigned imm5 field in a format 2 insn. */ -#define I5U (I5 + 1) - { 5, 0, NULL, NULL, 0 }, +/* Even register is allowed. */ +#define R2_EVEN (R2_NOTR0 + 1) + { 4, 12, NULL, NULL, V850_OPERAND_REG | V850_REG_EVEN, BFD_RELOC_NONE }, -/* The imm16 field in a format 6 insn. */ -#define I16 (I5U + 1) - { 16, 16, NULL, NULL, V850_OPERAND_SIGNED }, +/* Reg2 in dispose instruction. */ +#define R2_DISPOSE (R2_EVEN + 1) + { 5, 16, NULL, NULL, V850_OPERAND_REG | V850_NOT_R0, BFD_RELOC_NONE }, -/* The signed disp7 field in a format 4 insn. */ -#define D7 (I16 + 1) - { 7, 0, NULL, NULL, 0}, +/* The R3 field in a format 11, 12, C insn. */ +#define R3 (R2_DISPOSE + 1) + { 5, 27, NULL, NULL, V850_OPERAND_REG, BFD_RELOC_NONE }, -/* The disp16 field in a format 6 insn. */ -#define D16_15 (D7 + 1) - { 15, 17, insert_d16_15, extract_d16_15, V850_OPERAND_SIGNED }, +/* As above, but register 0 is not allowed. */ +#define R3_NOTR0 (R3 + 1) + { 5, 27, NULL, NULL, V850_OPERAND_REG | V850_NOT_R0, BFD_RELOC_NONE }, -/* The 3 bit immediate field in format 8 insn. */ -#define B3 (D16_15 + 1) - { 3, 11, NULL, NULL, 0 }, +/* As above, but odd number registers are not allowed. */ +#define R3_EVEN (R3_NOTR0 + 1) + { 4, 28, NULL, NULL, V850_OPERAND_REG | V850_REG_EVEN, BFD_RELOC_NONE }, -/* The 4 bit condition code in a setf instruction */ -#define CCCC (B3 + 1) - { 4, 0, NULL, NULL, V850_OPERAND_CC }, +/* As above, but register 0 is not allowed. */ +#define R3_EVEN_NOTR0 (R3_EVEN + 1) + { 4, 28, NULL, NULL, V850_OPERAND_REG | V850_REG_EVEN | V850_NOT_R0, BFD_RELOC_NONE }, -/* The unsigned DISP8 field in a format 4 insn. */ -#define D8_7 (CCCC + 1) - { 7, 0, insert_d8_7, extract_d8_7, 0 }, +/* Forth register in FPU Instruction. */ +#define R4 (R3_EVEN_NOTR0 + 1) + { 5, 0, insert_r4, extract_r4, V850_OPERAND_REG, BFD_RELOC_NONE }, -/* The unsigned DISP8 field in a format 4 insn. */ -#define D8_6 (D8_7 + 1) - { 6, 1, insert_d8_6, extract_d8_6, 0 }, +/* As above, but odd number registers are not allowed. */ +#define R4_EVEN (R4 + 1) + { 4, 17, NULL, NULL, V850_OPERAND_REG | V850_REG_EVEN, BFD_RELOC_NONE }, -/* System register operands. */ -#define SR1 (D8_6 + 1) - { 5, 0, NULL, NULL, V850_OPERAND_SRG }, +/* Stack pointer in prepare instruction. */ +#define SP (R4_EVEN + 1) + { 2, 0, insert_spe, extract_spe, V850_OPERAND_REG, BFD_RELOC_NONE }, /* EP Register. */ -#define EP (SR1 + 1) - { 0, 0, NULL, NULL, V850_OPERAND_EP }, +#define EP (SP + 1) + { 0, 0, NULL, NULL, V850_OPERAND_EP, BFD_RELOC_NONE }, + +/* A list of registers in a prepare/dispose instruction. */ +#define LIST12 (EP + 1) + { -1, 0xffe00001, NULL, NULL, V850E_OPERAND_REG_LIST, BFD_RELOC_NONE }, -/* The imm16 field (unsigned) in a format 6 insn. */ -#define I16U (EP + 1) - { 16, 16, NULL, NULL, 0}, +/* System register operands. */ +#define SR1 (LIST12 + 1) + { 5, 0, NULL, NULL, V850_OPERAND_SRG, BFD_RELOC_NONE }, /* The R2 field as a system register. */ -#define SR2 (I16U + 1) - { 5, 11, NULL, NULL, V850_OPERAND_SRG }, +#define SR2 (SR1 + 1) + { 5, 11, NULL, NULL, V850_OPERAND_SRG, BFD_RELOC_NONE }, -/* The disp16 field in a format 8 insn. */ -#define D16 (SR2 + 1) - { 16, 16, NULL, NULL, V850_OPERAND_SIGNED }, +/* FPU CC bit position. */ +#define FFF (SR2 + 1) + { 3, 17, NULL, NULL, 0, BFD_RELOC_NONE }, -/* The DISP9 field in a format 3 insn, relaxable. */ -#define D9_RELAX (D16 + 1) - { 9, 0, insert_d9, extract_d9, V850_OPERAND_RELAX | V850_OPERAND_SIGNED | V850_OPERAND_DISP }, +/* The 4 bit condition code in a setf instruction. */ +#define CCCC (FFF + 1) + { 4, 0, NULL, NULL, V850_OPERAND_CC, BFD_RELOC_NONE }, -/* The DISP22 field in a format 4 insn, relaxable. - This _must_ follow D9_RELAX; the assembler assumes that the longer - version immediately follows the shorter version for relaxing. */ -#define D22 (D9_RELAX + 1) - { 22, 0, insert_d22, extract_d22, V850_OPERAND_SIGNED | V850_OPERAND_DISP }, +/* Condition code in adf,sdf. */ +#define CCCC_NOTSA (CCCC + 1) + { 4, 17, NULL, NULL, V850_OPERAND_CC|V850_NOT_SA, BFD_RELOC_NONE }, -/* The signed disp4 field in a format 4 insn. */ -#define D4 (D22 + 1) - { 4, 0, NULL, NULL, 0}, +/* Condition code in conditional moves. */ +#define MOVCC (CCCC_NOTSA + 1) + { 4, 17, NULL, NULL, V850_OPERAND_CC, BFD_RELOC_NONE }, -/* The unsigned disp5 field in a format 4 insn. */ -#define D5_4 (D4 + 1) - { 4, 0, insert_d5_4, extract_d5_4, 0 }, +/* Condition code in FPU. */ +#define FLOAT_CCCC (MOVCC + 1) + { 4, 27, NULL, NULL, V850_OPERAND_FLOAT_CC, BFD_RELOC_NONE }, -/* The disp16 field in an format 7 unsigned byte load insn. */ -#define D16_16 (D5_4 + 1) - { -1, 0xfffe0020, insert_d16_16, extract_d16_16, 0 }, +/* The 1 bit immediate field in format C insn. */ +#define VI1 (FLOAT_CCCC + 1) + { 1, 3, NULL, NULL, 0, BFD_RELOC_NONE }, -/* Third register in conditional moves. */ -#define R3 (D16_16 + 1) - { 5, 27, NULL, NULL, V850_OPERAND_REG }, +/* The 1 bit immediate field in format C insn. */ +#define VC1 (VI1 + 1) + { 1, 0, NULL, NULL, 0, BFD_RELOC_NONE }, -/* Condition code in conditional moves. */ -#define MOVCC (R3 + 1) - { 4, 17, NULL, NULL, V850_OPERAND_CC }, +/* The 2 bit immediate field in format C insn. */ +#define DI2 (VC1 + 1) + { 2, 17, NULL, NULL, 0, BFD_RELOC_NONE }, -/* The imm9 field in a multiply word. */ -#define I9 (MOVCC + 1) - { 9, 0, insert_i9, extract_i9, V850_OPERAND_SIGNED }, +/* The 2 bit immediate field in format C insn. */ +#define VI2 (DI2 + 1) + { 2, 0, NULL, NULL, 0, BFD_RELOC_NONE }, -/* The unsigned imm9 field in a multiply word. */ -#define U9 (I9 + 1) - { 9, 0, insert_u9, extract_u9, 0 }, +/* The 2 bit immediate field in format C - DUP insn. */ +#define VI2DUP (VI2 + 1) + { 2, 2, NULL, NULL, 0, BFD_RELOC_NONE }, -/* A list of registers in a prepare/dispose instruction. */ -#define LIST12 (U9 + 1) - { -1, 0xffe00001, NULL, NULL, V850E_PUSH_POP }, +/* The 3 bit immediate field in format 8 insn. */ +#define B3 (VI2DUP + 1) + { 3, 11, NULL, NULL, 0, BFD_RELOC_NONE }, -/* The IMM6 field in a call instruction. */ -#define I6 (LIST12 + 1) - { 6, 0, NULL, NULL, 0 }, +/* The 3 bit immediate field in format C insn. */ +#define DI3 (B3 + 1) + { 3, 17, NULL, NULL, 0, BFD_RELOC_NONE }, -/* The 16 bit immediate following a 32 bit instruction. */ -#define IMM16 (I6 + 1) - { 16, 16, NULL, NULL, V850_OPERAND_SIGNED | V850E_IMMEDIATE16 }, +/* The 3 bit immediate field in format C insn. */ +#define I3U (DI3 + 1) + { 3, 0, NULL, NULL, 0, BFD_RELOC_NONE }, -/* The 32 bit immediate following a 32 bit instruction. */ -#define IMM32 (IMM16 + 1) - { 0, 0, NULL, NULL, V850E_IMMEDIATE32 }, +/* The 4 bit immediate field in format C insn. */ +#define I4U (I3U + 1) + { 4, 0, NULL, NULL, 0, BFD_RELOC_NONE }, -/* The imm5 field in a push/pop instruction. */ -#define IMM5 (IMM32 + 1) - { 5, 1, NULL, NULL, 0 }, +/* The 4 bit immediate field in fetrap. */ +#define I4U_NOTIMM0 (I4U + 1) + { 4, 11, NULL, NULL, V850_NOT_IMM0, BFD_RELOC_NONE }, -/* Reg2 in dispose instruction. */ -#define R2DISPOSE (IMM5 + 1) - { 5, 16, NULL, NULL, V850_OPERAND_REG | V850_NOT_R0 }, +/* The unsigned disp4 field in a sld.bu. */ +#define D4U (I4U_NOTIMM0 + 1) + { 4, 0, NULL, NULL, V850_OPERAND_DISP, BFD_RELOC_V850_TDA_4_4_OFFSET }, -/* Stack pointer in prepare instruction. */ -#define SP (R2DISPOSE + 1) - { 2, 19, insert_spe, extract_spe, V850_OPERAND_REG }, +/* The imm5 field in a format 2 insn. */ +#define I5 (D4U + 1) + { 5, 0, NULL, NULL, V850_OPERAND_SIGNED, BFD_RELOC_NONE }, -/* The IMM5 field in a divide N step instruction. */ -#define I5DIV (SP + 1) - { 9, 0, insert_i5div, extract_i5div, V850_OPERAND_SIGNED }, +/* The imm5 field in a format 11 insn. */ +#define I5DIV1 (I5 + 1) + { 5, 0, insert_i5div1, extract_i5div1, 0, BFD_RELOC_NONE }, - /* The list of registers in a PUSHMH/POPMH instruction. */ -#define LIST18_H (I5DIV + 1) - { -1, 0xfff8000f, NULL, NULL, V850E_PUSH_POP }, +#define I5DIV2 (I5DIV1 + 1) + { 5, 0, insert_i5div2, extract_i5div2, 0, BFD_RELOC_NONE }, - /* The list of registers in a PUSHML/POPML instruction. */ -#define LIST18_L (LIST18_H + 1) - /* The setting of the 4th bit is a flag to disassmble() in v850-dis.c. */ - { -1, 0xfff8001f, NULL, NULL, V850E_PUSH_POP }, -}; +#define I5DIV3 (I5DIV2 + 1) + { 5, 0, insert_i5div3, extract_i5div3, 0, BFD_RELOC_NONE }, - -/* Reg - Reg instruction format (Format I). */ -#define IF1 {R1, R2} +/* The unsigned imm5 field in a format 2 insn. */ +#define I5U (I5DIV3 + 1) + { 5, 0, NULL, NULL, 0, BFD_RELOC_NONE }, -/* Imm - Reg instruction format (Format II). */ -#define IF2 {I5, R2} +/* The imm5 field in a prepare/dispose instruction. */ +#define IMM5 (I5U + 1) + { 5, 1, NULL, NULL, 0, BFD_RELOC_NONE }, -/* Conditional branch instruction format (Format III). */ -#define IF3 {D9_RELAX} +/* The unsigned disp5 field in a sld.hu. */ +#define D5_4U (IMM5 + 1) + { 5, 0, insert_d5_4, extract_d5_4, V850_OPERAND_DISP, BFD_RELOC_V850_TDA_4_5_OFFSET }, + +/* The IMM6 field in a callt instruction. */ +#define IMM6 (D5_4U + 1) + { 6, 0, NULL, NULL, 0, BFD_RELOC_V850_CALLT_6_7_OFFSET }, + +/* The signed disp7 field in a format 4 insn. */ +#define D7U (IMM6 + 1) + { 7, 0, NULL, NULL, V850_OPERAND_DISP, BFD_RELOC_V850_TDA_7_7_OFFSET }, + +/* The unsigned DISP8 field in a format 4 insn. */ +#define D8_7U (D7U + 1) + { 8, 0, insert_d8_7, extract_d8_7, V850_OPERAND_DISP, BFD_RELOC_V850_TDA_7_8_OFFSET }, + +/* The unsigned DISP8 field in a format 4 insn. */ +#define D8_6U (D8_7U + 1) + { 8, 0, insert_d8_6, extract_d8_6, V850_OPERAND_DISP, BFD_RELOC_V850_TDA_6_8_OFFSET }, + +/* The unsigned DISP8 field in a format 4 insn. */ +#define V8 (D8_6U + 1) + { 8, 0, insert_v8, extract_v8, 0, BFD_RELOC_NONE }, + +/* The imm9 field in a multiply word. */ +#define I9 (V8 + 1) + { 9, 0, insert_i9, extract_i9, V850_OPERAND_SIGNED, BFD_RELOC_NONE }, + +/* The unsigned imm9 field in a multiply word. */ +#define U9 (I9 + 1) + { 9, 0, insert_u9, extract_u9, 0, BFD_RELOC_NONE }, + +/* The DISP9 field in a format 3 insn. */ +#define D9 (U9 + 1) + { 9, 0, insert_d9, extract_d9, V850_OPERAND_SIGNED | V850_OPERAND_DISP | V850_PCREL, BFD_RELOC_V850_9_PCREL }, + +/* The DISP9 field in a format 3 insn, relaxable. */ +#define D9_RELAX (D9 + 1) + { 9, 0, insert_d9, extract_d9, V850_OPERAND_RELAX | V850_OPERAND_SIGNED | V850_OPERAND_DISP | V850_PCREL, BFD_RELOC_V850_9_PCREL }, + +/* The imm16 field in a format 6 insn. */ +#define I16 (D9_RELAX + 1) + { 16, 16, NULL, NULL, V850_OPERAND_SIGNED, BFD_RELOC_16 }, + +/* The 16 bit immediate following a 32 bit instruction. */ +#define IMM16 (I16 + 1) + { 16, 32, NULL, NULL, V850E_IMMEDIATE16, BFD_RELOC_16 }, + +/* The 16 bit immediate following a 32 bit instruction. */ +#define IMM16LO (IMM16 + 1) + { 16, 32, NULL, NULL, V850E_IMMEDIATE16, BFD_RELOC_LO16 }, + +/* The hi 16 bit immediate following a 32 bit instruction. */ +#define IMM16HI (IMM16LO + 1) + { 16, 16, NULL, NULL, V850E_IMMEDIATE16HI, BFD_RELOC_HI16 }, + +/* The unsigned imm16 in a format 6 insn. */ +#define I16U (IMM16HI + 1) + { 16, 16, NULL, NULL, 0, BFD_RELOC_16 }, + +/* The disp16 field in a format 8 insn. */ +#define D16 (I16U + 1) + { 16, 16, NULL, NULL, V850_OPERAND_SIGNED | V850_OPERAND_DISP, BFD_RELOC_16 }, + +/* The disp16 field in an format 7 unsigned byte load insn. */ +#define D16_16 (D16 + 1) + { 16, 0, insert_d16_16, extract_d16_16, V850_OPERAND_SIGNED | V850_OPERAND_DISP, BFD_RELOC_V850_16_SPLIT_OFFSET }, + +/* The disp16 field in a format 6 insn. */ +#define D16_15 (D16_16 + 1) + { 16, 0, insert_d16_15, extract_d16_15, V850_OPERAND_SIGNED | V850_OPERAND_DISP , BFD_RELOC_V850_16_S1 }, + +/* The unsigned DISP16 field in a format 7 insn. */ +#define D16_LOOP (D16_15 + 1) + { 16, 0, insert_u16_loop, extract_u16_loop, V850_OPERAND_DISP | V850_PCREL, BFD_RELOC_V850_16_PCREL }, + +/* The DISP17 field in a format 7 insn. */ +#define D17_16 (D16_LOOP + 1) + { 17, 0, insert_d17_16, extract_d17_16, V850_OPERAND_SIGNED | V850_OPERAND_DISP | V850_PCREL, BFD_RELOC_V850_17_PCREL }, + +/* The DISP22 field in a format 4 insn, relaxable. + This _must_ follow D9_RELAX; the assembler assumes that the longer + version immediately follows the shorter version for relaxing. */ +#define D22 (D17_16 + 1) + { 22, 0, insert_d22, extract_d22, V850_OPERAND_SIGNED | V850_OPERAND_DISP | V850_PCREL, BFD_RELOC_V850_22_PCREL }, + +#define D23 (D22 + 1) + { 23, 0, insert_d23, extract_d23, V850E_IMMEDIATE23 | V850_OPERAND_SIGNED | V850_OPERAND_DISP, BFD_RELOC_V850_23 }, + +/* The 32 bit immediate following a 32 bit instruction. */ +#define IMM32 (D23 + 1) + { 32, 32, NULL, NULL, V850E_IMMEDIATE32, BFD_RELOC_32 }, + +#define D32_31 (IMM32 + 1) + { 32, 32, NULL, NULL, V850E_IMMEDIATE32 | V850_OPERAND_SIGNED | V850_OPERAND_DISP, BFD_RELOC_V850_32_ABS }, + +#define D32_31_PCREL (D32_31 + 1) + { 32, 32, NULL, NULL, V850E_IMMEDIATE32 | V850_OPERAND_SIGNED | V850_OPERAND_DISP | V850_PCREL, BFD_RELOC_V850_32_PCREL }, + +}; + + +/* Reg - Reg instruction format (Format I). */ +#define IF1 {R1, R2} + +/* Imm - Reg instruction format (Format II). */ +#define IF2 {I5, R2} + +/* Conditional branch instruction format (Format III). */ +#define IF3 {D9_RELAX} /* 3 operand instruction (Format VI). */ #define IF6 {I16, R1, R2} @@ -497,6 +824,8 @@ const struct v850_operand v850_operands[] = /* 3 operand instruction (Format VI). */ #define IF6U {I16U, R1, R2} +/* Conditional branch instruction format (Format VII). */ +#define IF7 {D17_16} /* The opcode table. @@ -531,150 +860,131 @@ const struct v850_operand v850_operands[] = const struct v850_opcode v850_opcodes[] = { -{ "breakpoint", 0xffff, 0xffff, {UNUSED}, 0, PROCESSOR_ALL }, -{ "dbtrap", one (0xf840), one (0xffff), {UNUSED}, 0, PROCESSOR_V850E1 }, - -{ "jmp", one (0x0060), one (0xffe0), {R1}, 1, PROCESSOR_ALL }, - -/* Load/store instructions. */ -{ "sld.bu", one (0x0060), one (0x07f0), {D4, EP, R2_NOTR0}, 1, PROCESSOR_V850E1 }, -{ "sld.bu", one (0x0060), one (0x07f0), {D4, EP, R2_NOTR0}, 1, PROCESSOR_V850E }, - -{ "sld.hu", one (0x0070), one (0x07f0), {D5_4, EP, R2_NOTR0}, 1, PROCESSOR_V850E1 }, -{ "sld.hu", one (0x0070), one (0x07f0), {D5_4, EP, R2_NOTR0}, 1, PROCESSOR_V850E }, - -{ "sld.b", one (0x0300), one (0x0780), {D7, EP, R2}, 1, PROCESSOR_V850E1 }, -{ "sld.b", one (0x0300), one (0x0780), {D7, EP, R2}, 1, PROCESSOR_V850E }, -{ "sld.b", one (0x0300), one (0x0780), {D7, EP, R2}, 1, PROCESSOR_V850 }, - -{ "sld.h", one (0x0400), one (0x0780), {D8_7, EP, R2}, 1, PROCESSOR_V850E1 }, -{ "sld.h", one (0x0400), one (0x0780), {D8_7, EP, R2}, 1, PROCESSOR_V850E }, -{ "sld.h", one (0x0400), one (0x0780), {D8_7, EP, R2}, 1, PROCESSOR_V850 }, -{ "sld.w", one (0x0500), one (0x0781), {D8_6, EP, R2}, 1, PROCESSOR_ALL }, -{ "sst.b", one (0x0380), one (0x0780), {R2, D7, EP}, 2, PROCESSOR_ALL }, -{ "sst.h", one (0x0480), one (0x0780), {R2, D8_7, EP}, 2, PROCESSOR_ALL }, -{ "sst.w", one (0x0501), one (0x0781), {R2, D8_6, EP}, 2, PROCESSOR_ALL }, - -{ "prepare", two (0x0780, 0x0003), two (0xffc0, 0x001f), {LIST12, IMM5, SP}, 0, PROCESSOR_NOT_V850 }, -{ "prepare", two (0x0780, 0x000b), two (0xffc0, 0x001f), {LIST12, IMM5, IMM16}, 0, PROCESSOR_NOT_V850 }, -{ "prepare", two (0x0780, 0x0013), two (0xffc0, 0x001f), {LIST12, IMM5, IMM16}, 0, PROCESSOR_NOT_V850 }, -{ "prepare", two (0x0780, 0x001b), two (0xffc0, 0x001f), {LIST12, IMM5, IMM32}, 0, PROCESSOR_NOT_V850 }, -{ "prepare", two (0x0780, 0x0001), two (0xffc0, 0x001f), {LIST12, IMM5}, 0, PROCESSOR_NOT_V850 }, -{ "dispose", one (0x0640), one (0xffc0), {IMM5, LIST12, R2DISPOSE},0, PROCESSOR_NOT_V850 }, -{ "dispose", two (0x0640, 0x0000), two (0xffc0, 0x001f), {IMM5, LIST12}, 0, PROCESSOR_NOT_V850 }, - -{ "ld.b", two (0x0700, 0x0000), two (0x07e0, 0x0000), {D16, R1, R2}, 1, PROCESSOR_ALL }, -{ "ld.h", two (0x0720, 0x0000), two (0x07e0, 0x0001), {D16_15, R1, R2}, 1, PROCESSOR_ALL }, -{ "ld.w", two (0x0720, 0x0001), two (0x07e0, 0x0001), {D16_15, R1, R2}, 1, PROCESSOR_ALL }, -{ "ld.bu", two (0x0780, 0x0001), two (0x07c0, 0x0001), {D16_16, R1, R2_NOTR0}, 1, PROCESSOR_NOT_V850 }, -{ "ld.hu", two (0x07e0, 0x0001), two (0x07e0, 0x0001), {D16_15, R1, R2_NOTR0}, 1, PROCESSOR_NOT_V850 }, -{ "st.b", two (0x0740, 0x0000), two (0x07e0, 0x0000), {R2, D16, R1}, 2, PROCESSOR_ALL }, -{ "st.h", two (0x0760, 0x0000), two (0x07e0, 0x0001), {R2, D16_15, R1}, 2, PROCESSOR_ALL }, -{ "st.w", two (0x0760, 0x0001), two (0x07e0, 0x0001), {R2, D16_15, R1}, 2, PROCESSOR_ALL }, - -/* Byte swap/extend instructions. */ -{ "zxb", one (0x0080), one (0xffe0), {R1_NOTR0}, 0, PROCESSOR_NOT_V850 }, -{ "zxh", one (0x00c0), one (0xffe0), {R1_NOTR0}, 0, PROCESSOR_NOT_V850 }, -{ "sxb", one (0x00a0), one (0xffe0), {R1_NOTR0}, 0, PROCESSOR_NOT_V850 }, -{ "sxh", one (0x00e0), one (0xffe0), {R1_NOTR0}, 0, PROCESSOR_NOT_V850 }, -{ "bsh", two (0x07e0, 0x0342), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_NOT_V850 }, -{ "bsw", two (0x07e0, 0x0340), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_NOT_V850 }, -{ "hsw", two (0x07e0, 0x0344), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_NOT_V850 }, - -/* Jump table instructions. */ -{ "switch", one (0x0040), one (0xffe0), {R1}, 1, PROCESSOR_NOT_V850 }, -{ "callt", one (0x0200), one (0xffc0), {I6}, 0, PROCESSOR_NOT_V850 }, -{ "ctret", two (0x07e0, 0x0144), two (0xffff, 0xffff), {0}, 0, PROCESSOR_NOT_V850 }, - -/* Arithmetic operation instructions. */ -{ "setf", two (0x07e0, 0x0000), two (0x07f0, 0xffff), {CCCC, R2}, 0, PROCESSOR_ALL }, -{ "cmov", two (0x07e0, 0x0320), two (0x07e0, 0x07e1), {MOVCC, R1, R2, R3}, 0, PROCESSOR_NOT_V850 }, -{ "cmov", two (0x07e0, 0x0300), two (0x07e0, 0x07e1), {MOVCC, I5, R2, R3}, 0, PROCESSOR_NOT_V850 }, - -{ "mul", two (0x07e0, 0x0220), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 }, -{ "mul", two (0x07e0, 0x0240), two (0x07e0, 0x07c3), {I9, R2, R3}, 0, PROCESSOR_NOT_V850 }, -{ "mulu", two (0x07e0, 0x0222), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 }, -{ "mulu", two (0x07e0, 0x0242), two (0x07e0, 0x07c3), {U9, R2, R3}, 0, PROCESSOR_NOT_V850 }, - -{ "div", two (0x07e0, 0x02c0), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 }, -{ "divu", two (0x07e0, 0x02c2), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 }, -{ "divhu", two (0x07e0, 0x0282), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 }, -{ "divh", two (0x07e0, 0x0280), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 }, -{ "divh", OP (0x02), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL }, - -{ "nop", one (0x00), one (0xffff), {0}, 0, PROCESSOR_ALL }, -{ "mov", OP (0x10), OP_MASK, {I5, R2_NOTR0}, 0, PROCESSOR_ALL }, -{ "mov", one (0x0620), one (0xffe0), {IMM32, R1_NOTR0}, 0, PROCESSOR_NOT_V850 }, -{ "mov", OP (0x00), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL }, -{ "movea", OP (0x31), OP_MASK, {I16, R1, R2_NOTR0}, 0, PROCESSOR_ALL }, -{ "movhi", OP (0x32), OP_MASK, {I16U, R1, R2_NOTR0}, 0, PROCESSOR_ALL }, +/* Standard instructions. */ { "add", OP (0x0e), OP_MASK, IF1, 0, PROCESSOR_ALL }, { "add", OP (0x12), OP_MASK, IF2, 0, PROCESSOR_ALL }, + { "addi", OP (0x30), OP_MASK, IF6, 0, PROCESSOR_ALL }, -{ "sub", OP (0x0d), OP_MASK, IF1, 0, PROCESSOR_ALL }, -{ "subr", OP (0x0c), OP_MASK, IF1, 0, PROCESSOR_ALL }, -{ "mulh", OP (0x17), OP_MASK, {I5, R2_NOTR0}, 0, PROCESSOR_ALL }, -{ "mulh", OP (0x07), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL }, -{ "mulhi", OP (0x37), OP_MASK, {I16, R1, R2_NOTR0}, 0, PROCESSOR_ALL }, -{ "cmp", OP (0x0f), OP_MASK, IF1, 0, PROCESSOR_ALL }, -{ "cmp", OP (0x13), OP_MASK, IF2, 0, PROCESSOR_ALL }, -/* Saturated operation instructions. */ -{ "satadd", OP (0x11), OP_MASK, {I5, R2_NOTR0}, 0, PROCESSOR_ALL }, -{ "satadd", OP (0x06), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL }, -{ "satsub", OP (0x05), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL }, -{ "satsubi", OP (0x33), OP_MASK, {I16, R1, R2_NOTR0}, 0, PROCESSOR_ALL }, -{ "satsubr", OP (0x04), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL }, +{ "adf", two (0x07e0, 0x03a0), two (0x07e0, 0x07e1), {CCCC_NOTSA, R1, R2, R3}, 0, PROCESSOR_V850E2_ALL }, -/* Logical operation instructions. */ -{ "tst", OP (0x0b), OP_MASK, IF1, 0, PROCESSOR_ALL }, -{ "or", OP (0x08), OP_MASK, IF1, 0, PROCESSOR_ALL }, -{ "ori", OP (0x34), OP_MASK, IF6U, 0, PROCESSOR_ALL }, { "and", OP (0x0a), OP_MASK, IF1, 0, PROCESSOR_ALL }, + { "andi", OP (0x36), OP_MASK, IF6U, 0, PROCESSOR_ALL }, -{ "xor", OP (0x09), OP_MASK, IF1, 0, PROCESSOR_ALL }, -{ "xori", OP (0x35), OP_MASK, IF6U, 0, PROCESSOR_ALL }, -{ "not", OP (0x01), OP_MASK, IF1, 0, PROCESSOR_ALL }, -{ "sar", OP (0x15), OP_MASK, {I5U, R2}, 0, PROCESSOR_ALL }, -{ "sar", two (0x07e0, 0x00a0), two (0x07e0, 0xffff), {R1, R2}, 0, PROCESSOR_ALL }, -{ "shl", OP (0x16), OP_MASK, {I5U, R2}, 0, PROCESSOR_ALL }, -{ "shl", two (0x07e0, 0x00c0), two (0x07e0, 0xffff), {R1, R2}, 0, PROCESSOR_ALL }, -{ "shr", OP (0x14), OP_MASK, {I5U, R2}, 0, PROCESSOR_ALL }, -{ "shr", two (0x07e0, 0x0080), two (0x07e0, 0xffff), {R1, R2}, 0, PROCESSOR_ALL }, -{ "sasf", two (0x07e0, 0x0200), two (0x07f0, 0xffff), {CCCC, R2}, 0, PROCESSOR_NOT_V850 }, -/* Branch instructions. */ /* Signed integer. */ -{ "bgt", BOP (0xf), BOP_MASK, IF3, 0, PROCESSOR_ALL }, { "bge", BOP (0xe), BOP_MASK, IF3, 0, PROCESSOR_ALL }, -{ "blt", BOP (0x6), BOP_MASK, IF3, 0, PROCESSOR_ALL }, +{ "bgt", BOP (0xf), BOP_MASK, IF3, 0, PROCESSOR_ALL }, { "ble", BOP (0x7), BOP_MASK, IF3, 0, PROCESSOR_ALL }, +{ "blt", BOP (0x6), BOP_MASK, IF3, 0, PROCESSOR_ALL }, /* Unsigned integer. */ { "bh", BOP (0xb), BOP_MASK, IF3, 0, PROCESSOR_ALL }, -{ "bnh", BOP (0x3), BOP_MASK, IF3, 0, PROCESSOR_ALL }, { "bl", BOP (0x1), BOP_MASK, IF3, 0, PROCESSOR_ALL }, +{ "bnh", BOP (0x3), BOP_MASK, IF3, 0, PROCESSOR_ALL }, { "bnl", BOP (0x9), BOP_MASK, IF3, 0, PROCESSOR_ALL }, /* Common. */ { "be", BOP (0x2), BOP_MASK, IF3, 0, PROCESSOR_ALL }, { "bne", BOP (0xa), BOP_MASK, IF3, 0, PROCESSOR_ALL }, /* Others. */ -{ "bv", BOP (0x0), BOP_MASK, IF3, 0, PROCESSOR_ALL }, -{ "bnv", BOP (0x8), BOP_MASK, IF3, 0, PROCESSOR_ALL }, -{ "bn", BOP (0x4), BOP_MASK, IF3, 0, PROCESSOR_ALL }, -{ "bp", BOP (0xc), BOP_MASK, IF3, 0, PROCESSOR_ALL }, { "bc", BOP (0x1), BOP_MASK, IF3, 0, PROCESSOR_ALL }, +{ "bf", BOP (0xa), BOP_MASK, IF3, 0, PROCESSOR_ALL }, +{ "bn", BOP (0x4), BOP_MASK, IF3, 0, PROCESSOR_ALL }, { "bnc", BOP (0x9), BOP_MASK, IF3, 0, PROCESSOR_ALL }, -{ "bz", BOP (0x2), BOP_MASK, IF3, 0, PROCESSOR_ALL }, +{ "bnv", BOP (0x8), BOP_MASK, IF3, 0, PROCESSOR_ALL }, { "bnz", BOP (0xa), BOP_MASK, IF3, 0, PROCESSOR_ALL }, +{ "bp", BOP (0xc), BOP_MASK, IF3, 0, PROCESSOR_ALL }, { "br", BOP (0x5), BOP_MASK, IF3, 0, PROCESSOR_ALL }, { "bsa", BOP (0xd), BOP_MASK, IF3, 0, PROCESSOR_ALL }, +{ "bt", BOP (0x2), BOP_MASK, IF3, 0, PROCESSOR_ALL }, +{ "bv", BOP (0x0), BOP_MASK, IF3, 0, PROCESSOR_ALL }, +{ "bz", BOP (0x2), BOP_MASK, IF3, 0, PROCESSOR_ALL }, -/* Branch macros. +{ "bsh", two (0x07e0, 0x0342), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_NOT_V850 }, - We use the short form in the opcode/mask fields. The assembler - will twiddle bits as necessary if the long form is needed. */ +{ "bsw", two (0x07e0, 0x0340), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_NOT_V850 }, - /* Signed integer. */ +{ "callt", one (0x0200), one (0xffc0), {IMM6}, 0, PROCESSOR_NOT_V850 }, + +{ "caxi", two (0x07e0, 0x00ee), two (0x07e0, 0x07ff), {R1, R2, R3}, 1, PROCESSOR_V850E2_ALL }, + +{ "clr1", two (0x87c0, 0x0000), two (0xc7e0, 0x0000), {B3, D16, R1}, 3, PROCESSOR_ALL }, +{ "clr1", two (0x07e0, 0x00e4), two (0x07e0, 0xffff), {R2, R1}, 3, PROCESSOR_NOT_V850 }, + +{ "cmov", two (0x07e0, 0x0320), two (0x07e0, 0x07e1), {MOVCC, R1, R2, R3}, 0, PROCESSOR_NOT_V850 }, +{ "cmov", two (0x07e0, 0x0300), two (0x07e0, 0x07e1), {MOVCC, I5, R2, R3}, 0, PROCESSOR_NOT_V850 }, + +{ "cmp", OP (0x0f), OP_MASK, IF1, 0, PROCESSOR_ALL }, +{ "cmp", OP (0x13), OP_MASK, IF2, 0, PROCESSOR_ALL }, + +{ "ctret", two (0x07e0, 0x0144), two (0xffff, 0xffff), {0}, 0, PROCESSOR_NOT_V850 }, + +{ "dbret", two (0x07e0, 0x0146), two (0xffff, 0xffff), {0}, 0, PROCESSOR_NOT_V850 }, + +{ "dbtrap", one (0xf840), one (0xffff), {0}, 0, PROCESSOR_NOT_V850 }, + +{ "di", two (0x07e0, 0x0160), two (0xffff, 0xffff), {0}, 0, PROCESSOR_ALL }, + +{ "dispose", two (0x0640, 0x0000), two (0xffc0, 0x0000), {IMM5, LIST12, R2_DISPOSE},3, PROCESSOR_NOT_V850 }, +{ "dispose", two (0x0640, 0x0000), two (0xffc0, 0x001f), {IMM5, LIST12}, 0, PROCESSOR_NOT_V850 }, + +{ "div", two (0x07e0, 0x02c0), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 }, + +{ "divh", two (0x07e0, 0x0280), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 }, +{ "divh", OP (0x02), OP_MASK, {R1_NOTR0, R2_NOTR0}, 0, PROCESSOR_ALL }, + +{ "divhn", two (0x07e0, 0x0280), two (0x07e0, 0x07c3), {I5DIV1, R1, R2, R3}, 0, PROCESSOR_NOT_V850 | PROCESSOR_OPTION_EXTENSION }, + +{ "divhu", two (0x07e0, 0x0282), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 }, + +{ "divhun", two (0x07e0, 0x0282), two (0x07e0, 0x07c3), {I5DIV1, R1, R2, R3}, 0, PROCESSOR_NOT_V850 | PROCESSOR_OPTION_EXTENSION }, +{ "divn", two (0x07e0, 0x02c0), two (0x07e0, 0x07c3), {I5DIV2, R1, R2, R3}, 0, PROCESSOR_NOT_V850 | PROCESSOR_OPTION_EXTENSION }, + +{ "divq", two (0x07e0, 0x02fc), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_V850E2_ALL }, + +{ "divqu", two (0x07e0, 0x02fe), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_V850E2_ALL }, + +{ "divu", two (0x07e0, 0x02c2), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 }, + +{ "divun", two (0x07e0, 0x02c2), two (0x07e0, 0x07c3), {I5DIV2, R1, R2, R3}, 0, PROCESSOR_NOT_V850 | PROCESSOR_OPTION_EXTENSION }, + +{ "ei", two (0x87e0, 0x0160), two (0xffff, 0xffff), {0}, 0, PROCESSOR_ALL }, + +{ "eiret", two (0x07e0, 0x0148), two (0xffff, 0xffff), {0}, 0, PROCESSOR_V850E2_ALL }, + +{ "feret", two (0x07e0, 0x014a), two (0xffff, 0xffff), {0}, 0, PROCESSOR_V850E2_ALL }, + +{ "fetrap", one (0x0040), one (0x87ff), {I4U_NOTIMM0}, 0, PROCESSOR_V850E2_ALL }, + +{ "halt", two (0x07e0, 0x0120), two (0xffff, 0xffff), {0}, 0, PROCESSOR_ALL }, + +{ "hsh", two (0x07e0, 0x0346), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2_ALL }, + +{ "hsw", two (0x07e0, 0x0344), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_NOT_V850 }, + +{ "jarl", two (0x0780, 0x0000), two (0x07c0, 0x0001), {D22, R2_NOTR0}, 0, PROCESSOR_ALL}, +{ "jarl", one (0x02e0), one (0xffe0), {D32_31_PCREL, R1_NOTR0}, 0, PROCESSOR_V850E2_ALL }, +/* Gas local alias of mov imm22(not defined in spec). */ +{ "jarl22", two (0x0780, 0x0000), two (0x07c0, 0x0001), {D22, R2_NOTR0}, 0, PROCESSOR_ALL | PROCESSOR_OPTION_ALIAS}, +/* Gas local alias of mov imm32(not defined in spec). */ +{ "jarl32", one (0x02e0), one (0xffe0), {D32_31_PCREL, R1_NOTR0}, 0, PROCESSOR_V850E2_ALL | PROCESSOR_OPTION_ALIAS }, +{ "jarlw", one (0x02e0), one (0xffe0), {D32_31_PCREL, R1_NOTR0}, 0, PROCESSOR_V850E2_ALL | PROCESSOR_OPTION_ALIAS }, + +{ "jmp", one (0x06e0), one (0xffe0), {D32_31, R1}, 2, PROCESSOR_V850E2_ALL }, +{ "jmp", one (0x0060), one (0xffe0), {R1}, 1, PROCESSOR_ALL }, +/* Gas local alias of jmp disp22(not defined in spec). */ +{ "jmp22", one (0x0060), one (0xffe0), {R1}, 1, PROCESSOR_ALL | PROCESSOR_OPTION_ALIAS }, +/* Gas local alias of jmp disp32(not defined in spec). */ +{ "jmp32", one (0x06e0), one (0xffe0), {D32_31, R1}, 2, PROCESSOR_V850E2_ALL | PROCESSOR_OPTION_ALIAS }, +{ "jmpw", one (0x06e0), one (0xffe0), {D32_31, R1}, 2, PROCESSOR_V850E2_ALL | PROCESSOR_OPTION_ALIAS }, + +{ "jr", two (0x0780, 0x0000), two (0xffc0, 0x0001), {D22}, 0, PROCESSOR_ALL }, +{ "jr", one (0x02e0), one (0xffff), {D32_31_PCREL}, 0, PROCESSOR_V850E2_ALL }, +/* Gas local alias of mov imm22(not defined in spec). */ +{ "jr22", two (0x0780, 0x0000), two (0xffc0, 0x0001), {D22}, 0, PROCESSOR_ALL | PROCESSOR_OPTION_ALIAS }, +/* Gas local alias of mov imm32(not defined in spec). */ +{ "jr32", one (0x02e0), one (0xffff), {D32_31_PCREL}, 0, PROCESSOR_V850E2_ALL | PROCESSOR_OPTION_ALIAS }, + +/* Alias of bcond (same as CA850). */ { "jgt", BOP (0xf), BOP_MASK, IF3, 0, PROCESSOR_ALL }, { "jge", BOP (0xe), BOP_MASK, IF3, 0, PROCESSOR_ALL }, { "jlt", BOP (0x6), BOP_MASK, IF3, 0, PROCESSOR_ALL }, @@ -696,33 +1006,295 @@ const struct v850_opcode v850_opcodes[] = { "jnc", BOP (0x9), BOP_MASK, IF3, 0, PROCESSOR_ALL }, { "jz", BOP (0x2), BOP_MASK, IF3, 0, PROCESSOR_ALL }, { "jnz", BOP (0xa), BOP_MASK, IF3, 0, PROCESSOR_ALL }, -{ "jsa", BOP (0xd), BOP_MASK, IF3, 0, PROCESSOR_ALL }, { "jbr", BOP (0x5), BOP_MASK, IF3, 0, PROCESSOR_ALL }, -{ "jr", one (0x0780), two (0xffc0, 0x0001), {D22}, 0, PROCESSOR_ALL }, -{ "jarl", one (0x0780), two (0x07c0, 0x0001), {D22, R2}, 0, PROCESSOR_ALL }, -/* Bit manipulation instructions. */ -{ "set1", two (0x07c0, 0x0000), two (0xc7e0, 0x0000), {B3, D16, R1}, 2, PROCESSOR_ALL }, -{ "set1", two (0x07e0, 0x00e0), two (0x07e0, 0xffff), {R2, R1}, 2, PROCESSOR_NOT_V850 }, -{ "not1", two (0x47c0, 0x0000), two (0xc7e0, 0x0000), {B3, D16, R1}, 2, PROCESSOR_ALL }, -{ "not1", two (0x07e0, 0x00e2), two (0x07e0, 0xffff), {R2, R1}, 2, PROCESSOR_NOT_V850 }, -{ "clr1", two (0x87c0, 0x0000), two (0xc7e0, 0x0000), {B3, D16, R1}, 2, PROCESSOR_ALL }, -{ "clr1", two (0x07e0, 0x00e4), two (0x07e0, 0xffff), {R2, R1}, 2, PROCESSOR_NOT_V850 }, -{ "tst1", two (0xc7c0, 0x0000), two (0xc7e0, 0x0000), {B3, D16, R1}, 2, PROCESSOR_ALL }, -{ "tst1", two (0x07e0, 0x00e6), two (0x07e0, 0xffff), {R2, R1}, 2, PROCESSOR_NOT_V850 }, +{ "ldacc", two (0x07e0, 0x0bc4), two (0x07e0, 0xffff), {R1, R2}, 0, PROCESSOR_V850E2_ALL | PROCESSOR_OPTION_EXTENSION }, + +{ "ld.b", two (0x0700, 0x0000), two (0x07e0, 0x0000), {D16, R1, R2}, 2, PROCESSOR_ALL }, +{ "ld.b", two (0x0780, 0x0005), two (0x07e0, 0x000f), {D23, R1, R3}, 2, PROCESSOR_V850E2_ALL }, +{ "ld.b23", two (0x0780, 0x0005), two (0x07e0, 0x000f), {D23, R1, R3}, 2, PROCESSOR_V850E2_ALL | PROCESSOR_OPTION_ALIAS }, + +{ "ld.bu", two (0x0780, 0x0001), two (0x07c0, 0x0001), {D16_16, R1, R2_NOTR0}, 2, PROCESSOR_NOT_V850 }, +{ "ld.bu", two (0x07a0, 0x0005), two (0x07e0, 0x000f), {D23, R1, R3}, 2, PROCESSOR_V850E2_ALL }, +{ "ld.bu23", two (0x07a0, 0x0005), two (0x07e0, 0x000f), {D23, R1, R3}, 2, PROCESSOR_V850E2_ALL | PROCESSOR_OPTION_ALIAS }, + +{ "ld.h", two (0x0720, 0x0000), two (0x07e0, 0x0001), {D16_15, R1, R2}, 2, PROCESSOR_ALL }, +{ "ld.h", two (0x0780, 0x0007), two (0x07e0, 0x000f), {D23, R1, R3}, 2, PROCESSOR_V850E2_ALL }, +{ "ld.h23", two (0x0780, 0x0007), two (0x07e0, 0x000f), {D23, R1, R3}, 2, PROCESSOR_V850E2_ALL | PROCESSOR_OPTION_ALIAS }, + +{ "ld.hu", two (0x07e0, 0x0001), two (0x07e0, 0x0001), {D16_15, R1, R2_NOTR0}, 2, PROCESSOR_NOT_V850 }, +{ "ld.hu", two (0x07a0, 0x0007), two (0x07e0, 0x000f), {D23, R1, R3}, 2, PROCESSOR_V850E2_ALL }, +{ "ld.hu23", two (0x07a0, 0x0007), two (0x07e0, 0x000f), {D23, R1, R3}, 2, PROCESSOR_V850E2_ALL | PROCESSOR_OPTION_ALIAS }, + + +{ "ld.w", two (0x0720, 0x0001), two (0x07e0, 0x0001), {D16_15, R1, R2}, 2, PROCESSOR_ALL }, +{ "ld.w", two (0x0780, 0x0009), two (0x07e0, 0x000f), {D23, R1, R3}, 2, PROCESSOR_V850E2_ALL }, +{ "ld.w23", two (0x0780, 0x0009), two (0x07e0, 0x000f), {D23, R1, R3}, 2, PROCESSOR_V850E2_ALL | PROCESSOR_OPTION_ALIAS }, -/* Special instructions. */ -{ "di", two (0x07e0, 0x0160), two (0xffff, 0xffff), {0}, 0, PROCESSOR_ALL }, -{ "ei", two (0x87e0, 0x0160), two (0xffff, 0xffff), {0}, 0, PROCESSOR_ALL }, -{ "halt", two (0x07e0, 0x0120), two (0xffff, 0xffff), {0}, 0, PROCESSOR_ALL }, -{ "reti", two (0x07e0, 0x0140), two (0xffff, 0xffff), {0}, 0, PROCESSOR_ALL }, -{ "trap", two (0x07e0, 0x0100), two (0xffe0, 0xffff), {I5U}, 0, PROCESSOR_ALL }, { "ldsr", two (0x07e0, 0x0020), two (0x07e0, 0xffff), {R1, SR2}, 0, PROCESSOR_ALL }, + +{ "macacc", two (0x07e0, 0x0bc0), two (0x07e0, 0xffff), {R1, R2}, 0, PROCESSOR_V850E2_ALL | PROCESSOR_OPTION_EXTENSION }, + +{ "mac", two (0x07e0, 0x03c0), two (0x07e0, 0x0fe1), {R1, R2, R3_EVEN, R4_EVEN}, 0, PROCESSOR_V850E2_ALL }, + +{ "macu", two (0x07e0, 0x03e0), two (0x07e0, 0x0fe1), {R1, R2, R3_EVEN, R4_EVEN}, 0, PROCESSOR_V850E2_ALL }, + +{ "macuacc", two (0x07e0, 0x0bc2), two (0x07e0, 0xffff), {R1, R2}, 0, PROCESSOR_V850E2_ALL | PROCESSOR_OPTION_EXTENSION }, + +{ "mov", OP (0x00), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL }, +{ "mov", OP (0x10), OP_MASK, {I5, R2_NOTR0}, 0, PROCESSOR_ALL }, +{ "mov", one (0x0620), one (0xffe0), {IMM32, R1}, 0, PROCESSOR_NOT_V850 }, +/* Gas local alias of mov imm32(not defined in spec). */ +{ "movl", one (0x0620), one (0xffe0), {IMM32, R1}, 0, PROCESSOR_NOT_V850 | PROCESSOR_OPTION_ALIAS }, + +{ "movea", OP (0x31), OP_MASK, {I16, R1, R2_NOTR0}, 0, PROCESSOR_ALL }, + +{ "movhi", OP (0x32), OP_MASK, {I16, R1, R2_NOTR0}, 0, PROCESSOR_ALL }, + +{ "mul", two (0x07e0, 0x0220), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 }, +{ "mul", two (0x07e0, 0x0240), two (0x07e0, 0x07c3), {I9, R2, R3}, 0, PROCESSOR_NOT_V850 }, + +{ "mulh", OP (0x17), OP_MASK, {I5, R2_NOTR0}, 0, PROCESSOR_ALL }, +{ "mulh", OP (0x07), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL }, + +{ "mulhi", OP (0x37), OP_MASK, {I16, R1, R2_NOTR0}, 0, PROCESSOR_ALL }, + +{ "mulu", two (0x07e0, 0x0222), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_NOT_V850 }, +{ "mulu", two (0x07e0, 0x0242), two (0x07e0, 0x07c3), {U9, R2, R3}, 0, PROCESSOR_NOT_V850 }, + +{ "nop", one (0x00), one (0xffff), {0}, 0, PROCESSOR_ALL }, + +{ "not", OP (0x01), OP_MASK, IF1, 0, PROCESSOR_ALL }, + +{ "not1", two (0x47c0, 0x0000), two (0xc7e0, 0x0000), {B3, D16, R1}, 3, PROCESSOR_ALL }, +{ "not1", two (0x07e0, 0x00e2), two (0x07e0, 0xffff), {R2, R1}, 3, PROCESSOR_NOT_V850 }, + +{ "or", OP (0x08), OP_MASK, IF1, 0, PROCESSOR_ALL }, + +{ "ori", OP (0x34), OP_MASK, IF6U, 0, PROCESSOR_ALL }, + +{ "prepare", two (0x0780, 0x0003), two (0xffc0, 0x001f), {LIST12, IMM5, SP}, 0, PROCESSOR_NOT_V850 }, +{ "prepare", two (0x0780, 0x000b), two (0xffc0, 0x001f), {LIST12, IMM5, IMM16LO},0, PROCESSOR_NOT_V850 }, +{ "prepare", two (0x0780, 0x0013), two (0xffc0, 0x001f), {LIST12, IMM5, IMM16HI},0, PROCESSOR_NOT_V850 }, +{ "prepare", two (0x0780, 0x001b), two (0xffc0, 0x001f), {LIST12, IMM5, IMM32}, 0, PROCESSOR_NOT_V850 }, +{ "prepare", two (0x0780, 0x0001), two (0xffc0, 0x001f), {LIST12, IMM5}, 0, PROCESSOR_NOT_V850 }, + +{ "reti", two (0x07e0, 0x0140), two (0xffff, 0xffff), {0}, 0, PROCESSOR_ALL }, + +{ "sar", two (0x07e0, 0x00a2), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_V850E2_ALL }, +{ "sar", OP (0x15), OP_MASK, {I5U, R2}, 0, PROCESSOR_ALL }, +{ "sar", two (0x07e0, 0x00a0), two (0x07e0, 0xffff), {R1, R2}, 0, PROCESSOR_ALL }, + +{ "sasf", two (0x07e0, 0x0200), two (0x07f0, 0xffff), {CCCC, R2}, 0, PROCESSOR_NOT_V850 }, + +{ "satadd", two (0x07e0, 0x03ba), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_V850E2_ALL }, +{ "satadd", OP (0x11), OP_MASK, {I5, R2_NOTR0}, 0, PROCESSOR_ALL }, +{ "satadd", OP (0x06), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL }, + +{ "satsub", two (0x07e0, 0x039a), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_V850E2_ALL }, +{ "satsub", OP (0x05), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL }, + +{ "satsubi", OP (0x33), OP_MASK, {I16, R1, R2_NOTR0}, 0, PROCESSOR_ALL }, + +{ "satsubr", OP (0x04), OP_MASK, {R1, R2_NOTR0}, 0, PROCESSOR_ALL }, + +{ "sbf", two (0x07e0, 0x0380), two (0x07e0, 0x07e1), {CCCC_NOTSA, R1, R2, R3}, 0, PROCESSOR_V850E2_ALL }, + +{ "sch0l", two (0x07e0, 0x0364), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2_ALL }, + +{ "sch0r", two (0x07e0, 0x0360), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2_ALL }, + +{ "sch1l", two (0x07e0, 0x0366), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2_ALL }, + +{ "sch1r", two (0x07e0, 0x0362), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2_ALL }, + +{ "sdivhn", two (0x07e0, 0x0180), two (0x07e0, 0x07c3), {I5DIV3, R1, R2, R3}, 0, PROCESSOR_NOT_V850 | PROCESSOR_OPTION_EXTENSION }, +{ "sdivhun", two (0x07e0, 0x0182), two (0x07e0, 0x07c3), {I5DIV3, R1, R2, R3}, 0, PROCESSOR_NOT_V850 | PROCESSOR_OPTION_EXTENSION }, +{ "sdivn", two (0x07e0, 0x01c0), two (0x07e0, 0x07c3), {I5DIV3, R1, R2, R3}, 0, PROCESSOR_NOT_V850 | PROCESSOR_OPTION_EXTENSION }, +{ "sdivun", two (0x07e0, 0x01c2), two (0x07e0, 0x07c3), {I5DIV3, R1, R2, R3}, 0, PROCESSOR_NOT_V850 | PROCESSOR_OPTION_EXTENSION }, + +{ "set1", two (0x07c0, 0x0000), two (0xc7e0, 0x0000), {B3, D16, R1}, 3, PROCESSOR_ALL }, +{ "set1", two (0x07e0, 0x00e0), two (0x07e0, 0xffff), {R2, R1}, 3, PROCESSOR_NOT_V850 }, + +{ "setf", two (0x07e0, 0x0000), two (0x07f0, 0xffff), {CCCC, R2}, 0, PROCESSOR_ALL }, + +{ "shl", two (0x07e0, 0x00c2), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_V850E2_ALL }, +{ "shl", OP (0x16), OP_MASK, {I5U, R2}, 0, PROCESSOR_ALL }, +{ "shl", two (0x07e0, 0x00c0), two (0x07e0, 0xffff), {R1, R2}, 0, PROCESSOR_ALL }, + +{ "shr", two (0x07e0, 0x0082), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_V850E2_ALL }, +{ "shr", OP (0x14), OP_MASK, {I5U, R2}, 0, PROCESSOR_ALL }, +{ "shr", two (0x07e0, 0x0080), two (0x07e0, 0xffff), {R1, R2}, 0, PROCESSOR_ALL }, + +{ "sld.b", one (0x0300), one (0x0780), {D7U, EP, R2}, 2, PROCESSOR_ALL }, + +{ "sld.bu", one (0x0060), one (0x07f0), {D4U, EP, R2_NOTR0}, 2, PROCESSOR_NOT_V850 }, + +{ "sld.h", one (0x0400), one (0x0780), {D8_7U,EP, R2}, 2, PROCESSOR_ALL }, + +{ "sld.hu", one (0x0070), one (0x07f0), {D5_4U,EP, R2_NOTR0}, 2, PROCESSOR_NOT_V850 }, + +{ "sld.w", one (0x0500), one (0x0781), {D8_6U,EP, R2}, 2, PROCESSOR_ALL }, + +{ "sst.b", one (0x0380), one (0x0780), {R2, D7U, EP}, 3, PROCESSOR_ALL }, + +{ "sst.h", one (0x0480), one (0x0780), {R2, D8_7U,EP}, 3, PROCESSOR_ALL }, + +{ "sst.w", one (0x0501), one (0x0781), {R2, D8_6U,EP}, 3, PROCESSOR_ALL }, + +{ "stacch", two (0x07e0, 0x0bca), two (0x07ff, 0xffff), {R2}, 0, PROCESSOR_V850E2_ALL | PROCESSOR_OPTION_EXTENSION }, +{ "staccl", two (0x07e0, 0x0bc8), two (0x07ff, 0xffff), {R2}, 0, PROCESSOR_V850E2_ALL | PROCESSOR_OPTION_EXTENSION }, + +{ "st.b", two (0x0740, 0x0000), two (0x07e0, 0x0000), {R2, D16, R1}, 3, PROCESSOR_ALL }, +{ "st.b", two (0x0780, 0x000d), two (0x07e0, 0x000f), {R3, D23, R1}, 3, PROCESSOR_V850E2_ALL }, +{ "st.b23", two (0x0780, 0x000d), two (0x07e0, 0x000f), {R3, D23, R1}, 3, PROCESSOR_V850E2_ALL | PROCESSOR_OPTION_ALIAS }, + +{ "st.h", two (0x0760, 0x0000), two (0x07e0, 0x0001), {R2, D16_15, R1}, 3, PROCESSOR_ALL }, +{ "st.h", two (0x07a0, 0x000d), two (0x07e0, 0x000f), {R3, D23, R1}, 3, PROCESSOR_V850E2_ALL }, +{ "st.h23", two (0x07a0, 0x000d), two (0x07e0, 0x000f), {R3, D23, R1}, 3, PROCESSOR_V850E2_ALL | PROCESSOR_OPTION_ALIAS }, + +{ "st.w", two (0x0760, 0x0001), two (0x07e0, 0x0001), {R2, D16_15, R1}, 3, PROCESSOR_ALL }, +{ "st.w", two (0x0780, 0x000f), two (0x07e0, 0x000f), {R3, D23, R1}, 3, PROCESSOR_V850E2_ALL }, +{ "st.w23", two (0x0780, 0x000f), two (0x07e0, 0x000f), {R3, D23, R1}, 3, PROCESSOR_V850E2_ALL | PROCESSOR_OPTION_ALIAS }, + { "stsr", two (0x07e0, 0x0040), two (0x07e0, 0xffff), {SR1, R2}, 0, PROCESSOR_ALL }, -{ "dbret", two (0x07e0, 0x0146), two (0xffff, 0xffff), {UNUSED}, 0, PROCESSOR_V850E1 }, -{ 0, 0, 0, {0}, 0, 0 }, +{ "sub", OP (0x0d), OP_MASK, IF1, 0, PROCESSOR_ALL }, + +{ "subr", OP (0x0c), OP_MASK, IF1, 0, PROCESSOR_ALL }, + +{ "switch", one (0x0040), one (0xffe0), {R1_NOTR0}, 0, PROCESSOR_NOT_V850 }, + +{ "sxb", one (0x00a0), one (0xffe0), {R1}, 0, PROCESSOR_NOT_V850 }, + +{ "sxh", one (0x00e0), one (0xffe0), {R1}, 0, PROCESSOR_NOT_V850 }, + +{ "trap", two (0x07e0, 0x0100), two (0xffe0, 0xffff), {I5U}, 0, PROCESSOR_ALL }, + +{ "tst", OP (0x0b), OP_MASK, IF1, 0, PROCESSOR_ALL }, + +{ "tst1", two (0xc7c0, 0x0000), two (0xc7e0, 0x0000), {B3, D16, R1}, 3, PROCESSOR_ALL }, +{ "tst1", two (0x07e0, 0x00e6), two (0x07e0, 0xffff), {R2, R1}, 3, PROCESSOR_NOT_V850 }, + +{ "xor", OP (0x09), OP_MASK, IF1, 0, PROCESSOR_ALL }, + +{ "xori", OP (0x35), OP_MASK, IF6U, 0, PROCESSOR_ALL }, + +{ "zxb", one (0x0080), one (0xffe0), {R1}, 0, PROCESSOR_NOT_V850 }, + +{ "zxh", one (0x00c0), one (0xffe0), {R1}, 0, PROCESSOR_NOT_V850 }, + +/* Floating point operation. */ +{ "absf.d", two (0x07e0, 0x0458), two (0x0fff, 0x0fff), {R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "absf.s", two (0x07e0, 0x0448), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2V3 }, +{ "addf.d", two (0x07e0, 0x0470), two (0x0fe1, 0x0fff), {R1_EVEN, R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "addf.s", two (0x07e0, 0x0460), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_V850E2V3 }, +{ "ceilf.dl", two (0x07e2, 0x0454), two (0x0fff, 0x0fff), {R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "ceilf.dul", two (0x07f2, 0x0454), two (0x0fff, 0x0fff), {R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "ceilf.duw", two (0x07f2, 0x0450), two (0x0fff, 0x07ff), {R2_EVEN, R3}, 0, PROCESSOR_V850E2V3 }, +{ "ceilf.dw", two (0x07e2, 0x0450), two (0x0fff, 0x07ff), {R2_EVEN, R3}, 0, PROCESSOR_V850E2V3 }, +{ "ceilf.sl", two (0x07e2, 0x0444), two (0x07ff, 0x0fff), {R2, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "ceilf.sul", two (0x07f2, 0x0444), two (0x07ff, 0x0fff), {R2, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "ceilf.suw", two (0x07f2, 0x0440), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2V3 }, +{ "ceilf.sw", two (0x07e2, 0x0440), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2V3 }, +{ "ceilf.sw", two (0x07e2, 0x0440), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2V3 }, +{ "cmovf.d", two (0x07e0, 0x0410), two (0x0fe1, 0x0ff1), {FFF, R1_EVEN, R2_EVEN, R3_EVEN_NOTR0}, 0, PROCESSOR_V850E2V3 }, +/* Default value for FFF is 0(not defined in spec). */ +{ "cmovf.d", two (0x07e0, 0x0410), two (0x0fe1, 0x0fff), {R1_EVEN, R2_EVEN, R3_EVEN_NOTR0}, 0, PROCESSOR_V850E2V3 }, +{ "cmovf.s", two (0x07e0, 0x0400), two (0x07e0, 0x07f1), {FFF, R1, R2, R3_NOTR0}, 0, PROCESSOR_V850E2V3 }, +/* Default value for FFF is 0(not defined in spec). */ +{ "cmovf.s", two (0x07e0, 0x0400), two (0x07e0, 0x07ff), {R1, R2, R3_NOTR0}, 0, PROCESSOR_V850E2V3 }, +{ "cmpf.d", two (0x07e0, 0x0430), two (0x0fe1, 0x87f1), {FLOAT_CCCC, R1_EVEN, R2_EVEN, FFF}, 0, PROCESSOR_V850E2V3 }, +{ "cmpf.d", two (0x07e0, 0x0430), two (0x0fe1, 0x87ff), {FLOAT_CCCC, R1_EVEN, R2_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "cmpf.s", two (0x07e0, 0x0420), two (0x07e0, 0x87f1), {FLOAT_CCCC, R1, R2, FFF}, 0, PROCESSOR_V850E2V3 }, +{ "cmpf.s", two (0x07e0, 0x0420), two (0x07e0, 0x87ff), {FLOAT_CCCC, R1, R2}, 0, PROCESSOR_V850E2V3 }, +{ "cvtf.dl", two (0x07e4, 0x0454), two (0x0fff, 0x0fff), {R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "cvtf.ds", two (0x07e3, 0x0452), two (0x0fff, 0x07ff), {R2_EVEN, R3}, 0, PROCESSOR_V850E2V3 }, +{ "cvtf.dul", two (0x07f4, 0x0454), two (0x0fff, 0x0fff), {R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "cvtf.duw", two (0x07f4, 0x0450), two (0x0fff, 0x07ff), {R2_EVEN, R3}, 0, PROCESSOR_V850E2V3 }, +{ "cvtf.dw", two (0x07e4, 0x0450), two (0x0fff, 0x07ff), {R2_EVEN, R3}, 0, PROCESSOR_V850E2V3 }, +{ "cvtf.ld", two (0x07e1, 0x0452), two (0x0fff, 0x0fff), {R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "cvtf.ls", two (0x07e1, 0x0442), two (0x0fff, 0x07ff), {R2_EVEN, R3}, 0, PROCESSOR_V850E2V3 }, +{ "cvtf.sd", two (0x07e2, 0x0452), two (0x07ff, 0x0fff), {R2, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "cvtf.sl", two (0x07e4, 0x0444), two (0x07ff, 0x0fff), {R2, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "cvtf.sul", two (0x07f4, 0x0444), two (0x07ff, 0x0fff), {R2, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "cvtf.suw", two (0x07f4, 0x0440), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2V3 }, +{ "cvtf.sw", two (0x07e4, 0x0440), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2V3 }, +{ "cvtf.uld", two (0x07f1, 0x0452), two (0x0fff, 0x0fff), {R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "cvtf.uls", two (0x07f1, 0x0442), two (0x0fff, 0x07ff), {R2_EVEN, R3}, 0, PROCESSOR_V850E2V3 }, +{ "cvtf.uwd", two (0x07f0, 0x0452), two (0x07ff, 0x0fff), {R2, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "cvtf.uws", two (0x07f0, 0x0442), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2V3 }, +{ "cvtf.wd", two (0x07e0, 0x0452), two (0x07ff, 0x0fff), {R2, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "cvtf.ws", two (0x07e0, 0x0442), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2V3 }, +{ "divf.d", two (0x07e0, 0x047e), two (0x0fe1, 0x0fff), {R1_EVEN, R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "divf.s", two (0x07e0, 0x046e), two (0x07e0, 0x07ff), {R1_NOTR0, R2, R3}, 0, PROCESSOR_V850E2V3 }, +{ "floorf.dl", two (0x07e3, 0x0454), two (0x0fff, 0x0fff), {R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "floorf.dul", two (0x07f3, 0x0454), two (0x0fff, 0x0fff), {R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "floorf.duw", two (0x07f3, 0x0450), two (0x0fff, 0x07ff), {R2_EVEN, R3}, 0, PROCESSOR_V850E2V3 }, +{ "floorf.dw", two (0x07e3, 0x0450), two (0x0fff, 0x07ff), {R2_EVEN, R3}, 0, PROCESSOR_V850E2V3 }, +{ "floorf.sl", two (0x07e3, 0x0444), two (0x07ff, 0x0fff), {R2, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "floorf.sul", two (0x07f3, 0x0444), two (0x07ff, 0x0fff), {R2, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "floorf.suw", two (0x07f3, 0x0440), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2V3 }, +{ "floorf.sw", two (0x07e3, 0x0440), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2V3 }, +{ "maddf.s", two (0x07e0, 0x0500), two (0x07e0, 0x0761), {R1, R2, R3, R4}, 0, PROCESSOR_V850E2V3 }, +{ "maxf.d", two (0x07e0, 0x0478), two (0x0fe1, 0x0fff), {R1_EVEN, R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "maxf.s", two (0x07e0, 0x0468), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_V850E2V3 }, +{ "minf.d", two (0x07e0, 0x047a), two (0x0fe1, 0x0fff), {R1_EVEN, R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "minf.s", two (0x07e0, 0x046a), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_V850E2V3 }, +{ "msubf.s", two (0x07e0, 0x0520), two (0x07e0, 0x0761), {R1, R2, R3, R4}, 0, PROCESSOR_V850E2V3 }, +{ "mulf.d", two (0x07e0, 0x0474), two (0x0fe1, 0x0fff), {R1_EVEN, R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "mulf.s", two (0x07e0, 0x0464), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_V850E2V3 }, +{ "negf.d", two (0x07e1, 0x0458), two (0x0fff, 0x0fff), {R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "negf.s", two (0x07e1, 0x0448), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2V3 }, +{ "nmaddf.s", two (0x07e0, 0x0540), two (0x07e0, 0x0761), {R1, R2, R3, R4}, 0, PROCESSOR_V850E2V3 }, +{ "nmsubf.s", two (0x07e0, 0x0560), two (0x07e0, 0x0761), {R1, R2, R3, R4}, 0, PROCESSOR_V850E2V3 }, +{ "recipf.d", two (0x07e1, 0x045e), two (0x0fff, 0x0fff), {R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "recipf.s", two (0x07e1, 0x044e), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2V3 }, + +{ "roundf.dl", two (0x07e0, 0x0454), two (0x0fff, 0x0fff), {R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 | PROCESSOR_OPTION_EXTENSION }, +{ "roundf.dul", two (0x07f0, 0x0454), two (0x0fff, 0x0fff), {R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 | PROCESSOR_OPTION_EXTENSION }, +{ "roundf.duw", two (0x07f0, 0x0450), two (0x0fff, 0x07ff), {R2_EVEN, R3}, 0, PROCESSOR_V850E2V3 | PROCESSOR_OPTION_EXTENSION }, +{ "roundf.dw", two (0x07e0, 0x0450), two (0x0fff, 0x07ff), {R2_EVEN, R3}, 0, PROCESSOR_V850E2V3 | PROCESSOR_OPTION_EXTENSION }, +{ "roundf.sl", two (0x07e0, 0x0444), two (0x07ff, 0x0fff), {R2, R3_EVEN}, 0, PROCESSOR_V850E2V3 | PROCESSOR_OPTION_EXTENSION }, +{ "roundf.sul", two (0x07f0, 0x0444), two (0x07ff, 0x0fff), {R2, R3_EVEN}, 0, PROCESSOR_V850E2V3 | PROCESSOR_OPTION_EXTENSION }, +{ "roundf.suw", two (0x07f0, 0x0440), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2V3 | PROCESSOR_OPTION_EXTENSION }, +{ "roundf.sw", two (0x07e0, 0x0440), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2V3 | PROCESSOR_OPTION_EXTENSION }, + +{ "rsqrtf.d", two (0x07e2, 0x045e), two (0x0fff, 0x0fff), {R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "rsqrtf.s", two (0x07e2, 0x044e), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2V3 }, +{ "sqrtf.d", two (0x07e0, 0x045e), two (0x0fff, 0x0fff), {R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "sqrtf.s", two (0x07e0, 0x044e), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2V3 }, +{ "subf.d", two (0x07e0, 0x0472), two (0x0fe1, 0x0fff), {R1_EVEN, R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "subf.s", two (0x07e0, 0x0462), two (0x07e0, 0x07ff), {R1, R2, R3}, 0, PROCESSOR_V850E2V3 }, +{ "trfsr", two (0x07e0, 0x0400), two (0xffff, 0xfff1), {FFF}, 0, PROCESSOR_V850E2V3 }, +{ "trfsr", two (0x07e0, 0x0400), two (0xffff, 0xffff), {0}, 0, PROCESSOR_V850E2V3 }, +{ "trncf.dl", two (0x07e1, 0x0454), two (0x0fff, 0x0fff), {R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "trncf.dul", two (0x07f1, 0x0454), two (0x0fff, 0x0fff), {R2_EVEN, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "trncf.duw", two (0x07f1, 0x0450), two (0x0fff, 0x07ff), {R2_EVEN, R3}, 0, PROCESSOR_V850E2V3 }, +{ "trncf.dw", two (0x07e1, 0x0450), two (0x0fff, 0x07ff), {R2_EVEN, R3}, 0, PROCESSOR_V850E2V3 }, +{ "trncf.sl", two (0x07e1, 0x0444), two (0x07ff, 0x0fff), {R2, R3_EVEN}, 0, PROCESSOR_V850E2V3 }, +{ "trncf.sul", two (0x07f1, 0x0444), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2V3 }, +{ "trncf.suw", two (0x07f1, 0x0440), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2V3 }, +{ "trncf.sw", two (0x07e1, 0x0440), two (0x07ff, 0x07ff), {R2, R3}, 0, PROCESSOR_V850E2V3 }, + + /* Special instruction (from gdb) mov 1, r0. */ +{ "breakpoint", one (0x0001), one (0xffff), {UNUSED}, 0, PROCESSOR_ALL }, + + /* V850e2-v3. */ +{ "synce", one (0x001d), one (0xffff), {0}, 0, PROCESSOR_V850E2V3 }, +{ "syncm", one (0x001e), one (0xffff), {0}, 0, PROCESSOR_V850E2V3 }, +{ "syncp", one (0x001f), one (0xffff), {0}, 0, PROCESSOR_V850E2V3 }, +{ "syscall", two (0xd7e0, 0x0160), two (0xffe0, 0xc7ff), {V8}, 0, PROCESSOR_V850E2V3 }, + /* Alias of syncp. */ +{ "sync", one (0x001f), one (0xffff), {0}, 0, PROCESSOR_V850E2V3 | PROCESSOR_OPTION_ALIAS }, +{ "rmtrap", one (0xf040), one (0xffff), {0}, 0, PROCESSOR_V850E2V3 }, + + +{ "rie", one (0x0040), one (0xffff), {0}, 0, PROCESSOR_V850E2V3 }, +{ "rie", two (0x07f0, 0x0000), two (0x07f0, 0xffff), {0}, 0, PROCESSOR_V850E2V3 }, + +{ 0, 0, 0, {0}, 0, 0 }, } ; const int v850_num_opcodes = -- 2.30.2