From c3b7224ae49a815ca1e60d058acc980530832881 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Mon, 2 Mar 2009 10:33:08 +0000 Subject: [PATCH] Add support for Score7 architecture. --- bfd/ChangeLog | 17 + bfd/Makefile.am | 9 +- bfd/Makefile.in | 8 + bfd/archures.c | 4 +- bfd/bfd-in2.h | 17 +- bfd/configure | 4 +- bfd/configure.in | 4 +- bfd/cpu-score.c | 68 +- bfd/elf32-score.c | 2252 +++-- bfd/elf32-score.h | 152 + bfd/elf32-score7.c | 3947 +++++++++ bfd/libbfd.h | 4 +- bfd/reloc.c | 17 +- gas/ChangeLog | 14 + gas/Makefile.am | 11 +- gas/Makefile.in | 6 +- gas/NEWS | 2 + gas/config/tc-score.c | 8989 +++++++++++--------- gas/config/tc-score.h | 11 +- gas/config/tc-score7.c | 6987 +++++++++++++++ gas/doc/Makefile.am | 3 +- gas/doc/Makefile.in | 1 + gas/doc/all.texi | 3 +- gas/doc/as.texinfo | 33 +- gas/doc/c-score.texi | 142 + gas/testsuite/ChangeLog | 32 + gas/testsuite/gas/score/arith_32-lt.d | 16 + gas/testsuite/gas/score/arith_32.d | 55 + gas/testsuite/gas/score/arith_32.s | 43 + gas/testsuite/gas/score/bit_32-lt.d | 17 + gas/testsuite/gas/score/bit_32.d | 69 + gas/testsuite/gas/score/bit_32.s | 43 + gas/testsuite/gas/score/branch_32-lt.d | 1652 ++++ gas/testsuite/gas/score/branch_32.d | 578 ++ gas/testsuite/gas/score/branch_32.s | 181 + gas/testsuite/gas/score/cmp_32-lt.d | 12 + gas/testsuite/gas/score/cmp_32.d | 39 + gas/testsuite/gas/score/cmp_32.s | 33 + gas/testsuite/gas/score/load_store_32-lt.d | 19 + gas/testsuite/gas/score/load_store_32.d | 79 + gas/testsuite/gas/score/load_store_32.s | 71 + gas/testsuite/gas/score/logical_32-lt.d | 13 + gas/testsuite/gas/score/logical_32.d | 38 + gas/testsuite/gas/score/logical_32.s | 26 + gas/testsuite/gas/score/mv_32-lt.d | 10 + gas/testsuite/gas/score/mv_32.d | 22 + gas/testsuite/gas/score/mv_32.s | 18 + gas/testsuite/gas/score/relax_32.exp | 24 + gas/testsuite/gas/score/relaxation_macro.h | 32 + gas/testsuite/gas/score/shift_32-lt.d | 13 + gas/testsuite/gas/score/shift_32.d | 40 + gas/testsuite/gas/score/shift_32.s | 26 + gas/testsuite/gas/score/syscontrol_32-lt.d | 11 + gas/testsuite/gas/score/syscontrol_32.d | 21 + gas/testsuite/gas/score/syscontrol_32.s | 19 + include/elf/ChangeLog | 5 + include/elf/common.h | 3 + include/elf/score.h | 13 +- include/opcode/ChangeLog | 6 + include/opcode/score-datadep.h | 227 +- include/opcode/score-inst.h | 313 +- ld/ChangeLog | 10 + ld/Makefile.am | 15 +- ld/Makefile.in | 15 +- ld/NEWS | 2 + ld/configure.tgt | 3 +- ld/emulparams/scoreelf.sh | 15 +- ld/emultempl/scoreelf.em | 21 +- opcodes/ChangeLog | 10 + opcodes/Makefile.am | 7 + opcodes/Makefile.in | 7 + opcodes/configure | 2 +- opcodes/configure.in | 2 +- opcodes/score-dis.c | 880 +- opcodes/score-opc.h | 460 +- opcodes/score7-dis.c | 972 +++ 76 files changed, 23333 insertions(+), 5612 deletions(-) create mode 100644 bfd/elf32-score.h create mode 100644 bfd/elf32-score7.c create mode 100644 gas/config/tc-score7.c create mode 100644 gas/doc/c-score.texi create mode 100644 gas/testsuite/gas/score/arith_32-lt.d create mode 100644 gas/testsuite/gas/score/arith_32.d create mode 100644 gas/testsuite/gas/score/arith_32.s create mode 100644 gas/testsuite/gas/score/bit_32-lt.d create mode 100644 gas/testsuite/gas/score/bit_32.d create mode 100644 gas/testsuite/gas/score/bit_32.s create mode 100644 gas/testsuite/gas/score/branch_32-lt.d create mode 100644 gas/testsuite/gas/score/branch_32.d create mode 100644 gas/testsuite/gas/score/branch_32.s create mode 100644 gas/testsuite/gas/score/cmp_32-lt.d create mode 100644 gas/testsuite/gas/score/cmp_32.d create mode 100644 gas/testsuite/gas/score/cmp_32.s create mode 100644 gas/testsuite/gas/score/load_store_32-lt.d create mode 100644 gas/testsuite/gas/score/load_store_32.d create mode 100644 gas/testsuite/gas/score/load_store_32.s create mode 100644 gas/testsuite/gas/score/logical_32-lt.d create mode 100644 gas/testsuite/gas/score/logical_32.d create mode 100644 gas/testsuite/gas/score/logical_32.s create mode 100644 gas/testsuite/gas/score/mv_32-lt.d create mode 100644 gas/testsuite/gas/score/mv_32.d create mode 100644 gas/testsuite/gas/score/mv_32.s create mode 100644 gas/testsuite/gas/score/relax_32.exp create mode 100644 gas/testsuite/gas/score/relaxation_macro.h create mode 100644 gas/testsuite/gas/score/shift_32-lt.d create mode 100644 gas/testsuite/gas/score/shift_32.d create mode 100644 gas/testsuite/gas/score/shift_32.s create mode 100644 gas/testsuite/gas/score/syscontrol_32-lt.d create mode 100644 gas/testsuite/gas/score/syscontrol_32.d create mode 100644 gas/testsuite/gas/score/syscontrol_32.s create mode 100644 opcodes/score7-dis.c diff --git a/bfd/ChangeLog b/bfd/ChangeLog index ff99690bcda..d431c0d5f90 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,20 @@ +2009-03-02 Qinwei + + * elf32-score7.c: New file. + * elf32-score.h: New file. + * elf32-score.c: Add code to support score 7. Set score7 as the + default. + * cpu-score.c: Add score7 architecure. + (compatibile): New function. + * Makefile.am: Add rules for building elf32-score7 object. + * Makefile.in: Regenerate. + * configure.in: Add elf32-score7 object to score vectors. + * configure: Regenerate. + * reloc.c: Add score7 relocs. + * archures.c: Add score3 and score7 machine numbers. + * bfd-in2.h: Regenerate. + * libbfd.h: Regenerate. + 2009-03-01 Ralf Wildenhues * configure: Regenerate. diff --git a/bfd/Makefile.am b/bfd/Makefile.am index 8d67cb8ef75..08f0c2a8318 100644 --- a/bfd/Makefile.am +++ b/bfd/Makefile.am @@ -289,6 +289,7 @@ BFD32_BACKENDS = \ elf32-ppc.lo \ elf32-s390.lo \ elf32-score.lo \ + elf32-score7.lo \ elf32-sh.lo \ elf32-sh-symbian.lo \ elf32-sh64.lo \ @@ -474,6 +475,7 @@ BFD32_BACKENDS_CFILES = \ elf32-sh64-com.c \ elf32-s390.c \ elf32-score.c \ + elf32-score7.c \ elf32-sh.c \ elf32-sh-symbian.c \ elfxx-sparc.c \ @@ -1570,7 +1572,12 @@ elf32-s390.lo: elf32-s390.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \ elf32-score.lo: elf32-score.c $(INCDIR)/filenames.h \ $(INCDIR)/hashtab.h $(INCDIR)/libiberty.h elf-bfd.h \ $(INCDIR)/elf/common.h $(INCDIR)/elf/external.h $(INCDIR)/elf/internal.h \ - $(INCDIR)/bfdlink.h $(INCDIR)/elf/score.h $(INCDIR)/elf/reloc-macros.h \ + $(INCDIR)/bfdlink.h elf32-score.h $(INCDIR)/elf/score.h $(INCDIR)/elf/reloc-macros.h \ + elf32-target.h +elf32-score7.lo: elf32-score7.c $(INCDIR)/filenames.h \ + $(INCDIR)/hashtab.h $(INCDIR)/libiberty.h elf-bfd.h \ + $(INCDIR)/elf/common.h $(INCDIR)/elf/external.h $(INCDIR)/elf/internal.h \ + $(INCDIR)/bfdlink.h elf32-score.h $(INCDIR)/elf/score.h $(INCDIR)/elf/reloc-macros.h \ elf32-target.h elf32-sh.lo: elf32-sh.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \ $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \ diff --git a/bfd/Makefile.in b/bfd/Makefile.in index 9932dea1324..1eb588789d8 100644 --- a/bfd/Makefile.in +++ b/bfd/Makefile.in @@ -555,6 +555,7 @@ BFD32_BACKENDS = \ elf32-ppc.lo \ elf32-s390.lo \ elf32-score.lo \ + elf32-score7.lo \ elf32-sh.lo \ elf32-sh-symbian.lo \ elf32-sh64.lo \ @@ -739,6 +740,7 @@ BFD32_BACKENDS_CFILES = \ elf32-sh64.c \ elf32-sh64-com.c \ elf32-s390.c \ + elf32-score7.c \ elf32-score.c \ elf32-sh.c \ elf32-sh-symbian.c \ @@ -2167,6 +2169,12 @@ elf32-score.lo: elf32-score.c $(INCDIR)/filenames.h \ $(INCDIR)/hashtab.h $(INCDIR)/libiberty.h elf-bfd.h \ $(INCDIR)/elf/common.h $(INCDIR)/elf/external.h $(INCDIR)/elf/internal.h \ $(INCDIR)/bfdlink.h $(INCDIR)/elf/score.h $(INCDIR)/elf/reloc-macros.h \ + $(INCDIR)/bfdlink.h elf32-score.h $(INCDIR)/elf/score.h $(INCDIR)/elf/reloc-macros.h \ + elf32-target.h +elf32-score7.lo: elf32-score7.c $(INCDIR)/filenames.h \ + $(INCDIR)/hashtab.h $(INCDIR)/libiberty.h elf-bfd.h \ + $(INCDIR)/elf/common.h $(INCDIR)/elf/external.h $(INCDIR)/elf/internal.h \ + $(INCDIR)/bfdlink.h elf32-score.h $(INCDIR)/elf/score.h $(INCDIR)/elf/reloc-macros.h \ elf32-target.h elf32-sh.lo: elf32-sh.c $(INCDIR)/filenames.h $(INCDIR)/bfdlink.h \ $(INCDIR)/hashtab.h elf-bfd.h $(INCDIR)/elf/common.h \ diff --git a/bfd/archures.c b/bfd/archures.c index f548ea21d45..fa03d81a698 100644 --- a/bfd/archures.c +++ b/bfd/archures.c @@ -1,6 +1,6 @@ /* BFD library support routines for architectures. Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 + 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Hacked by John Gilmore and Steve Chamberlain of Cygnus Support. @@ -376,6 +376,8 @@ DESCRIPTION .#define bfd_mach_s390_31 31 .#define bfd_mach_s390_64 64 . bfd_arch_score, {* Sunplus score *} +.#define bfd_mach_score3 3 +.#define bfd_mach_score7 7 . bfd_arch_openrisc, {* OpenRISC *} . bfd_arch_mmix, {* Donald Knuth's educational processor. *} . bfd_arch_xstormy16, diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 7870962f1af..be35ac4db63 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -2002,6 +2002,8 @@ enum bfd_architecture #define bfd_mach_s390_31 31 #define bfd_mach_s390_64 64 bfd_arch_score, /* Sunplus score */ +#define bfd_mach_score3 3 +#define bfd_mach_score7 7 bfd_arch_openrisc, /* OpenRISC */ bfd_arch_mmix, /* Donald Knuth's educational processor. */ bfd_arch_xstormy16, @@ -3889,10 +3891,8 @@ instructions */ BFD_RELOC_390_GOTPLT20, BFD_RELOC_390_TLS_GOTIE20, -/* Score relocations */ - BFD_RELOC_SCORE_DUMMY1, - -/* Low 16 bit for load/store */ +/* Score relocations +Low 16 bit for load/store */ BFD_RELOC_SCORE_GPREL15, /* This is a 24-bit reloc with the right 1 bit assumed to be 0 */ @@ -3902,12 +3902,21 @@ instructions */ /* This is a 19-bit reloc with the right 1 bit assumed to be 0 */ BFD_RELOC_SCORE_BRANCH, +/* This is a 32-bit reloc for 48-bit instructions. */ + BFD_RELOC_SCORE_IMM30, + +/* This is a 32-bit reloc for 48-bit instructions. */ + BFD_RELOC_SCORE_IMM32, + /* This is a 11-bit reloc with the right 1 bit assumed to be 0 */ BFD_RELOC_SCORE16_JMP, /* This is a 8-bit reloc with the right 1 bit assumed to be 0 */ BFD_RELOC_SCORE16_BRANCH, +/* This is a 9-bit reloc with the right 1 bit assumed to be 0 */ + BFD_RELOC_SCORE_BCMP, + /* Undocumented Score relocs */ BFD_RELOC_SCORE_GOT15, BFD_RELOC_SCORE_GOT_LO16, diff --git a/bfd/configure b/bfd/configure index edfb2f20f35..6c21291fea3 100755 --- a/bfd/configure +++ b/bfd/configure @@ -20783,8 +20783,8 @@ do bfd_elf32_powerpcle_vec) tb="$tb elf32-ppc.lo elf-vxworks.lo elf32.lo $elf" ;; bfd_elf32_powerpc_vxworks_vec) tb="$tb elf32-ppc.lo elf-vxworks.lo elf32.lo $elf" ;; bfd_elf32_s390_vec) tb="$tb elf32-s390.lo elf32.lo $elf" ;; - bfd_elf32_bigscore_vec) tb="$tb elf32-score.lo elf32.lo $elf" ;; - bfd_elf32_littlescore_vec) tb="$tb elf32-score.lo elf32.lo $elf" ;; + bfd_elf32_bigscore_vec) tb="$tb elf32-score.lo elf32-score7.lo elf32.lo $elf"; want64=true;; + bfd_elf32_littlescore_vec) tb="$tb elf32-score.lo elf32-score7.lo elf32.lo $elf"; want64=true;; # FIXME: We include cofflink.lo not because it's needed for # bfd_elf32_sh64[l]_vec, but because we include bfd_elf32_sh[l]_vec # which needs it but does not list it. Should be fixed in right place. diff --git a/bfd/configure.in b/bfd/configure.in index a4444185fd3..a56004d4acd 100644 --- a/bfd/configure.in +++ b/bfd/configure.in @@ -724,8 +724,8 @@ do bfd_elf32_powerpcle_vec) tb="$tb elf32-ppc.lo elf-vxworks.lo elf32.lo $elf" ;; bfd_elf32_powerpc_vxworks_vec) tb="$tb elf32-ppc.lo elf-vxworks.lo elf32.lo $elf" ;; bfd_elf32_s390_vec) tb="$tb elf32-s390.lo elf32.lo $elf" ;; - bfd_elf32_bigscore_vec) tb="$tb elf32-score.lo elf32.lo $elf" ;; - bfd_elf32_littlescore_vec) tb="$tb elf32-score.lo elf32.lo $elf" ;; + bfd_elf32_bigscore_vec) tb="$tb elf32-score.lo elf32-score7.lo elf32.lo $elf"; want64=true;; + bfd_elf32_littlescore_vec) tb="$tb elf32-score.lo elf32-score7.lo elf32.lo $elf"; want64=true;; # FIXME: We include cofflink.lo not because it's needed for # bfd_elf32_sh64[l]_vec, but because we include bfd_elf32_sh[l]_vec # which needs it but does not list it. Should be fixed in right place. diff --git a/bfd/cpu-score.c b/bfd/cpu-score.c index 0ccc371cabf..0ed4095c1a0 100644 --- a/bfd/cpu-score.c +++ b/bfd/cpu-score.c @@ -1,8 +1,9 @@ /* BFD support for the score processor - Copyright 2006, 2007 Free Software Foundation, Inc. + Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by + Brain.lin (brain.lin@sunplusct.com) Mei Ligang (ligang@sunnorth.com.cn) - Pei-Lin Tsai (pltsai@sunplus.com) + Pei-Lin Tsai (pltsai@sunplus.com) This file is part of BFD, the Binary File Descriptor library. @@ -21,32 +22,47 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "sysdep.h" #include "bfd.h" +#include "sysdep.h" #include "libbfd.h" -const bfd_arch_info_type -bfd_score_arch = +/* This routine is provided two arch_infos and works out which Score + machine which would be compatible with both and returns a pointer + to its info structure. */ + +static const bfd_arch_info_type * +compatible (const bfd_arch_info_type * a, const bfd_arch_info_type * b) { - 32, /* There's 32 bits_per_word. */ - 32, /* There's 32 bits_per_address. */ - 8, /* There's 8 bits_per_byte. */ - bfd_arch_score, /* One of enum bfd_architecture, defined - in archures.c and provided in - generated header files. */ - 0, /* Only 1 machine, but #255 for - historical reasons. */ - "score", /* The arch_name. */ - "score", /* The printable name is the same. */ - 4, /* Section alignment power; each section - is aligned to (only) 2^4 bytes. */ - TRUE, /* This is the default "machine", since - there's only one. */ - bfd_default_compatible, /* A default function for testing - "machine" compatibility of two - bfd_arch_info_type. */ - bfd_default_scan, /* Check if an bfd_arch_info_type is a - match. */ - NULL /* Pointer to next bfd_arch_info_type in - the same family. */ + /* If a & b are for different architectures we can do nothing. */ + if (a->arch != b->arch) + return NULL; + + if (a->mach != b->mach) + return NULL; + + return a; +} + +#define N(addr_bits, machine, print, default, next) \ +{ \ + 32, /* 16 bits in a word. */ \ + 32, /* Bits in an address. */ \ + 8, /* 8 bits in a byte. */ \ + bfd_arch_score, \ + machine, /* Machine number. */ \ + "score", /* Architecture name. */ \ + print, /* Printable name. */ \ + 4, /* Section align power. */ \ + default, /* The default machine. */ \ + compatible, \ + bfd_default_scan, \ + next \ +} + +static const bfd_arch_info_type arch_info_struct[] = +{ + N (16, bfd_mach_score3, "score3", FALSE, NULL), }; + +const bfd_arch_info_type bfd_score_arch = + N (16, bfd_mach_score7, "score7", TRUE, & arch_info_struct[0]); diff --git a/bfd/elf32-score.c b/bfd/elf32-score.c index 813f21ead97..d5e21b5383d 100644 --- a/bfd/elf32-score.c +++ b/bfd/elf32-score.c @@ -1,6 +1,7 @@ /* 32-bit ELF support for S+core. - Copyright 2006, 2007 Free Software Foundation, Inc. + Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by + Brain.lin (brain.lin@sunplusct.com) Mei Ligang (ligang@sunnorth.com.cn) Pei-Lin Tsai (pltsai@sunplus.com) @@ -30,10 +31,13 @@ #include "elf/common.h" #include "elf/internal.h" #include "hashtab.h" +#include "elf32-score.h" -/* Score ELF linker hash table. */ +int score3 = 0; +int score7 = 1; +/* Score ELF linker hash table. */ struct score_elf_link_hash_table { /* The main hash table. */ @@ -42,7 +46,6 @@ struct score_elf_link_hash_table /* The SCORE ELF linker needs additional information for each symbol in the global hash table. */ - struct score_elf_link_hash_entry { struct elf_link_hash_entry root; @@ -175,7 +178,7 @@ struct _score_elf_section_data #define SCORE_ELF_STUB_SECTION_NAME (".SCORE.stub") #define SCORE_FUNCTION_STUB_SIZE (16) -#define STUB_LW 0xc3bcc010 /* lw r29, [r28, -0x3ff0] */ +#define STUB_LW 0xc3bcc010 /* lw r29, [r28, -0x3ff0] */ #define STUB_MOVE 0x8363bc56 /* mv r27, r3 */ #define STUB_LI16 0x87548000 /* ori r26, .dynsym_index */ #define STUB_BRL 0x801dbc09 /* brl r29 */ @@ -198,10 +201,6 @@ struct _score_elf_section_data #define SCORE_ELF_LOG_FILE_ALIGN(abfd)\ (get_elf_backend_data (abfd)->s->log_file_align) -#ifndef NUM_ELEM -#define NUM_ELEM(a) (sizeof (a) / (sizeof (a)[0])) -#endif - static bfd_byte *hi16_rel_addr; /* This will be used when we sort the dynamic relocation records. */ @@ -216,14 +215,112 @@ static asection score_elf_scom_section; static asymbol score_elf_scom_symbol; static asymbol *score_elf_scom_symbol_ptr; +static bfd_vma +score_bfd_get_16 (bfd *abfd, const void *data) +{ + return bfd_get_16 (abfd, data); +} + +static bfd_vma +score3_bfd_getl32 (const void *p) +{ + const bfd_byte *addr = p; + unsigned long v; + + v = (unsigned long) addr[2]; + v |= (unsigned long) addr[3] << 8; + v |= (unsigned long) addr[0] << 16; + v |= (unsigned long) addr[1] << 24; + return v; +} + +static bfd_vma +score3_bfd_getl48 (const void *p) +{ + const bfd_byte *addr = p; + unsigned long long v; + + v = (unsigned long long) addr[4]; + v |= (unsigned long long) addr[5] << 8; + v |= (unsigned long long) addr[2] << 16; + v |= (unsigned long long) addr[3] << 24; + v |= (unsigned long long) addr[0] << 32; + v |= (unsigned long long) addr[1] << 40; + return v; +} + +static bfd_vma +score_bfd_get_32 (bfd *abfd, const void *data) +{ + if (/* score3 && */ abfd->xvec->byteorder == BFD_ENDIAN_LITTLE) + return score3_bfd_getl32 (data); + else + return bfd_get_32 (abfd, data); +} + +static bfd_vma +score_bfd_get_48 (bfd *abfd, const void *p) +{ + if (/* score3 && */ abfd->xvec->byteorder == BFD_ENDIAN_LITTLE) + return score3_bfd_getl48 (p); + else + return bfd_get_bits (p, 48, 1); +} + +static void +score_bfd_put_16 (bfd *abfd, bfd_vma addr, void *data) +{ + return bfd_put_16 (abfd, addr, data); +} + +static void +score3_bfd_putl32 (bfd_vma data, void *p) +{ + bfd_byte *addr = p; + addr[0] = (data >> 16) & 0xff; + addr[1] = (data >> 24) & 0xff; + addr[2] = data & 0xff; + addr[3] = (data >> 8) & 0xff; +} + +static void +score3_bfd_putl48 (bfd_vma data, void *p) +{ + bfd_byte *addr = p; + addr[0] = (data >> 32) & 0xff; + addr[1] = (data >> 40) & 0xff; + addr[2] = (data >> 16) & 0xff; + addr[3] = (data >> 24) & 0xff; + addr[4] = data & 0xff; + addr[5] = (data >> 8) & 0xff; +} + +static void +score_bfd_put_32 (bfd *abfd, bfd_vma addr, void *data) +{ + if (/* score3 && */ abfd->xvec->byteorder == BFD_ENDIAN_LITTLE) + return score3_bfd_putl32 (addr, data); + else + return bfd_put_32 (abfd, addr, data); +} + +static void +score_bfd_put_48 (bfd *abfd, bfd_vma val, void *p) +{ + if (/* score3 && */ abfd->xvec->byteorder == BFD_ENDIAN_LITTLE) + return score3_bfd_putl48 (val, p); + else + return bfd_put_bits (val, p, 48, 1); +} + static bfd_reloc_status_type score_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED, - arelent *reloc_entry, - asymbol *symbol ATTRIBUTE_UNUSED, - void * data, - asection *input_section ATTRIBUTE_UNUSED, - bfd *output_bfd ATTRIBUTE_UNUSED, - char **error_message ATTRIBUTE_UNUSED) + arelent *reloc_entry, + asymbol *symbol ATTRIBUTE_UNUSED, + void * data, + asection *input_section ATTRIBUTE_UNUSED, + bfd *output_bfd ATTRIBUTE_UNUSED, + char **error_message ATTRIBUTE_UNUSED) { hi16_rel_addr = (bfd_byte *) data + reloc_entry->address; return bfd_reloc_ok; @@ -231,20 +328,20 @@ score_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED, static bfd_reloc_status_type score_elf_lo16_reloc (bfd *abfd, - arelent *reloc_entry, - asymbol *symbol ATTRIBUTE_UNUSED, - void * data, - asection *input_section, - bfd *output_bfd ATTRIBUTE_UNUSED, - char **error_message ATTRIBUTE_UNUSED) + arelent *reloc_entry, + asymbol *symbol ATTRIBUTE_UNUSED, + void * data, + asection *input_section, + bfd *output_bfd ATTRIBUTE_UNUSED, + char **error_message ATTRIBUTE_UNUSED) { bfd_vma addend = 0, offset = 0; unsigned long val; unsigned long hi16_offset, hi16_value, uvalue; - hi16_value = bfd_get_32 (abfd, hi16_rel_addr); + hi16_value = score_bfd_get_32 (abfd, hi16_rel_addr); hi16_offset = ((((hi16_value >> 16) & 0x3) << 15) | (hi16_value & 0x7fff)) >> 1; - addend = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); + addend = score_bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1; val = reloc_entry->addend; if (reloc_entry->address > input_section->size) @@ -252,10 +349,10 @@ score_elf_lo16_reloc (bfd *abfd, uvalue = ((hi16_offset << 16) | (offset & 0xffff)) + val; hi16_offset = (uvalue >> 16) << 1; hi16_value = (hi16_value & ~0x37fff) | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000); - bfd_put_32 (abfd, hi16_value, hi16_rel_addr); + score_bfd_put_32 (abfd, hi16_value, hi16_rel_addr); offset = (uvalue & 0xffff) << 1; addend = (addend & ~0x37fff) | (offset & 0x7fff) | ((offset << 1) & 0x30000); - bfd_put_32 (abfd, addend, (bfd_byte *) data + reloc_entry->address); + score_bfd_put_32 (abfd, addend, (bfd_byte *) data + reloc_entry->address); return bfd_reloc_ok; } @@ -284,17 +381,17 @@ score_elf_assign_gp (bfd *output_bfd, bfd_vma *pgp) else { for (i = 0; i < count; i++, sym++) - { - const char *name; + { + const char *name; - name = bfd_asymbol_name (*sym); - if (*name == '_' && strcmp (name, "_gp") == 0) - { - *pgp = bfd_asymbol_value (*sym); - _bfd_set_gp_value (output_bfd, *pgp); - break; - } - } + name = bfd_asymbol_name (*sym); + if (*name == '_' && strcmp (name, "_gp") == 0) + { + *pgp = bfd_asymbol_value (*sym); + _bfd_set_gp_value (output_bfd, *pgp); + break; + } + } } if (i >= count) @@ -313,13 +410,12 @@ score_elf_assign_gp (bfd *output_bfd, bfd_vma *pgp) BFD. If we can't find it, we're stuck. We cache it in the ELF target data. We don't need to adjust the symbol value for an external symbol if we are producing relocatable output. */ - static bfd_reloc_status_type score_elf_final_gp (bfd *output_bfd, - asymbol *symbol, - bfd_boolean relocatable, - char **error_message, - bfd_vma *pgp) + asymbol *symbol, + bfd_boolean relocatable, + char **error_message, + bfd_vma *pgp) { if (bfd_is_und_section (symbol->section) && ! relocatable) @@ -331,20 +427,20 @@ score_elf_final_gp (bfd *output_bfd, *pgp = _bfd_get_gp_value (output_bfd); if (*pgp == 0 && (! relocatable - || (symbol->flags & BSF_SECTION_SYM) != 0)) + || (symbol->flags & BSF_SECTION_SYM) != 0)) { if (relocatable) - { - /* Make up a value. */ - *pgp = symbol->section->output_section->vma + 0x4000; - _bfd_set_gp_value (output_bfd, *pgp); - } + { + /* Make up a value. */ + *pgp = symbol->section->output_section->vma + 0x4000; + _bfd_set_gp_value (output_bfd, *pgp); + } else if (!score_elf_assign_gp (output_bfd, pgp)) - { - *error_message = - (char *) _("GP relative relocation when _gp not defined"); - return bfd_reloc_dangerous; - } + { + *error_message = + (char *) _("GP relative relocation when _gp not defined"); + return bfd_reloc_dangerous; + } } return bfd_reloc_ok; @@ -352,12 +448,12 @@ score_elf_final_gp (bfd *output_bfd, static bfd_reloc_status_type score_elf_gprel15_with_gp (bfd *abfd, - asymbol *symbol, - arelent *reloc_entry, - asection *input_section, - bfd_boolean relocateable, - void * data, - bfd_vma gp ATTRIBUTE_UNUSED) + asymbol *symbol, + arelent *reloc_entry, + asection *input_section, + bfd_boolean relocateable, + void * data, + bfd_vma gp ATTRIBUTE_UNUSED) { bfd_vma relocation; unsigned long insn; @@ -372,13 +468,13 @@ score_elf_gprel15_with_gp (bfd *abfd, if (reloc_entry->address > input_section->size) return bfd_reloc_outofrange; - insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); + insn = score_bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); if (((reloc_entry->addend & 0xffffc000) != 0) && ((reloc_entry->addend & 0xffffc000) != 0xffffc000)) return bfd_reloc_overflow; insn = (insn & ~0x7fff) | (reloc_entry->addend & 0x7fff); - bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address); + score_bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address); if (relocateable) reloc_entry->address += input_section->output_offset; @@ -387,8 +483,8 @@ score_elf_gprel15_with_gp (bfd *abfd, static bfd_reloc_status_type gprel32_with_gp (bfd *abfd, asymbol *symbol, arelent *reloc_entry, - asection *input_section, bfd_boolean relocatable, - void *data, bfd_vma gp) + asection *input_section, bfd_boolean relocatable, + void *data, bfd_vma gp) { bfd_vma relocation; bfd_vma val; @@ -408,7 +504,7 @@ gprel32_with_gp (bfd *abfd, asymbol *symbol, arelent *reloc_entry, val = reloc_entry->addend; if (reloc_entry->howto->partial_inplace) - val += bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); + val += score_bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); /* Adjust val for the final section location and GP value. If we are producing relocatable output, we don't want to do this for @@ -418,7 +514,7 @@ gprel32_with_gp (bfd *abfd, asymbol *symbol, arelent *reloc_entry, val += relocation - gp; if (reloc_entry->howto->partial_inplace) - bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address); + score_bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address); else reloc_entry->addend = val; @@ -430,24 +526,24 @@ gprel32_with_gp (bfd *abfd, asymbol *symbol, arelent *reloc_entry, static bfd_reloc_status_type score_elf_gprel15_reloc (bfd *abfd, - arelent *reloc_entry, - asymbol *symbol, - void * data, - asection *input_section, - bfd *output_bfd, - char **error_message) + arelent *reloc_entry, + asymbol *symbol, + void * data, + asection *input_section, + bfd *output_bfd, + char **error_message) { bfd_boolean relocateable; bfd_reloc_status_type ret; bfd_vma gp; - if (output_bfd != (bfd *) NULL + if (output_bfd != NULL && (symbol->flags & BSF_SECTION_SYM) == 0 && reloc_entry->addend == 0) { reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; } - if (output_bfd != (bfd *) NULL) + if (output_bfd != NULL) relocateable = TRUE; else { @@ -468,8 +564,8 @@ score_elf_gprel15_reloc (bfd *abfd, static bfd_reloc_status_type score_elf_gprel32_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, - void *data, asection *input_section, bfd *output_bfd, - char **error_message) + void *data, asection *input_section, bfd *output_bfd, + char **error_message) { bfd_boolean relocatable; bfd_reloc_status_type ret; @@ -481,7 +577,7 @@ score_elf_gprel32_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, && (symbol->flags & BSF_LOCAL) != 0) { *error_message = (char *) - _("32bits gp relative relocation occurs for an external symbol"); + _("32bits gp relative relocation occurs for an external symbol"); return bfd_reloc_outofrange; } @@ -497,48 +593,47 @@ score_elf_gprel32_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, if (ret != bfd_reloc_ok) return ret; - gp = 0; /* FIXME. */ + gp = 0; return gprel32_with_gp (abfd, symbol, reloc_entry, input_section, - relocatable, data, gp); + relocatable, data, gp); } /* A howto special_function for R_SCORE_GOT15 relocations. This is just like any other 16-bit relocation when applied to global symbols, but is treated in the same as R_SCORE_HI16 when applied to local symbols. */ - static bfd_reloc_status_type score_elf_got15_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, - void *data, asection *input_section, - bfd *output_bfd, char **error_message) + void *data, asection *input_section, + bfd *output_bfd, char **error_message) { if ((symbol->flags & (BSF_GLOBAL | BSF_WEAK)) != 0 || bfd_is_und_section (bfd_get_section (symbol)) || bfd_is_com_section (bfd_get_section (symbol))) /* The relocation is against a global symbol. */ return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, - input_section, output_bfd, - error_message); + input_section, output_bfd, + error_message); return score_elf_hi16_reloc (abfd, reloc_entry, symbol, data, - input_section, output_bfd, error_message); + input_section, output_bfd, error_message); } static bfd_reloc_status_type score_elf_got_lo16_reloc (bfd *abfd, - arelent *reloc_entry, - asymbol *symbol ATTRIBUTE_UNUSED, - void * data, - asection *input_section, - bfd *output_bfd ATTRIBUTE_UNUSED, - char **error_message ATTRIBUTE_UNUSED) + arelent *reloc_entry, + asymbol *symbol ATTRIBUTE_UNUSED, + void * data, + asection *input_section, + bfd *output_bfd ATTRIBUTE_UNUSED, + char **error_message ATTRIBUTE_UNUSED) { bfd_vma addend = 0, offset = 0; signed long val; signed long hi16_offset, hi16_value, uvalue; - hi16_value = bfd_get_32 (abfd, hi16_rel_addr); + hi16_value = score_bfd_get_32 (abfd, hi16_rel_addr); hi16_offset = ((((hi16_value >> 16) & 0x3) << 15) | (hi16_value & 0x7fff)) >> 1; - addend = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); + addend = score_bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1; val = reloc_entry->addend; if (reloc_entry->address > input_section->size) @@ -549,10 +644,10 @@ score_elf_got_lo16_reloc (bfd *abfd, else hi16_offset = (uvalue >> 16) & 0x7fff; hi16_value = (hi16_value & ~0x37fff) | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000); - bfd_put_32 (abfd, hi16_value, hi16_rel_addr); + score_bfd_put_32 (abfd, hi16_value, hi16_rel_addr); offset = (uvalue & 0xffff) << 1; addend = (addend & ~0x37fff) | (offset & 0x7fff) | ((offset << 1) & 0x30000); - bfd_put_32 (abfd, addend, (bfd_byte *) data + reloc_entry->address); + score_bfd_put_32 (abfd, addend, (bfd_byte *) data + reloc_entry->address); return bfd_reloc_ok; } @@ -581,7 +676,7 @@ static reloc_howto_type elf32_score_howto_table[] = FALSE, /* pc_relative */ 1, /* bitpos */ complain_overflow_dont,/* complain_on_overflow */ - score_elf_hi16_reloc, /* special_function */ + score_elf_hi16_reloc, /* special_function */ "R_SCORE_HI16", /* name */ TRUE, /* partial_inplace */ 0x37fff, /* src_mask */ @@ -603,19 +698,19 @@ static reloc_howto_type elf32_score_howto_table[] = 0x37fff, /* dst_mask */ FALSE), /* pcrel_offset */ - /* R_SCORE_DUMMY1 */ - HOWTO (R_SCORE_DUMMY1, /* type */ - 0, /* rightshift */ + /* R_SCORE_BCMP */ + HOWTO (R_SCORE_BCMP, /* type */ + 1, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ - FALSE, /* pc_relative */ + TRUE, /* pc_relative */ 1, /* bitpos */ complain_overflow_dont,/* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ - "R_SCORE_DUMMY1", /* name */ - TRUE, /* partial_inplace */ - 0x0000ffff, /* src_mask */ - 0x0000ffff, /* dst_mask */ + "R_SCORE_BCMP", /* name */ + FALSE, /* partial_inplace */ + 0x03e00381, /* src_mask */ + 0x03e00381, /* dst_mask */ FALSE), /* pcrel_offset */ /*R_SCORE_24 */ @@ -667,15 +762,15 @@ static reloc_howto_type elf32_score_howto_table[] = HOWTO (R_SCORE16_PC8, /* type */ 1, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ - 8, /* bitsize */ + 9, /* bitsize */ TRUE, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont,/* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_SCORE16_PC8", /* name */ FALSE, /* partial_inplace */ - 0x000000ff, /* src_mask */ - 0x000000ff, /* dst_mask */ + 0x000001ff, /* src_mask */ + 0x000001ff, /* dst_mask */ FALSE), /* pcrel_offset */ /* 32 bit absolute */ @@ -830,18 +925,18 @@ static reloc_howto_type elf32_score_howto_table[] = /* 32 bit symbol relative relocation. */ HOWTO (R_SCORE_REL32, /* type */ - 0, /* rightshift */ - 2, /* size (0 = byte, 1 = short, 2 = long) */ - 32, /* bitsize */ - FALSE, /* pc_relative */ - 0, /* bitpos */ - complain_overflow_dont,/* complain_on_overflow */ - bfd_elf_generic_reloc, /* special_function */ - "R_SCORE_REL32", /* name */ - TRUE, /* partial_inplace */ - 0xffffffff, /* src_mask */ - 0xffffffff, /* dst_mask */ - FALSE), /* pcrel_offset */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_SCORE_REL32", /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ /* R_SCORE_DUMMY_HI16 */ HOWTO (R_SCORE_DUMMY_HI16, /* type */ @@ -851,12 +946,42 @@ static reloc_howto_type elf32_score_howto_table[] = FALSE, /* pc_relative */ 1, /* bitpos */ complain_overflow_dont,/* complain_on_overflow */ - score_elf_hi16_reloc, /* special_function */ + score_elf_hi16_reloc, /* special_function */ "R_SCORE_DUMMY_HI16", /* name */ TRUE, /* partial_inplace */ 0x37fff, /* src_mask */ 0x37fff, /* dst_mask */ FALSE), /* pcrel_offset */ + + /* R_SCORE_IMM30 */ + HOWTO (R_SCORE_IMM30, /* type */ + 2, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 30, /* bitsize */ + FALSE, /* pc_relative */ + 7, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_SCORE_IMM30", /* name */ + FALSE, /* partial_inplace */ + 0x7f7fff7f80LL, /* src_mask */ + 0x7f7fff7f80LL, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* R_SCORE_IMM32 */ + HOWTO (R_SCORE_IMM32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 5, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_SCORE_IMM32", /* name */ + FALSE, /* partial_inplace */ + 0x7f7fff7fe0LL, /* src_mask */ + 0x7f7fff7fe0LL, /* dst_mask */ + FALSE), /* pcrel_offset */ }; struct score_reloc_map @@ -870,7 +995,7 @@ static const struct score_reloc_map elf32_score_reloc_map[] = {BFD_RELOC_NONE, R_SCORE_NONE}, {BFD_RELOC_HI16_S, R_SCORE_HI16}, {BFD_RELOC_LO16, R_SCORE_LO16}, - {BFD_RELOC_SCORE_DUMMY1, R_SCORE_DUMMY1}, + {BFD_RELOC_SCORE_BCMP, R_SCORE_BCMP}, {BFD_RELOC_SCORE_JMP, R_SCORE_24}, {BFD_RELOC_SCORE_BRANCH, R_SCORE_PC19}, {BFD_RELOC_SCORE16_JMP, R_SCORE16_11}, @@ -887,12 +1012,13 @@ static const struct score_reloc_map elf32_score_reloc_map[] = {BFD_RELOC_GPREL32, R_SCORE_GPREL32}, {BFD_RELOC_32_PCREL, R_SCORE_REL32}, {BFD_RELOC_SCORE_DUMMY_HI16, R_SCORE_DUMMY_HI16}, + {BFD_RELOC_SCORE_IMM30, R_SCORE_IMM30}, + {BFD_RELOC_SCORE_IMM32, R_SCORE_IMM32}, }; /* got_entries only match if they're identical, except for gotidx, so use all fields to compute the hash, and compare the appropriate union members. */ - static hashval_t score_elf_got_entry_hash (const void *entry_) { @@ -910,14 +1036,13 @@ score_elf_got_entry_eq (const void *entry1, const void *entry2) return e1->abfd == e2->abfd && e1->symndx == e2->symndx && (! e1->abfd ? e1->d.address == e2->d.address - : e1->symndx >= 0 ? e1->d.addend == e2->d.addend - : e1->d.h == e2->d.h); + : e1->symndx >= 0 ? e1->d.addend == e2->d.addend + : e1->d.h == e2->d.h); } /* If H needs a GOT entry, assign it the highest available dynamic index. Otherwise, assign it the lowest available dynamic index. */ - static bfd_boolean score_elf_sort_hash_table_f (struct score_elf_link_hash_entry *h, void *data) { @@ -937,7 +1062,7 @@ score_elf_sort_hash_table_f (struct score_elf_link_hash_entry *h, void *data) if (h->root.got.offset == 2) { if (hsd->max_unref_got_dynindx == hsd->min_got_dynindx) - hsd->low = (struct elf_link_hash_entry *) h; + hsd->low = (struct elf_link_hash_entry *) h; h->root.dynindx = hsd->max_unref_got_dynindx++; } else if (h->root.got.offset != 1) @@ -963,7 +1088,6 @@ score_elf_got_section (bfd *abfd, bfd_boolean maybe_excluded) /* Returns the GOT information associated with the link indicated by INFO. If SGOTP is non-NULL, it is filled in with the GOT section. */ - static struct score_got_info * score_elf_got_info (bfd *abfd, asection **sgotp) { @@ -985,12 +1109,11 @@ score_elf_got_info (bfd *abfd, asection **sgotp) appear towards the end. This reduces the amount of GOT space required. MAX_LOCAL is used to set the number of local symbols known to be in the dynamic symbol table. During - _bfd_score_elf_size_dynamic_sections, this value is 1. Afterward, the + s3_bfd_score_elf_size_dynamic_sections, this value is 1. Afterward, the section symbols are added and the count is higher. */ - static bfd_boolean score_elf_sort_hash_table (struct bfd_link_info *info, - unsigned long max_local) + unsigned long max_local) { struct score_elf_hash_sort_data hsd; struct score_got_info *g; @@ -1013,15 +1136,15 @@ score_elf_sort_hash_table (struct bfd_link_info *info, - (g->next ? g->assigned_gotno : 0); hsd.max_non_got_dynindx = max_local; score_elf_link_hash_traverse (((struct score_elf_link_hash_table *) - elf_hash_table (info)), - score_elf_sort_hash_table_f, - &hsd); + elf_hash_table (info)), + score_elf_sort_hash_table_f, + &hsd); /* There should have been enough room in the symbol table to accommodate both the GOT and non-GOT symbols. */ BFD_ASSERT (hsd.max_non_got_dynindx <= hsd.min_got_dynindx); BFD_ASSERT ((unsigned long)hsd.max_unref_got_dynindx - <= elf_hash_table (info)->dynsymcount); + <= elf_hash_table (info)->dynsymcount); /* Now we know which dynamic symbol has the lowest dynamic symbol table index in the GOT. */ @@ -1031,11 +1154,10 @@ score_elf_sort_hash_table (struct bfd_link_info *info, } /* Create an entry in an score ELF linker hash table. */ - static struct bfd_hash_entry * score_elf_link_hash_newfunc (struct bfd_hash_entry *entry, - struct bfd_hash_table *table, - const char *string) + struct bfd_hash_table *table, + const char *string) { struct score_elf_link_hash_entry *ret = (struct score_elf_link_hash_entry *)entry; @@ -1062,16 +1184,15 @@ score_elf_link_hash_newfunc (struct bfd_hash_entry *entry, /* Returns the first relocation of type r_type found, beginning with RELOCATION. RELEND is one-past-the-end of the relocation table. */ - static const Elf_Internal_Rela * score_elf_next_relocation (bfd *abfd ATTRIBUTE_UNUSED, unsigned int r_type, - const Elf_Internal_Rela *relocation, - const Elf_Internal_Rela *relend) + const Elf_Internal_Rela *relocation, + const Elf_Internal_Rela *relend) { while (relocation < relend) { if (ELF32_R_TYPE (relocation->r_info) == r_type) - return relocation; + return relocation; ++relocation; } @@ -1083,7 +1204,6 @@ score_elf_next_relocation (bfd *abfd ATTRIBUTE_UNUSED, unsigned int r_type, /* This function is called via qsort() to sort the dynamic relocation entries by increasing r_symndx value. */ - static int score_elf_sort_dynamic_relocs (const void *arg1, const void *arg2) { @@ -1097,11 +1217,11 @@ score_elf_sort_dynamic_relocs (const void *arg1, const void *arg2) } /* Return whether a relocation is against a local symbol. */ - static bfd_boolean score_elf_local_relocation_p (bfd *input_bfd, - const Elf_Internal_Rela *relocation, - bfd_boolean check_forced) + const Elf_Internal_Rela *relocation, + asection **local_sections, + bfd_boolean check_forced) { unsigned long r_symndx; Elf_Internal_Shdr *symtab_hdr; @@ -1110,29 +1230,30 @@ score_elf_local_relocation_p (bfd *input_bfd, r_symndx = ELF32_R_SYM (relocation->r_info); symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; - extsymoff = symtab_hdr->sh_info; + extsymoff = (elf_bad_symtab (input_bfd)) ? 0 : symtab_hdr->sh_info; if (r_symndx < extsymoff) return TRUE; + if (elf_bad_symtab (input_bfd) && local_sections[r_symndx] != NULL) + return TRUE; if (check_forced) { /* Look up the hash table to check whether the symbol was forced local. */ h = (struct score_elf_link_hash_entry *) - elf_sym_hashes (input_bfd) [r_symndx - extsymoff]; + elf_sym_hashes (input_bfd) [r_symndx - extsymoff]; /* Find the real hash-table entry for this symbol. */ while (h->root.root.type == bfd_link_hash_indirect - || h->root.root.type == bfd_link_hash_warning) - h = (struct score_elf_link_hash_entry *) h->root.root.u.i.link; + || h->root.root.type == bfd_link_hash_warning) + h = (struct score_elf_link_hash_entry *) h->root.root.u.i.link; if (h->root.forced_local) - return TRUE; + return TRUE; } return FALSE; } /* Returns the dynamic relocation section for DYNOBJ. */ - static asection * score_elf_rel_dyn_section (bfd *dynobj, bfd_boolean create_p) { @@ -1150,11 +1271,11 @@ score_elf_rel_dyn_section (bfd *dynobj, bfd_boolean create_p) | SEC_LINKER_CREATED | SEC_READONLY)); if (sreloc == NULL - || ! bfd_set_section_alignment (dynobj, sreloc, - SCORE_ELF_LOG_FILE_ALIGN (dynobj))) - return NULL; + || ! bfd_set_section_alignment (dynobj, sreloc, + SCORE_ELF_LOG_FILE_ALIGN (dynobj))) + return NULL; } - return sreloc; + return sreloc; } static void @@ -1178,14 +1299,13 @@ score_elf_allocate_dynamic_relocations (bfd *abfd, unsigned int n) is the original relocation, which is now being transformed into a dynamic relocation. The ADDENDP is adjusted if necessary; the caller should store the result in place of the original addend. */ - static bfd_boolean score_elf_create_dynamic_relocation (bfd *output_bfd, - struct bfd_link_info *info, - const Elf_Internal_Rela *rel, - struct score_elf_link_hash_entry *h, - bfd_vma symbol, - bfd_vma *addendp, asection *input_section) + struct bfd_link_info *info, + const Elf_Internal_Rela *rel, + struct score_elf_link_hash_entry *h, + bfd_vma symbol, + bfd_vma *addendp, asection *input_section) { Elf_Internal_Rela outrel[3]; asection *sreloc; @@ -1215,8 +1335,8 @@ score_elf_create_dynamic_relocation (bfd *output_bfd, if (outrel[0].r_offset == MINUS_TWO) { /* The relocation field has been converted into a relative value of - some sort. Functions like _bfd_elf_write_section_eh_frame expect - the field to be fully relocated, so add in the symbol's value. */ + some sort. Functions like _bfd_elf_write_section_eh_frame expect + the field to be fully relocated, so add in the symbol's value. */ *addendp += symbol; return TRUE; } @@ -1226,14 +1346,14 @@ score_elf_create_dynamic_relocation (bfd *output_bfd, if (h != NULL && (! info->symbolic || !h->root.def_regular) /* h->root.dynindx may be -1 if this symbol was marked to - become local. */ + become local. */ && h->root.dynindx != -1) { indx = h->root.dynindx; - /* ??? glibc's ld.so just adds the final GOT entry to the - relocation field. It therefore treats relocs against - defined symbols in the same way as relocs against - undefined symbols. */ + /* ??? glibc's ld.so just adds the final GOT entry to the + relocation field. It therefore treats relocs against + defined symbols in the same way as relocs against + undefined symbols. */ defined_p = FALSE; } else @@ -1271,11 +1391,11 @@ score_elf_create_dynamic_relocation (bfd *output_bfd, /* Adjust the output offset of the relocation to reference the correct location in the output file. */ outrel[0].r_offset += (input_section->output_section->vma - + input_section->output_offset); + + input_section->output_offset); outrel[1].r_offset += (input_section->output_section->vma - + input_section->output_offset); + + input_section->output_offset); outrel[2].r_offset += (input_section->output_section->vma - + input_section->output_offset); + + input_section->output_offset); /* Put the relocation back out. We have to use the special relocation outputter in the 64-bit case since the 64-bit @@ -1297,7 +1417,7 @@ score_elf_create_dynamic_relocation (bfd *output_bfd, static bfd_boolean score_elf_create_got_section (bfd *abfd, struct bfd_link_info *info, - bfd_boolean maybe_exclude) + bfd_boolean maybe_exclude) { flagword flags; asection *s; @@ -1311,7 +1431,7 @@ score_elf_create_got_section (bfd *abfd, if (s) { if (! maybe_exclude) - s->flags &= ~SEC_EXCLUDE; + s->flags &= ~SEC_EXCLUDE; return TRUE; } @@ -1332,8 +1452,8 @@ score_elf_create_got_section (bfd *abfd, are not creating a global offset table. */ bh = NULL; if (! (_bfd_generic_link_add_one_symbol - (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s, - 0, NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh))) + (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s, + 0, NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh))) return FALSE; h = (struct elf_link_hash_entry *) bh; @@ -1357,7 +1477,7 @@ score_elf_create_got_section (bfd *abfd, g->next = NULL; g->got_entries = htab_try_create (1, score_elf_got_entry_hash, - score_elf_got_entry_eq, NULL); + score_elf_got_entry_eq, NULL); if (g->got_entries == NULL) return FALSE; score_elf_section_data (s)->u.got_info = g; @@ -1367,7 +1487,6 @@ score_elf_create_got_section (bfd *abfd, } /* Calculate the %high function. */ - static bfd_vma score_elf_high (bfd_vma value) { @@ -1376,15 +1495,14 @@ score_elf_high (bfd_vma value) /* Create a local GOT entry for VALUE. Return the index of the entry, or -1 if it could not be created. */ - static struct score_got_entry * score_elf_create_local_got_entry (bfd *abfd, bfd *ibfd ATTRIBUTE_UNUSED, - struct score_got_info *gg, - asection *sgot, bfd_vma value, - unsigned long r_symndx ATTRIBUTE_UNUSED, - struct score_elf_link_hash_entry *h ATTRIBUTE_UNUSED, - int r_type ATTRIBUTE_UNUSED) + struct score_got_info *gg, + asection *sgot, bfd_vma value, + unsigned long r_symndx ATTRIBUTE_UNUSED, + struct score_elf_link_hash_entry *h ATTRIBUTE_UNUSED, + int r_type ATTRIBUTE_UNUSED) { struct score_got_entry entry, **loc; struct score_got_info *g; @@ -1412,22 +1530,21 @@ score_elf_create_local_got_entry (bfd *abfd, (*loc)->gotidx = -1; /* We didn't allocate enough space in the GOT. */ (*_bfd_error_handler) - (_("not enough GOT space for local GOT entries")); + (_("not enough GOT space for local GOT entries")); bfd_set_error (bfd_error_bad_value); return NULL; } - bfd_put_32 (abfd, value, (sgot->contents + entry.gotidx)); + score_bfd_put_32 (abfd, value, (sgot->contents + entry.gotidx)); return *loc; } /* Find a GOT entry whose higher-order 16 bits are the same as those for value. Return the index into the GOT for this entry. */ - static bfd_vma score_elf_got16_entry (bfd *abfd, bfd *ibfd, struct bfd_link_info *info, - bfd_vma value, bfd_boolean external) + bfd_vma value, bfd_boolean external) { asection *sgot; struct score_got_info *g; @@ -1436,16 +1553,16 @@ score_elf_got16_entry (bfd *abfd, bfd *ibfd, struct bfd_link_info *info, if (!external) { /* Although the ABI says that it is "the high-order 16 bits" that we - want, it is really the %high value. The complete value is - calculated with a `addiu' of a LO16 relocation, just as with a - HI16/LO16 pair. */ + want, it is really the %high value. The complete value is + calculated with a `addiu' of a LO16 relocation, just as with a + HI16/LO16 pair. */ value = score_elf_high (value) << 16; } g = score_elf_got_info (elf_hash_table (info)->dynobj, &sgot); entry = score_elf_create_local_got_entry (abfd, ibfd, g, sgot, value, 0, NULL, - R_SCORE_GOT15); + R_SCORE_GOT15); if (entry) return entry->gotidx; else @@ -1453,9 +1570,9 @@ score_elf_got16_entry (bfd *abfd, bfd *ibfd, struct bfd_link_info *info, } static void -_bfd_score_elf_hide_symbol (struct bfd_link_info *info, - struct elf_link_hash_entry *entry, - bfd_boolean force_local) +s3_bfd_score_elf_hide_symbol (struct bfd_link_info *info, + struct elf_link_hash_entry *entry, + bfd_boolean force_local) { bfd *dynobj; asection *got; @@ -1472,55 +1589,55 @@ _bfd_score_elf_hide_symbol (struct bfd_link_info *info, { got = score_elf_got_section (dynobj, FALSE); if (got == NULL) - return; + return; g = score_elf_section_data (got)->u.got_info; if (g->next) - { - struct score_got_entry e; - struct score_got_info *gg = g; - - /* Since we're turning what used to be a global symbol into a - local one, bump up the number of local entries of each GOT - that had an entry for it. This will automatically decrease - the number of global entries, since global_gotno is actually - the upper limit of global entries. */ - e.abfd = dynobj; - e.symndx = -1; - e.d.h = h; - - for (g = g->next; g != gg; g = g->next) - if (htab_find (g->got_entries, &e)) - { - BFD_ASSERT (g->global_gotno > 0); - g->local_gotno++; - g->global_gotno--; - } - - /* If this was a global symbol forced into the primary GOT, we - no longer need an entry for it. We can't release the entry - at this point, but we must at least stop counting it as one - of the symbols that required a forced got entry. */ - if (h->root.got.offset == 2) - { - BFD_ASSERT (gg->assigned_gotno > 0); - gg->assigned_gotno--; - } - } + { + struct score_got_entry e; + struct score_got_info *gg = g; + + /* Since we're turning what used to be a global symbol into a + local one, bump up the number of local entries of each GOT + that had an entry for it. This will automatically decrease + the number of global entries, since global_gotno is actually + the upper limit of global entries. */ + e.abfd = dynobj; + e.symndx = -1; + e.d.h = h; + + for (g = g->next; g != gg; g = g->next) + if (htab_find (g->got_entries, &e)) + { + BFD_ASSERT (g->global_gotno > 0); + g->local_gotno++; + g->global_gotno--; + } + + /* If this was a global symbol forced into the primary GOT, we + no longer need an entry for it. We can't release the entry + at this point, but we must at least stop counting it as one + of the symbols that required a forced got entry. */ + if (h->root.got.offset == 2) + { + BFD_ASSERT (gg->assigned_gotno > 0); + gg->assigned_gotno--; + } + } else if (g->global_gotno == 0 && g->global_gotsym == NULL) - /* If we haven't got through GOT allocation yet, just bump up the - number of local entries, as this symbol won't be counted as - global. */ - g->local_gotno++; + /* If we haven't got through GOT allocation yet, just bump up the + number of local entries, as this symbol won't be counted as + global. */ + g->local_gotno++; else if (h->root.got.offset == 1) - { - /* If we're past non-multi-GOT allocation and this symbol had - been marked for a global got entry, give it a local entry - instead. */ - BFD_ASSERT (g->global_gotno > 0); - g->local_gotno++; - g->global_gotno--; - } + { + /* If we're past non-multi-GOT allocation and this symbol had + been marked for a global got entry, give it a local entry + instead. */ + BFD_ASSERT (g->global_gotno > 0); + g->local_gotno++; + g->global_gotno--; + } } _bfd_elf_link_hash_hide_symbol (info, &h->root, force_local); @@ -1529,12 +1646,11 @@ _bfd_score_elf_hide_symbol (struct bfd_link_info *info, /* If H is a symbol that needs a global GOT entry, but has a dynamic symbol table index lower than any we've seen to date, record it for posterity. */ - static bfd_boolean score_elf_record_global_got_symbol (struct elf_link_hash_entry *h, - bfd *abfd, + bfd *abfd, struct bfd_link_info *info, - struct score_got_info *g) + struct score_got_info *g) { struct score_got_entry entry, **loc; @@ -1542,14 +1658,14 @@ score_elf_record_global_got_symbol (struct elf_link_hash_entry *h, if (h->dynindx == -1) { switch (ELF_ST_VISIBILITY (h->other)) - { - case STV_INTERNAL: - case STV_HIDDEN: - _bfd_score_elf_hide_symbol (info, h, TRUE); - break; - } + { + case STV_INTERNAL: + case STV_HIDDEN: + s3_bfd_score_elf_hide_symbol (info, h, TRUE); + break; + } if (!bfd_elf_link_record_dynamic_symbol (info, h)) - return FALSE; + return FALSE; } entry.abfd = abfd; @@ -1584,12 +1700,11 @@ score_elf_record_global_got_symbol (struct elf_link_hash_entry *h, /* Reserve space in G for a GOT entry containing the value of symbol SYMNDX in input bfd ABDF, plus ADDEND. */ - static bfd_boolean score_elf_record_local_got_symbol (bfd *abfd, long symndx, bfd_vma addend, - struct score_got_info *g) + struct score_got_info *g) { struct score_got_entry entry, **loc; @@ -1615,11 +1730,10 @@ score_elf_record_local_got_symbol (bfd *abfd, /* Returns the GOT offset at which the indicated address can be found. If there is not yet a GOT entry for this value, create one. Returns -1 if no satisfactory GOT offset can be found. */ - static bfd_vma score_elf_local_got_index (bfd *abfd, bfd *ibfd, struct bfd_link_info *info, - bfd_vma value, unsigned long r_symndx, - struct score_elf_link_hash_entry *h, int r_type) + bfd_vma value, unsigned long r_symndx, + struct score_elf_link_hash_entry *h, int r_type) { asection *sgot; struct score_got_info *g; @@ -1628,7 +1742,7 @@ score_elf_local_got_index (bfd *abfd, bfd *ibfd, struct bfd_link_info *info, g = score_elf_got_info (elf_hash_table (info)->dynobj, &sgot); entry = score_elf_create_local_got_entry (abfd, ibfd, g, sgot, value, - r_symndx, h, r_type); + r_symndx, h, r_type); if (!entry) return MINUS_ONE; @@ -1662,10 +1776,9 @@ score_elf_global_got_index (bfd *abfd, struct elf_link_hash_entry *h) } /* Returns the offset for the entry at the INDEXth position in the GOT. */ - static bfd_vma score_elf_got_offset_from_index (bfd *dynobj, bfd *output_bfd, - bfd *input_bfd ATTRIBUTE_UNUSED, bfd_vma index) + bfd *input_bfd ATTRIBUTE_UNUSED, bfd_vma index) { asection *sgot; bfd_vma gp; @@ -1694,30 +1807,30 @@ score_elf_resolve_final_got_entry (void **entryp, void *p) struct score_elf_link_hash_entry *h = entry->d.h; while (h->root.root.type == bfd_link_hash_indirect - || h->root.root.type == bfd_link_hash_warning) - h = (struct score_elf_link_hash_entry *) h->root.root.u.i.link; + || h->root.root.type == bfd_link_hash_warning) + h = (struct score_elf_link_hash_entry *) h->root.root.u.i.link; if (entry->d.h == h) - return 1; + return 1; entry->d.h = h; /* If we can't find this entry with the new bfd hash, re-insert - it, and get the traversal restarted. */ + it, and get the traversal restarted. */ if (! htab_find (got_entries, entry)) - { - htab_clear_slot (got_entries, entryp); - entryp = htab_find_slot (got_entries, entry, INSERT); - if (! *entryp) - *entryp = entry; - /* Abort the traversal, since the whole table may have - moved, and leave it up to the parent to restart the - process. */ - *(htab_t *)p = NULL; - return 0; - } + { + htab_clear_slot (got_entries, entryp); + entryp = htab_find_slot (got_entries, entry, INSERT); + if (! *entryp) + *entryp = entry; + /* Abort the traversal, since the whole table may have + moved, and leave it up to the parent to restart the + process. */ + *(htab_t *)p = NULL; + return 0; + } /* We might want to decrement the global_gotno count, but it's - either too early or too late for that at this point. */ + either too early or too late for that at this point. */ } return 1; @@ -1734,19 +1847,18 @@ score_elf_resolve_final_got_entries (struct score_got_info *g) got_entries = g->got_entries; htab_traverse (got_entries, - score_elf_resolve_final_got_entry, - &got_entries); + score_elf_resolve_final_got_entry, + &got_entries); } while (got_entries == NULL); } /* Add INCREMENT to the reloc (of type HOWTO) at ADDRESS. for -r */ - static void score_elf_add_to_rel (bfd *abfd, - bfd_byte *address, - reloc_howto_type *howto, - bfd_signed_vma increment) + bfd_byte *address, + reloc_howto_type *howto, + bfd_signed_vma increment) { bfd_signed_vma addend; bfd_vma contents; @@ -1754,7 +1866,7 @@ score_elf_add_to_rel (bfd *abfd, unsigned long r_type = howto->type; unsigned long hi16_addend, hi16_offset, hi16_value, uvalue; - contents = bfd_get_32 (abfd, address); + contents = score_bfd_get_32 (abfd, address); /* Get the (signed) value from the instruction. */ addend = contents & howto->src_mask; if (addend & ((howto->src_mask + 1) >> 1)) @@ -1775,12 +1887,12 @@ score_elf_add_to_rel (bfd *abfd, contents = (contents & ~howto-> src_mask) | (((offset << 6) & howto->src_mask) & 0x3ff0000) | (offset & 0x3ff); - bfd_put_32 (abfd, contents, address); + score_bfd_put_32 (abfd, contents, address); break; case R_SCORE_HI16: break; case R_SCORE_LO16: - hi16_addend = bfd_get_32 (abfd, address - 4); + hi16_addend = score_bfd_get_32 (abfd, address - 4); hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1; offset = ((((contents >> 16) & 0x3) << 15) | (contents & 0x7fff)) >> 1; offset = (hi16_offset << 16) | (offset & 0xffff); @@ -1788,10 +1900,10 @@ score_elf_add_to_rel (bfd *abfd, hi16_offset = (uvalue >> 16) << 1; hi16_value = (hi16_addend & (~(howto->dst_mask))) | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000); - bfd_put_32 (abfd, hi16_value, address - 4); + score_bfd_put_32 (abfd, hi16_value, address - 4); offset = (uvalue & 0xffff) << 1; contents = (contents & (~(howto->dst_mask))) | (offset & 0x7fff) | ((offset << 1) & 0x30000); - bfd_put_32 (abfd, contents, address); + score_bfd_put_32 (abfd, contents, address); break; case R_SCORE_24: offset = @@ -1800,48 +1912,78 @@ score_elf_add_to_rel (bfd *abfd, contents = (contents & ~howto-> src_mask) | (((offset << 1) & howto->src_mask) & 0x3ff0000) | (offset & 0x7fff); - bfd_put_32 (abfd, contents, address); + score_bfd_put_32 (abfd, contents, address); break; + case R_SCORE16_11: - contents = bfd_get_16 (abfd, address); + contents = score_bfd_get_16 (abfd, address); offset = contents & howto->src_mask; offset += increment; contents = (contents & ~howto->src_mask) | (offset & howto->src_mask); - bfd_put_16 (abfd, contents, address); + score_bfd_put_16 (abfd, contents, address); break; case R_SCORE16_PC8: - contents = bfd_get_16 (abfd, address); - offset = (contents & howto->src_mask) + ((increment >> 1) & 0xff); + contents = score_bfd_get_16 (abfd, address); + offset = (contents & howto->src_mask) + ((increment >> 1) & 0x1ff); + contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask); + score_bfd_put_16 (abfd, contents, address); + + break; + + case R_SCORE_BCMP: + contents = score_bfd_get_32 (abfd, address); + offset = (contents & howto->src_mask); + offset <<= howto->rightshift; + offset += increment; + offset >>= howto->rightshift; + contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask); + score_bfd_put_32 (abfd, contents, address); + break; + + case R_SCORE_IMM30: + contents = score_bfd_get_48 (abfd, address); + offset = (contents & howto->src_mask); + offset <<= howto->rightshift; + offset += increment; + offset >>= howto->rightshift; contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask); - bfd_put_16 (abfd, contents, address); + score_bfd_put_48 (abfd, contents, address); + break; + case R_SCORE_IMM32: + contents = score_bfd_get_48 (abfd, address); + offset = (contents & howto->src_mask); + offset += increment; + contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask); + score_bfd_put_48 (abfd, contents, address); break; + default: addend += increment; contents = (contents & ~howto->dst_mask) | (addend & howto->dst_mask); - bfd_put_32 (abfd, contents, address); + score_bfd_put_32 (abfd, contents, address); break; } } /* Perform a relocation as part of a final link. */ - static bfd_reloc_status_type score_elf_final_link_relocate (reloc_howto_type *howto, - bfd *input_bfd, - bfd *output_bfd, - asection *input_section, - bfd_byte *contents, - Elf_Internal_Rela *rel, - Elf_Internal_Rela *relocs, - bfd_vma symbol, - struct bfd_link_info *info, - const char *sym_name ATTRIBUTE_UNUSED, - int sym_flags ATTRIBUTE_UNUSED, - struct score_elf_link_hash_entry *h, + bfd *input_bfd, + bfd *output_bfd, + asection *input_section, + bfd_byte *contents, + Elf_Internal_Rela *rel, + Elf_Internal_Rela *relocs, + bfd_vma symbol, + struct bfd_link_info *info, + const char *sym_name ATTRIBUTE_UNUSED, + int sym_flags ATTRIBUTE_UNUSED, + struct score_elf_link_hash_entry *h, + asection **local_sections, bfd_boolean gp_disp_p) { unsigned long r_type; @@ -1864,13 +2006,14 @@ score_elf_final_link_relocate (reloc_howto_type *howto, bfd_vma value = symbol; unsigned long hi16_addend, hi16_offset, hi16_value, uvalue, offset, abs_value = 0; + if (elf_gp (output_bfd) == 0) { struct bfd_link_hash_entry *bh; asection *o; bh = bfd_link_hash_lookup (info->hash, "_gp", 0, 0, 1); - if (bh != (struct bfd_link_hash_entry *)NULL && bh->type == bfd_link_hash_defined) + if (bh != NULL && bh->type == bfd_link_hash_defined) elf_gp (output_bfd) = (bh->u.def.value + bh->u.def.section->output_section->vma + bh->u.def.section->output_offset); @@ -1879,7 +2022,7 @@ score_elf_final_link_relocate (reloc_howto_type *howto, bfd_vma lo = -1; /* Find the GP-relative section with the lowest offset. */ - for (o = output_bfd->sections; o != (asection *) NULL; o = o->next) + for (o = output_bfd->sections; o != NULL; o = o->next) if (o->vma < lo) lo = o->vma; /* And calculate GP relative to that. */ @@ -1897,7 +2040,7 @@ score_elf_final_link_relocate (reloc_howto_type *howto, r_symndx = ELF32_R_SYM (rel->r_info); r_type = ELF32_R_TYPE (rel->r_info); rel_addr = (input_section->output_section->vma + input_section->output_offset + rel->r_offset); - local_p = score_elf_local_relocation_p (input_bfd, rel, TRUE); + local_p = score_elf_local_relocation_p (input_bfd, rel, local_sections, TRUE); if (r_type == R_SCORE_GOT15) { @@ -1910,17 +2053,22 @@ score_elf_final_link_relocate (reloc_howto_type *howto, relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel; lo16_rel = score_elf_next_relocation (input_bfd, R_SCORE_GOT_LO16, rel, relend); if ((local_p) && (lo16_rel != NULL)) - { - bfd_vma tmp = 0; - tmp = bfd_get_32 (input_bfd, contents + lo16_rel->r_offset); - lo_value = (((tmp >> 16) & 0x3) << 14) | ((tmp & 0x7fff) >> 1); - } + { + bfd_vma tmp = 0; + tmp = score_bfd_get_32 (input_bfd, contents + lo16_rel->r_offset); + lo_value = (((tmp >> 16) & 0x3) << 14) | ((tmp & 0x7fff) >> 1); + } addend = lo_value; } - else + /* For score3 R_SCORE_ABS32. */ + else if (r_type == R_SCORE_ABS32 || r_type == R_SCORE_REL32) { addend = (bfd_get_32 (input_bfd, hit_data) >> howto->bitpos) & howto->src_mask; } + else + { + addend = (score_bfd_get_32 (input_bfd, hit_data) >> howto->bitpos) & howto->src_mask; + } /* If we haven't already determined the GOT offset, or the GP value, and we're going to need it, get it now. */ @@ -1942,26 +2090,26 @@ score_elf_final_link_relocate (reloc_howto_type *howto, We must initialize this entry in the GOT. */ bfd *tmpbfd = elf_hash_table (info)->dynobj; asection *sgot = score_elf_got_section (tmpbfd, FALSE); - bfd_put_32 (tmpbfd, value, sgot->contents + g); + score_bfd_put_32 (tmpbfd, value, sgot->contents + g); } } else if (r_type == R_SCORE_GOT15 || r_type == R_SCORE_CALL15) { - /* There's no need to create a local GOT entry here; the - calculation for a local GOT15 entry does not involve G. */ - ; - } + /* There's no need to create a local GOT entry here; the + calculation for a local GOT15 entry does not involve G. */ + ; + } else { - g = score_elf_local_got_index (output_bfd, input_bfd, info, + g = score_elf_local_got_index (output_bfd, input_bfd, info, symbol + addend, r_symndx, h, r_type); - if (g == MINUS_ONE) - return bfd_reloc_outofrange; + if (g == MINUS_ONE) + return bfd_reloc_outofrange; } /* Convert GOT indices to actual offsets. */ g = score_elf_got_offset_from_index (elf_hash_table (info)->dynobj, - output_bfd, input_bfd, g); + output_bfd, input_bfd, g); break; case R_SCORE_HI16: @@ -1986,30 +2134,35 @@ score_elf_final_link_relocate (reloc_howto_type *howto, case R_SCORE_ABS32: case R_SCORE_REL32: if ((info->shared - || (elf_hash_table (info)->dynamic_sections_created - && h != NULL - && h->root.def_dynamic - && !h->root.def_regular)) - && r_symndx != 0 - && (input_section->flags & SEC_ALLOC) != 0) - { - /* If we're creating a shared library, or this relocation is against a symbol + || (elf_hash_table (info)->dynamic_sections_created + && h != NULL + && h->root.def_dynamic + && !h->root.def_regular)) + && r_symndx != 0 + && (input_section->flags & SEC_ALLOC) != 0) + { + /* If we're creating a shared library, or this relocation is against a symbol in a shared library, then we can't know where the symbol will end up. So, we create a relocation record in the output, and leave the job up to the dynamic linker. */ - value = addend; - if (!score_elf_create_dynamic_relocation (output_bfd, info, rel, h, - symbol, &value, - input_section)) - return bfd_reloc_undefined; - } + value = addend; + if (!score_elf_create_dynamic_relocation (output_bfd, info, rel, h, + symbol, &value, + input_section)) + return bfd_reloc_undefined; + } + else if (r_symndx == 0) + /* r_symndx will be zero only for relocs against symbols + from removed linkonce sections, or sections discarded by + a linker script. */ + value = 0; else - { - if (r_type != R_SCORE_REL32) - value = symbol + addend; - else - value = addend; - } + { + if (r_type != R_SCORE_REL32) + value = symbol + addend; + else + value = addend; + } value &= howto->dst_mask; bfd_put_32 (input_bfd, value, hit_data); return bfd_reloc_ok; @@ -2018,22 +2171,71 @@ score_elf_final_link_relocate (reloc_howto_type *howto, value += addend; if ((long)value > 0x7fff || (long)value < -0x8000) return bfd_reloc_overflow; - bfd_put_16 (input_bfd, value, hit_data); + score_bfd_put_16 (input_bfd, value, hit_data); return bfd_reloc_ok; case R_SCORE_24: - addend = bfd_get_32 (input_bfd, hit_data); + addend = score_bfd_get_32 (input_bfd, hit_data); offset = (((addend & howto->src_mask) >> 1) & 0x1ff8000) | ((addend & howto->src_mask) & 0x7fff); if ((offset & 0x1000000) != 0) offset |= 0xfe000000; value += offset; + abs_value = abs (value - rel_addr); + if ((abs_value & 0xfe000000) != 0) + return bfd_reloc_overflow; addend = (addend & ~howto->src_mask) | (((value << 1) & howto->src_mask) & 0x3ff0000) | (value & 0x7fff); - bfd_put_32 (input_bfd, addend, hit_data); + score_bfd_put_32 (input_bfd, addend, hit_data); return bfd_reloc_ok; + /* signed imm32. */ + case R_SCORE_IMM30: + { + int not_word_align_p = 0; + bfd_vma imm_offset = 0; + addend = score_bfd_get_48 (input_bfd, hit_data); + imm_offset = ((addend >> 7) & 0xff) + | (((addend >> 16) & 0x7fff) << 8) + | (((addend >> 32) & 0x7f) << 23); + imm_offset <<= howto->rightshift; + value += imm_offset; + value &= 0xffffffff; + + /* Check lw48/sw48 rd, value/label word align. */ + if ((value & 0x3) != 0) + not_word_align_p = 1; + + value >>= howto->rightshift; + addend = (addend & ~howto->src_mask) + | (((value & 0xff) >> 0) << 7) + | (((value & 0x7fff00) >> 8) << 16) + | (((value & 0x3f800000) >> 23) << 32); + score_bfd_put_48 (input_bfd, addend, hit_data); + if (not_word_align_p) + return bfd_reloc_other; + else + return bfd_reloc_ok; + } + + case R_SCORE_IMM32: + { + bfd_vma imm_offset = 0; + addend = score_bfd_get_48 (input_bfd, hit_data); + imm_offset = ((addend >> 5) & 0x3ff) + | (((addend >> 16) & 0x7fff) << 10) + | (((addend >> 32) & 0x7f) << 25); + value += imm_offset; + value &= 0xffffffff; + addend = (addend & ~howto->src_mask) + | ((value & 0x3ff) << 5) + | (((value >> 10) & 0x7fff) << 16) + | (((value >> 25) & 0x7f) << 32); + score_bfd_put_48 (input_bfd, addend, hit_data); + return bfd_reloc_ok; + } + case R_SCORE_PC19: - addend = bfd_get_32 (input_bfd, hit_data); + addend = score_bfd_get_32 (input_bfd, hit_data); offset = (((addend & howto->src_mask) & 0x3ff0000) >> 6) | ((addend & howto->src_mask) & 0x3ff); if ((offset & 0x80000) != 0) offset |= 0xfff00000; @@ -2045,59 +2247,79 @@ score_elf_final_link_relocate (reloc_howto_type *howto, return bfd_reloc_overflow; addend = (addend & ~howto->src_mask) | (((value << 6) & howto->src_mask) & 0x3ff0000) | (value & 0x3ff); - bfd_put_32 (input_bfd, addend, hit_data); + score_bfd_put_32 (input_bfd, addend, hit_data); return bfd_reloc_ok; case R_SCORE16_11: - addend = bfd_get_16 (input_bfd, hit_data); + addend = score_bfd_get_16 (input_bfd, hit_data); offset = addend & howto->src_mask; if ((offset & 0x800) != 0) /* Offset is negative. */ offset |= 0xfffff000; value += offset; + abs_value = abs (value - rel_addr); + if ((abs_value & 0xfffff000) != 0) + return bfd_reloc_overflow; addend = (addend & ~howto->src_mask) | (value & howto->src_mask); - bfd_put_16 (input_bfd, addend, hit_data); + score_bfd_put_16 (input_bfd, addend, hit_data); return bfd_reloc_ok; case R_SCORE16_PC8: - addend = bfd_get_16 (input_bfd, hit_data); + addend = score_bfd_get_16 (input_bfd, hit_data); offset = (addend & howto->src_mask) << 1; - if ((offset & 0x100) != 0) /* Offset is negative. */ + if ((offset & 0x200) != 0) /* Offset is negative. */ offset |= 0xfffffe00; abs_value = value = value - rel_addr + offset; /* Sign bit + exceed 9 bit. */ - if (((value & 0xffffff00) != 0) && ((value & 0xffffff00) != 0xffffff00)) + if (((value & 0xfffffe00) != 0) && ((value & 0xfffffe00) != 0xfffffe00)) return bfd_reloc_overflow; value >>= 1; addend = (addend & ~howto->src_mask) | (value & howto->src_mask); - bfd_put_16 (input_bfd, addend, hit_data); + score_bfd_put_16 (input_bfd, addend, hit_data); + return bfd_reloc_ok; + + case R_SCORE_BCMP: + addend = score_bfd_get_32 (input_bfd, hit_data); + offset = (addend & howto->src_mask) << howto->rightshift; + if ((offset & 0x200) != 0) /* Offset is negative. */ + offset |= 0xfffffe00; + value = value - rel_addr + offset; + /* Sign bit + exceed 9 bit. */ + if (((value & 0xfffffe00) != 0) && ((value & 0xfffffe00) != 0xfffffe00)) + return bfd_reloc_overflow; + value >>= howto->rightshift; + addend = (addend & ~howto->src_mask) + | (value & 0x1) + | (((value >> 1) & 0x7) << 7) + | (((value >> 4) & 0x1f) << 21); + score_bfd_put_32 (input_bfd, addend, hit_data); return bfd_reloc_ok; case R_SCORE_HI16: return bfd_reloc_ok; case R_SCORE_LO16: - hi16_addend = bfd_get_32 (input_bfd, hit_data - 4); + hi16_addend = score_bfd_get_32 (input_bfd, hit_data - 4); hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1; - addend = bfd_get_32 (input_bfd, hit_data); + addend = score_bfd_get_32 (input_bfd, hit_data); offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1; offset = (hi16_offset << 16) | (offset & 0xffff); if (!gp_disp_p) - uvalue = value + offset; + uvalue = value + offset; else - uvalue = offset + gp - rel_addr + 4; + uvalue = offset + gp - rel_addr + 4; hi16_offset = (uvalue >> 16) << 1; hi16_value = (hi16_addend & (~(howto->dst_mask))) | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000); - bfd_put_32 (input_bfd, hi16_value, hit_data - 4); + score_bfd_put_32 (input_bfd, hi16_value, hit_data - 4); offset = (uvalue & 0xffff) << 1; value = (addend & (~(howto->dst_mask))) | (offset & 0x7fff) | ((offset << 1) & 0x30000); - bfd_put_32 (input_bfd, value, hit_data); + score_bfd_put_32 (input_bfd, value, hit_data); return bfd_reloc_ok; case R_SCORE_GP15: - addend = bfd_get_32 (input_bfd, hit_data); + addend = score_bfd_get_32 (input_bfd, hit_data); offset = addend & 0x7fff; if ((offset & 0x4000) == 0x4000) offset |= 0xffffc000; @@ -2105,52 +2327,53 @@ score_elf_final_link_relocate (reloc_howto_type *howto, if (((value & 0xffffc000) != 0) && ((value & 0xffffc000) != 0xffffc000)) return bfd_reloc_overflow; value = (addend & ~howto->src_mask) | (value & howto->src_mask); - bfd_put_32 (input_bfd, value, hit_data); + score_bfd_put_32 (input_bfd, value, hit_data); return bfd_reloc_ok; case R_SCORE_GOT15: case R_SCORE_CALL15: if (local_p) - { - bfd_boolean forced; + { + bfd_boolean forced; - /* The special case is when the symbol is forced to be local. We need the + /* The special case is when the symbol is forced to be local. We need the full address in the GOT since no R_SCORE_GOT_LO16 relocation follows. */ - forced = ! score_elf_local_relocation_p (input_bfd, rel, FALSE); - value = score_elf_got16_entry (output_bfd, input_bfd, info, - symbol + addend, forced); - if (value == MINUS_ONE) - return bfd_reloc_outofrange; - value = score_elf_got_offset_from_index (elf_hash_table (info)->dynobj, - output_bfd, input_bfd, value); - } + forced = ! score_elf_local_relocation_p (input_bfd, rel, + local_sections, FALSE); + value = score_elf_got16_entry (output_bfd, input_bfd, info, + symbol + addend, forced); + if (value == MINUS_ONE) + return bfd_reloc_outofrange; + value = score_elf_got_offset_from_index (elf_hash_table (info)->dynobj, + output_bfd, input_bfd, value); + } else - { - value = g; - } + { + value = g; + } if ((long) value > 0x3fff || (long) value < -0x4000) return bfd_reloc_overflow; - addend = bfd_get_32 (input_bfd, hit_data); + addend = score_bfd_get_32 (input_bfd, hit_data); value = (addend & ~howto->dst_mask) | (value & howto->dst_mask); - bfd_put_32 (input_bfd, value, hit_data); + score_bfd_put_32 (input_bfd, value, hit_data); return bfd_reloc_ok; case R_SCORE_GPREL32: value = (addend + symbol - gp); value &= howto->dst_mask; - bfd_put_32 (input_bfd, value, hit_data); + score_bfd_put_32 (input_bfd, value, hit_data); return bfd_reloc_ok; case R_SCORE_GOT_LO16: - addend = bfd_get_32 (input_bfd, hit_data); + addend = score_bfd_get_32 (input_bfd, hit_data); value = (((addend >> 16) & 0x3) << 14) | ((addend & 0x7fff) >> 1); value += symbol; - value = (addend & (~(howto->dst_mask))) | ((value & 0x3fff) << 1) + value = (addend & (~(howto->dst_mask))) | ((value & 0x3fff) << 1) | (((value >> 14) & 0x3) << 16); - bfd_put_32 (input_bfd, value, hit_data); + score_bfd_put_32 (input_bfd, value, hit_data); return bfd_reloc_ok; case R_SCORE_DUMMY_HI16: @@ -2167,32 +2390,30 @@ score_elf_final_link_relocate (reloc_howto_type *howto, } /* Score backend functions. */ - static void -_bfd_score_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, - arelent *bfd_reloc, - Elf_Internal_Rela *elf_reloc) +s3_bfd_score_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, + arelent *bfd_reloc, + Elf_Internal_Rela *elf_reloc) { unsigned int r_type; r_type = ELF32_R_TYPE (elf_reloc->r_info); - if (r_type >= NUM_ELEM (elf32_score_howto_table)) + if (r_type >= ARRAY_SIZE (elf32_score_howto_table)) bfd_reloc->howto = NULL; else bfd_reloc->howto = &elf32_score_howto_table[r_type]; } /* Relocate an score ELF section. */ - static bfd_boolean -_bfd_score_elf_relocate_section (bfd *output_bfd, - struct bfd_link_info *info, - bfd *input_bfd, - asection *input_section, - bfd_byte *contents, - Elf_Internal_Rela *relocs, - Elf_Internal_Sym *local_syms, - asection **local_sections) +s3_bfd_score_elf_relocate_section (bfd *output_bfd, + struct bfd_link_info *info, + bfd *input_bfd, + asection *input_section, + bfd_byte *contents, + Elf_Internal_Rela *relocs, + Elf_Internal_Sym *local_syms, + asection **local_sections) { Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes; @@ -2209,23 +2430,23 @@ _bfd_score_elf_relocate_section (bfd *output_bfd, { bfd_size_type dynsecsymcount = 0; if (info->shared) - { - asection * p; - const struct elf_backend_data *bed = get_elf_backend_data (output_bfd); - - for (p = output_bfd->sections; p ; p = p->next) - if ((p->flags & SEC_EXCLUDE) == 0 - && (p->flags & SEC_ALLOC) != 0 - && !(*bed->elf_backend_omit_section_dynsym) (output_bfd, info, p)) - ++ dynsecsymcount; - } + { + asection * p; + const struct elf_backend_data *bed = get_elf_backend_data (output_bfd); + + for (p = output_bfd->sections; p ; p = p->next) + if ((p->flags & SEC_EXCLUDE) == 0 + && (p->flags & SEC_ALLOC) != 0 + && !(*bed->elf_backend_omit_section_dynsym) (output_bfd, info, p)) + ++ dynsecsymcount; + } if (!score_elf_sort_hash_table (info, dynsecsymcount + 1)) - return FALSE; + return FALSE; } symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; - extsymoff = symtab_hdr->sh_info; + extsymoff = (elf_bad_symtab (input_bfd)) ? 0 : symtab_hdr->sh_info; sym_hashes = elf_sym_hashes (input_bfd); rel = relocs; relend = relocs + input_section->reloc_count; @@ -2244,7 +2465,7 @@ _bfd_score_elf_relocate_section (bfd *output_bfd, r_symndx = ELF32_R_SYM (rel->r_info); r_type = ELF32_R_TYPE (rel->r_info); - _bfd_score_info_to_howto (input_bfd, &bfd_reloc, (Elf_Internal_Rela *) rel); + s3_bfd_score_info_to_howto (input_bfd, &bfd_reloc, (Elf_Internal_Rela *) rel); howto = bfd_reloc.howto; h = NULL; @@ -2256,13 +2477,13 @@ _bfd_score_elf_relocate_section (bfd *output_bfd, sym = local_syms + r_symndx; sec = local_sections[r_symndx]; relocation = (sec->output_section->vma - + sec->output_offset - + sym->st_value); + + sec->output_offset + + sym->st_value); name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, sec); if (!info->relocatable - && (sec->flags & SEC_MERGE) != 0 - && ELF_ST_TYPE (sym->st_info) == STT_SECTION) + && (sec->flags & SEC_MERGE) + && ELF_ST_TYPE (sym->st_info) == STT_SECTION) { asection *msec; bfd_vma addend, value; @@ -2272,9 +2493,9 @@ _bfd_score_elf_relocate_section (bfd *output_bfd, case R_SCORE_HI16: break; case R_SCORE_LO16: - hi16_addend = bfd_get_32 (input_bfd, contents + rel->r_offset - 4); + hi16_addend = score_bfd_get_32 (input_bfd, contents + rel->r_offset - 4); hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1; - value = bfd_get_32 (input_bfd, contents + rel->r_offset); + value = score_bfd_get_32 (input_bfd, contents + rel->r_offset); offset = ((((value >> 16) & 0x3) << 15) | (value & 0x7fff)) >> 1; addend = (hi16_offset << 16) | (offset & 0xffff); msec = sec; @@ -2285,14 +2506,65 @@ _bfd_score_elf_relocate_section (bfd *output_bfd, hi16_offset = (uvalue >> 16) << 1; hi16_value = (hi16_addend & (~(howto->dst_mask))) | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000); - bfd_put_32 (input_bfd, hi16_value, contents + rel->r_offset - 4); + score_bfd_put_32 (input_bfd, hi16_value, contents + rel->r_offset - 4); offset = (uvalue & 0xffff) << 1; value = (value & (~(howto->dst_mask))) | (offset & 0x7fff) | ((offset << 1) & 0x30000); - bfd_put_32 (input_bfd, value, contents + rel->r_offset); + score_bfd_put_32 (input_bfd, value, contents + rel->r_offset); break; + + case R_SCORE_IMM32: + { + value = score_bfd_get_48 (input_bfd, contents + rel->r_offset); + addend = ((value >> 5) & 0x3ff) + | (((value >> 16) & 0x7fff) << 10) + | (((value >> 32) & 0x7f) << 25); + msec = sec; + addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend); + addend -= relocation; + addend += msec->output_section->vma + msec->output_offset; + addend &= 0xffffffff; + value = (value & ~howto->src_mask) + | ((addend & 0x3ff) << 5) + | (((addend >> 10) & 0x7fff) << 16) + | (((addend >> 25) & 0x7f) << 32); + score_bfd_put_48 (input_bfd, value, contents + rel->r_offset); + break; + } + + case R_SCORE_IMM30: + { + int not_word_align_p = 0; + value = score_bfd_get_48 (input_bfd, contents + rel->r_offset); + addend = ((value >> 7) & 0xff) + | (((value >> 16) & 0x7fff) << 8) + | (((value >> 32) & 0x7f) << 23); + addend <<= howto->rightshift; + msec = sec; + addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend); + addend -= relocation; + addend += msec->output_section->vma + msec->output_offset; + addend &= 0xffffffff; + + /* Check lw48/sw48 rd, value/label word align. */ + if ((addend & 0x3) != 0) + not_word_align_p = 1; + + addend >>= howto->rightshift; + value = (value & ~howto->src_mask) + | (((addend & 0xff) >> 0) << 7) + | (((addend & 0x7fff00) >> 8) << 16) + | (((addend & 0x3f800000) >> 23) << 32); + score_bfd_put_48 (input_bfd, value, contents + rel->r_offset); + + if (not_word_align_p) + return bfd_reloc_other; + else + break; + } + case R_SCORE_GOT_LO16: - value = bfd_get_32 (input_bfd, contents + rel->r_offset); + value = score_bfd_get_32 (input_bfd, contents + rel->r_offset); addend = (((value >> 16) & 0x3) << 14) | ((value & 0x7fff) >> 1); msec = sec; addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation; @@ -2300,9 +2572,11 @@ _bfd_score_elf_relocate_section (bfd *output_bfd, value = (value & (~(howto->dst_mask))) | ((addend & 0x3fff) << 1) | (((addend >> 14) & 0x3) << 16); - bfd_put_32 (input_bfd, value, contents + rel->r_offset); + score_bfd_put_32 (input_bfd, value, contents + rel->r_offset); break; - default: + + case R_SCORE_ABS32: + case R_SCORE_REL32: value = bfd_get_32 (input_bfd, contents + rel->r_offset); /* Get the (signed) value from the instruction. */ addend = value & howto->src_mask; @@ -2320,91 +2594,110 @@ _bfd_score_elf_relocate_section (bfd *output_bfd, value = (value & ~howto->dst_mask) | (addend & howto->dst_mask); bfd_put_32 (input_bfd, value, contents + rel->r_offset); break; + + default: + value = score_bfd_get_32 (input_bfd, contents + rel->r_offset); + /* Get the (signed) value from the instruction. */ + addend = value & howto->src_mask; + if (addend & ((howto->src_mask + 1) >> 1)) + { + bfd_signed_vma mask; + + mask = -1; + mask &= ~howto->src_mask; + addend |= mask; + } + msec = sec; + addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation; + addend += msec->output_section->vma + msec->output_offset; + value = (value & ~howto->dst_mask) | (addend & howto->dst_mask); + score_bfd_put_32 (input_bfd, value, contents + rel->r_offset); + break; } } } else { - /* For global symbols we look up the symbol in the hash-table. */ - h = ((struct score_elf_link_hash_entry *) - elf_sym_hashes (input_bfd) [r_symndx - extsymoff]); - /* Find the real hash-table entry for this symbol. */ - while (h->root.root.type == bfd_link_hash_indirect - || h->root.root.type == bfd_link_hash_warning) - h = (struct score_elf_link_hash_entry *) h->root.root.u.i.link; - - /* Record the name of this symbol, for our caller. */ - name = h->root.root.root.string; - - /* See if this is the special GP_DISP_LABEL symbol. Note that such a - symbol must always be a global symbol. */ - if (strcmp (name, GP_DISP_LABEL) == 0) - { - /* Relocations against GP_DISP_LABEL are permitted only with - R_SCORE_HI16 and R_SCORE_LO16 relocations. */ - if (r_type != R_SCORE_HI16 && r_type != R_SCORE_LO16) - return bfd_reloc_notsupported; - - gp_disp_p = TRUE; - } - - /* If this symbol is defined, calculate its address. Note that - GP_DISP_LABEL is a magic symbol, always implicitly defined by the - linker, so it's inappropriate to check to see whether or not - its defined. */ - else if ((h->root.root.type == bfd_link_hash_defined - || h->root.root.type == bfd_link_hash_defweak) - && h->root.root.u.def.section) - { - sec = h->root.root.u.def.section; - if (sec->output_section) - relocation = (h->root.root.u.def.value - + sec->output_section->vma - + sec->output_offset); - else - { - relocation = h->root.root.u.def.value; - } - } - else if (h->root.root.type == bfd_link_hash_undefweak) - /* We allow relocations against undefined weak symbols, giving - it the value zero, so that you can undefined weak functions - and check to see if they exist by looking at their addresses. */ - relocation = 0; - else if (info->unresolved_syms_in_objects == RM_IGNORE - && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT) - relocation = 0; - else if (strcmp (name, "_DYNAMIC_LINK") == 0) - { - /* If this is a dynamic link, we should have created a _DYNAMIC_LINK symbol - in _bfd_score_elf_create_dynamic_sections. Otherwise, we should define + /* For global symbols we look up the symbol in the hash-table. */ + h = ((struct score_elf_link_hash_entry *) + elf_sym_hashes (input_bfd) [r_symndx - extsymoff]); + /* Find the real hash-table entry for this symbol. */ + while (h->root.root.type == bfd_link_hash_indirect + || h->root.root.type == bfd_link_hash_warning) + h = (struct score_elf_link_hash_entry *) h->root.root.u.i.link; + + /* Record the name of this symbol, for our caller. */ + name = h->root.root.root.string; + + /* See if this is the special GP_DISP_LABEL symbol. Note that such a + symbol must always be a global symbol. */ + if (strcmp (name, GP_DISP_LABEL) == 0) + { + /* Relocations against GP_DISP_LABEL are permitted only with + R_SCORE_HI16 and R_SCORE_LO16 relocations. */ + if (r_type != R_SCORE_HI16 && r_type != R_SCORE_LO16) + return bfd_reloc_notsupported; + + gp_disp_p = TRUE; + } + + /* If this symbol is defined, calculate its address. Note that + GP_DISP_LABEL is a magic symbol, always implicitly defined by the + linker, so it's inappropriate to check to see whether or not + its defined. */ + else if ((h->root.root.type == bfd_link_hash_defined + || h->root.root.type == bfd_link_hash_defweak) + && h->root.root.u.def.section) + { + sec = h->root.root.u.def.section; + if (sec->output_section) + relocation = (h->root.root.u.def.value + + sec->output_section->vma + + sec->output_offset); + else + { + relocation = h->root.root.u.def.value; + } + } + else if (h->root.root.type == bfd_link_hash_undefweak) + /* We allow relocations against undefined weak symbols, giving + it the value zero, so that you can undefined weak functions + and check to see if they exist by looking at their addresses. */ + relocation = 0; + else if (info->unresolved_syms_in_objects == RM_IGNORE + && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT) + relocation = 0; + else if (strcmp (name, "_DYNAMIC_LINK") == 0) + { + /* If this is a dynamic link, we should have created a _DYNAMIC_LINK symbol + in s3_bfd_score_elf_create_dynamic_sections. Otherwise, we should define the symbol with a value of 0. */ - BFD_ASSERT (! info->shared); - BFD_ASSERT (bfd_get_section_by_name (output_bfd, ".dynamic") == NULL); - relocation = 0; - } - else if (!info->relocatable) - { - if (! ((*info->callbacks->undefined_symbol) - (info, h->root.root.root.string, input_bfd, - input_section, rel->r_offset, - (info->unresolved_syms_in_objects == RM_GENERATE_ERROR) - || ELF_ST_VISIBILITY (h->root.other)))) - return bfd_reloc_undefined; - relocation = 0; - } + BFD_ASSERT (! info->shared); + BFD_ASSERT (bfd_get_section_by_name (output_bfd, ".dynamic") == NULL); + relocation = 0; + } + else if (!info->relocatable) + { + if (! ((*info->callbacks->undefined_symbol) + (info, h->root.root.root.string, input_bfd, + input_section, rel->r_offset, + (info->unresolved_syms_in_objects == RM_GENERATE_ERROR) + || ELF_ST_VISIBILITY (h->root.other)))) + return bfd_reloc_undefined; + relocation = 0; + } } if (sec != NULL && elf_discarded_section (sec)) - { - /* For relocs against symbols from removed linkonce sections, - or sections discarded by a linker script, we just want the - section contents zeroed. Avoid any special processing. */ - _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset); - rel->r_info = 0; - rel->r_addend = 0; - continue; - } + { + /* For relocs against symbols from removed linkonce sections, + or sections discarded by a linker script, we just want the + section contents zeroed. Avoid any special processing. */ + _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset); + rel->r_info = 0; + rel->r_addend = 0; + continue; + } if (info->relocatable) { @@ -2412,17 +2705,25 @@ _bfd_score_elf_relocate_section (bfd *output_bfd, anything, unless the reloc is against a section symbol, in which case we have to adjust according to where the section symbol winds up in the output section. */ - if (sym != NULL && ELF_ST_TYPE (sym->st_info) == STT_SECTION) - score_elf_add_to_rel (input_bfd, contents + rel->r_offset, - howto, (bfd_signed_vma) sec->output_offset); + if (r_symndx < symtab_hdr->sh_info) + { + sym = local_syms + r_symndx; + if (ELF_ST_TYPE (sym->st_info) == STT_SECTION) + { + sec = local_sections[r_symndx]; + score_elf_add_to_rel (input_bfd, contents + rel->r_offset, + howto, (bfd_signed_vma) (sec->output_offset + sym->st_value)); + } + } continue; } + /* This is a final link. */ r = score_elf_final_link_relocate (howto, input_bfd, output_bfd, input_section, contents, rel, relocs, relocation, info, name, (h ? ELF_ST_TYPE ((unsigned int)h->root.root.type) : - ELF_ST_TYPE ((unsigned int)sym->st_info)), h, + ELF_ST_TYPE ((unsigned int)sym->st_info)), h, local_sections, gp_disp_p); if (r != bfd_reloc_ok) @@ -2459,6 +2760,11 @@ _bfd_score_elf_relocate_section (bfd *output_bfd, msg = _("internal error: dangerous error"); goto common_error; + /* Use bfd_reloc_other to check lw48, sw48 word align. */ + case bfd_reloc_other: + msg = _("address not word align"); + goto common_error; + default: msg = _("internal error: unknown error"); /* fall through */ @@ -2477,12 +2783,11 @@ _bfd_score_elf_relocate_section (bfd *output_bfd, /* Look through the relocs for a section during the first phase, and allocate space in the global offset table. */ - static bfd_boolean -_bfd_score_elf_check_relocs (bfd *abfd, - struct bfd_link_info *info, - asection *sec, - const Elf_Internal_Rela *relocs) +s3_bfd_score_elf_check_relocs (bfd *abfd, + struct bfd_link_info *info, + asection *sec, + const Elf_Internal_Rela *relocs) { const char *name; bfd *dynobj; @@ -2502,7 +2807,7 @@ _bfd_score_elf_check_relocs (bfd *abfd, dynobj = elf_hash_table (info)->dynobj; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); - extsymoff = symtab_hdr->sh_info; + extsymoff = (elf_bad_symtab (abfd)) ? 0 : symtab_hdr->sh_info; name = bfd_get_section_name (abfd, sec); @@ -2537,9 +2842,9 @@ _bfd_score_elf_check_relocs (bfd *abfd, r_type = ELF32_R_TYPE (rel->r_info); if (r_symndx < extsymoff) - { + { h = NULL; - } + } else if (r_symndx >= extsymoff + NUM_SHDR_ENTRIES (symtab_hdr)) { (*_bfd_error_handler) (_("%s: Malformed reloc detected for section %s"), abfd, name); @@ -2583,90 +2888,90 @@ _bfd_score_elf_check_relocs (bfd *abfd, if (!h && (r_type == R_SCORE_GOT_LO16)) { - if (! score_elf_record_local_got_symbol (abfd, r_symndx, rel->r_addend, g)) - return FALSE; + if (! score_elf_record_local_got_symbol (abfd, r_symndx, rel->r_addend, g)) + return FALSE; } switch (r_type) { case R_SCORE_CALL15: - if (h == NULL) - { - (*_bfd_error_handler) - (_("%B: CALL15 reloc at 0x%lx not against global symbol"), - abfd, (unsigned long) rel->r_offset); - bfd_set_error (bfd_error_bad_value); - return FALSE; - } - else - { - /* This symbol requires a global offset table entry. */ - if (! score_elf_record_global_got_symbol (h, abfd, info, g)) - return FALSE; - - /* We need a stub, not a plt entry for the undefined function. But we record + if (h == NULL) + { + (*_bfd_error_handler) + (_("%B: CALL15 reloc at 0x%lx not against global symbol"), + abfd, (unsigned long) rel->r_offset); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + else + { + /* This symbol requires a global offset table entry. */ + if (! score_elf_record_global_got_symbol (h, abfd, info, g)) + return FALSE; + + /* We need a stub, not a plt entry for the undefined function. But we record it as if it needs plt. See _bfd_elf_adjust_dynamic_symbol. */ - h->needs_plt = 1; - h->type = STT_FUNC; - } + h->needs_plt = 1; + h->type = STT_FUNC; + } + break; + case R_SCORE_GOT15: + if (h && ! score_elf_record_global_got_symbol (h, abfd, info, g)) + return FALSE; break; - case R_SCORE_GOT15: - if (h && ! score_elf_record_global_got_symbol (h, abfd, info, g)) - return FALSE; - break; case R_SCORE_ABS32: case R_SCORE_REL32: - if ((info->shared || h != NULL) && (sec->flags & SEC_ALLOC) != 0) - { - if (sreloc == NULL) - { - sreloc = score_elf_rel_dyn_section (dynobj, TRUE); - if (sreloc == NULL) - return FALSE; - } + if ((info->shared || h != NULL) && (sec->flags & SEC_ALLOC) != 0) + { + if (sreloc == NULL) + { + sreloc = score_elf_rel_dyn_section (dynobj, TRUE); + if (sreloc == NULL) + return FALSE; + } #define SCORE_READONLY_SECTION (SEC_ALLOC | SEC_LOAD | SEC_READONLY) - if (info->shared) - { - /* When creating a shared object, we must copy these reloc types into + if (info->shared) + { + /* When creating a shared object, we must copy these reloc types into the output file as R_SCORE_REL32 relocs. We make room for this reloc in the .rel.dyn reloc section. */ - score_elf_allocate_dynamic_relocations (dynobj, 1); - if ((sec->flags & SCORE_READONLY_SECTION) - == SCORE_READONLY_SECTION) - /* We tell the dynamic linker that there are - relocations against the text segment. */ - info->flags |= DF_TEXTREL; - } - else - { - struct score_elf_link_hash_entry *hscore; - - /* We only need to copy this reloc if the symbol is + score_elf_allocate_dynamic_relocations (dynobj, 1); + if ((sec->flags & SCORE_READONLY_SECTION) + == SCORE_READONLY_SECTION) + /* We tell the dynamic linker that there are + relocations against the text segment. */ + info->flags |= DF_TEXTREL; + } + else + { + struct score_elf_link_hash_entry *hscore; + + /* We only need to copy this reloc if the symbol is defined in a dynamic object. */ - hscore = (struct score_elf_link_hash_entry *)h; - ++hscore->possibly_dynamic_relocs; - if ((sec->flags & SCORE_READONLY_SECTION) - == SCORE_READONLY_SECTION) - /* We need it to tell the dynamic linker if there - are relocations against the text segment. */ - hscore->readonly_reloc = TRUE; - } - - /* Even though we don't directly need a GOT entry for this symbol, - a symbol must have a dynamic symbol table index greater that + hscore = (struct score_elf_link_hash_entry *)h; + ++hscore->possibly_dynamic_relocs; + if ((sec->flags & SCORE_READONLY_SECTION) + == SCORE_READONLY_SECTION) + /* We need it to tell the dynamic linker if there + are relocations against the text segment. */ + hscore->readonly_reloc = TRUE; + } + + /* Even though we don't directly need a GOT entry for this symbol, + a symbol must have a dynamic symbol table index greater that DT_SCORE_GOTSYM if there are dynamic relocations against it. */ - if (h != NULL) - { - if (dynobj == NULL) - elf_hash_table (info)->dynobj = dynobj = abfd; - if (! score_elf_create_got_section (dynobj, info, TRUE)) - return FALSE; - g = score_elf_got_info (dynobj, &sgot); - if (! score_elf_record_global_got_symbol (h, abfd, info, g)) - return FALSE; - } - } - break; + if (h != NULL) + { + if (dynobj == NULL) + elf_hash_table (info)->dynobj = dynobj = abfd; + if (! score_elf_create_got_section (dynobj, info, TRUE)) + return FALSE; + g = score_elf_got_info (dynobj, &sgot); + if (! score_elf_record_global_got_symbol (h, abfd, info, g)) + return FALSE; + } + } + break; /* This relocation describes the C++ object vtable hierarchy. Reconstruct it for later use during GC. */ @@ -2678,9 +2983,7 @@ _bfd_score_elf_check_relocs (bfd *abfd, /* This relocation describes which C++ vtable entries are actually used. Record for later use during GC. */ case R_SCORE_GNU_VTENTRY: - BFD_ASSERT (h != NULL); - if (h != NULL - && !bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset)) + if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset)) return FALSE; break; default: @@ -2690,32 +2993,32 @@ _bfd_score_elf_check_relocs (bfd *abfd, /* We must not create a stub for a symbol that has relocations related to taking the function's address. */ switch (r_type) - { - default: - if (h != NULL) - { - struct score_elf_link_hash_entry *sh; + { + default: + if (h != NULL) + { + struct score_elf_link_hash_entry *sh; - sh = (struct score_elf_link_hash_entry *) h; - sh->no_fn_stub = TRUE; - } - break; - case R_SCORE_CALL15: - break; - } + sh = (struct score_elf_link_hash_entry *) h; + sh->no_fn_stub = TRUE; + } + break; + case R_SCORE_CALL15: + break; + } } return TRUE; } static bfd_boolean -_bfd_score_elf_add_symbol_hook (bfd *abfd, - struct bfd_link_info *info ATTRIBUTE_UNUSED, - Elf_Internal_Sym *sym, - const char **namep ATTRIBUTE_UNUSED, - flagword *flagsp ATTRIBUTE_UNUSED, - asection **secp, - bfd_vma *valp) +s3_bfd_score_elf_add_symbol_hook (bfd *abfd, + struct bfd_link_info *info ATTRIBUTE_UNUSED, + Elf_Internal_Sym *sym, + const char **namep ATTRIBUTE_UNUSED, + flagword *flagsp ATTRIBUTE_UNUSED, + asection **secp, + bfd_vma *valp) { switch (sym->st_shndx) { @@ -2734,7 +3037,7 @@ _bfd_score_elf_add_symbol_hook (bfd *abfd, } static void -_bfd_score_elf_symbol_processing (bfd *abfd, asymbol *asym) +s3_bfd_score_elf_symbol_processing (bfd *abfd, asymbol *asym) { elf_symbol_type *elfsym; @@ -2766,11 +3069,11 @@ _bfd_score_elf_symbol_processing (bfd *abfd, asymbol *asym) } static bfd_boolean -_bfd_score_elf_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED, - const char *name ATTRIBUTE_UNUSED, - Elf_Internal_Sym *sym, - asection *input_sec, - struct elf_link_hash_entry *h ATTRIBUTE_UNUSED) +s3_bfd_score_elf_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED, + const char *name ATTRIBUTE_UNUSED, + Elf_Internal_Sym *sym, + asection *input_sec, + struct elf_link_hash_entry *h ATTRIBUTE_UNUSED) { /* If we see a common symbol, which implies a relocatable link, then if a symbol was small common in an input file, mark it as small @@ -2782,9 +3085,9 @@ _bfd_score_elf_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNU } static bfd_boolean -_bfd_score_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED, - asection *sec, - int *retval) +s3_bfd_score_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED, + asection *sec, + int *retval) { if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0) { @@ -2799,10 +3102,9 @@ _bfd_score_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED, regular object. The current definition is in some section of the dynamic object, but we're not including those sections. We have to change the definition to something the rest of the link can understand. */ - static bfd_boolean -_bfd_score_elf_adjust_dynamic_symbol (struct bfd_link_info *info, - struct elf_link_hash_entry *h) +s3_bfd_score_elf_adjust_dynamic_symbol (struct bfd_link_info *info, + struct elf_link_hash_entry *h) { bfd *dynobj; struct score_elf_link_hash_entry *hscore; @@ -2888,10 +3190,9 @@ _bfd_score_elf_adjust_dynamic_symbol (struct bfd_link_info *info, /* This function is called after all the input files have been read, and the input sections have been assigned to output sections. */ - static bfd_boolean -_bfd_score_elf_always_size_sections (bfd *output_bfd, - struct bfd_link_info *info) +s3_bfd_score_elf_always_size_sections (bfd *output_bfd, + struct bfd_link_info *info) { bfd *dynobj; asection *s; @@ -2917,14 +3218,14 @@ _bfd_score_elf_always_size_sections (bfd *output_bfd, asection *subsection; for (subsection = sub->sections; - subsection; - subsection = subsection->next) - { - if ((subsection->flags & SEC_ALLOC) == 0) - continue; - loadable_size += ((subsection->size + 0xf) - &~ (bfd_size_type) 0xf); - } + subsection; + subsection = subsection->next) + { + if ((subsection->flags & SEC_ALLOC) == 0) + continue; + loadable_size += ((subsection->size + 0xf) + &~ (bfd_size_type) 0xf); + } } /* There has to be a global GOT entry for every symbol with @@ -2966,9 +3267,8 @@ _bfd_score_elf_always_size_sections (bfd *output_bfd, } /* Set the sizes of the dynamic sections. */ - static bfd_boolean -_bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) +s3_bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) { bfd *dynobj; asection *s; @@ -3045,10 +3345,10 @@ _bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf } else if (CONST_STRNEQ (name, ".got")) { - /* _bfd_score_elf_always_size_sections() has already done - most of the work, but some symbols may have been mapped - to versions that we must now resolve in the got_entries - hash tables. */ + /* s3_bfd_score_elf_always_size_sections() has already done + most of the work, but some symbols may have been mapped + to versions that we must now resolve in the got_entries + hash tables. */ } else if (strcmp (name, SCORE_ELF_STUB_SECTION_NAME) == 0) { @@ -3074,37 +3374,37 @@ _bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf if (elf_hash_table (info)->dynamic_sections_created) { /* Add some entries to the .dynamic section. We fill in the - values later, in _bfd_score_elf_finish_dynamic_sections, but we - must add the entries now so that we get the correct size for - the .dynamic section. The DT_DEBUG entry is filled in by the - dynamic linker and used by the debugger. */ + values later, in s3_bfd_score_elf_finish_dynamic_sections, but we + must add the entries now so that we get the correct size for + the .dynamic section. The DT_DEBUG entry is filled in by the + dynamic linker and used by the debugger. */ if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_DEBUG, 0)) - return FALSE; + return FALSE; if (reltext) - info->flags |= DF_TEXTREL; + info->flags |= DF_TEXTREL; if ((info->flags & DF_TEXTREL) != 0) - { - if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_TEXTREL, 0)) - return FALSE; - } + { + if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_TEXTREL, 0)) + return FALSE; + } if (! SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTGOT, 0)) - return FALSE; + return FALSE; if (score_elf_rel_dyn_section (dynobj, FALSE)) - { - if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_REL, 0)) - return FALSE; + { + if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_REL, 0)) + return FALSE; - if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELSZ, 0)) - return FALSE; + if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELSZ, 0)) + return FALSE; - if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELENT, 0)) - return FALSE; - } + if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELENT, 0)) + return FALSE; + } if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_BASE_ADDRESS, 0)) return FALSE; @@ -3122,14 +3422,14 @@ _bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *inf return FALSE; if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_HIPAGENO, 0)) - return FALSE; + return FALSE; } return TRUE; } static bfd_boolean -_bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) +s3_bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) { struct elf_link_hash_entry *h; struct bfd_link_hash_entry *bh; @@ -3173,7 +3473,7 @@ _bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) bh = NULL; if (!(_bfd_generic_link_add_one_symbol (info, abfd, name, BSF_GLOBAL, bfd_abs_section_ptr, - (bfd_vma) 0, (const char *)NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh))) + (bfd_vma) 0, NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh))) return FALSE; h = (struct elf_link_hash_entry *)bh; @@ -3191,12 +3491,11 @@ _bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) /* Finish up dynamic symbol handling. We set the contents of various dynamic sections here. */ - static bfd_boolean -_bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd, - struct bfd_link_info *info, - struct elf_link_hash_entry *h, - Elf_Internal_Sym *sym) +s3_bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd, + struct bfd_link_info *info, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym) { bfd *dynobj; asection *sgot; @@ -3218,24 +3517,24 @@ _bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd, /* FIXME: Can h->dynindex be more than 64K? */ if (h->dynindx & 0xffff0000) - return FALSE; + return FALSE; /* Fill the stub. */ - bfd_put_32 (output_bfd, STUB_LW, stub); - bfd_put_32 (output_bfd, STUB_MOVE, stub + 4); - bfd_put_32 (output_bfd, STUB_LI16 | (h->dynindx << 1), stub + 8); - bfd_put_32 (output_bfd, STUB_BRL, stub + 12); + score_bfd_put_32 (output_bfd, STUB_LW, stub); + score_bfd_put_32 (output_bfd, STUB_MOVE, stub + 4); + score_bfd_put_32 (output_bfd, STUB_LI16 | (h->dynindx << 1), stub + 8); + score_bfd_put_32 (output_bfd, STUB_BRL, stub + 12); BFD_ASSERT (h->plt.offset <= s->size); memcpy (s->contents + h->plt.offset, stub, SCORE_FUNCTION_STUB_SIZE); /* Mark the symbol as undefined. plt.offset != -1 occurs - only for the referenced symbol. */ + only for the referenced symbol. */ sym->st_shndx = SHN_UNDEF; /* The run-time linker uses the st_value field of the symbol - to reset the global offset table entry for this external - to its stub address when unlinking a shared object. */ + to reset the global offset table entry for this external + to its stub address when unlinking a shared object. */ sym->st_value = (s->output_section->vma + s->output_offset + h->plt.offset); } @@ -3256,7 +3555,7 @@ _bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd, value = sym->st_value; offset = score_elf_global_got_index (dynobj, h); - bfd_put_32 (output_bfd, value, sgot->contents + offset); + score_bfd_put_32 (output_bfd, value, sgot->contents + offset); } /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */ @@ -3280,10 +3579,9 @@ _bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd, } /* Finish up the dynamic sections. */ - static bfd_boolean -_bfd_score_elf_finish_dynamic_sections (bfd *output_bfd, - struct bfd_link_info *info) +s3_bfd_score_elf_finish_dynamic_sections (bfd *output_bfd, + struct bfd_link_info *info) { bfd *dynobj; asection *sdyn; @@ -3313,88 +3611,88 @@ _bfd_score_elf_finish_dynamic_sections (bfd *output_bfd, BFD_ASSERT (g != NULL); for (b = sdyn->contents; - b < sdyn->contents + sdyn->size; - b += SCORE_ELF_DYN_SIZE (dynobj)) - { - Elf_Internal_Dyn dyn; - const char *name; - size_t elemsize; - bfd_boolean swap_out_p; - - /* Read in the current dynamic entry. */ - (*get_elf_backend_data (dynobj)->s->swap_dyn_in) (dynobj, b, &dyn); - - /* Assume that we're going to modify it and write it out. */ - swap_out_p = TRUE; - - switch (dyn.d_tag) - { - case DT_RELENT: - s = score_elf_rel_dyn_section (dynobj, FALSE); - BFD_ASSERT (s != NULL); - dyn.d_un.d_val = SCORE_ELF_REL_SIZE (dynobj); - break; - - case DT_STRSZ: - /* Rewrite DT_STRSZ. */ - dyn.d_un.d_val = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr); - break; - - case DT_PLTGOT: - name = ".got"; - s = bfd_get_section_by_name (output_bfd, name); - BFD_ASSERT (s != NULL); - dyn.d_un.d_ptr = s->vma; - break; - - case DT_SCORE_BASE_ADDRESS: - s = output_bfd->sections; - BFD_ASSERT (s != NULL); - dyn.d_un.d_ptr = s->vma & ~(bfd_vma) 0xffff; - break; - - case DT_SCORE_LOCAL_GOTNO: - dyn.d_un.d_val = g->local_gotno; - break; - - case DT_SCORE_UNREFEXTNO: - /* The index into the dynamic symbol table which is the - entry of the first external symbol that is not - referenced within the same object. */ - dyn.d_un.d_val = bfd_count_sections (output_bfd) + 1; - break; - - case DT_SCORE_GOTSYM: - if (g->global_gotsym) - { - dyn.d_un.d_val = g->global_gotsym->dynindx; - break; - } - /* In case if we don't have global got symbols we default - to setting DT_SCORE_GOTSYM to the same value as - DT_SCORE_SYMTABNO, so we just fall through. */ - - case DT_SCORE_SYMTABNO: - name = ".dynsym"; - elemsize = SCORE_ELF_SYM_SIZE (output_bfd); - s = bfd_get_section_by_name (output_bfd, name); - BFD_ASSERT (s != NULL); - - dyn.d_un.d_val = s->size / elemsize; - break; - - case DT_SCORE_HIPAGENO: - dyn.d_un.d_val = g->local_gotno - SCORE_RESERVED_GOTNO; - break; - - default: - swap_out_p = FALSE; - break; - } - - if (swap_out_p) - (*get_elf_backend_data (dynobj)->s->swap_dyn_out) (dynobj, &dyn, b); - } + b < sdyn->contents + sdyn->size; + b += SCORE_ELF_DYN_SIZE (dynobj)) + { + Elf_Internal_Dyn dyn; + const char *name; + size_t elemsize; + bfd_boolean swap_out_p; + + /* Read in the current dynamic entry. */ + (*get_elf_backend_data (dynobj)->s->swap_dyn_in) (dynobj, b, &dyn); + + /* Assume that we're going to modify it and write it out. */ + swap_out_p = TRUE; + + switch (dyn.d_tag) + { + case DT_RELENT: + s = score_elf_rel_dyn_section (dynobj, FALSE); + BFD_ASSERT (s != NULL); + dyn.d_un.d_val = SCORE_ELF_REL_SIZE (dynobj); + break; + + case DT_STRSZ: + /* Rewrite DT_STRSZ. */ + dyn.d_un.d_val = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr); + break; + + case DT_PLTGOT: + name = ".got"; + s = bfd_get_section_by_name (output_bfd, name); + BFD_ASSERT (s != NULL); + dyn.d_un.d_ptr = s->vma; + break; + + case DT_SCORE_BASE_ADDRESS: + s = output_bfd->sections; + BFD_ASSERT (s != NULL); + dyn.d_un.d_ptr = s->vma & ~(bfd_vma) 0xffff; + break; + + case DT_SCORE_LOCAL_GOTNO: + dyn.d_un.d_val = g->local_gotno; + break; + + case DT_SCORE_UNREFEXTNO: + /* The index into the dynamic symbol table which is the + entry of the first external symbol that is not + referenced within the same object. */ + dyn.d_un.d_val = bfd_count_sections (output_bfd) + 1; + break; + + case DT_SCORE_GOTSYM: + if (g->global_gotsym) + { + dyn.d_un.d_val = g->global_gotsym->dynindx; + break; + } + /* In case if we don't have global got symbols we default + to setting DT_SCORE_GOTSYM to the same value as + DT_SCORE_SYMTABNO, so we just fall through. */ + + case DT_SCORE_SYMTABNO: + name = ".dynsym"; + elemsize = SCORE_ELF_SYM_SIZE (output_bfd); + s = bfd_get_section_by_name (output_bfd, name); + BFD_ASSERT (s != NULL); + + dyn.d_un.d_val = s->size / elemsize; + break; + + case DT_SCORE_HIPAGENO: + dyn.d_un.d_val = g->local_gotno - SCORE_RESERVED_GOTNO; + break; + + default: + swap_out_p = FALSE; + break; + } + + if (swap_out_p) + (*get_elf_backend_data (dynobj)->s->swap_dyn_out) (dynobj, &dyn, b); + } } /* The first entry of the global offset table will be filled at @@ -3402,8 +3700,8 @@ _bfd_score_elf_finish_dynamic_sections (bfd *output_bfd, This isn't the case of IRIX rld. */ if (sgot != NULL && sgot->size > 0) { - bfd_put_32 (output_bfd, 0, sgot->contents); - bfd_put_32 (output_bfd, 0x80000000, sgot->contents + SCORE_ELF_GOT_SIZE (output_bfd)); + score_bfd_put_32 (output_bfd, 0, sgot->contents); + score_bfd_put_32 (output_bfd, 0x80000000, sgot->contents + SCORE_ELF_GOT_SIZE (output_bfd)); } if (sgot != NULL) @@ -3418,7 +3716,7 @@ _bfd_score_elf_finish_dynamic_sections (bfd *output_bfd, { reldyn_sorting_bfd = output_bfd; qsort ((Elf32_External_Rel *) s->contents + 1, s->reloc_count - 1, - sizeof (Elf32_External_Rel), score_elf_sort_dynamic_relocs); + sizeof (Elf32_External_Rel), score_elf_sort_dynamic_relocs); } return TRUE; @@ -3426,11 +3724,10 @@ _bfd_score_elf_finish_dynamic_sections (bfd *output_bfd, /* This function set up the ELF section header for a BFD section in preparation for writing it out. This is where the flags and type fields are set for unusual sections. */ - static bfd_boolean -_bfd_score_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, - Elf_Internal_Shdr *hdr, - asection *sec) +s3_bfd_score_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, + Elf_Internal_Shdr *hdr, + asection *sec) { const char *name; @@ -3452,38 +3749,35 @@ _bfd_score_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, warning message will be issued. backend_fake_section is called before assign_file_positions_except_relocs(); backend_section_processing after it. so, we modify section flag there, but not backend_fake_section. */ - static bfd_boolean -_bfd_score_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Shdr *hdr) +s3_bfd_score_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Shdr *hdr) { if (hdr->bfd_section != NULL) { const char *name = bfd_get_section_name (abfd, hdr->bfd_section); if (strcmp (name, ".sdata") == 0) - { - hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_SCORE_GPREL; - hdr->sh_type = SHT_PROGBITS; - } + { + hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_SCORE_GPREL; + hdr->sh_type = SHT_PROGBITS; + } else if (strcmp (name, ".sbss") == 0) - { - hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_SCORE_GPREL; - hdr->sh_type = SHT_NOBITS; - } + { + hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_SCORE_GPREL; + hdr->sh_type = SHT_NOBITS; + } else if (strcmp (name, ".srdata") == 0) - { - hdr->sh_flags |= SHF_ALLOC | SHF_SCORE_GPREL; - hdr->sh_type = SHT_PROGBITS; - } + { + hdr->sh_flags |= SHF_ALLOC | SHF_SCORE_GPREL; + hdr->sh_type = SHT_PROGBITS; + } } return TRUE; } static bfd_boolean -_bfd_score_elf_write_section (bfd *output_bfd, - struct bfd_link_info *link_info ATTRIBUTE_UNUSED, - asection *sec, bfd_byte *contents) +s3_bfd_score_elf_write_section (bfd *output_bfd, asection *sec, bfd_byte *contents) { bfd_byte *to, *from, *end; int i; @@ -3514,11 +3808,10 @@ _bfd_score_elf_write_section (bfd *output_bfd, /* Copy data from a SCORE ELF indirect symbol to its direct symbol, hiding the old indirect symbol. Process additional relocation information. */ - static void -_bfd_score_elf_copy_indirect_symbol (struct bfd_link_info *info, - struct elf_link_hash_entry *dir, - struct elf_link_hash_entry *ind) +s3_bfd_score_elf_copy_indirect_symbol (struct bfd_link_info *info, + struct elf_link_hash_entry *dir, + struct elf_link_hash_entry *ind) { struct score_elf_link_hash_entry *dirscore, *indscore; @@ -3539,10 +3832,9 @@ _bfd_score_elf_copy_indirect_symbol (struct bfd_link_info *info, } /* Remove information about discarded functions from other sections which mention them. */ - static bfd_boolean -_bfd_score_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie, - struct bfd_link_info *info) +s3_bfd_score_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie, + struct bfd_link_info *info) { asection *o; bfd_boolean ret = FALSE; @@ -3593,9 +3885,8 @@ _bfd_score_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie, } /* Signal that discard_info() has removed the discarded relocations for this section. */ - static bfd_boolean -_bfd_score_elf_ignore_discarded_relocs (asection *sec) +s3_bfd_score_elf_ignore_discarded_relocs (asection *sec) { if (strcmp (sec->name, ".pdr") == 0) return TRUE; @@ -3604,20 +3895,19 @@ _bfd_score_elf_ignore_discarded_relocs (asection *sec) /* Return the section that should be marked against GC for a given relocation. */ - static asection * -_bfd_score_elf_gc_mark_hook (asection *sec, - struct bfd_link_info *info, - Elf_Internal_Rela *rel, - struct elf_link_hash_entry *h, - Elf_Internal_Sym *sym) +s3_bfd_score_elf_gc_mark_hook (asection *sec, + struct bfd_link_info *info, + Elf_Internal_Rela *rel, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym) { if (h != NULL) switch (ELF32_R_TYPE (rel->r_info)) { case R_SCORE_GNU_VTINHERIT: case R_SCORE_GNU_VTENTRY: - return NULL; + return NULL; } return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); @@ -3626,7 +3916,7 @@ _bfd_score_elf_gc_mark_hook (asection *sec, /* Support for core dump NOTE sections. */ static bfd_boolean -_bfd_score_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) +s3_bfd_score_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) { int offset; unsigned int raw_size; @@ -3638,10 +3928,10 @@ _bfd_score_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) case 148: /* Linux/Score 32-bit. */ /* pr_cursig */ - elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); + elf_tdata (abfd)->core_signal = score_bfd_get_16 (abfd, note->descdata + 12); /* pr_pid */ - elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24); + elf_tdata (abfd)->core_pid = score_bfd_get_32 (abfd, note->descdata + 24); /* pr_reg */ offset = 72; @@ -3655,7 +3945,7 @@ _bfd_score_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) } static bfd_boolean -_bfd_score_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) +s3_bfd_score_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) { switch (note->descsz) { @@ -3684,13 +3974,12 @@ _bfd_score_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) /* Score BFD functions. */ - static reloc_howto_type * -elf32_score_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code) +s3_elf32_score_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code) { unsigned int i; - for (i = 0; i < NUM_ELEM (elf32_score_reloc_map); i++) + for (i = 0; i < ARRAY_SIZE (elf32_score_reloc_map); i++) if (elf32_score_reloc_map[i].bfd_reloc_val == code) return &elf32_score_howto_table[elf32_score_reloc_map[i].elf_reloc_val]; @@ -3699,16 +3988,16 @@ elf32_score_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_t static reloc_howto_type * elf32_score_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, - const char *r_name) + const char *r_name) { unsigned int i; for (i = 0; i < (sizeof (elf32_score_howto_table) - / sizeof (elf32_score_howto_table[0])); + / sizeof (elf32_score_howto_table[0])); i++) if (elf32_score_howto_table[i].name != NULL - && strcasecmp (elf32_score_howto_table[i].name, r_name) == 0) + && strcasecmp (elf32_score_howto_table[i].name, r_name) == 0) return &elf32_score_howto_table[i]; return NULL; @@ -3717,7 +4006,7 @@ elf32_score_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, /* Create a score elf linker hash table. */ static struct bfd_link_hash_table * -elf32_score_link_hash_table_create (bfd *abfd) +s3_elf32_score_link_hash_table_create (bfd *abfd) { struct score_elf_link_hash_table *ret; bfd_size_type amt = sizeof (struct score_elf_link_hash_table); @@ -3727,7 +4016,7 @@ elf32_score_link_hash_table_create (bfd *abfd) return NULL; if (!_bfd_elf_link_hash_table_init (&ret->root, abfd, score_elf_link_hash_newfunc, - sizeof (struct score_elf_link_hash_entry))) + sizeof (struct score_elf_link_hash_entry))) { free (ret); return NULL; @@ -3737,7 +4026,7 @@ elf32_score_link_hash_table_create (bfd *abfd) } static bfd_boolean -elf32_score_print_private_bfd_data (bfd *abfd, void * ptr) +s3_elf32_score_print_private_bfd_data (bfd *abfd, void * ptr) { FILE *file = (FILE *) ptr; @@ -3762,7 +4051,7 @@ elf32_score_print_private_bfd_data (bfd *abfd, void * ptr) } static bfd_boolean -elf32_score_merge_private_bfd_data (bfd *ibfd, bfd *obfd) +s3_elf32_score_merge_private_bfd_data (bfd *ibfd, bfd *obfd) { flagword in_flags; flagword out_flags; @@ -3786,10 +4075,10 @@ elf32_score_merge_private_bfd_data (bfd *ibfd, bfd *obfd) elf_elfheader (obfd)->e_flags = in_flags; if (bfd_get_arch (obfd) == bfd_get_arch (ibfd) - && bfd_get_arch_info (obfd)->the_default) - { - return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd)); - } + && bfd_get_arch_info (obfd)->the_default) + { + return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd)); + } return TRUE; } @@ -3805,7 +4094,7 @@ elf32_score_merge_private_bfd_data (bfd *ibfd, bfd *obfd) } static bfd_boolean -elf32_score_new_section_hook (bfd *abfd, asection *sec) +s3_elf32_score_new_section_hook (bfd *abfd, asection *sec) { struct _score_elf_section_data *sdata; bfd_size_type amt = sizeof (*sdata); @@ -3818,6 +4107,363 @@ elf32_score_new_section_hook (bfd *abfd, asection *sec) return _bfd_elf_new_section_hook (abfd, sec); } +/*****************************************************************************/ + +/* s3_s7: backend hooks. */ +static void +_bfd_score_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, + arelent *bfd_reloc, + Elf_Internal_Rela *elf_reloc) +{ + if (bfd_get_mach (abfd) == bfd_mach_score3) + return s3_bfd_score_info_to_howto (abfd, bfd_reloc, elf_reloc); + else + return s7_bfd_score_info_to_howto (abfd, bfd_reloc, elf_reloc); +} + +static bfd_boolean +_bfd_score_elf_relocate_section (bfd *output_bfd, + struct bfd_link_info *info, + bfd *input_bfd, + asection *input_section, + bfd_byte *contents, + Elf_Internal_Rela *relocs, + Elf_Internal_Sym *local_syms, + asection **local_sections) +{ + if (bfd_get_mach (output_bfd) == bfd_mach_score3) + return s3_bfd_score_elf_relocate_section (output_bfd, + info, input_bfd, input_section, contents, relocs, + local_syms, local_sections); + else + return s7_bfd_score_elf_relocate_section (output_bfd, + info, input_bfd, input_section, contents, relocs, + local_syms, local_sections); +} + +static bfd_boolean +_bfd_score_elf_check_relocs (bfd *abfd, + struct bfd_link_info *info, + asection *sec, + const Elf_Internal_Rela *relocs) +{ + if (bfd_get_mach (abfd) == bfd_mach_score3) + return s3_bfd_score_elf_check_relocs (abfd, info, sec, relocs); + else + return s7_bfd_score_elf_check_relocs (abfd, info, sec, relocs); +} + +static bfd_boolean +_bfd_score_elf_add_symbol_hook (bfd *abfd, + struct bfd_link_info *info ATTRIBUTE_UNUSED, + Elf_Internal_Sym *sym, + const char **namep ATTRIBUTE_UNUSED, + flagword *flagsp ATTRIBUTE_UNUSED, + asection **secp, + bfd_vma *valp) +{ + if (bfd_get_mach (abfd) == bfd_mach_score3) + return s3_bfd_score_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, + secp, valp); + else + return s7_bfd_score_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, + secp, valp); +} + +static void +_bfd_score_elf_symbol_processing (bfd *abfd, asymbol *asym) +{ + if (bfd_get_mach (abfd) == bfd_mach_score3) + return s3_bfd_score_elf_symbol_processing (abfd, asym); + else + return s7_bfd_score_elf_symbol_processing (abfd, asym); +} + +static bfd_boolean +_bfd_score_elf_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED, + const char *name ATTRIBUTE_UNUSED, + Elf_Internal_Sym *sym, + asection *input_sec, + struct elf_link_hash_entry *h ATTRIBUTE_UNUSED) +{ + /* If link a empty .o, then this filed is NULL. */ + if (info->input_bfds == NULL) + { + /* If we see a common symbol, which implies a relocatable link, then + if a symbol was small common in an input file, mark it as small + common in the output file. */ + if (sym->st_shndx == SHN_COMMON && strcmp (input_sec->name, ".scommon") == 0) + sym->st_shndx = SHN_SCORE_SCOMMON; + return TRUE; + } + + if (bfd_get_mach (info->input_bfds) == bfd_mach_score3) + return s3_bfd_score_elf_link_output_symbol_hook (info, name, sym, input_sec, h); + else + return s7_bfd_score_elf_link_output_symbol_hook (info, name, sym, input_sec, h); +} + +static bfd_boolean +_bfd_score_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED, + asection *sec, + int *retval) +{ + if (bfd_get_mach (abfd) == bfd_mach_score3) + return s3_bfd_score_elf_section_from_bfd_section (abfd, sec, retval); + else + return s7_bfd_score_elf_section_from_bfd_section (abfd, sec, retval); +} + +static bfd_boolean +_bfd_score_elf_adjust_dynamic_symbol (struct bfd_link_info *info, + struct elf_link_hash_entry *h) +{ + if (bfd_get_mach (info->input_bfds) == bfd_mach_score3) + return s3_bfd_score_elf_adjust_dynamic_symbol (info, h); + else + return s7_bfd_score_elf_adjust_dynamic_symbol (info, h); +} + +static bfd_boolean +_bfd_score_elf_always_size_sections (bfd *output_bfd, + struct bfd_link_info *info) +{ + if (bfd_get_mach (output_bfd) == bfd_mach_score3) + return s3_bfd_score_elf_always_size_sections (output_bfd, info); + else + return s7_bfd_score_elf_always_size_sections (output_bfd, info); +} + +static bfd_boolean +_bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) +{ + if (bfd_get_mach (output_bfd) == bfd_mach_score3) + return s3_bfd_score_elf_size_dynamic_sections (output_bfd, info); + else + return s7_bfd_score_elf_size_dynamic_sections (output_bfd, info); +} + +static bfd_boolean +_bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) +{ + if (bfd_get_mach (abfd) == bfd_mach_score3) + return s3_bfd_score_elf_create_dynamic_sections (abfd, info); + else + return s7_bfd_score_elf_create_dynamic_sections (abfd, info); +} + +static bfd_boolean +_bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd, + struct bfd_link_info *info, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym) +{ + if (bfd_get_mach (output_bfd) == bfd_mach_score3) + return s3_bfd_score_elf_finish_dynamic_symbol (output_bfd, info, h, sym); + else + return s7_bfd_score_elf_finish_dynamic_symbol (output_bfd, info, h, sym); +} + +static bfd_boolean +_bfd_score_elf_finish_dynamic_sections (bfd *output_bfd, + struct bfd_link_info *info) +{ + if (bfd_get_mach (output_bfd) == bfd_mach_score3) + return s3_bfd_score_elf_finish_dynamic_sections (output_bfd, info); + else + return s7_bfd_score_elf_finish_dynamic_sections (output_bfd, info); +} + +static bfd_boolean +_bfd_score_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, + Elf_Internal_Shdr *hdr, + asection *sec) +{ + if (bfd_get_mach (abfd) == bfd_mach_score3) + return s3_bfd_score_elf_fake_sections (abfd, hdr, sec); + else + return s7_bfd_score_elf_fake_sections (abfd, hdr, sec); +} + +static bfd_boolean +_bfd_score_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Shdr *hdr) +{ + if (bfd_get_mach (abfd) == bfd_mach_score3) + return s3_bfd_score_elf_section_processing (abfd, hdr); + else + return s7_bfd_score_elf_section_processing (abfd, hdr); +} + +static bfd_boolean +_bfd_score_elf_write_section (bfd *output_bfd, + struct bfd_link_info *link_info ATTRIBUTE_UNUSED, + asection *sec, bfd_byte *contents) +{ + if (bfd_get_mach (output_bfd) == bfd_mach_score3) + return s3_bfd_score_elf_write_section (output_bfd, sec, contents); + else + return s7_bfd_score_elf_write_section (output_bfd, sec, contents); +} + +static void +_bfd_score_elf_copy_indirect_symbol (struct bfd_link_info *info, + struct elf_link_hash_entry *dir, + struct elf_link_hash_entry *ind) +{ + if (bfd_get_mach (info->input_bfds) == bfd_mach_score3) + return s3_bfd_score_elf_copy_indirect_symbol (info, dir, ind); + else + return s7_bfd_score_elf_copy_indirect_symbol (info, dir, ind); +} + +static void +_bfd_score_elf_hide_symbol (struct bfd_link_info *info, + struct elf_link_hash_entry *entry, + bfd_boolean force_local) +{ + if (bfd_get_mach (info->input_bfds) == bfd_mach_score3) + return s3_bfd_score_elf_hide_symbol (info, entry, force_local); + else + return s7_bfd_score_elf_hide_symbol (info, entry, force_local); +} + +static bfd_boolean +_bfd_score_elf_discard_info (bfd *abfd, struct elf_reloc_cookie *cookie, + struct bfd_link_info *info) +{ + if (bfd_get_mach (abfd) == bfd_mach_score3) + return s3_bfd_score_elf_discard_info (abfd, cookie, info); + else + return s7_bfd_score_elf_discard_info (abfd, cookie, info); +} + +static bfd_boolean +_bfd_score_elf_ignore_discarded_relocs (asection *sec) +{ + if (bfd_get_mach (sec->owner) == bfd_mach_score3) + return s3_bfd_score_elf_ignore_discarded_relocs (sec); + else + return s7_bfd_score_elf_ignore_discarded_relocs (sec); +} + +static asection * +_bfd_score_elf_gc_mark_hook (asection *sec, + struct bfd_link_info *info, + Elf_Internal_Rela *rel, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym) +{ + if (bfd_get_mach (info->input_bfds) == bfd_mach_score3) + return s3_bfd_score_elf_gc_mark_hook (sec, info, rel, h, sym); + else + return s7_bfd_score_elf_gc_mark_hook (sec, info, rel, h, sym); +} + +static bfd_boolean +_bfd_score_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) +{ + if (bfd_get_mach (abfd) == bfd_mach_score3) + return s3_bfd_score_elf_grok_prstatus (abfd, note); + else + return s7_bfd_score_elf_grok_prstatus (abfd, note); +} + +static bfd_boolean +_bfd_score_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) +{ + if (bfd_get_mach (abfd) == bfd_mach_score3) + return s3_bfd_score_elf_grok_psinfo (abfd, note); + else + return s7_bfd_score_elf_grok_psinfo (abfd, note); +} + +static reloc_howto_type * +elf32_score_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code) +{ + /* s3: NOTE!!! + gas will call elf32_score_reloc_type_lookup, and don't write elf file. + So just using score3, but we don't know ld will call this or not. + If so, this way can't work. */ + + if (score3) + return s3_elf32_score_reloc_type_lookup (abfd, code); + else + return s7_elf32_score_reloc_type_lookup (abfd, code); +} + +static struct bfd_link_hash_table * +elf32_score_link_hash_table_create (bfd *abfd) +{ + if (bfd_get_mach (abfd) == bfd_mach_score3) + return s3_elf32_score_link_hash_table_create (abfd); + else + return s7_elf32_score_link_hash_table_create (abfd); +} + +static bfd_boolean +elf32_score_print_private_bfd_data (bfd *abfd, void * ptr) +{ + if (bfd_get_mach (abfd) == bfd_mach_score3) + return s3_elf32_score_print_private_bfd_data (abfd, ptr); + else + return s7_elf32_score_print_private_bfd_data (abfd, ptr); +} + +static bfd_boolean +elf32_score_merge_private_bfd_data (bfd *ibfd, bfd *obfd) +{ + if (bfd_get_mach (obfd) == bfd_mach_score3) + return s3_elf32_score_merge_private_bfd_data (ibfd, obfd); + else + return s7_elf32_score_merge_private_bfd_data (ibfd, obfd); +} + +static bfd_boolean +elf32_score_new_section_hook (bfd *abfd, asection *sec) +{ + if (bfd_get_mach (abfd) == bfd_mach_score3) + return s3_elf32_score_new_section_hook (abfd, sec); + else + return s7_elf32_score_new_section_hook (abfd, sec); +} + + +/* s3_s7: don't need to split. */ + +/* Set the right machine number. */ +static bfd_boolean +_bfd_score_elf_score_object_p (bfd * abfd) +{ + int e_set = bfd_mach_score7; + + if (elf_elfheader (abfd)->e_machine == EM_SCORE) + { + int e_mach = elf_elfheader (abfd)->e_flags & EF_SCORE_MACH & EF_OMIT_PIC_FIXDD; + switch (e_mach) + { + /* Set default target is score7. */ + default: + case E_SCORE_MACH_SCORE7: + e_set = bfd_mach_score7; + break; + + case E_SCORE_MACH_SCORE3: + e_set = bfd_mach_score3; + break; + } + } + + return bfd_default_set_arch_mach (abfd, bfd_arch_score, e_set); +} + +bfd_boolean +_bfd_score_elf_common_definition (Elf_Internal_Sym *sym) +{ + return (sym->st_shndx == SHN_COMMON || sym->st_shndx == SHN_SCORE_SCOMMON); +} + +/*****************************************************************************/ + #define USE_REL 1 #define TARGET_LITTLE_SYM bfd_elf32_littlescore_vec @@ -3826,6 +4472,7 @@ elf32_score_new_section_hook (bfd *abfd, asection *sec) #define TARGET_BIG_NAME "elf32-bigscore" #define ELF_ARCH bfd_arch_score #define ELF_MACHINE_CODE EM_SCORE +#define ELF_MACHINE_ALT1 EM_SCORE_OLD #define ELF_MAXPAGESIZE 0x8000 #define elf_info_to_howto 0 @@ -3869,6 +4516,7 @@ elf32_score_new_section_hook (bfd *abfd, asection *sec) #define elf_backend_plt_header_size 0 #define elf_backend_collect TRUE #define elf_backend_type_change_ok TRUE +#define elf_backend_object_p _bfd_score_elf_score_object_p #define bfd_elf32_bfd_reloc_type_lookup elf32_score_reloc_type_lookup #define bfd_elf32_bfd_reloc_name_lookup \ diff --git a/bfd/elf32-score.h b/bfd/elf32-score.h new file mode 100644 index 00000000000..d842051f696 --- /dev/null +++ b/bfd/elf32-score.h @@ -0,0 +1,152 @@ +/* 32-bit ELF support for S+core. + Copyright 2009 Free Software Foundation, Inc. + Contributed by + Brain.lin (brain.lin@sunplusct.com) + Mei Ligang (ligang@sunnorth.com.cn) + Pei-Lin Tsai (pltsai@sunplus.com) + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "elf/common.h" +#include "elf/internal.h" + +extern void +s7_bfd_score_elf_hide_symbol (struct bfd_link_info *, + struct elf_link_hash_entry *, + bfd_boolean); + +extern void +s7_bfd_score_info_to_howto (bfd *, arelent *, Elf_Internal_Rela *); + +extern bfd_boolean +s7_bfd_score_elf_relocate_section (bfd *, + struct bfd_link_info *, + bfd *, + asection *, + bfd_byte *, + Elf_Internal_Rela *, + Elf_Internal_Sym *, + asection **); + +extern bfd_boolean +s7_bfd_score_elf_check_relocs (bfd *, + struct bfd_link_info *, + asection *, + const Elf_Internal_Rela *); + +extern bfd_boolean +s7_bfd_score_elf_add_symbol_hook (bfd *, + struct bfd_link_info *, + Elf_Internal_Sym *, + const char **, + flagword *, + asection **, + bfd_vma *); + +extern void +s7_bfd_score_elf_symbol_processing (bfd *, asymbol *); + +extern bfd_boolean +s7_bfd_score_elf_link_output_symbol_hook (struct bfd_link_info *, + const char *, + Elf_Internal_Sym *, + asection *, + struct elf_link_hash_entry *); + +extern bfd_boolean +s7_bfd_score_elf_section_from_bfd_section (bfd *, + asection *, + int *); + +extern bfd_boolean +s7_bfd_score_elf_adjust_dynamic_symbol (struct bfd_link_info *, + struct elf_link_hash_entry *); + +extern bfd_boolean +s7_bfd_score_elf_always_size_sections (bfd *, struct bfd_link_info *); + +extern bfd_boolean +s7_bfd_score_elf_size_dynamic_sections (bfd *, struct bfd_link_info *); + +extern bfd_boolean +s7_bfd_score_elf_create_dynamic_sections (bfd *, struct bfd_link_info *); + +extern bfd_boolean +s7_bfd_score_elf_finish_dynamic_symbol (bfd *, + struct bfd_link_info *, + struct elf_link_hash_entry *, + Elf_Internal_Sym *); + +extern bfd_boolean +s7_bfd_score_elf_finish_dynamic_sections (bfd *, struct bfd_link_info *); + +extern bfd_boolean +s7_bfd_score_elf_fake_sections (bfd *, + Elf_Internal_Shdr *, + asection *); + +extern bfd_boolean +s7_bfd_score_elf_section_processing (bfd *, Elf_Internal_Shdr *); + +extern bfd_boolean +s7_bfd_score_elf_write_section (bfd *, asection *, bfd_byte *); + +extern void +s7_bfd_score_elf_copy_indirect_symbol (struct bfd_link_info *, + struct elf_link_hash_entry *, + struct elf_link_hash_entry *); + +extern bfd_boolean +s7_bfd_score_elf_discard_info (bfd *, struct elf_reloc_cookie *, + struct bfd_link_info *); + +extern bfd_boolean +s7_bfd_score_elf_ignore_discarded_relocs (asection *); + +extern asection * +s7_bfd_score_elf_gc_mark_hook (asection *, + struct bfd_link_info *, + Elf_Internal_Rela *, + struct elf_link_hash_entry *, + Elf_Internal_Sym *); + +extern bfd_boolean +s7_bfd_score_elf_grok_prstatus (bfd *, Elf_Internal_Note *); + +extern bfd_boolean +s7_bfd_score_elf_grok_psinfo (bfd *, Elf_Internal_Note *); + +extern reloc_howto_type * +s7_elf32_score_reloc_type_lookup (bfd *, bfd_reloc_code_real_type); + +extern struct bfd_link_hash_table * +s7_elf32_score_link_hash_table_create (bfd *); + +extern bfd_boolean +s7_elf32_score_print_private_bfd_data (bfd *, void *); + +extern bfd_boolean +s7_elf32_score_merge_private_bfd_data (bfd *, bfd *); + +extern bfd_boolean +s7_elf32_score_new_section_hook (bfd *, asection *); + +extern bfd_boolean +_bfd_score_elf_common_definition (Elf_Internal_Sym *); + +#define elf_backend_common_definition _bfd_score_elf_common_definition diff --git a/bfd/elf32-score7.c b/bfd/elf32-score7.c new file mode 100644 index 00000000000..81d0dcb6941 --- /dev/null +++ b/bfd/elf32-score7.c @@ -0,0 +1,3947 @@ +/* 32-bit ELF support for S+core. + Copyright 2009 Free Software Foundation, Inc. + Contributed by + Brain.lin (brain.lin@sunplusct.com) + Mei Ligang (ligang@sunnorth.com.cn) + Pei-Lin Tsai (pltsai@sunplus.com) + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "bfd.h" +#include "sysdep.h" +#include "libbfd.h" +#include "libiberty.h" +#include "elf-bfd.h" +#include "elf/score.h" +#include "elf/common.h" +#include "elf/internal.h" +#include "hashtab.h" +#include "elf32-score.h" + + +/* Score ELF linker hash table. */ +struct score_elf_link_hash_table +{ + /* The main hash table. */ + struct elf_link_hash_table root; +}; + +/* The SCORE ELF linker needs additional information for each symbol in + the global hash table. */ +struct score_elf_link_hash_entry +{ + struct elf_link_hash_entry root; + + /* Number of R_SCORE_ABS32, R_SCORE_REL32 relocs against this symbol. */ + unsigned int possibly_dynamic_relocs; + + /* If the R_SCORE_ABS32, R_SCORE_REL32 reloc is against a readonly section. */ + bfd_boolean readonly_reloc; + + /* We must not create a stub for a symbol that has relocations related to + taking the function's address, i.e. any but R_SCORE_CALL15 ones. */ + bfd_boolean no_fn_stub; + + /* Are we forced local? This will only be set if we have converted + the initial global GOT entry to a local GOT entry. */ + bfd_boolean forced_local; +}; + +/* Traverse a score ELF linker hash table. */ +#define score_elf_link_hash_traverse(table, func, info) \ + (elf_link_hash_traverse \ + (&(table)->root, \ + (bfd_boolean (*) (struct elf_link_hash_entry *, void *)) (func), \ + (info))) + +/* Get the SCORE elf linker hash table from a link_info structure. */ +#define score_elf_hash_table(info) \ + ((struct score_elf_link_hash_table *) ((info)->hash)) + +/* This structure is used to hold .got entries while estimating got sizes. */ +struct score_got_entry +{ + /* The input bfd in which the symbol is defined. */ + bfd *abfd; + /* The index of the symbol, as stored in the relocation r_info, if + we have a local symbol; -1 otherwise. */ + long symndx; + union + { + /* If abfd == NULL, an address that must be stored in the got. */ + bfd_vma address; + /* If abfd != NULL && symndx != -1, the addend of the relocation + that should be added to the symbol value. */ + bfd_vma addend; + /* If abfd != NULL && symndx == -1, the hash table entry + corresponding to a global symbol in the got (or, local, if + h->forced_local). */ + struct score_elf_link_hash_entry *h; + } d; + + /* The offset from the beginning of the .got section to the entry + corresponding to this symbol+addend. If it's a global symbol + whose offset is yet to be decided, it's going to be -1. */ + long gotidx; +}; + +/* This structure is passed to score_elf_sort_hash_table_f when sorting + the dynamic symbols. */ +struct score_elf_hash_sort_data +{ + /* The symbol in the global GOT with the lowest dynamic symbol table index. */ + struct elf_link_hash_entry *low; + /* The least dynamic symbol table index corresponding to a symbol with a GOT entry. */ + long min_got_dynindx; + /* The greatest dynamic symbol table index corresponding to a symbol + with a GOT entry that is not referenced (e.g., a dynamic symbol + with dynamic relocations pointing to it from non-primary GOTs). */ + long max_unref_got_dynindx; + /* The greatest dynamic symbol table index not corresponding to a + symbol without a GOT entry. */ + long max_non_got_dynindx; +}; + +struct score_got_info +{ + /* The global symbol in the GOT with the lowest index in the dynamic + symbol table. */ + struct elf_link_hash_entry *global_gotsym; + /* The number of global .got entries. */ + unsigned int global_gotno; + /* The number of local .got entries. */ + unsigned int local_gotno; + /* The number of local .got entries we have used. */ + unsigned int assigned_gotno; + /* A hash table holding members of the got. */ + struct htab *got_entries; + /* In multi-got links, a pointer to the next got (err, rather, most + of the time, it points to the previous got). */ + struct score_got_info *next; +}; + +/* A structure used to count GOT entries, for GOT entry or ELF symbol table traversal. */ +struct _score_elf_section_data +{ + struct bfd_elf_section_data elf; + union + { + struct score_got_info *got_info; + bfd_byte *tdata; + } + u; +}; + +#define score_elf_section_data(sec) \ + ((struct _score_elf_section_data *) elf_section_data (sec)) + +/* The size of a symbol-table entry. */ +#define SCORE_ELF_SYM_SIZE(abfd) \ + (get_elf_backend_data (abfd)->s->sizeof_sym) + +/* In case we're on a 32-bit machine, construct a 64-bit "-1" value + from smaller values. Start with zero, widen, *then* decrement. */ +#define MINUS_ONE (((bfd_vma)0) - 1) +#define MINUS_TWO (((bfd_vma)0) - 2) + +#define PDR_SIZE 32 + + +/* The number of local .got entries we reserve. */ +#define SCORE_RESERVED_GOTNO (2) +#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1" + +/* The offset of $gp from the beginning of the .got section. */ +#define ELF_SCORE_GP_OFFSET(abfd) (0x3ff0) + +/* The maximum size of the GOT for it to be addressable using 15-bit offsets from $gp. */ +#define SCORE_ELF_GOT_MAX_SIZE(abfd) (ELF_SCORE_GP_OFFSET(abfd) + 0x3fff) + +#define SCORE_ELF_STUB_SECTION_NAME (".SCORE.stub") +#define SCORE_FUNCTION_STUB_SIZE (16) + +#define STUB_LW 0xc3bcc010 /* lw r29, [r28, -0x3ff0] */ +#define STUB_MOVE 0x8323bc56 /* mv r25, r3 */ +#define STUB_LI16 0x87548000 /* ori r26, .dynsym_index */ +#define STUB_BRL 0x801dbc09 /* brl r29 */ + +#define SCORE_ELF_GOT_SIZE(abfd) \ + (get_elf_backend_data (abfd)->s->arch_size / 8) + +#define SCORE_ELF_ADD_DYNAMIC_ENTRY(info, tag, val) \ + (_bfd_elf_add_dynamic_entry (info, (bfd_vma) tag, (bfd_vma) val)) + +/* The size of an external dynamic table entry. */ +#define SCORE_ELF_DYN_SIZE(abfd) \ + (get_elf_backend_data (abfd)->s->sizeof_dyn) + +/* The size of an external REL relocation. */ +#define SCORE_ELF_REL_SIZE(abfd) \ + (get_elf_backend_data (abfd)->s->sizeof_rel) + +/* The default alignment for sections, as a power of two. */ +#define SCORE_ELF_LOG_FILE_ALIGN(abfd)\ + (get_elf_backend_data (abfd)->s->log_file_align) + +static bfd_byte *hi16_rel_addr; + +/* This will be used when we sort the dynamic relocation records. */ +static bfd *reldyn_sorting_bfd; + +/* SCORE ELF uses two common sections. One is the usual one, and the + other is for small objects. All the small objects are kept + together, and then referenced via the gp pointer, which yields + faster assembler code. This is what we use for the small common + section. This approach is copied from ecoff.c. */ +static asection score_elf_scom_section; +static asymbol score_elf_scom_symbol; +static asymbol * score_elf_scom_symbol_ptr; + +static bfd_reloc_status_type +score_elf_hi16_reloc (bfd *abfd ATTRIBUTE_UNUSED, + arelent *reloc_entry, + asymbol *symbol ATTRIBUTE_UNUSED, + void * data, + asection *input_section ATTRIBUTE_UNUSED, + bfd *output_bfd ATTRIBUTE_UNUSED, + char **error_message ATTRIBUTE_UNUSED) +{ + hi16_rel_addr = (bfd_byte *) data + reloc_entry->address; + return bfd_reloc_ok; +} + +static bfd_reloc_status_type +score_elf_lo16_reloc (bfd *abfd, + arelent *reloc_entry, + asymbol *symbol ATTRIBUTE_UNUSED, + void * data, + asection *input_section, + bfd *output_bfd ATTRIBUTE_UNUSED, + char **error_message ATTRIBUTE_UNUSED) +{ + bfd_vma addend = 0, offset = 0; + unsigned long val; + unsigned long hi16_offset, hi16_value, uvalue; + + hi16_value = bfd_get_32 (abfd, hi16_rel_addr); + hi16_offset = ((((hi16_value >> 16) & 0x3) << 15) | (hi16_value & 0x7fff)) >> 1; + addend = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); + offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1; + val = reloc_entry->addend; + if (reloc_entry->address > input_section->size) + return bfd_reloc_outofrange; + uvalue = ((hi16_offset << 16) | (offset & 0xffff)) + val; + hi16_offset = (uvalue >> 16) << 1; + hi16_value = (hi16_value & ~0x37fff) | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000); + bfd_put_32 (abfd, hi16_value, hi16_rel_addr); + offset = (uvalue & 0xffff) << 1; + addend = (addend & ~0x37fff) | (offset & 0x7fff) | ((offset << 1) & 0x30000); + bfd_put_32 (abfd, addend, (bfd_byte *) data + reloc_entry->address); + return bfd_reloc_ok; +} + +/* Set the GP value for OUTPUT_BFD. Returns FALSE if this is a + dangerous relocation. */ + +static bfd_boolean +score_elf_assign_gp (bfd *output_bfd, bfd_vma *pgp) +{ + unsigned int count; + asymbol **sym; + unsigned int i; + + /* If we've already figured out what GP will be, just return it. */ + *pgp = _bfd_get_gp_value (output_bfd); + if (*pgp) + return TRUE; + + count = bfd_get_symcount (output_bfd); + sym = bfd_get_outsymbols (output_bfd); + + /* The linker script will have created a symbol named `_gp' with the + appropriate value. */ + if (sym == NULL) + i = count; + else + { + for (i = 0; i < count; i++, sym++) + { + const char *name; + + name = bfd_asymbol_name (*sym); + if (*name == '_' && strcmp (name, "_gp") == 0) + { + *pgp = bfd_asymbol_value (*sym); + _bfd_set_gp_value (output_bfd, *pgp); + break; + } + } + } + + if (i >= count) + { + /* Only get the error once. */ + *pgp = 4; + _bfd_set_gp_value (output_bfd, *pgp); + return FALSE; + } + + return TRUE; +} + +/* We have to figure out the gp value, so that we can adjust the + symbol value correctly. We look up the symbol _gp in the output + BFD. If we can't find it, we're stuck. We cache it in the ELF + target data. We don't need to adjust the symbol value for an + external symbol if we are producing relocatable output. */ + +static bfd_reloc_status_type +score_elf_final_gp (bfd *output_bfd, + asymbol *symbol, + bfd_boolean relocatable, + char **error_message, + bfd_vma *pgp) +{ + if (bfd_is_und_section (symbol->section) + && ! relocatable) + { + *pgp = 0; + return bfd_reloc_undefined; + } + + *pgp = _bfd_get_gp_value (output_bfd); + if (*pgp == 0 + && (! relocatable + || (symbol->flags & BSF_SECTION_SYM) != 0)) + { + if (relocatable) + { + /* Make up a value. */ + *pgp = symbol->section->output_section->vma + 0x4000; + _bfd_set_gp_value (output_bfd, *pgp); + } + else if (!score_elf_assign_gp (output_bfd, pgp)) + { + *error_message = + (char *) _("GP relative relocation when _gp not defined"); + return bfd_reloc_dangerous; + } + } + + return bfd_reloc_ok; +} + +static bfd_reloc_status_type +score_elf_gprel15_with_gp (bfd *abfd, + asymbol *symbol, + arelent *reloc_entry, + asection *input_section, + bfd_boolean relocateable, + void * data, + bfd_vma gp ATTRIBUTE_UNUSED) +{ + bfd_vma relocation; + unsigned long insn; + + if (bfd_is_com_section (symbol->section)) + relocation = 0; + else + relocation = symbol->value; + + relocation += symbol->section->output_section->vma; + relocation += symbol->section->output_offset; + if (reloc_entry->address > input_section->size) + return bfd_reloc_outofrange; + + insn = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); + if (((reloc_entry->addend & 0xffffc000) != 0) + && ((reloc_entry->addend & 0xffffc000) != 0xffffc000)) + return bfd_reloc_overflow; + + insn = (insn & ~0x7fff) | (reloc_entry->addend & 0x7fff); + bfd_put_32 (abfd, insn, (bfd_byte *) data + reloc_entry->address); + if (relocateable) + reloc_entry->address += input_section->output_offset; + + return bfd_reloc_ok; +} + +static bfd_reloc_status_type +gprel32_with_gp (bfd *abfd, asymbol *symbol, arelent *reloc_entry, + asection *input_section, bfd_boolean relocatable, + void *data, bfd_vma gp) +{ + bfd_vma relocation; + bfd_vma val; + + if (bfd_is_com_section (symbol->section)) + relocation = 0; + else + relocation = symbol->value; + + relocation += symbol->section->output_section->vma; + relocation += symbol->section->output_offset; + + if (reloc_entry->address > bfd_get_section_limit (abfd, input_section)) + return bfd_reloc_outofrange; + + /* Set val to the offset into the section or symbol. */ + val = reloc_entry->addend; + + if (reloc_entry->howto->partial_inplace) + val += bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); + + /* Adjust val for the final section location and GP value. If we + are producing relocatable output, we don't want to do this for + an external symbol. */ + if (! relocatable + || (symbol->flags & BSF_SECTION_SYM) != 0) + val += relocation - gp; + + if (reloc_entry->howto->partial_inplace) + bfd_put_32 (abfd, val, (bfd_byte *) data + reloc_entry->address); + else + reloc_entry->addend = val; + + if (relocatable) + reloc_entry->address += input_section->output_offset; + + return bfd_reloc_ok; +} + +static bfd_reloc_status_type +score_elf_gprel15_reloc (bfd *abfd, + arelent *reloc_entry, + asymbol *symbol, + void * data, + asection *input_section, + bfd *output_bfd, + char **error_message) +{ + bfd_boolean relocateable; + bfd_reloc_status_type ret; + bfd_vma gp; + + if (output_bfd != NULL + && (symbol->flags & BSF_SECTION_SYM) == 0 && reloc_entry->addend == 0) + { + reloc_entry->address += input_section->output_offset; + return bfd_reloc_ok; + } + if (output_bfd != NULL) + relocateable = TRUE; + else + { + relocateable = FALSE; + output_bfd = symbol->section->output_section->owner; + } + + ret = score_elf_final_gp (output_bfd, symbol, relocateable, error_message, &gp); + if (ret != bfd_reloc_ok) + return ret; + + return score_elf_gprel15_with_gp (abfd, symbol, reloc_entry, + input_section, relocateable, data, gp); +} + +/* Do a R_SCORE_GPREL32 relocation. This is a 32 bit value which must + become the offset from the gp register. */ + +static bfd_reloc_status_type +score_elf_gprel32_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, + void *data, asection *input_section, bfd *output_bfd, + char **error_message) +{ + bfd_boolean relocatable; + bfd_reloc_status_type ret; + bfd_vma gp; + + /* R_SCORE_GPREL32 relocations are defined for local symbols only. */ + if (output_bfd != NULL + && (symbol->flags & BSF_SECTION_SYM) == 0 + && (symbol->flags & BSF_LOCAL) != 0) + { + *error_message = (char *) + _("32bits gp relative relocation occurs for an external symbol"); + return bfd_reloc_outofrange; + } + + if (output_bfd != NULL) + relocatable = TRUE; + else + { + relocatable = FALSE; + output_bfd = symbol->section->output_section->owner; + } + + ret = score_elf_final_gp (output_bfd, symbol, relocatable, error_message, &gp); + if (ret != bfd_reloc_ok) + return ret; + + gp = 0; + return gprel32_with_gp (abfd, symbol, reloc_entry, input_section, + relocatable, data, gp); +} + +/* A howto special_function for R_SCORE_GOT15 relocations. This is just + like any other 16-bit relocation when applied to global symbols, but is + treated in the same as R_SCORE_HI16 when applied to local symbols. */ + +static bfd_reloc_status_type +score_elf_got15_reloc (bfd *abfd, arelent *reloc_entry, asymbol *symbol, + void *data, asection *input_section, + bfd *output_bfd, char **error_message) +{ + if ((symbol->flags & (BSF_GLOBAL | BSF_WEAK)) != 0 + || bfd_is_und_section (bfd_get_section (symbol)) + || bfd_is_com_section (bfd_get_section (symbol))) + /* The relocation is against a global symbol. */ + return bfd_elf_generic_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, + error_message); + + return score_elf_hi16_reloc (abfd, reloc_entry, symbol, data, + input_section, output_bfd, error_message); +} + +static bfd_reloc_status_type +score_elf_got_lo16_reloc (bfd *abfd, + arelent *reloc_entry, + asymbol *symbol ATTRIBUTE_UNUSED, + void * data, + asection *input_section, + bfd *output_bfd ATTRIBUTE_UNUSED, + char **error_message ATTRIBUTE_UNUSED) +{ + bfd_vma addend = 0, offset = 0; + signed long val; + signed long hi16_offset, hi16_value, uvalue; + + hi16_value = bfd_get_32 (abfd, hi16_rel_addr); + hi16_offset = ((((hi16_value >> 16) & 0x3) << 15) | (hi16_value & 0x7fff)) >> 1; + addend = bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address); + offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1; + val = reloc_entry->addend; + if (reloc_entry->address > input_section->size) + return bfd_reloc_outofrange; + uvalue = ((hi16_offset << 16) | (offset & 0xffff)) + val; + if ((uvalue > -0x8000) && (uvalue < 0x7fff)) + hi16_offset = 0; + else + hi16_offset = (uvalue >> 16) & 0x7fff; + hi16_value = (hi16_value & ~0x37fff) | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000); + bfd_put_32 (abfd, hi16_value, hi16_rel_addr); + offset = (uvalue & 0xffff) << 1; + addend = (addend & ~0x37fff) | (offset & 0x7fff) | ((offset << 1) & 0x30000); + bfd_put_32 (abfd, addend, (bfd_byte *) data + reloc_entry->address); + return bfd_reloc_ok; +} + +static reloc_howto_type elf32_score_howto_table[] = +{ + /* No relocation. */ + HOWTO (R_SCORE_NONE, /* type */ + 0, /* rightshift */ + 0, /* size (0 = byte, 1 = short, 2 = long) */ + 0, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_SCORE_NONE", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* R_SCORE_HI16 */ + HOWTO (R_SCORE_HI16, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 1, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + score_elf_hi16_reloc, /* special_function */ + "R_SCORE_HI16", /* name */ + TRUE, /* partial_inplace */ + 0x37fff, /* src_mask */ + 0x37fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* R_SCORE_LO16 */ + HOWTO (R_SCORE_LO16, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 1, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + score_elf_lo16_reloc, /* special_function */ + "R_SCORE_LO16", /* name */ + TRUE, /* partial_inplace */ + 0x37fff, /* src_mask */ + 0x37fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* R_SCORE_BCMP */ + HOWTO (R_SCORE_BCMP, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 1, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_SCORE_BCMP", /* name */ + TRUE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + HOWTO (R_SCORE_24, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 24, /* bitsize */ + FALSE, /* pc_relative */ + 1, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_SCORE_24", /* name */ + FALSE, /* partial_inplace */ + 0x3ff7fff, /* src_mask */ + 0x3ff7fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /*R_SCORE_PC19 */ + HOWTO (R_SCORE_PC19, /* type */ + 1, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 19, /* bitsize */ + TRUE, /* pc_relative */ + 1, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_SCORE_PC19", /* name */ + FALSE, /* partial_inplace */ + 0x3ff03fe, /* src_mask */ + 0x3ff03fe, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /*R_SCORE16_11 */ + HOWTO (R_SCORE16_11, /* type */ + 1, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 11, /* bitsize */ + FALSE, /* pc_relative */ + 1, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_SCORE16_11", /* name */ + FALSE, /* partial_inplace */ + 0x000000ffe, /* src_mask */ + 0x000000ffe, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* R_SCORE16_PC8 */ + HOWTO (R_SCORE16_PC8, /* type */ + 1, /* rightshift */ + 1, /* size (0 = byte, 1 = short, 2 = long) */ + 8, /* bitsize */ + TRUE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_SCORE16_PC8", /* name */ + FALSE, /* partial_inplace */ + 0x000000ff, /* src_mask */ + 0x000000ff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 32 bit absolute */ + HOWTO (R_SCORE_ABS32, /* type 8 */ + 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_SCORE_ABS32", /* name */ + FALSE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 16 bit absolute */ + HOWTO (R_SCORE_ABS16, /* type 11 */ + 0, /* rightshift */ + 1, /* 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_SCORE_ABS16", /* name */ + FALSE, /* partial_inplace */ + 0x0000ffff, /* src_mask */ + 0x0000ffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* R_SCORE_DUMMY2 */ + HOWTO (R_SCORE_DUMMY2, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_SCORE_DUMMY2", /* name */ + TRUE, /* partial_inplace */ + 0x00007fff, /* src_mask */ + 0x00007fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* R_SCORE_GP15 */ + HOWTO (R_SCORE_GP15, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + score_elf_gprel15_reloc,/* special_function */ + "R_SCORE_GP15", /* name */ + TRUE, /* partial_inplace */ + 0x00007fff, /* src_mask */ + 0x00007fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* GNU extension to record C++ vtable hierarchy. */ + HOWTO (R_SCORE_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_SCORE_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_SCORE_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_SCORE_GNU_VTENTRY", /* name */ + FALSE, /* partial_inplace */ + 0, /* src_mask */ + 0, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Reference to global offset table. */ + HOWTO (R_SCORE_GOT15, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + score_elf_got15_reloc, /* special_function */ + "R_SCORE_GOT15", /* name */ + TRUE, /* partial_inplace */ + 0x00007fff, /* src_mask */ + 0x00007fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* Low 16 bits of displacement in global offset table. */ + HOWTO (R_SCORE_GOT_LO16, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 1, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + score_elf_got_lo16_reloc, /* special_function */ + "R_SCORE_GOT_LO16", /* name */ + TRUE, /* partial_inplace */ + 0x37ffe, /* src_mask */ + 0x37ffe, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 15 bit call through global offset table. */ + HOWTO (R_SCORE_CALL15, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_signed, /* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_SCORE_CALL15", /* name */ + TRUE, /* partial_inplace */ + 0x00007fff, /* src_mask */ + 0x00007fff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 32 bit GP relative reference. */ + HOWTO (R_SCORE_GPREL32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + score_elf_gprel32_reloc, /* special_function */ + "R_SCORE_GPREL32", /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* 32 bit symbol relative relocation. */ + HOWTO (R_SCORE_REL32, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 32, /* bitsize */ + FALSE, /* pc_relative */ + 0, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + bfd_elf_generic_reloc, /* special_function */ + "R_SCORE_REL32", /* name */ + TRUE, /* partial_inplace */ + 0xffffffff, /* src_mask */ + 0xffffffff, /* dst_mask */ + FALSE), /* pcrel_offset */ + + /* R_SCORE_DUMMY_HI16 */ + HOWTO (R_SCORE_DUMMY_HI16, /* type */ + 0, /* rightshift */ + 2, /* size (0 = byte, 1 = short, 2 = long) */ + 16, /* bitsize */ + FALSE, /* pc_relative */ + 1, /* bitpos */ + complain_overflow_dont,/* complain_on_overflow */ + score_elf_hi16_reloc, /* special_function */ + "R_SCORE_DUMMY_HI16", /* name */ + TRUE, /* partial_inplace */ + 0x37fff, /* src_mask */ + 0x37fff, /* dst_mask */ + FALSE), /* pcrel_offset */ +}; + +struct score_reloc_map +{ + bfd_reloc_code_real_type bfd_reloc_val; + unsigned char elf_reloc_val; +}; + +static const struct score_reloc_map elf32_score_reloc_map[] = +{ + {BFD_RELOC_NONE, R_SCORE_NONE}, + {BFD_RELOC_HI16_S, R_SCORE_HI16}, + {BFD_RELOC_LO16, R_SCORE_LO16}, + {BFD_RELOC_SCORE_BCMP, R_SCORE_BCMP}, + {BFD_RELOC_SCORE_JMP, R_SCORE_24}, + {BFD_RELOC_SCORE_BRANCH, R_SCORE_PC19}, + {BFD_RELOC_SCORE16_JMP, R_SCORE16_11}, + {BFD_RELOC_SCORE16_BRANCH, R_SCORE16_PC8}, + {BFD_RELOC_32, R_SCORE_ABS32}, + {BFD_RELOC_16, R_SCORE_ABS16}, + {BFD_RELOC_SCORE_DUMMY2, R_SCORE_DUMMY2}, + {BFD_RELOC_SCORE_GPREL15, R_SCORE_GP15}, + {BFD_RELOC_VTABLE_INHERIT, R_SCORE_GNU_VTINHERIT}, + {BFD_RELOC_VTABLE_ENTRY, R_SCORE_GNU_VTENTRY}, + {BFD_RELOC_SCORE_GOT15, R_SCORE_GOT15}, + {BFD_RELOC_SCORE_GOT_LO16, R_SCORE_GOT_LO16}, + {BFD_RELOC_SCORE_CALL15, R_SCORE_CALL15}, + {BFD_RELOC_GPREL32, R_SCORE_GPREL32}, + {BFD_RELOC_32_PCREL, R_SCORE_REL32}, + {BFD_RELOC_SCORE_DUMMY_HI16, R_SCORE_DUMMY_HI16}, +}; + +static INLINE hashval_t +score_elf_hash_bfd_vma (bfd_vma addr) +{ +#ifdef BFD64 + return addr + (addr >> 32); +#else + return addr; +#endif +} + +/* got_entries only match if they're identical, except for gotidx, so + use all fields to compute the hash, and compare the appropriate + union members. */ + +static hashval_t +score_elf_got_entry_hash (const void *entry_) +{ + const struct score_got_entry *entry = (struct score_got_entry *) entry_; + + return entry->symndx + + (! entry->abfd ? score_elf_hash_bfd_vma (entry->d.address) + : entry->abfd->id + + (entry->symndx >= 0 ? score_elf_hash_bfd_vma (entry->d.addend) + : entry->d.h->root.root.root.hash)); +} + +static int +score_elf_got_entry_eq (const void *entry1, const void *entry2) +{ + const struct score_got_entry *e1 = (struct score_got_entry *) entry1; + const struct score_got_entry *e2 = (struct score_got_entry *) entry2; + + return e1->abfd == e2->abfd && e1->symndx == e2->symndx + && (! e1->abfd ? e1->d.address == e2->d.address + : e1->symndx >= 0 ? e1->d.addend == e2->d.addend + : e1->d.h == e2->d.h); +} + +/* If H needs a GOT entry, assign it the highest available dynamic + index. Otherwise, assign it the lowest available dynamic + index. */ + +static bfd_boolean +score_elf_sort_hash_table_f (struct score_elf_link_hash_entry *h, void *data) +{ + struct score_elf_hash_sort_data *hsd = data; + + if (h->root.root.type == bfd_link_hash_warning) + h = (struct score_elf_link_hash_entry *) h->root.root.u.i.link; + + /* Symbols without dynamic symbol table entries aren't interesting at all. */ + if (h->root.dynindx == -1) + return TRUE; + + /* Global symbols that need GOT entries that are not explicitly + referenced are marked with got offset 2. Those that are + referenced get a 1, and those that don't need GOT entries get + -1. */ + if (h->root.got.offset == 2) + { + if (hsd->max_unref_got_dynindx == hsd->min_got_dynindx) + hsd->low = (struct elf_link_hash_entry *) h; + h->root.dynindx = hsd->max_unref_got_dynindx++; + } + else if (h->root.got.offset != 1) + h->root.dynindx = hsd->max_non_got_dynindx++; + else + { + h->root.dynindx = --hsd->min_got_dynindx; + hsd->low = (struct elf_link_hash_entry *) h; + } + + return TRUE; +} + +static asection * +score_elf_got_section (bfd *abfd, bfd_boolean maybe_excluded) +{ + asection *sgot = bfd_get_section_by_name (abfd, ".got"); + + if (sgot == NULL || (! maybe_excluded && (sgot->flags & SEC_EXCLUDE) != 0)) + return NULL; + return sgot; +} + +/* Returns the GOT information associated with the link indicated by + INFO. If SGOTP is non-NULL, it is filled in with the GOT section. */ + +static struct score_got_info * +score_elf_got_info (bfd *abfd, asection **sgotp) +{ + asection *sgot; + struct score_got_info *g; + + sgot = score_elf_got_section (abfd, TRUE); + BFD_ASSERT (sgot != NULL); + BFD_ASSERT (elf_section_data (sgot) != NULL); + g = score_elf_section_data (sgot)->u.got_info; + BFD_ASSERT (g != NULL); + + if (sgotp) + *sgotp = sgot; + return g; +} + +/* Sort the dynamic symbol table so that symbols that need GOT entries + appear towards the end. This reduces the amount of GOT space + required. MAX_LOCAL is used to set the number of local symbols + known to be in the dynamic symbol table. During + s7_bfd_score_elf_size_dynamic_sections, this value is 1. Afterward, the + section symbols are added and the count is higher. */ + +static bfd_boolean +score_elf_sort_hash_table (struct bfd_link_info *info, + unsigned long max_local) +{ + struct score_elf_hash_sort_data hsd; + struct score_got_info *g; + bfd *dynobj; + + dynobj = elf_hash_table (info)->dynobj; + + g = score_elf_got_info (dynobj, NULL); + + hsd.low = NULL; + hsd.max_unref_got_dynindx = + hsd.min_got_dynindx = elf_hash_table (info)->dynsymcount + /* In the multi-got case, assigned_gotno of the master got_info + indicate the number of entries that aren't referenced in the + primary GOT, but that must have entries because there are + dynamic relocations that reference it. Since they aren't + referenced, we move them to the end of the GOT, so that they + don't prevent other entries that are referenced from getting + too large offsets. */ + - (g->next ? g->assigned_gotno : 0); + hsd.max_non_got_dynindx = max_local; + score_elf_link_hash_traverse (((struct score_elf_link_hash_table *) + elf_hash_table (info)), + score_elf_sort_hash_table_f, + &hsd); + + /* There should have been enough room in the symbol table to + accommodate both the GOT and non-GOT symbols. */ + BFD_ASSERT (hsd.max_non_got_dynindx <= hsd.min_got_dynindx); + BFD_ASSERT ((unsigned long) hsd.max_unref_got_dynindx + <= elf_hash_table (info)->dynsymcount); + + /* Now we know which dynamic symbol has the lowest dynamic symbol + table index in the GOT. */ + g->global_gotsym = hsd.low; + + return TRUE; +} + +/* Create an entry in an score ELF linker hash table. */ + +static struct bfd_hash_entry * +score_elf_link_hash_newfunc (struct bfd_hash_entry *entry, + struct bfd_hash_table *table, + const char *string) +{ + struct score_elf_link_hash_entry *ret = (struct score_elf_link_hash_entry *) entry; + + /* Allocate the structure if it has not already been allocated by a subclass. */ + if (ret == NULL) + ret = bfd_hash_allocate (table, sizeof (struct score_elf_link_hash_entry)); + if (ret == NULL) + return (struct bfd_hash_entry *) ret; + + /* Call the allocation method of the superclass. */ + ret = ((struct score_elf_link_hash_entry *) + _bfd_elf_link_hash_newfunc ((struct bfd_hash_entry *) ret, table, string)); + + if (ret != NULL) + { + ret->possibly_dynamic_relocs = 0; + ret->readonly_reloc = FALSE; + ret->no_fn_stub = FALSE; + ret->forced_local = FALSE; + } + + return (struct bfd_hash_entry *) ret; +} + +/* Returns the first relocation of type r_type found, beginning with + RELOCATION. RELEND is one-past-the-end of the relocation table. */ + +static const Elf_Internal_Rela * +score_elf_next_relocation (bfd *abfd ATTRIBUTE_UNUSED, unsigned int r_type, + const Elf_Internal_Rela *relocation, + const Elf_Internal_Rela *relend) +{ + while (relocation < relend) + { + if (ELF32_R_TYPE (relocation->r_info) == r_type) + return relocation; + + ++relocation; + } + + /* We didn't find it. */ + bfd_set_error (bfd_error_bad_value); + return NULL; +} + +/* This function is called via qsort() to sort the dynamic relocation + entries by increasing r_symndx value. */ +static int +score_elf_sort_dynamic_relocs (const void *arg1, const void *arg2) +{ + Elf_Internal_Rela int_reloc1; + Elf_Internal_Rela int_reloc2; + + bfd_elf32_swap_reloc_in (reldyn_sorting_bfd, arg1, &int_reloc1); + bfd_elf32_swap_reloc_in (reldyn_sorting_bfd, arg2, &int_reloc2); + + return (ELF32_R_SYM (int_reloc1.r_info) - ELF32_R_SYM (int_reloc2.r_info)); +} + +/* Return whether a relocation is against a local symbol. */ +static bfd_boolean +score_elf_local_relocation_p (bfd *input_bfd, + const Elf_Internal_Rela *relocation, + asection **local_sections, + bfd_boolean check_forced) +{ + unsigned long r_symndx; + Elf_Internal_Shdr *symtab_hdr; + struct score_elf_link_hash_entry *h; + size_t extsymoff; + + r_symndx = ELF32_R_SYM (relocation->r_info); + symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; + extsymoff = (elf_bad_symtab (input_bfd)) ? 0 : symtab_hdr->sh_info; + + if (r_symndx < extsymoff) + return TRUE; + if (elf_bad_symtab (input_bfd) && local_sections[r_symndx] != NULL) + return TRUE; + + if (check_forced) + { + /* Look up the hash table to check whether the symbol was forced local. */ + h = (struct score_elf_link_hash_entry *) + elf_sym_hashes (input_bfd) [r_symndx - extsymoff]; + /* Find the real hash-table entry for this symbol. */ + while (h->root.root.type == bfd_link_hash_indirect + || h->root.root.type == bfd_link_hash_warning) + h = (struct score_elf_link_hash_entry *) h->root.root.u.i.link; + if (h->root.forced_local) + return TRUE; + } + + return FALSE; +} + +/* Returns the dynamic relocation section for DYNOBJ. */ + +static asection * +score_elf_rel_dyn_section (bfd *dynobj, bfd_boolean create_p) +{ + static const char dname[] = ".rel.dyn"; + asection *sreloc; + + sreloc = bfd_get_section_by_name (dynobj, dname); + if (sreloc == NULL && create_p) + { + sreloc = bfd_make_section_with_flags (dynobj, dname, + (SEC_ALLOC + | SEC_LOAD + | SEC_HAS_CONTENTS + | SEC_IN_MEMORY + | SEC_LINKER_CREATED + | SEC_READONLY)); + if (sreloc == NULL + || ! bfd_set_section_alignment (dynobj, sreloc, + SCORE_ELF_LOG_FILE_ALIGN (dynobj))) + return NULL; + } + return sreloc; +} + +static void +score_elf_allocate_dynamic_relocations (bfd *abfd, unsigned int n) +{ + asection *s; + + s = score_elf_rel_dyn_section (abfd, FALSE); + BFD_ASSERT (s != NULL); + + if (s->size == 0) + { + /* Make room for a null element. */ + s->size += SCORE_ELF_REL_SIZE (abfd); + ++s->reloc_count; + } + s->size += n * SCORE_ELF_REL_SIZE (abfd); +} + +/* Create a rel.dyn relocation for the dynamic linker to resolve. REL + is the original relocation, which is now being transformed into a + dynamic relocation. The ADDENDP is adjusted if necessary; the + caller should store the result in place of the original addend. */ + +static bfd_boolean +score_elf_create_dynamic_relocation (bfd *output_bfd, + struct bfd_link_info *info, + const Elf_Internal_Rela *rel, + struct score_elf_link_hash_entry *h, + bfd_vma symbol, + bfd_vma *addendp, asection *input_section) +{ + Elf_Internal_Rela outrel[3]; + asection *sreloc; + bfd *dynobj; + int r_type; + long indx; + bfd_boolean defined_p; + + r_type = ELF32_R_TYPE (rel->r_info); + dynobj = elf_hash_table (info)->dynobj; + sreloc = score_elf_rel_dyn_section (dynobj, FALSE); + BFD_ASSERT (sreloc != NULL); + BFD_ASSERT (sreloc->contents != NULL); + BFD_ASSERT (sreloc->reloc_count * SCORE_ELF_REL_SIZE (output_bfd) < sreloc->size); + + outrel[0].r_offset = + _bfd_elf_section_offset (output_bfd, info, input_section, rel[0].r_offset); + outrel[1].r_offset = + _bfd_elf_section_offset (output_bfd, info, input_section, rel[1].r_offset); + outrel[2].r_offset = + _bfd_elf_section_offset (output_bfd, info, input_section, rel[2].r_offset); + + if (outrel[0].r_offset == MINUS_ONE) + /* The relocation field has been deleted. */ + return TRUE; + + if (outrel[0].r_offset == MINUS_TWO) + { + /* The relocation field has been converted into a relative value of + some sort. Functions like _bfd_elf_write_section_eh_frame expect + the field to be fully relocated, so add in the symbol's value. */ + *addendp += symbol; + return TRUE; + } + + /* We must now calculate the dynamic symbol table index to use + in the relocation. */ + if (h != NULL + && (! info->symbolic || !h->root.def_regular) + /* h->root.dynindx may be -1 if this symbol was marked to + become local. */ + && h->root.dynindx != -1) + { + indx = h->root.dynindx; + /* ??? glibc's ld.so just adds the final GOT entry to the + relocation field. It therefore treats relocs against + defined symbols in the same way as relocs against + undefined symbols. */ + defined_p = FALSE; + } + else + { + indx = 0; + defined_p = TRUE; + } + + /* If the relocation was previously an absolute relocation and + this symbol will not be referred to by the relocation, we must + adjust it by the value we give it in the dynamic symbol table. + Otherwise leave the job up to the dynamic linker. */ + if (defined_p && r_type != R_SCORE_REL32) + *addendp += symbol; + + /* The relocation is always an REL32 relocation because we don't + know where the shared library will wind up at load-time. */ + outrel[0].r_info = ELF32_R_INFO ((unsigned long) indx, R_SCORE_REL32); + + /* For strict adherence to the ABI specification, we should + generate a R_SCORE_64 relocation record by itself before the + _REL32/_64 record as well, such that the addend is read in as + a 64-bit value (REL32 is a 32-bit relocation, after all). + However, since none of the existing ELF64 SCORE dynamic + loaders seems to care, we don't waste space with these + artificial relocations. If this turns out to not be true, + score_elf_allocate_dynamic_relocations() should be tweaked so + as to make room for a pair of dynamic relocations per + invocation if ABI_64_P, and here we should generate an + additional relocation record with R_SCORE_64 by itself for a + NULL symbol before this relocation record. */ + outrel[1].r_info = ELF32_R_INFO (0, R_SCORE_NONE); + outrel[2].r_info = ELF32_R_INFO (0, R_SCORE_NONE); + + /* Adjust the output offset of the relocation to reference the + correct location in the output file. */ + outrel[0].r_offset += (input_section->output_section->vma + + input_section->output_offset); + outrel[1].r_offset += (input_section->output_section->vma + + input_section->output_offset); + outrel[2].r_offset += (input_section->output_section->vma + + input_section->output_offset); + + /* Put the relocation back out. We have to use the special + relocation outputter in the 64-bit case since the 64-bit + relocation format is non-standard. */ + bfd_elf32_swap_reloc_out + (output_bfd, &outrel[0], + (sreloc->contents + sreloc->reloc_count * sizeof (Elf32_External_Rel))); + + /* We've now added another relocation. */ + ++sreloc->reloc_count; + + /* Make sure the output section is writable. The dynamic linker + will be writing to it. */ + elf_section_data (input_section->output_section)->this_hdr.sh_flags |= SHF_WRITE; + + return TRUE; +} + +static bfd_boolean +score_elf_create_got_section (bfd *abfd, + struct bfd_link_info *info, + bfd_boolean maybe_exclude) +{ + flagword flags; + asection *s; + struct elf_link_hash_entry *h; + struct bfd_link_hash_entry *bh; + struct score_got_info *g; + bfd_size_type amt; + + /* This function may be called more than once. */ + s = score_elf_got_section (abfd, TRUE); + if (s) + { + if (! maybe_exclude) + s->flags &= ~SEC_EXCLUDE; + return TRUE; + } + + flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); + + if (maybe_exclude) + flags |= SEC_EXCLUDE; + + /* We have to use an alignment of 2**4 here because this is hardcoded + in the function stub generation and in the linker script. */ + s = bfd_make_section_with_flags (abfd, ".got", flags); + if (s == NULL + || ! bfd_set_section_alignment (abfd, s, 4)) + return FALSE; + + /* Define the symbol _GLOBAL_OFFSET_TABLE_. We don't do this in the + linker script because we don't want to define the symbol if we + are not creating a global offset table. */ + bh = NULL; + if (! (_bfd_generic_link_add_one_symbol + (info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL, s, + 0, NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh))) + return FALSE; + + h = (struct elf_link_hash_entry *) bh; + h->non_elf = 0; + h->def_regular = 1; + h->type = STT_OBJECT; + + if (info->shared && ! bfd_elf_link_record_dynamic_symbol (info, h)) + return FALSE; + + amt = sizeof (struct score_got_info); + g = bfd_alloc (abfd, amt); + if (g == NULL) + return FALSE; + + g->global_gotsym = NULL; + g->global_gotno = 0; + + g->local_gotno = SCORE_RESERVED_GOTNO; + g->assigned_gotno = SCORE_RESERVED_GOTNO; + g->next = NULL; + + g->got_entries = htab_try_create (1, score_elf_got_entry_hash, + score_elf_got_entry_eq, NULL); + if (g->got_entries == NULL) + return FALSE; + score_elf_section_data (s)->u.got_info = g; + score_elf_section_data (s)->elf.this_hdr.sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_SCORE_GPREL; + + return TRUE; +} + +/* Calculate the %high function. */ + +static bfd_vma +score_elf_high (bfd_vma value) +{ + return ((value + (bfd_vma) 0x8000) >> 16) & 0xffff; +} + +/* Create a local GOT entry for VALUE. Return the index of the entry, + or -1 if it could not be created. */ + +static struct score_got_entry * +score_elf_create_local_got_entry (bfd *abfd, + bfd *ibfd ATTRIBUTE_UNUSED, + struct score_got_info *gg, + asection *sgot, bfd_vma value, + unsigned long r_symndx ATTRIBUTE_UNUSED, + struct score_elf_link_hash_entry *h ATTRIBUTE_UNUSED, + int r_type ATTRIBUTE_UNUSED) +{ + struct score_got_entry entry, **loc; + struct score_got_info *g; + + entry.abfd = NULL; + entry.symndx = -1; + entry.d.address = value; + + g = gg; + loc = (struct score_got_entry **) htab_find_slot (g->got_entries, &entry, INSERT); + if (*loc) + return *loc; + + entry.gotidx = SCORE_ELF_GOT_SIZE (abfd) * g->assigned_gotno++; + + *loc = bfd_alloc (abfd, sizeof entry); + + if (! *loc) + return NULL; + + memcpy (*loc, &entry, sizeof entry); + + if (g->assigned_gotno >= g->local_gotno) + { + (*loc)->gotidx = -1; + /* We didn't allocate enough space in the GOT. */ + (*_bfd_error_handler) + (_("not enough GOT space for local GOT entries")); + bfd_set_error (bfd_error_bad_value); + return NULL; + } + + bfd_put_32 (abfd, value, (sgot->contents + entry.gotidx)); + + return *loc; +} + +/* Find a GOT entry whose higher-order 16 bits are the same as those + for value. Return the index into the GOT for this entry. */ + +static bfd_vma +score_elf_got16_entry (bfd *abfd, bfd *ibfd, struct bfd_link_info *info, + bfd_vma value, bfd_boolean external) +{ + asection *sgot; + struct score_got_info *g; + struct score_got_entry *entry; + + if (!external) + { + /* Although the ABI says that it is "the high-order 16 bits" that we + want, it is really the %high value. The complete value is + calculated with a `addiu' of a LO16 relocation, just as with a + HI16/LO16 pair. */ + value = score_elf_high (value) << 16; + } + + g = score_elf_got_info (elf_hash_table (info)->dynobj, &sgot); + + entry = score_elf_create_local_got_entry (abfd, ibfd, g, sgot, value, 0, NULL, + R_SCORE_GOT15); + if (entry) + return entry->gotidx; + else + return MINUS_ONE; +} + +void +s7_bfd_score_elf_hide_symbol (struct bfd_link_info *info, + struct elf_link_hash_entry *entry, + bfd_boolean force_local) +{ + bfd *dynobj; + asection *got; + struct score_got_info *g; + struct score_elf_link_hash_entry *h; + + h = (struct score_elf_link_hash_entry *) entry; + if (h->forced_local) + return; + h->forced_local = TRUE; + + dynobj = elf_hash_table (info)->dynobj; + if (dynobj != NULL && force_local) + { + got = score_elf_got_section (dynobj, FALSE); + if (got == NULL) + return; + g = score_elf_section_data (got)->u.got_info; + + if (g->next) + { + struct score_got_entry e; + struct score_got_info *gg = g; + + /* Since we're turning what used to be a global symbol into a + local one, bump up the number of local entries of each GOT + that had an entry for it. This will automatically decrease + the number of global entries, since global_gotno is actually + the upper limit of global entries. */ + e.abfd = dynobj; + e.symndx = -1; + e.d.h = h; + + for (g = g->next; g != gg; g = g->next) + if (htab_find (g->got_entries, &e)) + { + BFD_ASSERT (g->global_gotno > 0); + g->local_gotno++; + g->global_gotno--; + } + + /* If this was a global symbol forced into the primary GOT, we + no longer need an entry for it. We can't release the entry + at this point, but we must at least stop counting it as one + of the symbols that required a forced got entry. */ + if (h->root.got.offset == 2) + { + BFD_ASSERT (gg->assigned_gotno > 0); + gg->assigned_gotno--; + } + } + else if (g->global_gotno == 0 && g->global_gotsym == NULL) + /* If we haven't got through GOT allocation yet, just bump up the + number of local entries, as this symbol won't be counted as + global. */ + g->local_gotno++; + else if (h->root.got.offset == 1) + { + /* If we're past non-multi-GOT allocation and this symbol had + been marked for a global got entry, give it a local entry + instead. */ + BFD_ASSERT (g->global_gotno > 0); + g->local_gotno++; + g->global_gotno--; + } + } + + _bfd_elf_link_hash_hide_symbol (info, &h->root, force_local); +} + +/* If H is a symbol that needs a global GOT entry, but has a dynamic + symbol table index lower than any we've seen to date, record it for + posterity. */ + +static bfd_boolean +score_elf_record_global_got_symbol (struct elf_link_hash_entry *h, + bfd *abfd, + struct bfd_link_info *info, + struct score_got_info *g) +{ + struct score_got_entry entry, **loc; + + /* A global symbol in the GOT must also be in the dynamic symbol table. */ + if (h->dynindx == -1) + { + switch (ELF_ST_VISIBILITY (h->other)) + { + case STV_INTERNAL: + case STV_HIDDEN: + s7_bfd_score_elf_hide_symbol (info, h, TRUE); + break; + } + if (!bfd_elf_link_record_dynamic_symbol (info, h)) + return FALSE; + } + + entry.abfd = abfd; + entry.symndx = -1; + entry.d.h = (struct score_elf_link_hash_entry *) h; + + loc = (struct score_got_entry **) htab_find_slot (g->got_entries, &entry, INSERT); + + /* If we've already marked this entry as needing GOT space, we don't + need to do it again. */ + if (*loc) + return TRUE; + + *loc = bfd_alloc (abfd, sizeof entry); + if (! *loc) + return FALSE; + + entry.gotidx = -1; + + memcpy (*loc, &entry, sizeof (entry)); + + if (h->got.offset != MINUS_ONE) + return TRUE; + + /* By setting this to a value other than -1, we are indicating that + there needs to be a GOT entry for H. Avoid using zero, as the + generic ELF copy_indirect_symbol tests for <= 0. */ + h->got.offset = 1; + + return TRUE; +} + +/* Reserve space in G for a GOT entry containing the value of symbol + SYMNDX in input bfd ABDF, plus ADDEND. */ + +static bfd_boolean +score_elf_record_local_got_symbol (bfd *abfd, + long symndx, + bfd_vma addend, + struct score_got_info *g) +{ + struct score_got_entry entry, **loc; + + entry.abfd = abfd; + entry.symndx = symndx; + entry.d.addend = addend; + loc = (struct score_got_entry **) htab_find_slot (g->got_entries, &entry, INSERT); + + if (*loc) + return TRUE; + + entry.gotidx = g->local_gotno++; + + *loc = bfd_alloc (abfd, sizeof(entry)); + if (! *loc) + return FALSE; + + memcpy (*loc, &entry, sizeof (entry)); + + return TRUE; +} + +/* Returns the GOT offset at which the indicated address can be found. + If there is not yet a GOT entry for this value, create one. + Returns -1 if no satisfactory GOT offset can be found. */ + +static bfd_vma +score_elf_local_got_index (bfd *abfd, bfd *ibfd, struct bfd_link_info *info, + bfd_vma value, unsigned long r_symndx, + struct score_elf_link_hash_entry *h, int r_type) +{ + asection *sgot; + struct score_got_info *g; + struct score_got_entry *entry; + + g = score_elf_got_info (elf_hash_table (info)->dynobj, &sgot); + + entry = score_elf_create_local_got_entry (abfd, ibfd, g, sgot, value, + r_symndx, h, r_type); + if (!entry) + return MINUS_ONE; + + else + return entry->gotidx; +} + +/* Returns the GOT index for the global symbol indicated by H. */ + +static bfd_vma +score_elf_global_got_index (bfd *abfd, struct elf_link_hash_entry *h) +{ + bfd_vma index; + asection *sgot; + struct score_got_info *g; + long global_got_dynindx = 0; + + g = score_elf_got_info (abfd, &sgot); + if (g->global_gotsym != NULL) + global_got_dynindx = g->global_gotsym->dynindx; + + /* Once we determine the global GOT entry with the lowest dynamic + symbol table index, we must put all dynamic symbols with greater + indices into the GOT. That makes it easy to calculate the GOT + offset. */ + BFD_ASSERT (h->dynindx >= global_got_dynindx); + index = ((h->dynindx - global_got_dynindx + g->local_gotno) * SCORE_ELF_GOT_SIZE (abfd)); + BFD_ASSERT (index < sgot->size); + + return index; +} + +/* Returns the offset for the entry at the INDEXth position in the GOT. */ + +static bfd_vma +score_elf_got_offset_from_index (bfd *dynobj, bfd *output_bfd, + bfd *input_bfd ATTRIBUTE_UNUSED, bfd_vma index) +{ + asection *sgot; + bfd_vma gp; + struct score_got_info *g; + + g = score_elf_got_info (dynobj, &sgot); + gp = _bfd_get_gp_value (output_bfd); + + return sgot->output_section->vma + sgot->output_offset + index - gp; +} + +/* Follow indirect and warning hash entries so that each got entry + points to the final symbol definition. P must point to a pointer + to the hash table we're traversing. Since this traversal may + modify the hash table, we set this pointer to NULL to indicate + we've made a potentially-destructive change to the hash table, so + the traversal must be restarted. */ + +static int +score_elf_resolve_final_got_entry (void **entryp, void *p) +{ + struct score_got_entry *entry = (struct score_got_entry *) *entryp; + htab_t got_entries = *(htab_t *) p; + + if (entry->abfd != NULL && entry->symndx == -1) + { + struct score_elf_link_hash_entry *h = entry->d.h; + + while (h->root.root.type == bfd_link_hash_indirect + || h->root.root.type == bfd_link_hash_warning) + h = (struct score_elf_link_hash_entry *) h->root.root.u.i.link; + + if (entry->d.h == h) + return 1; + + entry->d.h = h; + + /* If we can't find this entry with the new bfd hash, re-insert + it, and get the traversal restarted. */ + if (! htab_find (got_entries, entry)) + { + htab_clear_slot (got_entries, entryp); + entryp = htab_find_slot (got_entries, entry, INSERT); + if (! *entryp) + *entryp = entry; + /* Abort the traversal, since the whole table may have + moved, and leave it up to the parent to restart the + process. */ + *(htab_t *) p = NULL; + return 0; + } + /* We might want to decrement the global_gotno count, but it's + either too early or too late for that at this point. */ + } + + return 1; +} + +/* Turn indirect got entries in a got_entries table into their final locations. */ + +static void +score_elf_resolve_final_got_entries (struct score_got_info *g) +{ + htab_t got_entries; + + do + { + got_entries = g->got_entries; + + htab_traverse (got_entries, + score_elf_resolve_final_got_entry, + &got_entries); + } + while (got_entries == NULL); +} + +/* Add INCREMENT to the reloc (of type HOWTO) at ADDRESS. for -r */ + +static void +score_elf_add_to_rel (bfd *abfd, + bfd_byte *address, + reloc_howto_type *howto, + bfd_signed_vma increment) +{ + bfd_signed_vma addend; + bfd_vma contents; + unsigned long offset; + unsigned long r_type = howto->type; + unsigned long hi16_addend, hi16_offset, hi16_value, uvalue; + + contents = bfd_get_32 (abfd, address); + /* Get the (signed) value from the instruction. */ + addend = contents & howto->src_mask; + if (addend & ((howto->src_mask + 1) >> 1)) + { + bfd_signed_vma mask; + + mask = -1; + mask &= ~howto->src_mask; + addend |= mask; + } + /* Add in the increment, (which is a byte value). */ + switch (r_type) + { + case R_SCORE_PC19: + offset = + (((contents & howto->src_mask) & 0x3ff0000) >> 6) | ((contents & howto->src_mask) & 0x3ff); + offset += increment; + contents = + (contents & ~howto-> + src_mask) | (((offset << 6) & howto->src_mask) & 0x3ff0000) | (offset & 0x3ff); + bfd_put_32 (abfd, contents, address); + break; + case R_SCORE_HI16: + break; + case R_SCORE_LO16: + hi16_addend = bfd_get_32 (abfd, address - 4); + hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1; + offset = ((((contents >> 16) & 0x3) << 15) | (contents & 0x7fff)) >> 1; + offset = (hi16_offset << 16) | (offset & 0xffff); + uvalue = increment + offset; + hi16_offset = (uvalue >> 16) << 1; + hi16_value = (hi16_addend & (~(howto->dst_mask))) + | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000); + bfd_put_32 (abfd, hi16_value, address - 4); + offset = (uvalue & 0xffff) << 1; + contents = (contents & (~(howto->dst_mask))) | (offset & 0x7fff) | ((offset << 1) & 0x30000); + bfd_put_32 (abfd, contents, address); + break; + case R_SCORE_24: + offset = + (((contents & howto->src_mask) >> 1) & 0x1ff8000) | ((contents & howto->src_mask) & 0x7fff); + offset += increment; + contents = + (contents & ~howto-> + src_mask) | (((offset << 1) & howto->src_mask) & 0x3ff0000) | (offset & 0x7fff); + bfd_put_32 (abfd, contents, address); + break; + case R_SCORE16_11: + + contents = bfd_get_16 (abfd, address); + offset = contents & howto->src_mask; + offset += increment; + contents = (contents & ~howto->src_mask) | (offset & howto->src_mask); + bfd_put_16 (abfd, contents, address); + + break; + case R_SCORE16_PC8: + + contents = bfd_get_16 (abfd, address); + offset = (contents & howto->src_mask) + ((increment >> 1) & 0xff); + contents = (contents & (~howto->src_mask)) | (offset & howto->src_mask); + bfd_put_16 (abfd, contents, address); + + break; + case R_SCORE_GOT15: + case R_SCORE_GOT_LO16: + break; + + default: + addend += increment; + contents = (contents & ~howto->dst_mask) | (addend & howto->dst_mask); + bfd_put_32 (abfd, contents, address); + break; + } +} + +/* Perform a relocation as part of a final link. */ + +static bfd_reloc_status_type +score_elf_final_link_relocate (reloc_howto_type *howto, + bfd *input_bfd, + bfd *output_bfd, + asection *input_section, + bfd_byte *contents, + Elf_Internal_Rela *rel, + Elf_Internal_Rela *relocs, + bfd_vma symbol, + struct bfd_link_info *info, + const char *sym_name ATTRIBUTE_UNUSED, + int sym_flags ATTRIBUTE_UNUSED, + struct score_elf_link_hash_entry *h, + Elf_Internal_Sym *local_syms, + asection **local_sections, + bfd_boolean gp_disp_p) +{ + unsigned long r_type; + unsigned long r_symndx; + bfd_byte *hit_data = contents + rel->r_offset; + bfd_vma addend; + /* The final GP value to be used for the relocatable, executable, or + shared object file being produced. */ + bfd_vma gp = MINUS_ONE; + /* The place (section offset or address) of the storage unit being relocated. */ + bfd_vma rel_addr; + /* The value of GP used to create the relocatable object. */ + bfd_vma gp0 = MINUS_ONE; + /* The offset into the global offset table at which the address of the relocation entry + symbol, adjusted by the addend, resides during execution. */ + bfd_vma g = MINUS_ONE; + /* TRUE if the symbol referred to by this relocation is a local symbol. */ + bfd_boolean local_p; + /* The eventual value we will relocate. */ + bfd_vma value = symbol; + unsigned long hi16_addend, hi16_offset, hi16_value, uvalue, offset, abs_value = 0; + + Elf_Internal_Sym *sym = 0; + asection *sec = NULL; + bfd_boolean merge_p = 0; + + + if (elf_gp (output_bfd) == 0) + { + struct bfd_link_hash_entry *bh; + asection *o; + + bh = bfd_link_hash_lookup (info->hash, "_gp", 0, 0, 1); + if (bh != NULL && bh->type == bfd_link_hash_defined) + elf_gp (output_bfd) = (bh->u.def.value + + bh->u.def.section->output_section->vma + + bh->u.def.section->output_offset); + else if (info->relocatable) + { + bfd_vma lo = -1; + + /* Find the GP-relative section with the lowest offset. */ + for (o = output_bfd->sections; o != NULL; o = o->next) + if (o->vma < lo) + lo = o->vma; + /* And calculate GP relative to that. */ + elf_gp (output_bfd) = lo + ELF_SCORE_GP_OFFSET (input_bfd); + } + else + { + /* If the relocate_section function needs to do a reloc + involving the GP value, it should make a reloc_dangerous + callback to warn that GP is not defined. */ + } + } + + /* Parse the relocation. */ + r_symndx = ELF32_R_SYM (rel->r_info); + r_type = ELF32_R_TYPE (rel->r_info); + rel_addr = (input_section->output_section->vma + input_section->output_offset + rel->r_offset); + + /* For hidden symbol. */ + local_p = score_elf_local_relocation_p (input_bfd, rel, local_sections, FALSE); + if (local_p) + { + sym = local_syms + r_symndx; + sec = local_sections[r_symndx]; + + symbol = sec->output_section->vma + sec->output_offset; + if (ELF_ST_TYPE (sym->st_info) != STT_SECTION + || (sec->flags & SEC_MERGE)) + symbol += sym->st_value; + if ((sec->flags & SEC_MERGE) + && ELF_ST_TYPE (sym->st_info) == STT_SECTION) + merge_p = 1; + } + + if (r_type == R_SCORE_GOT15) + { + const Elf_Internal_Rela *relend; + const Elf_Internal_Rela *lo16_rel; + const struct elf_backend_data *bed; + bfd_vma lo_value = 0; + + bed = get_elf_backend_data (output_bfd); + relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel; + lo16_rel = score_elf_next_relocation (input_bfd, R_SCORE_GOT_LO16, rel, relend); + if ((local_p) && (lo16_rel != NULL)) + { + bfd_vma tmp = 0; + tmp = bfd_get_32 (input_bfd, contents + lo16_rel->r_offset); + lo_value = (((tmp >> 16) & 0x3) << 14) | ((tmp & 0x7fff) >> 1); + if (merge_p) + { + asection *msec = sec; + lo_value = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, lo_value); + lo_value -= symbol; + lo_value += msec->output_section->vma + msec->output_offset; + } + } + addend = lo_value; + } + else + { + addend = (bfd_get_32 (input_bfd, hit_data) >> howto->bitpos) & howto->src_mask; + } + + /* Figure out the value of the symbol. */ + if (local_p && !merge_p) + { + if (r_type == R_SCORE_GOT15) + { + const Elf_Internal_Rela *relend; + const Elf_Internal_Rela *lo16_rel; + const struct elf_backend_data *bed; + bfd_vma lo_value = 0; + + value = bfd_get_32 (input_bfd, contents + rel->r_offset); + addend = value & 0x7fff; + if ((addend & 0x4000) == 0x4000) + addend |= 0xffffc000; + + bed = get_elf_backend_data (output_bfd); + relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel; + lo16_rel = score_elf_next_relocation (input_bfd, R_SCORE_GOT_LO16, rel, relend); + if ((local_p) && (lo16_rel != NULL)) + { + bfd_vma tmp = 0; + tmp = bfd_get_32 (input_bfd, contents + lo16_rel->r_offset); + lo_value = (((tmp >> 16) & 0x3) << 14) | ((tmp & 0x7fff) >> 1); + } + + addend <<= 16; + addend += lo_value; + } + } + + local_p = score_elf_local_relocation_p (input_bfd, rel, local_sections, TRUE); + + /* If we haven't already determined the GOT offset, or the GP value, + and we're going to need it, get it now. */ + switch (r_type) + { + case R_SCORE_CALL15: + case R_SCORE_GOT15: + if (!local_p) + { + g = score_elf_global_got_index (elf_hash_table (info)->dynobj, + (struct elf_link_hash_entry *) h); + if ((! elf_hash_table(info)->dynamic_sections_created + || (info->shared + && (info->symbolic || h->root.dynindx == -1) + && h->root.def_regular))) + { + /* This is a static link or a -Bsymbolic link. The + symbol is defined locally, or was forced to be local. + We must initialize this entry in the GOT. */ + bfd *tmpbfd = elf_hash_table (info)->dynobj; + asection *sgot = score_elf_got_section (tmpbfd, FALSE); + bfd_put_32 (tmpbfd, value, sgot->contents + g); + } + } + else if (r_type == R_SCORE_GOT15 || r_type == R_SCORE_CALL15) + { + /* There's no need to create a local GOT entry here; the + calculation for a local GOT15 entry does not involve G. */ + ; + } + else + { + g = score_elf_local_got_index (output_bfd, input_bfd, info, + symbol + addend, r_symndx, h, r_type); + if (g == MINUS_ONE) + return bfd_reloc_outofrange; + } + + /* Convert GOT indices to actual offsets. */ + g = score_elf_got_offset_from_index (elf_hash_table (info)->dynobj, + output_bfd, input_bfd, g); + break; + + case R_SCORE_HI16: + case R_SCORE_LO16: + case R_SCORE_GPREL32: + gp0 = _bfd_get_gp_value (input_bfd); + gp = _bfd_get_gp_value (output_bfd); + break; + + case R_SCORE_GP15: + gp = _bfd_get_gp_value (output_bfd); + + default: + break; + } + + switch (r_type) + { + case R_SCORE_NONE: + return bfd_reloc_ok; + + case R_SCORE_ABS32: + case R_SCORE_REL32: + if ((info->shared + || (elf_hash_table (info)->dynamic_sections_created + && h != NULL + && h->root.def_dynamic + && !h->root.def_regular)) + && r_symndx != 0 + && (input_section->flags & SEC_ALLOC) != 0) + { + /* If we're creating a shared library, or this relocation is against a symbol + in a shared library, then we can't know where the symbol will end up. + So, we create a relocation record in the output, and leave the job up + to the dynamic linker. */ + value = addend; + if (!score_elf_create_dynamic_relocation (output_bfd, info, rel, h, + symbol, &value, + input_section)) + return bfd_reloc_undefined; + } + else if (r_symndx == 0) + /* r_symndx will be zero only for relocs against symbols + from removed linkonce sections, or sections discarded by + a linker script. */ + value = 0; + else + { + if (r_type != R_SCORE_REL32) + value = symbol + addend; + else + value = addend; + } + value &= howto->dst_mask; + bfd_put_32 (input_bfd, value, hit_data); + return bfd_reloc_ok; + + case R_SCORE_ABS16: + value += addend; + if ((long) value > 0x7fff || (long) value < -0x8000) + return bfd_reloc_overflow; + bfd_put_16 (input_bfd, value, hit_data); + return bfd_reloc_ok; + + case R_SCORE_24: + addend = bfd_get_32 (input_bfd, hit_data); + offset = (((addend & howto->src_mask) >> 1) & 0x1ff8000) | ((addend & howto->src_mask) & 0x7fff); + if ((offset & 0x1000000) != 0) + offset |= 0xfe000000; + value += offset; + abs_value = abs (value - rel_addr); + if ((abs_value & 0xfe000000) != 0) + return bfd_reloc_overflow; + addend = (addend & ~howto->src_mask) + | (((value << 1) & howto->src_mask) & 0x3ff0000) | (value & 0x7fff); + bfd_put_32 (input_bfd, addend, hit_data); + return bfd_reloc_ok; + + case R_SCORE_PC19: + addend = bfd_get_32 (input_bfd, hit_data); + offset = (((addend & howto->src_mask) & 0x3ff0000) >> 6) | ((addend & howto->src_mask) & 0x3ff); + if ((offset & 0x80000) != 0) + offset |= 0xfff00000; + abs_value = value = value - rel_addr + offset; + /* exceed 20 bit : overflow. */ + if ((abs_value & 0x80000000) == 0x80000000) + abs_value = 0xffffffff - value + 1; + if ((abs_value & 0xfff80000) != 0) + return bfd_reloc_overflow; + addend = (addend & ~howto->src_mask) + | (((value << 6) & howto->src_mask) & 0x3ff0000) | (value & 0x3ff); + bfd_put_32 (input_bfd, addend, hit_data); + return bfd_reloc_ok; + + case R_SCORE16_11: + addend = bfd_get_16 (input_bfd, hit_data); + offset = addend & howto->src_mask; + if ((offset & 0x800) != 0) /* Offset is negative. */ + offset |= 0xfffff000; + value += offset; + abs_value = abs (value - rel_addr); + if ((abs_value & 0xfffff000) != 0) + return bfd_reloc_overflow; + addend = (addend & ~howto->src_mask) | (value & howto->src_mask); + bfd_put_16 (input_bfd, addend, hit_data); + return bfd_reloc_ok; + + case R_SCORE16_PC8: + addend = bfd_get_16 (input_bfd, hit_data); + offset = (addend & howto->src_mask) << 1; + if ((offset & 0x100) != 0) /* Offset is negative. */ + offset |= 0xfffffe00; + abs_value = value = value - rel_addr + offset; + /* Sign bit + exceed 9 bit. */ + if (((value & 0xffffff00) != 0) && ((value & 0xffffff00) != 0xffffff00)) + return bfd_reloc_overflow; + value >>= 1; + addend = (addend & ~howto->src_mask) | (value & howto->src_mask); + bfd_put_16 (input_bfd, addend, hit_data); + return bfd_reloc_ok; + + case R_SCORE_HI16: + return bfd_reloc_ok; + + case R_SCORE_LO16: + hi16_addend = bfd_get_32 (input_bfd, hit_data - 4); + hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1; + addend = bfd_get_32 (input_bfd, hit_data); + offset = ((((addend >> 16) & 0x3) << 15) | (addend & 0x7fff)) >> 1; + offset = (hi16_offset << 16) | (offset & 0xffff); + + if (!gp_disp_p) + uvalue = value + offset; + else + uvalue = offset + gp - rel_addr + 4; + + hi16_offset = (uvalue >> 16) << 1; + hi16_value = (hi16_addend & (~(howto->dst_mask))) + | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000); + bfd_put_32 (input_bfd, hi16_value, hit_data - 4); + offset = (uvalue & 0xffff) << 1; + value = (addend & (~(howto->dst_mask))) | (offset & 0x7fff) | ((offset << 1) & 0x30000); + bfd_put_32 (input_bfd, value, hit_data); + return bfd_reloc_ok; + + case R_SCORE_GP15: + addend = bfd_get_32 (input_bfd, hit_data); + offset = addend & 0x7fff; + if ((offset & 0x4000) == 0x4000) + offset |= 0xffffc000; + value = value + offset - gp; + if (((value & 0xffffc000) != 0) && ((value & 0xffffc000) != 0xffffc000)) + return bfd_reloc_overflow; + value = (addend & ~howto->src_mask) | (value & howto->src_mask); + bfd_put_32 (input_bfd, value, hit_data); + return bfd_reloc_ok; + + case R_SCORE_GOT15: + case R_SCORE_CALL15: + if (local_p) + { + bfd_boolean forced; + + /* The special case is when the symbol is forced to be local. We need the + full address in the GOT since no R_SCORE_GOT_LO16 relocation follows. */ + forced = ! score_elf_local_relocation_p (input_bfd, rel, + local_sections, FALSE); + value = score_elf_got16_entry (output_bfd, input_bfd, info, + symbol + addend, forced); + if (value == MINUS_ONE) + return bfd_reloc_outofrange; + value = score_elf_got_offset_from_index (elf_hash_table (info)->dynobj, + output_bfd, input_bfd, value); + } + else + { + value = g; + } + + if ((long) value > 0x3fff || (long) value < -0x4000) + return bfd_reloc_overflow; + + addend = bfd_get_32 (input_bfd, hit_data); + value = (addend & ~howto->dst_mask) | (value & howto->dst_mask); + bfd_put_32 (input_bfd, value, hit_data); + return bfd_reloc_ok; + + case R_SCORE_GPREL32: + value = (addend + symbol + gp0 - gp); + value &= howto->dst_mask; + bfd_put_32 (input_bfd, value, hit_data); + return bfd_reloc_ok; + + case R_SCORE_GOT_LO16: + addend = bfd_get_32 (input_bfd, hit_data); + value = (((addend >> 16) & 0x3) << 14) | ((addend & 0x7fff) >> 1); + value += symbol; + value = (addend & (~(howto->dst_mask))) | ((value & 0x3fff) << 1) + | (((value >> 14) & 0x3) << 16); + + bfd_put_32 (input_bfd, value, hit_data); + return bfd_reloc_ok; + + case R_SCORE_DUMMY_HI16: + return bfd_reloc_ok; + + case R_SCORE_GNU_VTINHERIT: + case R_SCORE_GNU_VTENTRY: + /* We don't do anything with these at present. */ + return bfd_reloc_continue; + + default: + return bfd_reloc_notsupported; + } +} + +/* Score backend functions. */ + +void +s7_bfd_score_info_to_howto (bfd *abfd ATTRIBUTE_UNUSED, + arelent *bfd_reloc, + Elf_Internal_Rela *elf_reloc) +{ + unsigned int r_type; + + r_type = ELF32_R_TYPE (elf_reloc->r_info); + if (r_type >= ARRAY_SIZE (elf32_score_howto_table)) + bfd_reloc->howto = NULL; + else + bfd_reloc->howto = &elf32_score_howto_table[r_type]; +} + +/* Relocate an score ELF section. */ + +bfd_boolean +s7_bfd_score_elf_relocate_section (bfd *output_bfd, + struct bfd_link_info *info, + bfd *input_bfd, + asection *input_section, + bfd_byte *contents, + Elf_Internal_Rela *relocs, + Elf_Internal_Sym *local_syms, + asection **local_sections) +{ + Elf_Internal_Shdr *symtab_hdr; + struct elf_link_hash_entry **sym_hashes; + Elf_Internal_Rela *rel; + Elf_Internal_Rela *relend; + const char *name; + unsigned long offset; + unsigned long hi16_addend, hi16_offset, hi16_value, uvalue; + size_t extsymoff; + bfd_boolean gp_disp_p = FALSE; + + /* Sort dynsym. */ + if (elf_hash_table (info)->dynamic_sections_created) + { + bfd_size_type dynsecsymcount = 0; + if (info->shared) + { + asection * p; + const struct elf_backend_data *bed = get_elf_backend_data (output_bfd); + + for (p = output_bfd->sections; p ; p = p->next) + if ((p->flags & SEC_EXCLUDE) == 0 + && (p->flags & SEC_ALLOC) != 0 + && !(*bed->elf_backend_omit_section_dynsym) (output_bfd, info, p)) + ++ dynsecsymcount; + } + + if (!score_elf_sort_hash_table (info, dynsecsymcount + 1)) + return FALSE; + } + + symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; + extsymoff = (elf_bad_symtab (input_bfd)) ? 0 : symtab_hdr->sh_info; + sym_hashes = elf_sym_hashes (input_bfd); + rel = relocs; + relend = relocs + input_section->reloc_count; + for (; rel < relend; rel++) + { + int r_type; + reloc_howto_type *howto; + unsigned long r_symndx; + Elf_Internal_Sym *sym; + asection *sec; + struct score_elf_link_hash_entry *h; + bfd_vma relocation = 0; + bfd_reloc_status_type r; + arelent bfd_reloc; + + r_symndx = ELF32_R_SYM (rel->r_info); + r_type = ELF32_R_TYPE (rel->r_info); + + s7_bfd_score_info_to_howto (input_bfd, &bfd_reloc, (Elf_Internal_Rela *) rel); + howto = bfd_reloc.howto; + + h = NULL; + sym = NULL; + sec = NULL; + + if (r_symndx < extsymoff) + { + sym = local_syms + r_symndx; + sec = local_sections[r_symndx]; + relocation = sec->output_section->vma + sec->output_offset; + name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym, sec); + + if (!info->relocatable) + { + if (ELF_ST_TYPE (sym->st_info) != STT_SECTION + || (sec->flags & SEC_MERGE)) + { + relocation += sym->st_value; + } + + if ((sec->flags & SEC_MERGE) + && ELF_ST_TYPE (sym->st_info) == STT_SECTION) + { + asection *msec; + bfd_vma addend, value; + + switch (r_type) + { + case R_SCORE_HI16: + break; + case R_SCORE_LO16: + hi16_addend = bfd_get_32 (input_bfd, contents + rel->r_offset - 4); + hi16_offset = ((((hi16_addend >> 16) & 0x3) << 15) | (hi16_addend & 0x7fff)) >> 1; + value = bfd_get_32 (input_bfd, contents + rel->r_offset); + offset = ((((value >> 16) & 0x3) << 15) | (value & 0x7fff)) >> 1; + addend = (hi16_offset << 16) | (offset & 0xffff); + msec = sec; + addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend); + addend -= relocation; + addend += msec->output_section->vma + msec->output_offset; + uvalue = addend; + hi16_offset = (uvalue >> 16) << 1; + hi16_value = (hi16_addend & (~(howto->dst_mask))) + | (hi16_offset & 0x7fff) | ((hi16_offset << 1) & 0x30000); + bfd_put_32 (input_bfd, hi16_value, contents + rel->r_offset - 4); + offset = (uvalue & 0xffff) << 1; + value = (value & (~(howto->dst_mask))) + | (offset & 0x7fff) | ((offset << 1) & 0x30000); + bfd_put_32 (input_bfd, value, contents + rel->r_offset); + break; + case R_SCORE_GOT_LO16: + value = bfd_get_32 (input_bfd, contents + rel->r_offset); + addend = (((value >> 16) & 0x3) << 14) | ((value & 0x7fff) >> 1); + msec = sec; + addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation; + addend += msec->output_section->vma + msec->output_offset; + value = (value & (~(howto->dst_mask))) | ((addend & 0x3fff) << 1) + | (((addend >> 14) & 0x3) << 16); + + bfd_put_32 (input_bfd, value, contents + rel->r_offset); + break; + default: + value = bfd_get_32 (input_bfd, contents + rel->r_offset); + /* Get the (signed) value from the instruction. */ + addend = value & howto->src_mask; + if (addend & ((howto->src_mask + 1) >> 1)) + { + bfd_signed_vma mask; + + mask = -1; + mask &= ~howto->src_mask; + addend |= mask; + } + msec = sec; + addend = _bfd_elf_rel_local_sym (output_bfd, sym, &msec, addend) - relocation; + addend += msec->output_section->vma + msec->output_offset; + value = (value & ~howto->dst_mask) | (addend & howto->dst_mask); + bfd_put_32 (input_bfd, value, contents + rel->r_offset); + break; + } + } + } + } + else + { + /* For global symbols we look up the symbol in the hash-table. */ + h = ((struct score_elf_link_hash_entry *) + elf_sym_hashes (input_bfd) [r_symndx - extsymoff]); + /* Find the real hash-table entry for this symbol. */ + while (h->root.root.type == bfd_link_hash_indirect + || h->root.root.type == bfd_link_hash_warning) + h = (struct score_elf_link_hash_entry *) h->root.root.u.i.link; + + /* Record the name of this symbol, for our caller. */ + name = h->root.root.root.string; + + /* See if this is the special GP_DISP_LABEL symbol. Note that such a + symbol must always be a global symbol. */ + if (strcmp (name, GP_DISP_LABEL) == 0) + { + /* Relocations against GP_DISP_LABEL are permitted only with + R_SCORE_HI16 and R_SCORE_LO16 relocations. */ + if (r_type != R_SCORE_HI16 && r_type != R_SCORE_LO16) + return bfd_reloc_notsupported; + + gp_disp_p = TRUE; + } + + /* If this symbol is defined, calculate its address. Note that + GP_DISP_LABEL is a magic symbol, always implicitly defined by the + linker, so it's inappropriate to check to see whether or not + its defined. */ + else if ((h->root.root.type == bfd_link_hash_defined + || h->root.root.type == bfd_link_hash_defweak) + && h->root.root.u.def.section) + { + sec = h->root.root.u.def.section; + if (sec->output_section) + relocation = (h->root.root.u.def.value + + sec->output_section->vma + + sec->output_offset); + else + { + relocation = h->root.root.u.def.value; + } + } + else if (h->root.root.type == bfd_link_hash_undefweak) + /* We allow relocations against undefined weak symbols, giving + it the value zero, so that you can undefined weak functions + and check to see if they exist by looking at their addresses. */ + relocation = 0; + else if (info->unresolved_syms_in_objects == RM_IGNORE + && ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT) + relocation = 0; + else if (strcmp (name, "_DYNAMIC_LINK") == 0) + { + /* If this is a dynamic link, we should have created a _DYNAMIC_LINK symbol + in s7_bfd_score_elf_create_dynamic_sections. Otherwise, we should define + the symbol with a value of 0. */ + BFD_ASSERT (! info->shared); + BFD_ASSERT (bfd_get_section_by_name (output_bfd, ".dynamic") == NULL); + relocation = 0; + } + else if (!info->relocatable) + { + if (! ((*info->callbacks->undefined_symbol) + (info, h->root.root.root.string, input_bfd, + input_section, rel->r_offset, + (info->unresolved_syms_in_objects == RM_GENERATE_ERROR) + || ELF_ST_VISIBILITY (h->root.other)))) + return bfd_reloc_undefined; + relocation = 0; + } + } + + if (sec != NULL && elf_discarded_section (sec)) + { + /* For relocs against symbols from removed linkonce sections, + or sections discarded by a linker script, we just want the + section contents zeroed. Avoid any special processing. */ + _bfd_clear_contents (howto, input_bfd, contents + rel->r_offset); + rel->r_info = 0; + rel->r_addend = 0; + continue; + } + + if (info->relocatable) + { + /* This is a relocatable link. We don't have to change + anything, unless the reloc is against a section symbol, + in which case we have to adjust according to where the + section symbol winds up in the output section. */ + if (r_symndx < symtab_hdr->sh_info) + { + sym = local_syms + r_symndx; + + if (r_type == R_SCORE_GOT15) + { + const Elf_Internal_Rela *relend; + const Elf_Internal_Rela *lo16_rel; + const struct elf_backend_data *bed; + bfd_vma lo_addend = 0, lo_value = 0; + bfd_vma addend, value; + + value = bfd_get_32 (input_bfd, contents + rel->r_offset); + addend = value & 0x7fff; + if ((addend & 0x4000) == 0x4000) + addend |= 0xffffc000; + + bed = get_elf_backend_data (output_bfd); + relend = relocs + input_section->reloc_count * bed->s->int_rels_per_ext_rel; + lo16_rel = score_elf_next_relocation (input_bfd, R_SCORE_GOT_LO16, rel, relend); + if (lo16_rel != NULL) + { + lo_value = bfd_get_32 (input_bfd, contents + lo16_rel->r_offset); + lo_addend = (((lo_value >> 16) & 0x3) << 14) | ((lo_value & 0x7fff) >> 1); + } + + addend <<= 16; + addend += lo_addend; + + if (ELF_ST_TYPE (sym->st_info) == STT_SECTION) + addend += local_sections[r_symndx]->output_offset; + + lo_addend = addend & 0xffff; + lo_value = (lo_value & (~(howto->dst_mask))) | ((lo_addend & 0x3fff) << 1) + | (((lo_addend >> 14) & 0x3) << 16); + bfd_put_32 (input_bfd, lo_value, contents + lo16_rel->r_offset); + + addend = addend >> 16; + value = (value & ~howto->src_mask) | (addend & howto->src_mask); + bfd_put_32 (input_bfd, value, contents + rel->r_offset); + } + else if (ELF_ST_TYPE (sym->st_info) == STT_SECTION) + { + sec = local_sections[r_symndx]; + score_elf_add_to_rel (input_bfd, contents + rel->r_offset, + howto, (bfd_signed_vma) (sec->output_offset + sym->st_value)); + } + } + continue; + } + + /* This is a final link. */ + r = score_elf_final_link_relocate (howto, input_bfd, output_bfd, + input_section, contents, rel, relocs, + relocation, info, name, + (h ? ELF_ST_TYPE ((unsigned int) h->root.root.type) : + ELF_ST_TYPE ((unsigned int) sym->st_info)), h, local_syms, + local_sections, gp_disp_p); + + if (r != bfd_reloc_ok) + { + const char *msg = (const char *)0; + + switch (r) + { + case bfd_reloc_overflow: + /* If the overflowing reloc was to an undefined symbol, + we have already printed one error message and there + is no point complaining again. */ + if (((!h) || (h->root.root.type != bfd_link_hash_undefined)) + && (!((*info->callbacks->reloc_overflow) + (info, NULL, name, howto->name, (bfd_vma) 0, + input_bfd, input_section, rel->r_offset)))) + return FALSE; + break; + case bfd_reloc_undefined: + if (!((*info->callbacks->undefined_symbol) + (info, name, input_bfd, input_section, rel->r_offset, TRUE))) + return FALSE; + break; + + case bfd_reloc_outofrange: + msg = _("internal error: out of range error"); + goto common_error; + + case bfd_reloc_notsupported: + msg = _("internal error: unsupported relocation error"); + goto common_error; + + case bfd_reloc_dangerous: + msg = _("internal error: dangerous error"); + goto common_error; + + default: + msg = _("internal error: unknown error"); + /* fall through */ + + common_error: + if (!((*info->callbacks->warning) + (info, msg, name, input_bfd, input_section, rel->r_offset))) + return FALSE; + break; + } + } + } + + return TRUE; +} + +/* Look through the relocs for a section during the first phase, and + allocate space in the global offset table. */ + +bfd_boolean +s7_bfd_score_elf_check_relocs (bfd *abfd, + struct bfd_link_info *info, + asection *sec, + const Elf_Internal_Rela *relocs) +{ + const char *name; + bfd *dynobj; + Elf_Internal_Shdr *symtab_hdr; + struct elf_link_hash_entry **sym_hashes; + struct score_got_info *g; + size_t extsymoff; + const Elf_Internal_Rela *rel; + const Elf_Internal_Rela *rel_end; + asection *sgot; + asection *sreloc; + const struct elf_backend_data *bed; + + if (info->relocatable) + return TRUE; + + dynobj = elf_hash_table (info)->dynobj; + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + sym_hashes = elf_sym_hashes (abfd); + extsymoff = (elf_bad_symtab (abfd)) ? 0 : symtab_hdr->sh_info; + + name = bfd_get_section_name (abfd, sec); + + if (dynobj == NULL) + { + sgot = NULL; + g = NULL; + } + else + { + sgot = score_elf_got_section (dynobj, FALSE); + if (sgot == NULL) + g = NULL; + else + { + BFD_ASSERT (score_elf_section_data (sgot) != NULL); + g = score_elf_section_data (sgot)->u.got_info; + BFD_ASSERT (g != NULL); + } + } + + sreloc = NULL; + bed = get_elf_backend_data (abfd); + rel_end = relocs + sec->reloc_count * bed->s->int_rels_per_ext_rel; + for (rel = relocs; rel < rel_end; ++rel) + { + unsigned long r_symndx; + unsigned int r_type; + struct elf_link_hash_entry *h; + + r_symndx = ELF32_R_SYM (rel->r_info); + r_type = ELF32_R_TYPE (rel->r_info); + + if (r_symndx < extsymoff) + { + h = NULL; + } + else if (r_symndx >= extsymoff + NUM_SHDR_ENTRIES (symtab_hdr)) + { + (*_bfd_error_handler) (_("%s: Malformed reloc detected for section %s"), abfd, name); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + else + { + h = sym_hashes[r_symndx - extsymoff]; + + /* This may be an indirect symbol created because of a version. */ + if (h != NULL) + { + while (h->root.type == bfd_link_hash_indirect) + h = (struct elf_link_hash_entry *) h->root.u.i.link; + } + } + + /* Some relocs require a global offset table. */ + if (dynobj == NULL || sgot == NULL) + { + switch (r_type) + { + case R_SCORE_GOT15: + case R_SCORE_CALL15: + if (dynobj == NULL) + elf_hash_table (info)->dynobj = dynobj = abfd; + if (!score_elf_create_got_section (dynobj, info, FALSE)) + return FALSE; + g = score_elf_got_info (dynobj, &sgot); + break; + case R_SCORE_ABS32: + case R_SCORE_REL32: + if (dynobj == NULL && (info->shared || h != NULL) && (sec->flags & SEC_ALLOC) != 0) + elf_hash_table (info)->dynobj = dynobj = abfd; + break; + default: + break; + } + } + + if (!h && (r_type == R_SCORE_GOT_LO16)) + { + if (! score_elf_record_local_got_symbol (abfd, r_symndx, rel->r_addend, g)) + return FALSE; + } + + switch (r_type) + { + case R_SCORE_CALL15: + if (h == NULL) + { + (*_bfd_error_handler) + (_("%B: CALL15 reloc at 0x%lx not against global symbol"), + abfd, (unsigned long) rel->r_offset); + bfd_set_error (bfd_error_bad_value); + return FALSE; + } + else + { + /* This symbol requires a global offset table entry. */ + if (! score_elf_record_global_got_symbol (h, abfd, info, g)) + return FALSE; + + /* We need a stub, not a plt entry for the undefined function. But we record + it as if it needs plt. See _bfd_elf_adjust_dynamic_symbol. */ + h->needs_plt = 1; + h->type = STT_FUNC; + } + break; + case R_SCORE_GOT15: + if (h && ! score_elf_record_global_got_symbol (h, abfd, info, g)) + return FALSE; + break; + case R_SCORE_ABS32: + case R_SCORE_REL32: + if ((info->shared || h != NULL) && (sec->flags & SEC_ALLOC) != 0) + { + if (sreloc == NULL) + { + sreloc = score_elf_rel_dyn_section (dynobj, TRUE); + if (sreloc == NULL) + return FALSE; + } +#define SCORE_READONLY_SECTION (SEC_ALLOC | SEC_LOAD | SEC_READONLY) + if (info->shared) + { + /* When creating a shared object, we must copy these reloc types into + the output file as R_SCORE_REL32 relocs. We make room for this reloc + in the .rel.dyn reloc section. */ + score_elf_allocate_dynamic_relocations (dynobj, 1); + if ((sec->flags & SCORE_READONLY_SECTION) + == SCORE_READONLY_SECTION) + /* We tell the dynamic linker that there are + relocations against the text segment. */ + info->flags |= DF_TEXTREL; + } + else + { + struct score_elf_link_hash_entry *hscore; + + /* We only need to copy this reloc if the symbol is + defined in a dynamic object. */ + hscore = (struct score_elf_link_hash_entry *) h; + ++hscore->possibly_dynamic_relocs; + if ((sec->flags & SCORE_READONLY_SECTION) + == SCORE_READONLY_SECTION) + /* We need it to tell the dynamic linker if there + are relocations against the text segment. */ + hscore->readonly_reloc = TRUE; + } + + /* Even though we don't directly need a GOT entry for this symbol, + a symbol must have a dynamic symbol table index greater that + DT_SCORE_GOTSYM if there are dynamic relocations against it. */ + if (h != NULL) + { + if (dynobj == NULL) + elf_hash_table (info)->dynobj = dynobj = abfd; + if (! score_elf_create_got_section (dynobj, info, TRUE)) + return FALSE; + g = score_elf_got_info (dynobj, &sgot); + if (! score_elf_record_global_got_symbol (h, abfd, info, g)) + return FALSE; + } + } + break; + + /* This relocation describes the C++ object vtable hierarchy. + Reconstruct it for later use during GC. */ + case R_SCORE_GNU_VTINHERIT: + if (!bfd_elf_gc_record_vtinherit (abfd, sec, h, rel->r_offset)) + return FALSE; + break; + + /* This relocation describes which C++ vtable entries are actually + used. Record for later use during GC. */ + case R_SCORE_GNU_VTENTRY: + if (!bfd_elf_gc_record_vtentry (abfd, sec, h, rel->r_offset)) + return FALSE; + break; + default: + break; + } + + /* We must not create a stub for a symbol that has relocations + related to taking the function's address. */ + switch (r_type) + { + default: + if (h != NULL) + { + struct score_elf_link_hash_entry *sh; + + sh = (struct score_elf_link_hash_entry *) h; + sh->no_fn_stub = TRUE; + } + break; + case R_SCORE_CALL15: + break; + } + } + + return TRUE; +} + +bfd_boolean +s7_bfd_score_elf_add_symbol_hook (bfd *abfd, + struct bfd_link_info *info ATTRIBUTE_UNUSED, + Elf_Internal_Sym *sym, + const char **namep ATTRIBUTE_UNUSED, + flagword *flagsp ATTRIBUTE_UNUSED, + asection **secp, + bfd_vma *valp) +{ + switch (sym->st_shndx) + { + case SHN_COMMON: + if (sym->st_size > elf_gp_size (abfd)) + break; + /* Fall through. */ + case SHN_SCORE_SCOMMON: + *secp = bfd_make_section_old_way (abfd, ".scommon"); + (*secp)->flags |= SEC_IS_COMMON; + *valp = sym->st_size; + break; + } + + return TRUE; +} + +void +s7_bfd_score_elf_symbol_processing (bfd *abfd, asymbol *asym) +{ + elf_symbol_type *elfsym; + + elfsym = (elf_symbol_type *) asym; + switch (elfsym->internal_elf_sym.st_shndx) + { + case SHN_COMMON: + if (asym->value > elf_gp_size (abfd)) + break; + /* Fall through. */ + case SHN_SCORE_SCOMMON: + if (score_elf_scom_section.name == NULL) + { + /* Initialize the small common section. */ + score_elf_scom_section.name = ".scommon"; + score_elf_scom_section.flags = SEC_IS_COMMON; + score_elf_scom_section.output_section = &score_elf_scom_section; + score_elf_scom_section.symbol = &score_elf_scom_symbol; + score_elf_scom_section.symbol_ptr_ptr = &score_elf_scom_symbol_ptr; + score_elf_scom_symbol.name = ".scommon"; + score_elf_scom_symbol.flags = BSF_SECTION_SYM; + score_elf_scom_symbol.section = &score_elf_scom_section; + score_elf_scom_symbol_ptr = &score_elf_scom_symbol; + } + asym->section = &score_elf_scom_section; + asym->value = elfsym->internal_elf_sym.st_size; + break; + } +} + +bfd_boolean +s7_bfd_score_elf_link_output_symbol_hook (struct bfd_link_info *info ATTRIBUTE_UNUSED, + const char *name ATTRIBUTE_UNUSED, + Elf_Internal_Sym *sym, + asection *input_sec, + struct elf_link_hash_entry *h ATTRIBUTE_UNUSED) +{ + /* If we see a common symbol, which implies a relocatable link, then + if a symbol was small common in an input file, mark it as small + common in the output file. */ + if (sym->st_shndx == SHN_COMMON && strcmp (input_sec->name, ".scommon") == 0) + sym->st_shndx = SHN_SCORE_SCOMMON; + + return TRUE; +} + +bfd_boolean +s7_bfd_score_elf_section_from_bfd_section (bfd *abfd ATTRIBUTE_UNUSED, + asection *sec, + int *retval) +{ + if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0) + { + *retval = SHN_SCORE_SCOMMON; + return TRUE; + } + + return FALSE; +} + +/* Adjust a symbol defined by a dynamic object and referenced by a + regular object. The current definition is in some section of the + dynamic object, but we're not including those sections. We have to + change the definition to something the rest of the link can understand. */ + +bfd_boolean +s7_bfd_score_elf_adjust_dynamic_symbol (struct bfd_link_info *info, + struct elf_link_hash_entry *h) +{ + bfd *dynobj; + struct score_elf_link_hash_entry *hscore; + asection *s; + + dynobj = elf_hash_table (info)->dynobj; + + /* Make sure we know what is going on here. */ + BFD_ASSERT (dynobj != NULL + && (h->needs_plt + || h->u.weakdef != NULL + || (h->def_dynamic && h->ref_regular && !h->def_regular))); + + /* If this symbol is defined in a dynamic object, we need to copy + any R_SCORE_ABS32 or R_SCORE_REL32 relocs against it into the output + file. */ + hscore = (struct score_elf_link_hash_entry *) h; + if (!info->relocatable + && hscore->possibly_dynamic_relocs != 0 + && (h->root.type == bfd_link_hash_defweak || !h->def_regular)) + { + score_elf_allocate_dynamic_relocations (dynobj, hscore->possibly_dynamic_relocs); + if (hscore->readonly_reloc) + /* We tell the dynamic linker that there are relocations + against the text segment. */ + info->flags |= DF_TEXTREL; + } + + /* For a function, create a stub, if allowed. */ + if (!hscore->no_fn_stub && h->needs_plt) + { + if (!elf_hash_table (info)->dynamic_sections_created) + return TRUE; + + /* If this symbol is not defined in a regular file, then set + the symbol to the stub location. This is required to make + function pointers compare as equal between the normal + executable and the shared library. */ + if (!h->def_regular) + { + /* We need .stub section. */ + s = bfd_get_section_by_name (dynobj, SCORE_ELF_STUB_SECTION_NAME); + BFD_ASSERT (s != NULL); + + h->root.u.def.section = s; + h->root.u.def.value = s->size; + + /* XXX Write this stub address somewhere. */ + h->plt.offset = s->size; + + /* Make room for this stub code. */ + s->size += SCORE_FUNCTION_STUB_SIZE; + + /* The last half word of the stub will be filled with the index + of this symbol in .dynsym section. */ + return TRUE; + } + } + else if ((h->type == STT_FUNC) && !h->needs_plt) + { + /* This will set the entry for this symbol in the GOT to 0, and + the dynamic linker will take care of this. */ + h->root.u.def.value = 0; + return TRUE; + } + + /* If this is a weak symbol, and there is a real definition, the + processor independent code will have arranged for us to see the + real definition first, and we can just use the same value. */ + if (h->u.weakdef != NULL) + { + BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined + || h->u.weakdef->root.type == bfd_link_hash_defweak); + h->root.u.def.section = h->u.weakdef->root.u.def.section; + h->root.u.def.value = h->u.weakdef->root.u.def.value; + return TRUE; + } + + /* This is a reference to a symbol defined by a dynamic object which + is not a function. */ + return TRUE; +} + +/* This function is called after all the input files have been read, + and the input sections have been assigned to output sections. */ + +bfd_boolean +s7_bfd_score_elf_always_size_sections (bfd *output_bfd, + struct bfd_link_info *info) +{ + bfd *dynobj; + asection *s; + struct score_got_info *g; + int i; + bfd_size_type loadable_size = 0; + bfd_size_type local_gotno; + bfd *sub; + + dynobj = elf_hash_table (info)->dynobj; + if (dynobj == NULL) + /* Relocatable links don't have it. */ + return TRUE; + + g = score_elf_got_info (dynobj, &s); + if (s == NULL) + return TRUE; + + /* Calculate the total loadable size of the output. That will give us the + maximum number of GOT_PAGE entries required. */ + for (sub = info->input_bfds; sub; sub = sub->link_next) + { + asection *subsection; + + for (subsection = sub->sections; + subsection; + subsection = subsection->next) + { + if ((subsection->flags & SEC_ALLOC) == 0) + continue; + loadable_size += ((subsection->size + 0xf) + &~ (bfd_size_type) 0xf); + } + } + + /* There has to be a global GOT entry for every symbol with + a dynamic symbol table index of DT_SCORE_GOTSYM or + higher. Therefore, it make sense to put those symbols + that need GOT entries at the end of the symbol table. We + do that here. */ + if (! score_elf_sort_hash_table (info, 1)) + return FALSE; + + if (g->global_gotsym != NULL) + i = elf_hash_table (info)->dynsymcount - g->global_gotsym->dynindx; + else + /* If there are no global symbols, or none requiring + relocations, then GLOBAL_GOTSYM will be NULL. */ + i = 0; + + /* In the worst case, we'll get one stub per dynamic symbol. */ + loadable_size += SCORE_FUNCTION_STUB_SIZE * i; + + /* Assume there are two loadable segments consisting of + contiguous sections. Is 5 enough? */ + local_gotno = (loadable_size >> 16) + 5; + + g->local_gotno += local_gotno; + s->size += g->local_gotno * SCORE_ELF_GOT_SIZE (output_bfd); + + g->global_gotno = i; + s->size += i * SCORE_ELF_GOT_SIZE (output_bfd); + + score_elf_resolve_final_got_entries (g); + + if (s->size > SCORE_ELF_GOT_MAX_SIZE (output_bfd)) + { + /* Fixme. Error message or Warning message should be issued here. */ + } + + return TRUE; +} + +/* Set the sizes of the dynamic sections. */ + +bfd_boolean +s7_bfd_score_elf_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info) +{ + bfd *dynobj; + asection *s; + bfd_boolean reltext; + + dynobj = elf_hash_table (info)->dynobj; + BFD_ASSERT (dynobj != NULL); + + if (elf_hash_table (info)->dynamic_sections_created) + { + /* Set the contents of the .interp section to the interpreter. */ + if (!info->shared) + { + s = bfd_get_section_by_name (dynobj, ".interp"); + BFD_ASSERT (s != NULL); + s->size = strlen (ELF_DYNAMIC_INTERPRETER) + 1; + s->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER; + } + } + + /* The check_relocs and adjust_dynamic_symbol entry points have + determined the sizes of the various dynamic sections. Allocate + memory for them. */ + reltext = FALSE; + for (s = dynobj->sections; s != NULL; s = s->next) + { + const char *name; + + if ((s->flags & SEC_LINKER_CREATED) == 0) + continue; + + /* It's OK to base decisions on the section name, because none + of the dynobj section names depend upon the input files. */ + name = bfd_get_section_name (dynobj, s); + + if (CONST_STRNEQ (name, ".rel")) + { + if (s->size == 0) + { + /* We only strip the section if the output section name + has the same name. Otherwise, there might be several + input sections for this output section. FIXME: This + code is probably not needed these days anyhow, since + the linker now does not create empty output sections. */ + if (s->output_section != NULL + && strcmp (name, + bfd_get_section_name (s->output_section->owner, + s->output_section)) == 0) + s->flags |= SEC_EXCLUDE; + } + else + { + const char *outname; + asection *target; + + /* If this relocation section applies to a read only + section, then we probably need a DT_TEXTREL entry. + If the relocation section is .rel.dyn, we always + assert a DT_TEXTREL entry rather than testing whether + there exists a relocation to a read only section or + not. */ + outname = bfd_get_section_name (output_bfd, s->output_section); + target = bfd_get_section_by_name (output_bfd, outname + 4); + if ((target != NULL + && (target->flags & SEC_READONLY) != 0 + && (target->flags & SEC_ALLOC) != 0) || strcmp (outname, ".rel.dyn") == 0) + reltext = TRUE; + + /* We use the reloc_count field as a counter if we need + to copy relocs into the output file. */ + if (strcmp (name, ".rel.dyn") != 0) + s->reloc_count = 0; + } + } + else if (CONST_STRNEQ (name, ".got")) + { + /* s7_bfd_score_elf_always_size_sections() has already done + most of the work, but some symbols may have been mapped + to versions that we must now resolve in the got_entries + hash tables. */ + } + else if (strcmp (name, SCORE_ELF_STUB_SECTION_NAME) == 0) + { + /* IRIX rld assumes that the function stub isn't at the end + of .text section. So put a dummy. XXX */ + s->size += SCORE_FUNCTION_STUB_SIZE; + } + else if (! CONST_STRNEQ (name, ".init")) + { + /* It's not one of our sections, so don't allocate space. */ + continue; + } + + /* Allocate memory for the section contents. */ + s->contents = bfd_zalloc (dynobj, s->size); + if (s->contents == NULL && s->size != 0) + { + bfd_set_error (bfd_error_no_memory); + return FALSE; + } + } + + if (elf_hash_table (info)->dynamic_sections_created) + { + /* Add some entries to the .dynamic section. We fill in the + values later, in s7_bfd_score_elf_finish_dynamic_sections, but we + must add the entries now so that we get the correct size for + the .dynamic section. The DT_DEBUG entry is filled in by the + dynamic linker and used by the debugger. */ + + if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_DEBUG, 0)) + return FALSE; + + if (reltext) + info->flags |= DF_TEXTREL; + + if ((info->flags & DF_TEXTREL) != 0) + { + if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_TEXTREL, 0)) + return FALSE; + } + + if (! SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_PLTGOT, 0)) + return FALSE; + + if (score_elf_rel_dyn_section (dynobj, FALSE)) + { + if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_REL, 0)) + return FALSE; + + if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELSZ, 0)) + return FALSE; + + if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_RELENT, 0)) + return FALSE; + } + + if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_BASE_ADDRESS, 0)) + return FALSE; + + if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_LOCAL_GOTNO, 0)) + return FALSE; + + if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_SYMTABNO, 0)) + return FALSE; + + if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_UNREFEXTNO, 0)) + return FALSE; + + if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_GOTSYM, 0)) + return FALSE; + + if (!SCORE_ELF_ADD_DYNAMIC_ENTRY (info, DT_SCORE_HIPAGENO, 0)) + return FALSE; + } + + return TRUE; +} + +bfd_boolean +s7_bfd_score_elf_create_dynamic_sections (bfd *abfd, struct bfd_link_info *info) +{ + struct elf_link_hash_entry *h; + struct bfd_link_hash_entry *bh; + flagword flags; + asection *s; + + flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY + | SEC_LINKER_CREATED | SEC_READONLY); + + /* ABI requests the .dynamic section to be read only. */ + s = bfd_get_section_by_name (abfd, ".dynamic"); + if (s != NULL) + { + if (!bfd_set_section_flags (abfd, s, flags)) + return FALSE; + } + + /* We need to create .got section. */ + if (!score_elf_create_got_section (abfd, info, FALSE)) + return FALSE; + + if (!score_elf_rel_dyn_section (elf_hash_table (info)->dynobj, TRUE)) + return FALSE; + + /* Create .stub section. */ + if (bfd_get_section_by_name (abfd, SCORE_ELF_STUB_SECTION_NAME) == NULL) + { + s = bfd_make_section_with_flags (abfd, SCORE_ELF_STUB_SECTION_NAME, + flags | SEC_CODE); + if (s == NULL + || !bfd_set_section_alignment (abfd, s, 2)) + + return FALSE; + } + + if (!info->shared) + { + const char *name; + + name = "_DYNAMIC_LINK"; + bh = NULL; + if (!(_bfd_generic_link_add_one_symbol + (info, abfd, name, BSF_GLOBAL, bfd_abs_section_ptr, + (bfd_vma) 0, NULL, FALSE, get_elf_backend_data (abfd)->collect, &bh))) + return FALSE; + + h = (struct elf_link_hash_entry *) bh; + h->non_elf = 0; + h->def_regular = 1; + h->type = STT_SECTION; + + if (!bfd_elf_link_record_dynamic_symbol (info, h)) + return FALSE; + } + + return TRUE; +} + + +/* Finish up dynamic symbol handling. We set the contents of various + dynamic sections here. */ + +bfd_boolean +s7_bfd_score_elf_finish_dynamic_symbol (bfd *output_bfd, + struct bfd_link_info *info, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym) +{ + bfd *dynobj; + asection *sgot; + struct score_got_info *g; + const char *name; + + dynobj = elf_hash_table (info)->dynobj; + + if (h->plt.offset != MINUS_ONE) + { + asection *s; + bfd_byte stub[SCORE_FUNCTION_STUB_SIZE]; + + /* This symbol has a stub. Set it up. */ + BFD_ASSERT (h->dynindx != -1); + + s = bfd_get_section_by_name (dynobj, SCORE_ELF_STUB_SECTION_NAME); + BFD_ASSERT (s != NULL); + + /* FIXME: Can h->dynindex be more than 64K? */ + if (h->dynindx & 0xffff0000) + return FALSE; + + /* Fill the stub. */ + bfd_put_32 (output_bfd, STUB_LW, stub); + bfd_put_32 (output_bfd, STUB_MOVE, stub + 4); + bfd_put_32 (output_bfd, STUB_LI16 | (h->dynindx << 1), stub + 8); + bfd_put_32 (output_bfd, STUB_BRL, stub + 12); + + BFD_ASSERT (h->plt.offset <= s->size); + memcpy (s->contents + h->plt.offset, stub, SCORE_FUNCTION_STUB_SIZE); + + /* Mark the symbol as undefined. plt.offset != -1 occurs + only for the referenced symbol. */ + sym->st_shndx = SHN_UNDEF; + + /* The run-time linker uses the st_value field of the symbol + to reset the global offset table entry for this external + to its stub address when unlinking a shared object. */ + sym->st_value = (s->output_section->vma + s->output_offset + h->plt.offset); + } + + BFD_ASSERT (h->dynindx != -1 || h->forced_local); + + sgot = score_elf_got_section (dynobj, FALSE); + BFD_ASSERT (sgot != NULL); + BFD_ASSERT (score_elf_section_data (sgot) != NULL); + g = score_elf_section_data (sgot)->u.got_info; + BFD_ASSERT (g != NULL); + + /* Run through the global symbol table, creating GOT entries for all + the symbols that need them. */ + if (g->global_gotsym != NULL && h->dynindx >= g->global_gotsym->dynindx) + { + bfd_vma offset; + bfd_vma value; + + value = sym->st_value; + offset = score_elf_global_got_index (dynobj, h); + bfd_put_32 (output_bfd, value, sgot->contents + offset); + } + + /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */ + name = h->root.root.string; + if (strcmp (name, "_DYNAMIC") == 0 || strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0) + sym->st_shndx = SHN_ABS; + else if (strcmp (name, "_DYNAMIC_LINK") == 0) + { + sym->st_shndx = SHN_ABS; + sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION); + sym->st_value = 1; + } + else if (strcmp (name, GP_DISP_LABEL) == 0) + { + sym->st_shndx = SHN_ABS; + sym->st_info = ELF_ST_INFO (STB_GLOBAL, STT_SECTION); + sym->st_value = elf_gp (output_bfd); + } + + return TRUE; +} + +/* Finish up the dynamic sections. */ + +bfd_boolean +s7_bfd_score_elf_finish_dynamic_sections (bfd *output_bfd, + struct bfd_link_info *info) +{ + bfd *dynobj; + asection *sdyn; + asection *sgot; + asection *s; + struct score_got_info *g; + + dynobj = elf_hash_table (info)->dynobj; + + sdyn = bfd_get_section_by_name (dynobj, ".dynamic"); + + sgot = score_elf_got_section (dynobj, FALSE); + if (sgot == NULL) + g = NULL; + else + { + BFD_ASSERT (score_elf_section_data (sgot) != NULL); + g = score_elf_section_data (sgot)->u.got_info; + BFD_ASSERT (g != NULL); + } + + if (elf_hash_table (info)->dynamic_sections_created) + { + bfd_byte *b; + + BFD_ASSERT (sdyn != NULL); + BFD_ASSERT (g != NULL); + + for (b = sdyn->contents; + b < sdyn->contents + sdyn->size; + b += SCORE_ELF_DYN_SIZE (dynobj)) + { + Elf_Internal_Dyn dyn; + const char *name; + size_t elemsize; + bfd_boolean swap_out_p; + + /* Read in the current dynamic entry. */ + (*get_elf_backend_data (dynobj)->s->swap_dyn_in) (dynobj, b, &dyn); + + /* Assume that we're going to modify it and write it out. */ + swap_out_p = TRUE; + + switch (dyn.d_tag) + { + case DT_RELENT: + s = score_elf_rel_dyn_section (dynobj, FALSE); + BFD_ASSERT (s != NULL); + dyn.d_un.d_val = SCORE_ELF_REL_SIZE (dynobj); + break; + + case DT_STRSZ: + /* Rewrite DT_STRSZ. */ + dyn.d_un.d_val = _bfd_elf_strtab_size (elf_hash_table (info)->dynstr); + break; + + case DT_PLTGOT: + name = ".got"; + s = bfd_get_section_by_name (output_bfd, name); + BFD_ASSERT (s != NULL); + dyn.d_un.d_ptr = s->vma; + break; + + case DT_SCORE_BASE_ADDRESS: + s = output_bfd->sections; + BFD_ASSERT (s != NULL); + dyn.d_un.d_ptr = s->vma & ~(bfd_vma) 0xffff; + break; + + case DT_SCORE_LOCAL_GOTNO: + dyn.d_un.d_val = g->local_gotno; + break; + + case DT_SCORE_UNREFEXTNO: + /* The index into the dynamic symbol table which is the + entry of the first external symbol that is not + referenced within the same object. */ + dyn.d_un.d_val = bfd_count_sections (output_bfd) + 1; + break; + + case DT_SCORE_GOTSYM: + if (g->global_gotsym) + { + dyn.d_un.d_val = g->global_gotsym->dynindx; + break; + } + /* In case if we don't have global got symbols we default + to setting DT_SCORE_GOTSYM to the same value as + DT_SCORE_SYMTABNO, so we just fall through. */ + + case DT_SCORE_SYMTABNO: + name = ".dynsym"; + elemsize = SCORE_ELF_SYM_SIZE (output_bfd); + s = bfd_get_section_by_name (output_bfd, name); + BFD_ASSERT (s != NULL); + + dyn.d_un.d_val = s->size / elemsize; + break; + + case DT_SCORE_HIPAGENO: + dyn.d_un.d_val = g->local_gotno - SCORE_RESERVED_GOTNO; + break; + + default: + swap_out_p = FALSE; + break; + } + + if (swap_out_p) + (*get_elf_backend_data (dynobj)->s->swap_dyn_out) (dynobj, &dyn, b); + } + } + + /* The first entry of the global offset table will be filled at + runtime. The second entry will be used by some runtime loaders. + This isn't the case of IRIX rld. */ + if (sgot != NULL && sgot->size > 0) + { + bfd_put_32 (output_bfd, 0, sgot->contents); + bfd_put_32 (output_bfd, 0x80000000, sgot->contents + SCORE_ELF_GOT_SIZE (output_bfd)); + } + + if (sgot != NULL) + elf_section_data (sgot->output_section)->this_hdr.sh_entsize + = SCORE_ELF_GOT_SIZE (output_bfd); + + + /* We need to sort the entries of the dynamic relocation section. */ + s = score_elf_rel_dyn_section (dynobj, FALSE); + + if (s != NULL && s->size > (bfd_vma)2 * SCORE_ELF_REL_SIZE (output_bfd)) + { + reldyn_sorting_bfd = output_bfd; + qsort ((Elf32_External_Rel *) s->contents + 1, s->reloc_count - 1, + sizeof (Elf32_External_Rel), score_elf_sort_dynamic_relocs); + } + + return TRUE; +} + +/* This function set up the ELF section header for a BFD section in preparation for writing + it out. This is where the flags and type fields are set for unusual sections. */ + +bfd_boolean +s7_bfd_score_elf_fake_sections (bfd *abfd ATTRIBUTE_UNUSED, + Elf_Internal_Shdr *hdr, + asection *sec) +{ + const char *name; + + name = bfd_get_section_name (abfd, sec); + + if (strcmp (name, ".got") == 0 + || strcmp (name, ".srdata") == 0 + || strcmp (name, ".sdata") == 0 + || strcmp (name, ".sbss") == 0) + hdr->sh_flags |= SHF_SCORE_GPREL; + + return TRUE; +} + +/* This function do additional processing on the ELF section header before writing + it out. This is used to set the flags and type fields for some sections. */ + +/* assign_file_positions_except_relocs() check section flag and if it is allocatable, + warning message will be issued. backend_fake_section is called before + assign_file_positions_except_relocs(); backend_section_processing after it. so, we + modify section flag there, but not backend_fake_section. */ + +bfd_boolean +s7_bfd_score_elf_section_processing (bfd *abfd ATTRIBUTE_UNUSED, Elf_Internal_Shdr *hdr) +{ + if (hdr->bfd_section != NULL) + { + const char *name = bfd_get_section_name (abfd, hdr->bfd_section); + + if (strcmp (name, ".sdata") == 0) + { + hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_SCORE_GPREL; + hdr->sh_type = SHT_PROGBITS; + } + else if (strcmp (name, ".sbss") == 0) + { + hdr->sh_flags |= SHF_ALLOC | SHF_WRITE | SHF_SCORE_GPREL; + hdr->sh_type = SHT_NOBITS; + } + else if (strcmp (name, ".srdata") == 0) + { + hdr->sh_flags |= SHF_ALLOC | SHF_SCORE_GPREL; + hdr->sh_type = SHT_PROGBITS; + } + } + + return TRUE; +} + +bfd_boolean +s7_bfd_score_elf_write_section (bfd *output_bfd, asection *sec, bfd_byte *contents) +{ + bfd_byte *to, *from, *end; + int i; + + if (strcmp (sec->name, ".pdr") != 0) + return FALSE; + + if (score_elf_section_data (sec)->u.tdata == NULL) + return FALSE; + + to = contents; + end = contents + sec->size; + for (from = contents, i = 0; from < end; from += PDR_SIZE, i++) + { + if ((score_elf_section_data (sec)->u.tdata)[i] == 1) + continue; + + if (to != from) + memcpy (to, from, PDR_SIZE); + + to += PDR_SIZE; + } + bfd_set_section_contents (output_bfd, sec->output_section, contents, + (file_ptr) sec->output_offset, sec->size); + + return TRUE; +} + +/* Copy data from a SCORE ELF indirect symbol to its direct symbol, hiding the old + indirect symbol. Process additional relocation information. */ + +void +s7_bfd_score_elf_copy_indirect_symbol (struct bfd_link_info *info, + struct elf_link_hash_entry *dir, + struct elf_link_hash_entry *ind) +{ + struct score_elf_link_hash_entry *dirscore, *indscore; + + _bfd_elf_link_hash_copy_indirect (info, dir, ind); + + if (ind->root.type != bfd_link_hash_indirect) + return; + + dirscore = (struct score_elf_link_hash_entry *) dir; + indscore = (struct score_elf_link_hash_entry *) ind; + dirscore->possibly_dynamic_relocs += indscore->possibly_dynamic_relocs; + + if (indscore->readonly_reloc) + dirscore->readonly_reloc = TRUE; + + if (indscore->no_fn_stub) + dirscore->no_fn_stub = TRUE; +} + +/* Remove information about discarded functions from other sections which mention them. */ + +bfd_boolean +s7_bfd_score_elf_discard_info (bfd *abfd, + struct elf_reloc_cookie *cookie, + struct bfd_link_info *info) +{ + asection *o; + bfd_boolean ret = FALSE; + unsigned char *tdata; + size_t i, skip; + + o = bfd_get_section_by_name (abfd, ".pdr"); + if ((!o) || (o->size == 0) || (o->size % PDR_SIZE != 0) + || (o->output_section != NULL && bfd_is_abs_section (o->output_section))) + return FALSE; + + tdata = bfd_zmalloc (o->size / PDR_SIZE); + if (!tdata) + return FALSE; + + cookie->rels = _bfd_elf_link_read_relocs (abfd, o, NULL, NULL, info->keep_memory); + if (!cookie->rels) + { + free (tdata); + return FALSE; + } + + cookie->rel = cookie->rels; + cookie->relend = cookie->rels + o->reloc_count; + + for (i = 0, skip = 0; i < o->size; i++) + { + if (bfd_elf_reloc_symbol_deleted_p (i * PDR_SIZE, cookie)) + { + tdata[i] = 1; + skip++; + } + } + + if (skip != 0) + { + score_elf_section_data (o)->u.tdata = tdata; + o->size -= skip * PDR_SIZE; + ret = TRUE; + } + else + free (tdata); + + if (!info->keep_memory) + free (cookie->rels); + + return ret; +} + +/* Signal that discard_info() has removed the discarded relocations for this section. */ + +bfd_boolean +s7_bfd_score_elf_ignore_discarded_relocs (asection *sec) +{ + if (strcmp (sec->name, ".pdr") == 0) + return TRUE; + return FALSE; +} + +/* Return the section that should be marked against GC for a given + relocation. */ + +asection * +s7_bfd_score_elf_gc_mark_hook (asection *sec, + struct bfd_link_info *info, + Elf_Internal_Rela *rel, + struct elf_link_hash_entry *h, + Elf_Internal_Sym *sym) +{ + if (h != NULL) + switch (ELF32_R_TYPE (rel->r_info)) + { + case R_SCORE_GNU_VTINHERIT: + case R_SCORE_GNU_VTENTRY: + return NULL; + } + + return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym); +} + +/* Support for core dump NOTE sections. */ + +bfd_boolean +s7_bfd_score_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) +{ + int offset; + unsigned int raw_size; + + switch (note->descsz) + { + default: + return FALSE; + case 272: /* Linux/Score elf_prstatus */ + + /* pr_cursig */ + elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12); + + /* pr_pid */ + elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 24); + + /* pr_reg */ + offset = 72; + + /* sizeof(elf_gregset_t) */ + raw_size = 196; + + break; + } + + /* Make a ".reg/999" section. */ + return _bfd_elfcore_make_pseudosection (abfd, ".reg", raw_size, note->descpos + offset); +} + +bfd_boolean +s7_bfd_score_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note) +{ + switch (note->descsz) + { + default: + return FALSE; + + case 128: /* Linux/Score elf_prpsinfo. */ + /* pr_fname */ + elf_tdata (abfd)->core_program = _bfd_elfcore_strndup (abfd, note->descdata + 32, 16); + + /* pr_psargs */ + elf_tdata (abfd)->core_command = _bfd_elfcore_strndup (abfd, note->descdata + 48, 80); + break; + } + + /* Note that for some reason, a spurious space is tacked + onto the end of the args in some (at least one anyway) + implementations, so strip it off if it exists. */ + + { + char *command = elf_tdata (abfd)->core_command; + int n = strlen (command); + + if (0 < n && command[n - 1] == ' ') + command[n - 1] = '\0'; + } + + return TRUE; +} + + +/* Score BFD functions. */ + +reloc_howto_type * +s7_elf32_score_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE (elf32_score_reloc_map); i++) + if (elf32_score_reloc_map[i].bfd_reloc_val == code) + return &elf32_score_howto_table[elf32_score_reloc_map[i].elf_reloc_val]; + + return NULL; +} + +/* Create a score elf linker hash table. */ + +struct bfd_link_hash_table * +s7_elf32_score_link_hash_table_create (bfd *abfd) +{ + struct score_elf_link_hash_table *ret; + bfd_size_type amt = sizeof (struct score_elf_link_hash_table); + + ret = bfd_malloc (amt); + if (ret == NULL) + return NULL; + + if (!_bfd_elf_link_hash_table_init (&ret->root, abfd, score_elf_link_hash_newfunc, + sizeof (struct score_elf_link_hash_entry))) + { + free (ret); + return NULL; + } + + return &ret->root.root; +} + +bfd_boolean +s7_elf32_score_print_private_bfd_data (bfd *abfd, void * ptr) +{ + FILE *file = (FILE *) ptr; + + BFD_ASSERT (abfd != NULL && ptr != NULL); + + /* Print normal ELF private data. */ + _bfd_elf_print_private_bfd_data (abfd, ptr); + + /* xgettext:c-format */ + fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags); + if (elf_elfheader (abfd)->e_flags & EF_SCORE_PIC) + { + fprintf (file, _(" [pic]")); + } + if (elf_elfheader (abfd)->e_flags & EF_SCORE_FIXDEP) + { + fprintf (file, _(" [fix dep]")); + } + fputc ('\n', file); + + return TRUE; +} + +bfd_boolean +s7_elf32_score_merge_private_bfd_data (bfd *ibfd, bfd *obfd) +{ + flagword in_flags; + flagword out_flags; + + if (!_bfd_generic_verify_endian_match (ibfd, obfd)) + return FALSE; + + in_flags = elf_elfheader (ibfd)->e_flags; + out_flags = elf_elfheader (obfd)->e_flags; + + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour + || bfd_get_flavour (obfd) != bfd_target_elf_flavour) + return TRUE; + + in_flags = elf_elfheader (ibfd)->e_flags; + out_flags = elf_elfheader (obfd)->e_flags; + + if (! elf_flags_init (obfd)) + { + elf_flags_init (obfd) = TRUE; + elf_elfheader (obfd)->e_flags = in_flags; + + if (bfd_get_arch (obfd) == bfd_get_arch (ibfd) + && bfd_get_arch_info (obfd)->the_default) + { + return bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd)); + } + + return TRUE; + } + + if (((in_flags & EF_SCORE_PIC) != 0) != ((out_flags & EF_SCORE_PIC) != 0)) + { + (*_bfd_error_handler) (_("%B: warning: linking PIC files with non-PIC files"), ibfd); + } + + /* Maybe dependency fix compatibility should be checked here. */ + return TRUE; +} + +bfd_boolean +s7_elf32_score_new_section_hook (bfd *abfd, asection *sec) +{ + struct _score_elf_section_data *sdata; + bfd_size_type amt = sizeof (*sdata); + + sdata = bfd_zalloc (abfd, amt); + if (sdata == NULL) + return FALSE; + sec->used_by_bfd = sdata; + + return _bfd_elf_new_section_hook (abfd, sec); +} + +#define elf_backend_omit_section_dynsym \ + ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true) diff --git a/bfd/libbfd.h b/bfd/libbfd.h index 2ba7fc8b9df..5814863f9d8 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1683,13 +1683,15 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_390_GOT20", "BFD_RELOC_390_GOTPLT20", "BFD_RELOC_390_TLS_GOTIE20", - "BFD_RELOC_SCORE_DUMMY1", "BFD_RELOC_SCORE_GPREL15", "BFD_RELOC_SCORE_DUMMY2", "BFD_RELOC_SCORE_JMP", "BFD_RELOC_SCORE_BRANCH", + "BFD_RELOC_SCORE_IMM30", + "BFD_RELOC_SCORE_IMM32", "BFD_RELOC_SCORE16_JMP", "BFD_RELOC_SCORE16_BRANCH", + "BFD_RELOC_SCORE_BCMP", "BFD_RELOC_SCORE_GOT15", "BFD_RELOC_SCORE_GOT_LO16", "BFD_RELOC_SCORE_CALL15", diff --git a/bfd/reloc.c b/bfd/reloc.c index 781147e98aa..9e610255b1f 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -4194,13 +4194,10 @@ ENUMX ENUMDOC Long displacement extension. -ENUM - BFD_RELOC_SCORE_DUMMY1 -ENUMDOC - Score relocations ENUM BFD_RELOC_SCORE_GPREL15 ENUMDOC + Score relocations Low 16 bit for load/store ENUM BFD_RELOC_SCORE_DUMMY2 @@ -4212,6 +4209,14 @@ ENUM BFD_RELOC_SCORE_BRANCH ENUMDOC This is a 19-bit reloc with the right 1 bit assumed to be 0 +ENUM + BFD_RELOC_SCORE_IMM30 +ENUMDOC + This is a 32-bit reloc for 48-bit instructions. +ENUM + BFD_RELOC_SCORE_IMM32 +ENUMDOC + This is a 32-bit reloc for 48-bit instructions. ENUM BFD_RELOC_SCORE16_JMP ENUMDOC @@ -4220,6 +4225,10 @@ ENUM BFD_RELOC_SCORE16_BRANCH ENUMDOC This is a 8-bit reloc with the right 1 bit assumed to be 0 +ENUM + BFD_RELOC_SCORE_BCMP +ENUMDOC + This is a 9-bit reloc with the right 1 bit assumed to be 0 ENUM BFD_RELOC_SCORE_GOT15 ENUMX diff --git a/gas/ChangeLog b/gas/ChangeLog index 8b8db8ec3b6..bcf762d1651 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,17 @@ +2009-03-02 Qinwei + + * config/tc-score7.c: New file. + * doc/c-score.texi: New file. + * Makefile.am: Update dependencies for tc-score.c. + * Makefile.in: Regenerate. + * NEWS: Mention support for Score7 architecture. + * config/tc-score.c: Add support for Score7 architecture. + * config/tc-score.h: Likewise. + * doc/Makefile.am: Add c-score.texi. + * doc/Makefile.in: Regenerate. + * doc/all.texi: Add Score7. + * doc/as.texinfo: Add Score7. + 2009-03-01 Mark Mitchell * config/tc-arm.c (md_assemble): Allow barrier instructions on diff --git a/gas/Makefile.am b/gas/Makefile.am index 228624e79f3..3d18cf038ca 100644 --- a/gas/Makefile.am +++ b/gas/Makefile.am @@ -1396,8 +1396,9 @@ DEPTC_score_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ $(INCDIR)/elf/common.h $(INCDIR)/elf/external.h $(INCDIR)/elf/internal.h \ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-score.h dwarf2dbg.h \ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/safe-ctype.h \ - $(INCDIR)/opcode/score-inst.h $(INCDIR)/opcode/score-datadep.h \ - struc-symbol.h $(INCDIR)/elf/score.h $(INCDIR)/elf/reloc-macros.h + $(INCDIR)/opcode/score-inst.h $(srcdir)/config/tc-score7.c \ + struc-symbol.h $(INCDIR)/elf/score.h $(INCDIR)/elf/reloc-macros.h \ + dwarf2dbg.h DEPTC_sh_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-sh.h \ $(INCDIR)/coff/internal.h $(INCDIR)/coff/sh.h $(INCDIR)/coff/external.h \ $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h subsegs.h $(INCDIR)/obstack.h \ @@ -1786,8 +1787,8 @@ DEPOBJ_s390_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ DEPOBJ_score_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ $(INCDIR)/elf/common.h $(INCDIR)/elf/external.h $(INCDIR)/elf/internal.h \ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-score.h dwarf2dbg.h \ - $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \ - struc-symbol.h $(INCDIR)/aout/aout64.h + $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h $(srcdir)/config/tc-score7.c \ + $(INCDIR)/obstack.h struc-symbol.h dwarf2dbg.h $(INCDIR)/aout/aout64.h DEPOBJ_sh_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-sh.h \ $(INCDIR)/coff/internal.h $(INCDIR)/coff/sh.h $(INCDIR)/coff/external.h \ $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h $(INCDIR)/obstack.h \ @@ -2116,7 +2117,7 @@ DEP_score_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ $(INCDIR)/elf/common.h $(INCDIR)/elf/external.h $(INCDIR)/elf/internal.h \ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-score.h dwarf2dbg.h \ $(srcdir)/config/obj-coff.h $(INCDIR)/coff/internal.h \ - $(BFDDIR)/libcoff.h + $(BFDDIR)/libcoff.h $(srcdir)/config/tc-score7.c DEP_sh_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-sh.h \ $(INCDIR)/coff/internal.h $(INCDIR)/coff/sh.h $(INCDIR)/coff/external.h \ $(BFDDIR)/libcoff.h $(INCDIR)/bfdlink.h diff --git a/gas/Makefile.in b/gas/Makefile.in index 2cf670da49e..711701cda34 100644 --- a/gas/Makefile.in +++ b/gas/Makefile.in @@ -1200,7 +1200,7 @@ DEPTC_score_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ $(INCDIR)/elf/common.h $(INCDIR)/elf/external.h $(INCDIR)/elf/internal.h \ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-score.h dwarf2dbg.h \ subsegs.h $(INCDIR)/obstack.h $(INCDIR)/safe-ctype.h \ - $(INCDIR)/opcode/score-inst.h $(INCDIR)/opcode/score-datadep.h \ + $(INCDIR)/opcode/score-inst.h dwarf2dbg.h $(srcdir)/config/tc-score7.c \ struc-symbol.h $(INCDIR)/elf/score.h $(INCDIR)/elf/reloc-macros.h DEPTC_sh_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-sh.h \ @@ -1671,8 +1671,8 @@ DEPOBJ_s390_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ DEPOBJ_score_elf = $(srcdir)/config/obj-elf.h $(BFDDIR)/elf-bfd.h \ $(INCDIR)/elf/common.h $(INCDIR)/elf/external.h $(INCDIR)/elf/internal.h \ $(INCDIR)/bfdlink.h $(srcdir)/config/tc-score.h dwarf2dbg.h \ - $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h \ - struc-symbol.h $(INCDIR)/aout/aout64.h + $(INCDIR)/safe-ctype.h subsegs.h $(INCDIR)/obstack.h $(srcdir)/config/tc-score7.c \ + $(INCDIR)/obstack.h struc-symbol.h dwarf2dbg.h $(INCDIR)/aout/aout64.h DEPOBJ_sh_coff = $(srcdir)/config/obj-coff.h $(srcdir)/config/tc-sh.h \ $(INCDIR)/coff/internal.h $(INCDIR)/coff/sh.h $(INCDIR)/coff/external.h \ diff --git a/gas/NEWS b/gas/NEWS index e3fed78f3d6..d4a69189fa6 100644 --- a/gas/NEWS +++ b/gas/NEWS @@ -1,5 +1,7 @@ -*- text -*- +* Add support for Sunplus score architecture. + * Add support for Lattice Mico32 (lm32) architecture. Changes in 2.19: diff --git a/gas/config/tc-score.c b/gas/config/tc-score.c index 5c12bd56726..3b0450862d7 100644 --- a/gas/config/tc-score.c +++ b/gas/config/tc-score.c @@ -1,6 +1,7 @@ /* tc-score.c -- Assembler for Score - Copyright 2006, 2007 Free Software Foundation, Inc. + Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by: + Brain.lin (brain.lin@sunplusct.com) Mei Ligang (ligang@sunnorth.com.cn) Pei-Lin Tsai (pltsai@sunplus.com) @@ -21,44 +22,251 @@ Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "as.h" -#include "config.h" -#include "subsegs.h" -#include "safe-ctype.h" -#include "opcode/score-inst.h" -#include "opcode/score-datadep.h" -#include "struc-symbol.h" +#include "tc-score7.c" + +static void s3_s_score_bss (int ignore ATTRIBUTE_UNUSED); +static void s3_s_score_text (int ignore); +static void s3_score_s_section (int ignore); +static void s3_s_change_sec (int sec); +static void s3_s_score_mask (int reg_type ATTRIBUTE_UNUSED); +static void s3_s_score_ent (int aent); +static void s3_s_score_frame (int ignore ATTRIBUTE_UNUSED); +static void s3_s_score_end (int x ATTRIBUTE_UNUSED); +static void s3_s_score_set (int x ATTRIBUTE_UNUSED); +static void s3_s_score_cpload (int ignore ATTRIBUTE_UNUSED); +static void s3_s_score_cprestore (int ignore ATTRIBUTE_UNUSED); +static void s3_s_score_gpword (int ignore ATTRIBUTE_UNUSED); +static void s3_s_score_cpadd (int ignore ATTRIBUTE_UNUSED); +static void s3_s_score_lcomm (int bytes_p); + +static void s_score_bss (int ignore ATTRIBUTE_UNUSED); +static void s_score_text (int ignore); +static void s_section (int ignore); +static void s_change_sec (int sec); +static void s_score_mask (int reg_type ATTRIBUTE_UNUSED); +static void s_score_ent (int aent); +static void s_score_frame (int ignore ATTRIBUTE_UNUSED); +static void s_score_end (int x ATTRIBUTE_UNUSED); +static void s_score_set (int x ATTRIBUTE_UNUSED); +static void s_score_cpload (int ignore ATTRIBUTE_UNUSED); +static void s_score_cprestore (int ignore ATTRIBUTE_UNUSED); +static void s_score_gpword (int ignore ATTRIBUTE_UNUSED); +static void s_score_cpadd (int ignore ATTRIBUTE_UNUSED); +static void s_score_lcomm (int bytes_p); + +/* s3: hooks. */ +static void s3_md_number_to_chars (char *buf, valueT val, int n); +static valueT s3_md_chars_to_number (char *buf, int n); +static void s3_assemble (char *str); +static void s3_operand (expressionS * expr); +static void s3_begin (void); +static void s3_number_to_chars (char *buf, valueT val, int n); +static char *s3_atof (int type, char *litP, int *sizeP); +static void s3_frag_check (fragS * fragp ATTRIBUTE_UNUSED); +static void s3_validate_fix (fixS *fixP); +static int s3_force_relocation (struct fix *fixp); +static bfd_boolean s3_fix_adjustable (fixS * fixP); +static void s3_elf_final_processing (void); +static int s3_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED); +static int s3_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED); +static void s3_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp); +static long s3_pcrel_from (fixS * fixP); +static valueT s3_section_align (segT segment ATTRIBUTE_UNUSED, valueT size); +static void s3_apply_fix (fixS *fixP, valueT *valP, segT seg); +static arelent **s3_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp); + +/* s3: utils. */ +static void s3_do_ldst_insn (char *); +static void s3_do_crdcrscrsimm5 (char *); +static void s3_do_ldst_unalign (char *); +static void s3_do_ldst_atomic (char *); +static void s3_do_ldst_cop (char *); +static void s3_do_macro_li_rdi32 (char *); +static void s3_do_macro_la_rdi32 (char *); +static void s3_do_macro_rdi32hi (char *); +static void s3_do_macro_rdi32lo (char *); +static void s3_do_macro_mul_rdrsrs (char *); +static void s3_do_macro_bcmp (char *); +static void s3_do_macro_bcmpz (char *); +static void s3_do_macro_ldst_label (char *); +static void s3_do_branch (char *); +static void s3_do_jump (char *); +static void s3_do_empty (char *); +static void s3_do16_int (char *); +static void s3_do_rdrsrs (char *); +static void s3_do_rdsi16 (char *); +static void s3_do_rdrssi14 (char *); +static void s3_do_sub_rdsi16 (char *); +static void s3_do_sub_rdi16 (char *); +static void s3_do_sub_rdrssi14 (char *); +static void s3_do_rdrsi5 (char *); +static void s3_do_rdrsi14 (char *); +static void s3_do_rdi16 (char *); +static void s3_do_ldis (char *); +static void s3_do_xrsi5 (char *); +static void s3_do_rdrs (char *); +static void s3_do_rdxrs (char *); +static void s3_do_rsrs (char *); +static void s3_do_rdcrs (char *); +static void s3_do_rdsrs (char *); +static void s3_do_rd (char *); +static void s3_do16_dsp (char *); +static void s3_do16_dsp2 (char *); +static void s3_do_dsp (char *); +static void s3_do_dsp2 (char *); +static void s3_do_dsp3 (char *); +static void s3_do_rs (char *); +static void s3_do_i15 (char *); +static void s3_do_xi5x (char *); +static void s3_do_ceinst (char *); +static void s3_do_cache (char *); +static void s3_do16_rdrs2 (char *); +static void s3_do16_br (char *); +static void s3_do16_brr (char *); +static void s3_do_ltb (char *); +static void s3_do16_mv_cmp (char *); +static void s3_do16_addi (char *); +static void s3_do16_cmpi (char *); +static void s3_do16_rdi5 (char *); +static void s3_do16_xi5 (char *); +static void s3_do16_ldst_insn (char *); +static void s3_do16_slli_srli(char *); +static void s3_do16_ldiu(char *); +static void s3_do16_push_pop (char *); +static void s3_do16_rpush (char *); +static void s3_do16_rpop (char *); +static void s3_do16_branch (char *); +static void s3_do_lw48 (char *); +static void s3_do_sw48 (char *); +static void s3_do_ldi48 (char *); +static void s3_do_sdbbp48 (char *); +static void s3_do_and48 (char *); +static void s3_do_or48 (char *); +static void s3_do_mbitclr (char *); +static void s3_do_mbitset (char *); +static void s3_do_rdi16_pic (char *); +static void s3_do_addi_s_pic (char *); +static void s3_do_addi_u_pic (char *); +static void s3_do_lw_pic (char *); + +#define MARCH_SCORE3 "score3" +#define MARCH_SCORE3D "score3d" +#define MARCH_SCORE7 "score7" +#define MARCH_SCORE7D "score7d" +#define MARCH_SCORE5 "score5" +#define MARCH_SCORE5U "score5u" + +#define SCORE_BI_ENDIAN + +#ifdef SCORE_BI_ENDIAN +#define OPTION_EB (OPTION_MD_BASE + 0) +#define OPTION_EL (OPTION_MD_BASE + 1) +#else +#if TARGET_BYTES_BIG_ENDIAN +#define OPTION_EB (OPTION_MD_BASE + 0) +#else +#define OPTION_EL (OPTION_MD_BASE + 1) +#endif +#endif +#define OPTION_FIXDD (OPTION_MD_BASE + 2) +#define OPTION_NWARN (OPTION_MD_BASE + 3) +#define OPTION_SCORE5 (OPTION_MD_BASE + 4) +#define OPTION_SCORE5U (OPTION_MD_BASE + 5) +#define OPTION_SCORE7 (OPTION_MD_BASE + 6) +#define OPTION_R1 (OPTION_MD_BASE + 7) +#define OPTION_O0 (OPTION_MD_BASE + 8) +#define OPTION_SCORE_VERSION (OPTION_MD_BASE + 9) +#define OPTION_PIC (OPTION_MD_BASE + 10) +#define OPTION_MARCH (OPTION_MD_BASE + 11) +#define OPTION_SCORE3 (OPTION_MD_BASE + 12) + +/* This array holds the chars that always start a comment. If the + pre-processor is disabled, these aren't very useful. */ +const char comment_chars[] = "#"; +const char line_comment_chars[] = "#"; +const char line_separator_chars[] = ";"; +/* Chars that can be used to separate mant from exp in floating point numbers. */ +const char EXP_CHARS[] = "eE"; +const char FLT_CHARS[] = "rRsSfFdDxXeEpP"; #ifdef OBJ_ELF -#include "elf/score.h" -#include "dwarf2dbg.h" +/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */ +symbolS *GOT_symbol; +#endif + +const pseudo_typeS md_pseudo_table[] = +{ + {"bss", s_score_bss, 0}, + {"text", s_score_text, 0}, + {"word", cons, 4}, + {"long", cons, 4}, + {"extend", float_cons, 'x'}, + {"ldouble", float_cons, 'x'}, + {"packed", float_cons, 'p'}, + {"end", s_score_end, 0}, + {"ent", s_score_ent, 0}, + {"frame", s_score_frame, 0}, + {"rdata", s_change_sec, 'r'}, + {"sdata", s_change_sec, 's'}, + {"set", s_score_set, 0}, + {"mask", s_score_mask, 'R'}, + {"dword", cons, 8}, + {"lcomm", s_score_lcomm, 1}, + {"section", s_section, 0}, + {"cpload", s_score_cpload, 0}, + {"cprestore", s_score_cprestore, 0}, + {"gpword", s_score_gpword, 0}, + {"cpadd", s_score_cpadd, 0}, + {0, 0, 0} +}; + +const char *md_shortopts = "nO::g::G:"; +struct option md_longopts[] = +{ +#ifdef OPTION_EB + {"EB" , no_argument, NULL, OPTION_EB}, +#endif +#ifdef OPTION_EL + {"EL" , no_argument, NULL, OPTION_EL}, #endif + {"FIXDD" , no_argument, NULL, OPTION_FIXDD}, + {"NWARN" , no_argument, NULL, OPTION_NWARN}, + {"SCORE5" , no_argument, NULL, OPTION_SCORE5}, + {"SCORE5U", no_argument, NULL, OPTION_SCORE5U}, + {"SCORE7" , no_argument, NULL, OPTION_SCORE7}, + {"USE_R1" , no_argument, NULL, OPTION_R1}, + {"O0" , no_argument, NULL, OPTION_O0}, + {"V" , no_argument, NULL, OPTION_SCORE_VERSION}, + {"KPIC" , no_argument, NULL, OPTION_PIC}, + {"march=" , required_argument, NULL, OPTION_MARCH}, + {"SCORE3" , no_argument, NULL, OPTION_SCORE3}, + {NULL , no_argument, NULL, 0} +}; + +size_t md_longopts_size = sizeof (md_longopts); -#define GP 28 -#define PIC_CALL_REG 29 -#define MAX_LITERAL_POOL_SIZE 1024 -#define FAIL 0x80000000 -#define SUCCESS 0 -#define INSN_SIZE 4 -#define INSN16_SIZE 2 -#define RELAX_INST_NUM 3 +#define s3_GP 28 +#define s3_PIC_CALL_REG 29 +#define s3_MAX_LITERAL_POOL_SIZE 1024 +#define s3_FAIL 0x80000000 +#define s3_SUCCESS 0 +#define s3_INSN48_SIZE 6 +#define s3_INSN_SIZE 4 +#define s3_INSN16_SIZE 2 +#define s3_RELAX_INST_NUM 3 /* For score5u : div/mul will pop warning message, mmu/alw/asw will pop error message. */ -#define BAD_ARGS _("bad arguments to instruction") -#define BAD_PC _("r15 not allowed here") -#define BAD_COND _("instruction is not conditional") -#define ERR_NO_ACCUM _("acc0 expected") -#define ERR_FOR_SCORE5U_MUL_DIV _("div / mul are reserved instructions") -#define ERR_FOR_SCORE5U_MMU _("This architecture doesn't support mmu") -#define ERR_FOR_SCORE5U_ATOMIC _("This architecture doesn't support atomic instruction") -#define LONG_LABEL_LEN _("the label length is longer than 1024"); -#define BAD_SKIP_COMMA BAD_ARGS -#define BAD_GARBAGE _("garbage following instruction"); - -#define skip_whitespace(str) while (*(str) == ' ') ++(str) +#define s3_BAD_ARGS _("bad arguments to instruction") +#define s3_ERR_FOR_SCORE5U_MUL_DIV _("div / mul are reserved instructions") +#define s3_ERR_FOR_SCORE5U_MMU _("This architecture doesn't support mmu") +#define s3_ERR_FOR_SCORE5U_ATOMIC _("This architecture doesn't support atomic instruction") +#define s3_BAD_SKIP_COMMA s3_BAD_ARGS +#define s3_BAD_GARBAGE _("garbage following instruction"); + +#define s3_skip_whitespace(str) while (*(str) == ' ') ++(str) /* The name of the readonly data section. */ -#define RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \ +#define s3_RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \ ? ".data" \ : OUTPUT_FLAVOR == bfd_target_ecoff_flavour \ ? ".rdata" \ @@ -68,7 +276,7 @@ ? ".rodata" \ : (abort (), "")) -#define RELAX_ENCODE(old, new, type, reloc1, reloc2, opt) \ +#define s3_RELAX_ENCODE(old, new, type, reloc1, reloc2, opt) \ ((relax_substateT) \ (((old) << 23) \ | ((new) << 16) \ @@ -77,76 +285,113 @@ | ((reloc2) << 1) \ | ((opt) ? 1 : 0))) -#define RELAX_OLD(i) (((i) >> 23) & 0x7f) -#define RELAX_NEW(i) (((i) >> 16) & 0x7f) -#define RELAX_TYPE(i) (((i) >> 9) & 0x7f) -#define RELAX_RELOC1(i) ((valueT) ((i) >> 5) & 0xf) -#define RELAX_RELOC2(i) ((valueT) ((i) >> 1) & 0xf) -#define RELAX_OPT(i) ((i) & 1) -#define RELAX_OPT_CLEAR(i) ((i) & ~1) +#define s3_RELAX_OLD(i) (((i) >> 23) & 0x7f) +#define s3_RELAX_NEW(i) (((i) >> 16) & 0x7f) +#define s3_RELAX_TYPE(i) (((i) >> 9) & 0x7f) +#define s3_RELAX_RELOC1(i) ((valueT) ((i) >> 5) & 0xf) +#define s3_RELAX_RELOC2(i) ((valueT) ((i) >> 1) & 0xf) +#define s3_RELAX_OPT(i) ((i) & 1) -#define SET_INSN_ERROR(s) (inst.error = (s)) -#define INSN_IS_PCE_P(s) (strstr (str, "||") != NULL) +#define s3_SET_INSN_ERROR(s) (s3_inst.error = (s)) +#define s3_INSN_IS_PCE_P(s) (strstr (str, "||") != NULL) +#define s3_INSN_IS_48_P(s) (strstr (str, "48") != NULL) +#define s3_GET_INSN_CLASS(type) (s3_get_insn_class_from_type (type)) +#define s3_GET_INSN_SIZE(type) ((s3_GET_INSN_CLASS (type) == INSN_CLASS_16) \ + ? s3_INSN16_SIZE : (s3_GET_INSN_CLASS (type) == INSN_CLASS_48) \ + ? s3_INSN48_SIZE : s3_INSN_SIZE) -#define GET_INSN_CLASS(type) (get_insn_class_from_type (type)) +#define s3_MAX_LITTLENUMS 6 +#define s3_INSN_NAME_LEN 16 -#define GET_INSN_SIZE(type) ((GET_INSN_CLASS (type) == INSN_CLASS_16) \ - ? INSN16_SIZE : INSN_SIZE) +/* Relax will need some padding for alignment. */ +#define s3_RELAX_PAD_BYTE 3 -/* This array holds the chars that always start a comment. If the - pre-processor is disabled, these aren't very useful. */ -const char comment_chars[] = "#"; -const char line_comment_chars[] = "#"; -const char line_separator_chars[] = ";"; -/* Chars that can be used to separate mant from exp in floating point numbers. */ -const char EXP_CHARS[] = "eE"; -const char FLT_CHARS[] = "rRsSfFdDxXeEpP"; +#define s3_USE_GLOBAL_POINTER_OPT 1 -/* Used to contain constructed error messages. */ -static char err_msg[255]; +/* Enumeration matching entries in table above. */ +enum s3_score_reg_type +{ + s3_REG_TYPE_SCORE = 0, +#define s3_REG_TYPE_FIRST s3_REG_TYPE_SCORE + s3_REG_TYPE_SCORE_SR = 1, + s3_REG_TYPE_SCORE_CR = 2, + s3_REG_TYPE_MAX = 3 +}; + +enum s3_score_pic_level +{ + s3_NO_PIC, + s3_PIC +}; +static enum s3_score_pic_level s3_score_pic = s3_NO_PIC; -fragS *score_fragp = 0; -static int fix_data_dependency = 0; -static int warn_fix_data_dependency = 1; -static int score7 = 1; -static int university_version = 0; +enum s3_insn_type_for_dependency +{ + s3_D_mtcr, + s3_D_all_insn +}; -static int in_my_get_expression = 0; +struct s3_insn_to_dependency +{ + char *insn_name; + enum s3_insn_type_for_dependency type; +}; -#define USE_GLOBAL_POINTER_OPT 1 -#define SCORE_BI_ENDIAN +struct s3_data_dependency +{ + enum s3_insn_type_for_dependency pre_insn_type; + char pre_reg[6]; + enum s3_insn_type_for_dependency cur_insn_type; + char cur_reg[6]; + int bubblenum_7; + int bubblenum_3; + int warn_or_error; /* warning - 0; error - 1 */ +}; + +static const struct s3_insn_to_dependency s3_insn_to_dependency_table[] = +{ + /* move spectial instruction. */ + {"mtcr", s3_D_mtcr}, +}; + +static const struct s3_data_dependency s3_data_dependency_table[] = +{ + /* Status regiser. */ + {s3_D_mtcr, "cr0", s3_D_all_insn, "", 5, 1, 0}, +}; + +/* Used to contain constructed error messages. */ +static char s3_err_msg[255]; + +static int s3_fix_data_dependency = 0; +static int s3_warn_fix_data_dependency = 1; + +static int s3_in_my_get_expression = 0; /* Default, pop warning message when using r1. */ -static int nor1 = 1; +static int s3_nor1 = 1; -/* Default will do instruction relax, -O0 will set g_opt = 0. */ -static unsigned int g_opt = 1; +/* Default will do instruction relax, -O0 will set s3_g_opt = 0. */ +static unsigned int s3_g_opt = 1; /* The size of the small data section. */ -static unsigned int g_switch_value = 8; - -#ifdef OBJ_ELF -/* Pre-defined "_GLOBAL_OFFSET_TABLE_" */ -symbolS *GOT_symbol; -#endif -static segT pdr_seg; +static unsigned int s3_g_switch_value = 8; -enum score_pic_level score_pic = NO_PIC; +static segT s3_pdr_seg; -#define INSN_NAME_LEN 16 -struct score_it +struct s3_score_it { - char name[INSN_NAME_LEN]; - unsigned long instruction; - unsigned long relax_inst; + char name[s3_INSN_NAME_LEN]; + bfd_vma instruction; + bfd_vma relax_inst; int size; int relax_size; enum score_insn_type type; - char str[MAX_LITERAL_POOL_SIZE]; + char str[s3_MAX_LITERAL_POOL_SIZE]; const char *error; int bwarn; - char reg[INSN_NAME_LEN]; + char reg[s3_INSN_NAME_LEN]; struct { bfd_reloc_code_real_type type; @@ -154,9 +399,9 @@ struct score_it int pc_rel; }reloc; }; -struct score_it inst; +static struct s3_score_it s3_inst; -typedef struct proc +typedef struct s3_proc { symbolS *isym; unsigned long reg_mask; @@ -166,29 +411,20 @@ typedef struct proc unsigned long frame_offset; unsigned long frame_reg; unsigned long pc_reg; -} -procS; - -static procS cur_proc; -static procS *cur_proc_ptr; -static int numprocs; +} s3_procS; +static s3_procS s3_cur_proc; +static s3_procS *s3_cur_proc_ptr; +static int s3_numprocs; -#define SCORE7_PIPELINE 7 -#define SCORE5_PIPELINE 5 -static int vector_size = SCORE7_PIPELINE; -struct score_it dependency_vector[SCORE7_PIPELINE]; - -/* Relax will need some padding for alignment. */ -#define RELAX_PAD_BYTE 3 /* Structure for a hash table entry for a register. */ -struct reg_entry +struct s3_reg_entry { const char *name; int number; }; -static const struct reg_entry score_rn_table[] = +static const struct s3_reg_entry s3_score_rn_table[] = { {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3}, {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7}, @@ -201,13 +437,13 @@ static const struct reg_entry score_rn_table[] = {NULL, 0} }; -static const struct reg_entry score_srn_table[] = +static const struct s3_reg_entry s3_score_srn_table[] = { {"sr0", 0}, {"sr1", 1}, {"sr2", 2}, {NULL, 0} }; -static const struct reg_entry score_crn_table[] = +static const struct s3_reg_entry s3_score_crn_table[] = { {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3}, {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7}, @@ -220,603 +456,588 @@ static const struct reg_entry score_crn_table[] = {NULL, 0} }; -struct reg_map +struct s3_reg_map { - const struct reg_entry *names; + const struct s3_reg_entry *names; int max_regno; struct hash_control *htab; const char *expected; }; -struct reg_map all_reg_maps[] = +static struct s3_reg_map s3_all_reg_maps[] = { - {score_rn_table, 31, NULL, N_("S+core register expected")}, - {score_srn_table, 2, NULL, N_("S+core special-register expected")}, - {score_crn_table, 31, NULL, N_("S+core co-processor register expected")}, + {s3_score_rn_table, 31, NULL, N_("S+core register expected")}, + {s3_score_srn_table, 2, NULL, N_("S+core special-register expected")}, + {s3_score_crn_table, 31, NULL, N_("S+core co-processor register expected")}, }; -static struct hash_control *score_ops_hsh = NULL; +static struct hash_control *s3_score_ops_hsh = NULL; +static struct hash_control *s3_dependency_insn_hsh = NULL; -static struct hash_control *dependency_insn_hsh = NULL; -/* Enumeration matching entries in table above. */ -enum score_reg_type +struct s3_datafield_range +{ + int data_type; + int bits; + int range[2]; +}; + +static struct s3_datafield_range s3_score_df_range[] = +{ + {_IMM4, 4, {0, (1 << 4) - 1}}, /* ( 0 ~ 15 ) */ + {_IMM5, 5, {0, (1 << 5) - 1}}, /* ( 0 ~ 31 ) */ + {_IMM8, 8, {0, (1 << 8) - 1}}, /* ( 0 ~ 255 ) */ + {_IMM14, 14, {0, (1 << 14) - 1}}, /* ( 0 ~ 16383) */ + {_IMM15, 15, {0, (1 << 15) - 1}}, /* ( 0 ~ 32767) */ + {_IMM16, 16, {0, (1 << 16) - 1}}, /* ( 0 ~ 65535) */ + {_SIMM10, 10, {-(1 << 9), (1 << 9) - 1}}, /* ( -512 ~ 511 ) */ + {_SIMM12, 12, {-(1 << 11), (1 << 11) - 1}}, /* ( -2048 ~ 2047 ) */ + {_SIMM14, 14, {-(1 << 13), (1 << 13) - 1}}, /* ( -8192 ~ 8191 ) */ + {_SIMM15, 15, {-(1 << 14), (1 << 14) - 1}}, /* (-16384 ~ 16383) */ + {_SIMM16, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */ + {_SIMM14_NEG, 14, {-(1 << 13), (1 << 13) - 1}}, /* ( -8191 ~ 8192 ) */ + {_IMM16_NEG, 16, {0, (1 << 16) - 1}}, /* (-65535 ~ 0 ) */ + {_SIMM16_NEG, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */ + {_IMM20, 20, {0, (1 << 20) - 1}}, + {_IMM25, 25, {0, (1 << 25) - 1}}, + {_DISP8div2, 8, {-(1 << 8), (1 << 8) - 1}}, /* ( -256 ~ 255 ) */ + {_DISP11div2, 11, {0, 0}}, + {_DISP19div2, 19, {-(1 << 19), (1 << 19) - 1}}, /* (-524288 ~ 524287) */ + {_DISP24div2, 24, {0, 0}}, + {_VALUE, 32, {0, ((unsigned int)1 << 31) - 1}}, + {_VALUE_HI16, 16, {0, (1 << 16) - 1}}, + {_VALUE_LO16, 16, {0, (1 << 16) - 1}}, + {_VALUE_LDST_LO16, 16, {0, (1 << 16) - 1}}, + {_SIMM16_LA, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */ + {_IMM5_RSHIFT_1, 5, {0, (1 << 6) - 1}}, /* ( 0 ~ 63 ) */ + {_IMM5_RSHIFT_2, 5, {0, (1 << 7) - 1}}, /* ( 0 ~ 127 ) */ + {_SIMM16_LA_POS, 16, {0, (1 << 15) - 1}}, /* ( 0 ~ 32767) */ + {_IMM5_RANGE_8_31, 5, {8, 31}}, /* But for cop0 the valid data : (8 ~ 31). */ + {_IMM10_RSHIFT_2, 10, {-(1 << 11), (1 << 11) - 1}}, /* For ldc#, stc#. */ + {_SIMM10, 10, {0, (1 << 10) - 1}}, /* ( -1024 ~ 1023 ) */ + {_SIMM12, 12, {0, (1 << 12) - 1}}, /* ( -2048 ~ 2047 ) */ + {_SIMM14, 14, {0, (1 << 14) - 1}}, /* ( -8192 ~ 8191 ) */ + {_SIMM15, 15, {0, (1 << 15) - 1}}, /* (-16384 ~ 16383) */ + {_SIMM16, 16, {0, (1 << 16) - 1}}, /* (-65536 ~ 65536) */ + {_SIMM14_NEG, 14, {0, (1 << 16) - 1}}, /* ( -8191 ~ 8192 ) */ + {_IMM16_NEG, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */ + {_SIMM16_NEG, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */ + {_IMM20, 20, {0, (1 << 20) - 1}}, /* (-32768 ~ 32767) */ + {_IMM25, 25, {0, (1 << 25) - 1}}, /* (-32768 ~ 32767) */ + {_GP_IMM15, 15, {0, (1 << 15) - 1}}, /* ( 0 ~ 65535) */ + {_GP_IMM14, 14, {0, (1 << 14) - 1}}, /* ( 0 ~ 65535) */ + {_SIMM16_pic, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */ + {_IMM16_LO16_pic, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */ + {_IMM16_pic, 16, {0, (1 << 16) - 1}}, /* ( 0 ~ 65535) */ + {_SIMM5, 5, {-(1 << 4), (1 << 4) - 1}}, /* ( -16 ~ 15 ) */ + {_SIMM6, 6, {-(1 << 5), (1 << 5) - 1}}, /* ( -32 ~ 31 ) */ + {_IMM32, 32, {0, 0xfffffff}}, + {_SIMM32, 32, {-0x80000000, 0x7fffffff}}, + {_IMM11, 11, {0, (1 << 11) - 1}}, +}; + +struct s3_asm_opcode { - REG_TYPE_SCORE = 0, -#define REG_TYPE_FIRST REG_TYPE_SCORE - REG_TYPE_SCORE_SR = 1, - REG_TYPE_SCORE_CR = 2, - REG_TYPE_MAX = 3 + /* Instruction name. */ + const char *template; + + /* Instruction Opcode. */ + bfd_vma value; + + /* Instruction bit mask. */ + bfd_vma bitmask; + + /* Relax instruction opcode. 0x8000 imply no relaxation. */ + bfd_vma relax_value; + + /* Instruction type. */ + enum score_insn_type type; + + /* Function to call to parse args. */ + void (*parms) (char *); }; -typedef struct literalS -{ - struct expressionS exp; - struct score_it *inst; -} -literalT; - -literalT literals[MAX_LITERAL_POOL_SIZE]; - -static void do_ldst_insn (char *); -static void do_crdcrscrsimm5 (char *); -static void do_ldst_unalign (char *); -static void do_ldst_atomic (char *); -static void do_ldst_cop (char *); -static void do_macro_li_rdi32 (char *); -static void do_macro_la_rdi32 (char *); -static void do_macro_rdi32hi (char *); -static void do_macro_rdi32lo (char *); -static void do_macro_mul_rdrsrs (char *); -static void do_macro_ldst_label (char *); -static void do_branch (char *); -static void do_jump (char *); -static void do_empty (char *); -static void do_rdrsrs (char *); -static void do_rdsi16 (char *); -static void do_rdrssi14 (char *); -static void do_sub_rdsi16 (char *); -static void do_sub_rdrssi14 (char *); -static void do_rdrsi5 (char *); -static void do_rdrsi14 (char *); -static void do_rdi16 (char *); -static void do_xrsi5 (char *); -static void do_rdrs (char *); -static void do_rdxrs (char *); -static void do_rsrs (char *); -static void do_rdcrs (char *); -static void do_rdsrs (char *); -static void do_rd (char *); -static void do_rs (char *); -static void do_i15 (char *); -static void do_xi5x (char *); -static void do_ceinst (char *); -static void do_cache (char *); -static void do16_rdrs (char *); -static void do16_rs (char *); -static void do16_xrs (char *); -static void do16_mv_rdrs (char *); -static void do16_hrdrs (char *); -static void do16_rdhrs (char *); -static void do16_rdi4 (char *); -static void do16_rdi5 (char *); -static void do16_xi5 (char *); -static void do16_ldst_insn (char *); -static void do16_ldst_imm_insn (char *); -static void do16_push_pop (char *); -static void do16_branch (char *); -static void do16_jump (char *); -static void do_rdi16_pic (char *); -static void do_addi_s_pic (char *); -static void do_addi_u_pic (char *); -static void do_lw_pic (char *); - -static const struct asm_opcode score_ldst_insns[] = -{ - {"lw", 0x20000000, 0x3e000000, 0x2008, Rd_rvalueRs_SI15, do_ldst_insn}, - {"lw", 0x06000000, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn}, - {"lw", 0x0e000000, 0x3e000007, 0x200a, Rd_rvalueRs_postSI12, do_ldst_insn}, - {"lh", 0x22000000, 0x3e000000, 0x2009, Rd_rvalueRs_SI15, do_ldst_insn}, - {"lh", 0x06000001, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn}, - {"lh", 0x0e000001, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, do_ldst_insn}, - {"lhu", 0x24000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, do_ldst_insn}, - {"lhu", 0x06000002, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn}, - {"lhu", 0x0e000002, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, do_ldst_insn}, - {"lb", 0x26000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, do_ldst_insn}, - {"lb", 0x06000003, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn}, - {"lb", 0x0e000003, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, do_ldst_insn}, - {"sw", 0x28000000, 0x3e000000, 0x200c, Rd_lvalueRs_SI15, do_ldst_insn}, - {"sw", 0x06000004, 0x3e000007, 0x200e, Rd_lvalueRs_preSI12, do_ldst_insn}, - {"sw", 0x0e000004, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, do_ldst_insn}, - {"sh", 0x2a000000, 0x3e000000, 0x200d, Rd_lvalueRs_SI15, do_ldst_insn}, - {"sh", 0x06000005, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, do_ldst_insn}, - {"sh", 0x0e000005, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, do_ldst_insn}, - {"lbu", 0x2c000000, 0x3e000000, 0x200b, Rd_rvalueRs_SI15, do_ldst_insn}, - {"lbu", 0x06000006, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, do_ldst_insn}, - {"lbu", 0x0e000006, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, do_ldst_insn}, - {"sb", 0x2e000000, 0x3e000000, 0x200f, Rd_lvalueRs_SI15, do_ldst_insn}, - {"sb", 0x06000007, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, do_ldst_insn}, - {"sb", 0x0e000007, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, do_ldst_insn}, +static const struct s3_asm_opcode s3_score_ldst_insns[] = +{ + {"lw", 0x20000000, 0x3e000000, 0x1000, Rd_rvalueRs_SI15, s3_do_ldst_insn}, + {"lw", 0x06000000, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s3_do_ldst_insn}, + {"lw", 0x0e000000, 0x3e000007, 0x0040, Rd_rvalueRs_postSI12, s3_do_ldst_insn}, + {"lh", 0x22000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, s3_do_ldst_insn}, + {"lh", 0x06000001, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s3_do_ldst_insn}, + {"lh", 0x0e000001, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s3_do_ldst_insn}, + {"lhu", 0x24000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, s3_do_ldst_insn}, + {"lhu", 0x06000002, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s3_do_ldst_insn}, + {"lhu", 0x0e000002, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s3_do_ldst_insn}, + {"lb", 0x26000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, s3_do_ldst_insn}, + {"lb", 0x06000003, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s3_do_ldst_insn}, + {"lb", 0x0e000003, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s3_do_ldst_insn}, + {"sw", 0x28000000, 0x3e000000, 0x2000, Rd_lvalueRs_SI15, s3_do_ldst_insn}, + {"sw", 0x06000004, 0x3e000007, 0x0060, Rd_lvalueRs_preSI12, s3_do_ldst_insn}, + {"sw", 0x0e000004, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, s3_do_ldst_insn}, + {"sh", 0x2a000000, 0x3e000000, 0x8000, Rd_lvalueRs_SI15, s3_do_ldst_insn}, + {"sh", 0x06000005, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, s3_do_ldst_insn}, + {"sh", 0x0e000005, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, s3_do_ldst_insn}, + {"lbu", 0x2c000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, s3_do_ldst_insn}, + {"lbu", 0x06000006, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s3_do_ldst_insn}, + {"lbu", 0x0e000006, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s3_do_ldst_insn}, + {"sb", 0x2e000000, 0x3e000000, 0x8000, Rd_lvalueRs_SI15, s3_do_ldst_insn}, + {"sb", 0x06000007, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, s3_do_ldst_insn}, + {"sb", 0x0e000007, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, s3_do_ldst_insn}, }; -static const struct asm_opcode score_insns[] = -{ - {"abs", 0x3800000a, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, - {"abs.s", 0x3800004b, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, - {"add", 0x00000010, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"add.c", 0x00000011, 0x3e0003ff, 0x2000, Rd_Rs_Rs, do_rdrsrs}, - {"add.s", 0x38000048, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"addc", 0x00000012, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"addc.c", 0x00000013, 0x3e0003ff, 0x0009, Rd_Rs_Rs, do_rdrsrs}, - {"addi", 0x02000000, 0x3e0e0001, 0x8000, Rd_SI16, do_rdsi16}, - {"addi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, do_rdsi16}, - {"addis", 0x0a000000, 0x3e0e0001, 0x8000, Rd_SI16, do_rdi16}, - {"addis.c", 0x0a000001, 0x3e0e0001, 0x8000, Rd_SI16, do_rdi16}, - {"addri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, do_rdrssi14}, - {"addri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, do_rdrssi14}, - {"addc!", 0x0009, 0x700f, 0x00000013, Rd_Rs, do16_rdrs}, - {"add!", 0x2000, 0x700f, 0x00000011, Rd_Rs, do16_rdrs}, - {"addei!", 0x6000 , 0x7087, 0x02000001, Rd_I4, do16_rdi4}, - {"subi", 0x02000000, 0x3e0e0001, 0x8000, Rd_SI16, do_sub_rdsi16}, - {"subi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, do_sub_rdsi16}, - {"subri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, do_sub_rdrssi14}, - {"subri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, do_sub_rdrssi14}, - {"and", 0x00000020, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"and.c", 0x00000021, 0x3e0003ff, 0x2004, Rd_Rs_Rs, do_rdrsrs}, - {"andi", 0x02080000, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16}, - {"andi.c", 0x02080001, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16}, - {"andis", 0x0a080000, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16}, - {"andis.c", 0x0a080001, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16}, - {"andri", 0x18000000, 0x3e000001, 0x8000, Rd_Rs_I14, do_rdrsi14}, - {"andri.c", 0x18000001, 0x3e000001, 0x8000, Rd_Rs_I14, do_rdrsi14}, - {"and!", 0x2004, 0x700f, 0x00000021, Rd_Rs, do16_rdrs}, - {"bcs", 0x08000000, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, - {"bcc", 0x08000400, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, - {"bcnz", 0x08003800, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, - {"bcsl", 0x08000001, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, - {"bccl", 0x08000401, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, - {"bcnzl", 0x08003801, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, - {"bcs!", 0x4000, 0x7f00, 0x08000000, PC_DISP8div2, do16_branch}, - {"bcc!", 0x4100, 0x7f00, 0x08000400, PC_DISP8div2, do16_branch}, - {"bcnz!", 0x4e00, 0x7f00, 0x08003800, PC_DISP8div2, do16_branch}, - {"beq", 0x08001000, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, - {"beql", 0x08001001, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, - {"beq!", 0x4400, 0x7f00, 0x08001000, PC_DISP8div2, do16_branch}, - {"bgtu", 0x08000800, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, - {"bgt", 0x08001800, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, - {"bge", 0x08002000, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, - {"bgtul", 0x08000801, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, - {"bgtl", 0x08001801, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, - {"bgel", 0x08002001, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, - {"bgtu!", 0x4200, 0x7f00, 0x08000800, PC_DISP8div2, do16_branch}, - {"bgt!", 0x4600, 0x7f00, 0x08001800, PC_DISP8div2, do16_branch}, - {"bge!", 0x4800, 0x7f00, 0x08002000, PC_DISP8div2, do16_branch}, - {"bitclr.c", 0x00000029, 0x3e0003ff, 0x6004, Rd_Rs_I5, do_rdrsi5}, - {"bitrev", 0x3800000c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"bitset.c", 0x0000002b, 0x3e0003ff, 0x6005, Rd_Rs_I5, do_rdrsi5}, - {"bittst.c", 0x0000002d, 0x3e0003ff, 0x6006, x_Rs_I5, do_xrsi5}, - {"bittgl.c", 0x0000002f, 0x3e0003ff, 0x6007, Rd_Rs_I5, do_rdrsi5}, - {"bitclr!", 0x6004, 0x7007, 0x00000029, Rd_I5, do16_rdi5}, - {"bitset!", 0x6005, 0x7007, 0x0000002b, Rd_I5, do16_rdi5}, - {"bittst!", 0x6006, 0x7007, 0x0000002d, Rd_I5, do16_rdi5}, - {"bittgl!", 0x6007, 0x7007, 0x0000002f, Rd_I5, do16_rdi5}, - {"bleu", 0x08000c00, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, - {"ble", 0x08001c00, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, - {"blt", 0x08002400, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, - {"bleul", 0x08000c01, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, - {"blel", 0x08001c01, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, - {"bltl", 0x08002401, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, - {"bl", 0x08003c01, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, - {"bleu!", 0x4300, 0x7f00, 0x08000c00, PC_DISP8div2, do16_branch}, - {"ble!", 0x4700, 0x7f00, 0x08001c00, PC_DISP8div2, do16_branch}, - {"blt!", 0x4900, 0x7f00, 0x08002400, PC_DISP8div2, do16_branch}, - {"bmi", 0x08002800, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, - {"bmil", 0x08002801, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, - {"bmi!", 0x00004a00, 0x00007f00, 0x08002800, PC_DISP8div2, do16_branch}, - {"bne", 0x08001400, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, - {"bnel", 0x08001401, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, - {"bne!", 0x4500, 0x7f00, 0x08001400, PC_DISP8div2, do16_branch}, - {"bpl", 0x08002c00, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, - {"bpll", 0x08002c01, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, - {"bpl!", 0x4b00, 0x7f00, 0x08002c00, PC_DISP8div2, do16_branch}, - {"brcs", 0x00000008, 0x3e007fff, 0x0004, x_Rs_x, do_rs}, - {"brcc", 0x00000408, 0x3e007fff, 0x0104, x_Rs_x, do_rs}, - {"brgtu", 0x00000808, 0x3e007fff, 0x0204, x_Rs_x, do_rs}, - {"brleu", 0x00000c08, 0x3e007fff, 0x0304, x_Rs_x, do_rs}, - {"breq", 0x00001008, 0x3e007fff, 0x0404, x_Rs_x, do_rs}, - {"brne", 0x00001408, 0x3e007fff, 0x0504, x_Rs_x, do_rs}, - {"brgt", 0x00001808, 0x3e007fff, 0x0604, x_Rs_x, do_rs}, - {"brle", 0x00001c08, 0x3e007fff, 0x0704, x_Rs_x, do_rs}, - {"brge", 0x00002008, 0x3e007fff, 0x0804, x_Rs_x, do_rs}, - {"brlt", 0x00002408, 0x3e007fff, 0x0904, x_Rs_x, do_rs}, - {"brmi", 0x00002808, 0x3e007fff, 0x0a04, x_Rs_x, do_rs}, - {"brpl", 0x00002c08, 0x3e007fff, 0x0b04, x_Rs_x, do_rs}, - {"brvs", 0x00003008, 0x3e007fff, 0x0c04, x_Rs_x, do_rs}, - {"brvc", 0x00003408, 0x3e007fff, 0x0d04, x_Rs_x, do_rs}, - {"brcnz", 0x00003808, 0x3e007fff, 0x0e04, x_Rs_x, do_rs}, - {"br", 0x00003c08, 0x3e007fff, 0x0f04, x_Rs_x, do_rs}, - {"brcsl", 0x00000009, 0x3e007fff, 0x000c, x_Rs_x, do_rs}, - {"brccl", 0x00000409, 0x3e007fff, 0x010c, x_Rs_x, do_rs}, - {"brgtul", 0x00000809, 0x3e007fff, 0x020c, x_Rs_x, do_rs}, - {"brleul", 0x00000c09, 0x3e007fff, 0x030c, x_Rs_x, do_rs}, - {"breql", 0x00001009, 0x3e007fff, 0x040c, x_Rs_x, do_rs}, - {"brnel", 0x00001409, 0x3e007fff, 0x050c, x_Rs_x, do_rs}, - {"brgtl", 0x00001809, 0x3e007fff, 0x060c, x_Rs_x, do_rs}, - {"brlel", 0x00001c09, 0x3e007fff, 0x070c, x_Rs_x, do_rs}, - {"brgel", 0x00002009, 0x3e007fff, 0x080c, x_Rs_x, do_rs}, - {"brltl", 0x00002409, 0x3e007fff, 0x090c, x_Rs_x, do_rs}, - {"brmil", 0x00002809, 0x3e007fff, 0x0a0c, x_Rs_x, do_rs}, - {"brpll", 0x00002c09, 0x3e007fff, 0x0b0c, x_Rs_x, do_rs}, - {"brvsl", 0x00003009, 0x3e007fff, 0x0c0c, x_Rs_x, do_rs}, - {"brvcl", 0x00003409, 0x3e007fff, 0x0d0c, x_Rs_x, do_rs}, - {"brcnzl", 0x00003809, 0x3e007fff, 0x0e0c, x_Rs_x, do_rs}, - {"brl", 0x00003c09, 0x3e007fff, 0x0f0c, x_Rs_x, do_rs}, - {"brcs!", 0x0004, 0x7f0f, 0x00000008, x_Rs, do16_xrs}, - {"brcc!", 0x0104, 0x7f0f, 0x00000408, x_Rs, do16_xrs}, - {"brgtu!", 0x0204, 0x7f0f, 0x00000808, x_Rs, do16_xrs}, - {"brleu!", 0x0304, 0x7f0f, 0x00000c08, x_Rs, do16_xrs}, - {"breq!", 0x0404, 0x7f0f, 0x00001008, x_Rs, do16_xrs}, - {"brne!", 0x0504, 0x7f0f, 0x00001408, x_Rs, do16_xrs}, - {"brgt!", 0x0604, 0x7f0f, 0x00001808, x_Rs, do16_xrs}, - {"brle!", 0x0704, 0x7f0f, 0x00001c08, x_Rs, do16_xrs}, - {"brge!", 0x0804, 0x7f0f, 0x00002008, x_Rs, do16_xrs}, - {"brlt!", 0x0904, 0x7f0f, 0x00002408, x_Rs, do16_xrs}, - {"brmi!", 0x0a04, 0x7f0f, 0x00002808, x_Rs, do16_xrs}, - {"brpl!", 0x0b04, 0x7f0f, 0x00002c08, x_Rs, do16_xrs}, - {"brvs!", 0x0c04, 0x7f0f, 0x00003008, x_Rs, do16_xrs}, - {"brvc!", 0x0d04, 0x7f0f, 0x00003408, x_Rs, do16_xrs}, - {"brcnz!", 0x0e04, 0x7f0f, 0x00003808, x_Rs, do16_xrs}, - {"br!", 0x0f04, 0x7f0f, 0x00003c08, x_Rs, do16_xrs}, - {"brcsl!", 0x000c, 0x7f0f, 0x00000009, x_Rs, do16_xrs}, - {"brccl!", 0x010c, 0x7f0f, 0x00000409, x_Rs, do16_xrs}, - {"brgtul!", 0x020c, 0x7f0f, 0x00000809, x_Rs, do16_xrs}, - {"brleul!", 0x030c, 0x7f0f, 0x00000c09, x_Rs, do16_xrs}, - {"breql!", 0x040c, 0x7f0f, 0x00001009, x_Rs, do16_xrs}, - {"brnel!", 0x050c, 0x7f0f, 0x00001409, x_Rs, do16_xrs}, - {"brgtl!", 0x060c, 0x7f0f, 0x00001809, x_Rs, do16_xrs}, - {"brlel!", 0x070c, 0x7f0f, 0x00001c09, x_Rs, do16_xrs}, - {"brgel!", 0x080c, 0x7f0f, 0x00002009, x_Rs, do16_xrs}, - {"brltl!", 0x090c, 0x7f0f, 0x00002409, x_Rs, do16_xrs}, - {"brmil!", 0x0a0c, 0x7f0f, 0x00002809, x_Rs, do16_xrs}, - {"brpll!", 0x0b0c, 0x7f0f, 0x00002c09, x_Rs, do16_xrs}, - {"brvsl!", 0x0c0c, 0x7f0f, 0x00003009, x_Rs, do16_xrs}, - {"brvcl!", 0x0d0c, 0x7f0f, 0x00003409, x_Rs, do16_xrs}, - {"brcnzl!", 0x0e0c, 0x7f0f, 0x00003809, x_Rs, do16_xrs}, - {"brl!", 0x0f0c, 0x7f0f, 0x00003c09, x_Rs, do16_xrs}, - {"bvs", 0x08003000, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, - {"bvc", 0x08003400, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, - {"bvsl", 0x08003001, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, - {"bvcl", 0x08003401, 0x3e007c01, 0x8000, PC_DISP19div2, do_branch}, - {"bvs!", 0x4c00, 0x7f00, 0x08003000, PC_DISP8div2, do16_branch}, - {"bvc!", 0x4d00, 0x7f00, 0x08003400, PC_DISP8div2, do16_branch}, - {"b!", 0x4f00, 0x7f00, 0x08003c00, PC_DISP8div2, do16_branch}, - {"b", 0x08003c00, 0x3e007c01, 0x4000, PC_DISP19div2, do_branch}, - {"cache", 0x30000000, 0x3ff00000, 0x8000, OP5_rvalueRs_SI15, do_cache}, - {"ceinst", 0x38000000, 0x3e000000, 0x8000, I5_Rs_Rs_I5_OP5, do_ceinst}, - {"clz", 0x3800000d, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, - {"cmpteq.c", 0x00000019, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"cmptmi.c", 0x00100019, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"cmp.c", 0x00300019, 0x3ff003ff, 0x2003, x_Rs_Rs, do_rsrs}, - {"cmpzteq.c", 0x0000001b, 0x3ff07fff, 0x8000, x_Rs_x, do_rs}, - {"cmpztmi.c", 0x0010001b, 0x3ff07fff, 0x8000, x_Rs_x, do_rs}, - {"cmpz.c", 0x0030001b, 0x3ff07fff, 0x8000, x_Rs_x, do_rs}, - {"cmpi.c", 0x02040001, 0x3e0e0001, 0x8000, Rd_SI16, do_rdsi16}, - {"cmp!", 0x2003, 0x700f, 0x00300019, Rd_Rs, do16_rdrs}, - {"cop1", 0x0c00000c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, do_crdcrscrsimm5}, - {"cop2", 0x0c000014, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, do_crdcrscrsimm5}, - {"cop3", 0x0c00001c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, do_crdcrscrsimm5}, - {"drte", 0x0c0000a4, 0x3e0003ff, 0x8000, NO_OPD, do_empty}, - {"extsb", 0x00000058, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs}, - {"extsb.c", 0x00000059, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs}, - {"extsh", 0x0000005a, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs}, - {"extsh.c", 0x0000005b, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs}, - {"extzb", 0x0000005c, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs}, - {"extzb.c", 0x0000005d, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs}, - {"extzh", 0x0000005e, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs}, - {"extzh.c", 0x0000005f, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs}, - {"jl", 0x04000001, 0x3e000001, 0x8000, PC_DISP24div2, do_jump}, - {"jl!", 0x3001, 0x7001, 0x04000001, PC_DISP11div2, do16_jump}, - {"j!", 0x3000, 0x7001, 0x04000000, PC_DISP11div2, do16_jump}, - {"j", 0x04000000, 0x3e000001, 0x8000, PC_DISP24div2, do_jump}, - {"lbu!", 0x200b, 0x0000700f, 0x2c000000, Rd_rvalueRs, do16_ldst_insn}, - {"lbup!", 0x7003, 0x7007, 0x2c000000, Rd_rvalueBP_I5, do16_ldst_imm_insn}, - {"alw", 0x0000000c, 0x3e0003ff, 0x8000, Rd_rvalue32Rs, do_ldst_atomic}, - {"lcb", 0x00000060, 0x3e0003ff, 0x8000, x_rvalueRs_post4, do_ldst_unalign}, - {"lcw", 0x00000062, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, do_ldst_unalign}, - {"lce", 0x00000066, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, do_ldst_unalign}, - {"ldc1", 0x0c00000a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, do_ldst_cop}, - {"ldc2", 0x0c000012, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, do_ldst_cop}, - {"ldc3", 0x0c00001a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, do_ldst_cop}, - {"lh!", 0x2009, 0x700f, 0x22000000, Rd_rvalueRs, do16_ldst_insn}, - {"lhp!", 0x7001, 0x7007, 0x22000000, Rd_rvalueBP_I5, do16_ldst_imm_insn}, - {"ldi", 0x020c0000, 0x3e0e0000, 0x5000, Rd_SI16, do_rdsi16}, - {"ldis", 0x0a0c0000, 0x3e0e0000, 0x8000, Rd_I16, do_rdi16}, - {"ldiu!", 0x5000, 0x7000, 0x020c0000, Rd_I8, do16_ldst_imm_insn}, - {"lw!", 0x2008, 0x700f, 0x20000000, Rd_rvalueRs, do16_ldst_insn}, - {"lwp!", 0x7000, 0x7007, 0x20000000, Rd_rvalueBP_I5, do16_ldst_imm_insn}, - {"mfcel", 0x00000448, 0x3e007fff, 0x8000, Rd_x_x, do_rd}, - {"mfcel!", 0x1001, 0x7f0f, 0x00000448, x_Rs, do16_rs}, - {"mad", 0x38000000, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"mad.f!", 0x1004, 0x700f, 0x38000080, Rd_Rs, do16_rdrs}, - {"madh", 0x38000203, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"madh.fs", 0x380002c3, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"madh.fs!", 0x100b, 0x700f, 0x380002c3, Rd_Rs, do16_rdrs}, - {"madl", 0x38000002, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"madl.fs", 0x380000c2, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"madl.fs!", 0x100a, 0x700f, 0x380000c2, Rd_Rs, do16_rdrs}, - {"madu", 0x38000020, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"madu!", 0x1005, 0x700f, 0x38000020, Rd_Rs, do16_rdrs}, - {"mad.f", 0x38000080, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"max", 0x38000007, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"mazh", 0x38000303, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"mazh.f", 0x38000383, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"mazh.f!", 0x1009, 0x700f, 0x3800038c, Rd_Rs, do16_rdrs}, - {"mazl", 0x38000102, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"mazl.f", 0x38000182, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"mazl.f!", 0x1008, 0x700f, 0x38000182, Rd_Rs, do16_rdrs}, - {"mfceh", 0x00000848, 0x3e007fff, 0x8000, Rd_x_x, do_rd}, - {"mfceh!", 0x1101, 0x7f0f, 0x00000848, x_Rs, do16_rs}, - {"mfcehl", 0x00000c48, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, - {"mfsr", 0x00000050, 0x3e0003ff, 0x8000, Rd_x_I5, do_rdsrs}, - {"mfcr", 0x0c000001, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, - {"mfc1", 0x0c000009, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, - {"mfc2", 0x0c000011, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, - {"mfc3", 0x0c000019, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, - {"mfcc1", 0x0c00000f, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, - {"mfcc2", 0x0c000017, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, - {"mfcc3", 0x0c00001f, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, - {"mhfl!", 0x0002, 0x700f, 0x00003c56, Rd_LowRs, do16_hrdrs}, - {"min", 0x38000006, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"mlfh!", 0x0001, 0x700f, 0x00003c56, Rd_HighRs, do16_rdhrs}, - {"msb", 0x38000001, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"msb.f!", 0x1006, 0x700f, 0x38000081, Rd_Rs, do16_rdrs}, - {"msbh", 0x38000205, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"msbh.fs", 0x380002c5, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"msbh.fs!", 0x100f, 0x700f, 0x380002c5, Rd_Rs, do16_rdrs}, - {"msbl", 0x38000004, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"msbl.fs", 0x380000c4, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"msbl.fs!", 0x100e, 0x700f, 0x380000c4, Rd_Rs, do16_rdrs}, - {"msbu", 0x38000021, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"msbu!", 0x1007, 0x700f, 0x38000021, Rd_Rs, do16_rdrs}, - {"msb.f", 0x38000081, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"mszh", 0x38000305, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"mszh.f", 0x38000385, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"mszh.f!", 0x100d, 0x700f, 0x38000385, Rd_Rs, do16_rdrs}, - {"mszl", 0x38000104, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"mszl.f", 0x38000184, 0x3ff003ff, 0x8000, x_Rs_Rs, do_rsrs}, - {"mszl.f!", 0x100c, 0x700f, 0x38000184, Rd_Rs, do16_rdrs}, - {"mtcel!", 0x1000, 0x7f0f, 0x0000044a, x_Rs, do16_rs}, - {"mtcel", 0x0000044a, 0x3e007fff, 0x8000, Rd_x_x, do_rd}, - {"mtceh", 0x0000084a, 0x3e007fff, 0x8000, Rd_x_x, do_rd}, - {"mtceh!", 0x1100, 0x7f0f, 0x0000084a, x_Rs, do16_rs}, - {"mtcehl", 0x00000c4a, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, - {"mtsr", 0x00000052, 0x3e0003ff, 0x8000, x_Rs_I5, do_rdsrs}, - {"mtcr", 0x0c000000, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, - {"mtc1", 0x0c000008, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, - {"mtc2", 0x0c000010, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, - {"mtc3", 0x0c000018, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, - {"mtcc1", 0x0c00000e, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, - {"mtcc2", 0x0c000016, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, - {"mtcc3", 0x0c00001e, 0x3e00001f, 0x8000, Rd_Rs_x, do_rdcrs}, - {"mul.f!", 0x1002, 0x700f, 0x00000041, Rd_Rs, do16_rdrs}, - {"mulu!", 0x1003, 0x700f, 0x00000042, Rd_Rs, do16_rdrs}, - {"mvcs", 0x00000056, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, - {"mvcc", 0x00000456, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, - {"mvgtu", 0x00000856, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, - {"mvleu", 0x00000c56, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, - {"mveq", 0x00001056, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, - {"mvne", 0x00001456, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, - {"mvgt", 0x00001856, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, - {"mvle", 0x00001c56, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, - {"mvge", 0x00002056, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, - {"mvlt", 0x00002456, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, - {"mvmi", 0x00002856, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, - {"mvpl", 0x00002c56, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, - {"mvvs", 0x00003056, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, - {"mvvc", 0x00003456, 0x3e007fff, 0x8000, Rd_Rs_x, do_rdrs}, - {"mv", 0x00003c56, 0x3e007fff, 0x0003, Rd_Rs_x, do_rdrs}, - {"mv!", 0x0003, 0x700f, 0x00003c56, Rd_Rs, do16_mv_rdrs}, - {"neg", 0x0000001e, 0x3e0003ff, 0x8000, Rd_x_Rs, do_rdxrs}, - {"neg.c", 0x0000001f, 0x3e0003ff, 0x2002, Rd_x_Rs, do_rdxrs}, - {"neg!", 0x2002, 0x700f, 0x0000001f, Rd_Rs, do16_rdrs}, - {"nop", 0x00000000, 0x3e0003ff, 0x0000, NO_OPD, do_empty}, - {"not", 0x00000024, 0x3e0003ff, 0x8000, Rd_Rs_x, do_rdrs}, - {"not.c", 0x00000025, 0x3e0003ff, 0x2006, Rd_Rs_x, do_rdrs}, - {"nop!", 0x0000, 0x700f, 0x00000000, NO16_OPD, do_empty}, - {"not!", 0x2006, 0x700f, 0x00000025, Rd_Rs, do16_rdrs}, - {"or", 0x00000022, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"or.c", 0x00000023, 0x3e0003ff, 0x2005, Rd_Rs_Rs, do_rdrsrs}, - {"ori", 0x020a0000, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16}, - {"ori.c", 0x020a0001, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16}, - {"oris", 0x0a0a0000, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16}, - {"oris.c", 0x0a0a0001, 0x3e0e0001, 0x8000, Rd_I16, do_rdi16}, - {"orri", 0x1a000000, 0x3e000001, 0x8000, Rd_Rs_I14, do_rdrsi14}, - {"orri.c", 0x1a000001, 0x3e000001, 0x8000, Rd_Rs_I14, do_rdrsi14}, - {"or!", 0x2005, 0x700f, 0x00000023, Rd_Rs, do16_rdrs}, - {"pflush", 0x0000000a, 0x3e0003ff, 0x8000, NO_OPD, do_empty}, - {"pop!", 0x200a, 0x700f, 0x0e000000, Rd_rvalueRs, do16_push_pop}, - {"push!", 0x200e, 0x700f, 0x06000004, Rd_lvalueRs, do16_push_pop}, - {"ror", 0x00000038, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"ror.c", 0x00000039, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"rorc.c", 0x0000003b, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"rol", 0x0000003c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"rol.c", 0x0000003d, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"rolc.c", 0x0000003f, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"rori", 0x00000078, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5}, - {"rori.c", 0x00000079, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5}, - {"roric.c", 0x0000007b, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5}, - {"roli", 0x0000007c, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5}, - {"roli.c", 0x0000007d, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5}, - {"rolic.c", 0x0000007f, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5}, - {"rte", 0x0c000084, 0x3e0003ff, 0x8000, NO_OPD, do_empty}, - {"sb!", 0x200f, 0x700f, 0x2e000000, Rd_lvalueRs, do16_ldst_insn}, - {"sbp!", 0x7007, 0x7007, 0x2e000000, Rd_lvalueBP_I5, do16_ldst_imm_insn}, - {"asw", 0x0000000e, 0x3e0003ff, 0x8000, Rd_lvalue32Rs, do_ldst_atomic}, - {"scb", 0x00000068, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, do_ldst_unalign}, - {"scw", 0x0000006a, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, do_ldst_unalign}, - {"sce", 0x0000006e, 0x3e0003ff, 0x8000, x_lvalueRs_post4, do_ldst_unalign}, - {"sdbbp", 0x00000006, 0x3e0003ff, 0x6002, x_I5_x, do_xi5x}, - {"sdbbp!", 0x6002, 0x7007, 0x00000006, Rd_I5, do16_xi5}, - {"sh!", 0x200d, 0x700f, 0x2a000000, Rd_lvalueRs, do16_ldst_insn}, - {"shp!", 0x7005, 0x7007, 0x2a000000, Rd_lvalueBP_I5, do16_ldst_imm_insn}, - {"sleep", 0x0c0000c4, 0x3e0003ff, 0x8000, NO_OPD, do_empty}, - {"sll", 0x00000030, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"sll.c", 0x00000031, 0x3e0003ff, 0x0008, Rd_Rs_Rs, do_rdrsrs}, - {"sll.s", 0x3800004e, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"slli", 0x00000070, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5}, - {"slli.c", 0x00000071, 0x3e0003ff, 0x6001, Rd_Rs_I5, do_rdrsi5}, - {"sll!", 0x0008, 0x700f, 0x00000031, Rd_Rs, do16_rdrs}, - {"slli!", 0x6001, 0x7007, 0x00000071, Rd_I5, do16_rdi5}, - {"srl", 0x00000034, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"srl.c", 0x00000035, 0x3e0003ff, 0x000a, Rd_Rs_Rs, do_rdrsrs}, - {"sra", 0x00000036, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"sra.c", 0x00000037, 0x3e0003ff, 0x000b, Rd_Rs_Rs, do_rdrsrs}, - {"srli", 0x00000074, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5}, - {"srli.c", 0x00000075, 0x3e0003ff, 0x6003, Rd_Rs_I5, do_rdrsi5}, - {"srai", 0x00000076, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5}, - {"srai.c", 0x00000077, 0x3e0003ff, 0x8000, Rd_Rs_I5, do_rdrsi5}, - {"srl!", 0x000a, 0x700f, 0x00000035, Rd_Rs, do16_rdrs}, - {"sra!", 0x000b, 0x700f, 0x00000037, Rd_Rs, do16_rdrs}, - {"srli!", 0x6003, 0x7007, 0x00000075, Rd_Rs, do16_rdi5}, - {"stc1", 0x0c00000b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, do_ldst_cop}, - {"stc2", 0x0c000013, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, do_ldst_cop}, - {"stc3", 0x0c00001b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, do_ldst_cop}, - {"sub", 0x00000014, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"sub.c", 0x00000015, 0x3e0003ff, 0x2001, Rd_Rs_Rs, do_rdrsrs}, - {"sub.s", 0x38000049, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"subc", 0x00000016, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"subc.c", 0x00000017, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"sub!", 0x2001, 0x700f, 0x00000015, Rd_Rs, do16_rdrs}, - {"subei!", 0x6080, 0x7087, 0x02000001, Rd_I4, do16_rdi4}, - {"sw!", 0x200c, 0x700f, 0x28000000, Rd_lvalueRs, do16_ldst_insn}, - {"swp!", 0x7004, 0x7007, 0x28000000, Rd_lvalueBP_I5, do16_ldst_imm_insn}, - {"syscall", 0x00000002, 0x3e0003ff, 0x8000, I15, do_i15}, - {"tcs", 0x00000054, 0x3e007fff, 0x0005, NO_OPD, do_empty}, - {"tcc", 0x00000454, 0x3e007fff, 0x0105, NO_OPD, do_empty}, - {"tcnz", 0x00003854, 0x3e007fff, 0x0e05, NO_OPD, do_empty}, - {"tcs!", 0x0005, 0x7f0f, 0x00000054, NO16_OPD, do_empty}, - {"tcc!", 0x0105, 0x7f0f, 0x00000454, NO16_OPD, do_empty}, - {"tcnz!", 0x0e05, 0x7f0f, 0x00003854, NO16_OPD, do_empty}, - {"teq", 0x00001054, 0x3e007fff, 0x0405, NO_OPD, do_empty}, - {"teq!", 0x0405, 0x7f0f, 0x00001054, NO16_OPD, do_empty}, - {"tgtu", 0x00000854, 0x3e007fff, 0x0205, NO_OPD, do_empty}, - {"tgt", 0x00001854, 0x3e007fff, 0x0605, NO_OPD, do_empty}, - {"tge", 0x00002054, 0x3e007fff, 0x0805, NO_OPD, do_empty}, - {"tgtu!", 0x0205, 0x7f0f, 0x00000854, NO16_OPD, do_empty}, - {"tgt!", 0x0605, 0x7f0f, 0x00001854, NO16_OPD, do_empty}, - {"tge!", 0x0805, 0x7f0f, 0x00002054, NO16_OPD, do_empty}, - {"tleu", 0x00000c54, 0x3e007fff, 0x0305, NO_OPD, do_empty}, - {"tle", 0x00001c54, 0x3e007fff, 0x0705, NO_OPD, do_empty}, - {"tlt", 0x00002454, 0x3e007fff, 0x0905, NO_OPD, do_empty}, - {"stlb", 0x0c000004, 0x3e0003ff, 0x8000, NO_OPD, do_empty}, - {"mftlb", 0x0c000024, 0x3e0003ff, 0x8000, NO_OPD, do_empty}, - {"mtptlb", 0x0c000044, 0x3e0003ff, 0x8000, NO_OPD, do_empty}, - {"mtrtlb", 0x0c000064, 0x3e0003ff, 0x8000, NO_OPD, do_empty}, - {"tleu!", 0x0305, 0x7f0f, 0x00000c54, NO16_OPD, do_empty}, - {"tle!", 0x0705, 0x7f0f, 0x00001c54, NO16_OPD, do_empty}, - {"tlt!", 0x0905, 0x7f0f, 0x00002454, NO16_OPD, do_empty}, - {"tmi", 0x00002854, 0x3e007fff, 0x0a05, NO_OPD, do_empty}, - {"tmi!", 0x0a05, 0x7f0f, 0x00002854, NO16_OPD, do_empty}, - {"tne", 0x00001454, 0x3e007fff, 0x0505, NO_OPD, do_empty}, - {"tne!", 0x0505, 0x7f0f, 0x00001454, NO16_OPD, do_empty}, - {"tpl", 0x00002c54, 0x3e007fff, 0x0b05, NO_OPD, do_empty}, - {"tpl!", 0x0b05, 0x7f0f, 0x00002c54, NO16_OPD, do_empty}, - {"trapcs", 0x00000004, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, - {"trapcc", 0x00000404, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, - {"trapgtu", 0x00000804, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, - {"trapleu", 0x00000c04, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, - {"trapeq", 0x00001004, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, - {"trapne", 0x00001404, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, - {"trapgt", 0x00001804, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, - {"traple", 0x00001c04, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, - {"trapge", 0x00002004, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, - {"traplt", 0x00002404, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, - {"trapmi", 0x00002804, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, - {"trappl", 0x00002c04, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, - {"trapvs", 0x00003004, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, - {"trapvc", 0x00003404, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, - {"trap", 0x00003c04, 0x3e007fff, 0x8000, x_I5_x, do_xi5x}, - {"tset", 0x00003c54, 0x3e007fff, 0x0f05, NO_OPD, do_empty}, - {"tset!", 0x0f05, 0x00007f0f, 0x00003c54, NO16_OPD, do_empty}, - {"tvs", 0x00003054, 0x3e007fff, 0x0c05, NO_OPD, do_empty}, - {"tvc", 0x00003454, 0x3e007fff, 0x0d05, NO_OPD, do_empty}, - {"tvs!", 0x0c05, 0x7f0f, 0x00003054, NO16_OPD, do_empty}, - {"tvc!", 0x0d05, 0x7f0f, 0x00003454, NO16_OPD, do_empty}, - {"xor", 0x00000026, 0x3e0003ff, 0x8000, Rd_Rs_Rs, do_rdrsrs}, - {"xor.c", 0x00000027, 0x3e0003ff, 0x2007, Rd_Rs_Rs, do_rdrsrs}, - {"xor!", 0x2007, 0x700f, 0x00000027, Rd_Rs, do16_rdrs}, +static const struct s3_asm_opcode s3_score_insns[] = +{ + {"abs", 0x3800000a, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_dsp3}, + {"abs.s", 0x3800004b, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_dsp3}, + {"add", 0x00000010, 0x3e0003ff, 0x4800, Rd_Rs_Rs, s3_do_rdrsrs}, + {"add.c", 0x00000011, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + {"add.s", 0x38000048, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_dsp2}, + {"addc", 0x00000012, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + {"addc.c", 0x00000013, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + {"addi", 0x02000000, 0x3e0e0001, 0x5c00, Rd_SI16, s3_do_rdsi16}, + {"addi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, s3_do_rdsi16}, + {"addis", 0x0a000000, 0x3e0e0001, 0x8000, Rd_SI16, s3_do_rdi16}, + {"addis.c", 0x0a000001, 0x3e0e0001, 0x8000, Rd_SI16, s3_do_rdi16}, + {"addi!", 0x5c00, 0x7c00, 0x8000, Rd_SI6, s3_do16_addi}, + {"addri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, s3_do_rdrssi14}, + {"addri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, s3_do_rdrssi14}, + + /* add.c <-> add!. */ + {"add!", 0x4800, 0x7f00, 0x8000, Rd_Rs, s3_do16_rdrs2}, + {"subi", 0x02000000, 0x3e0e0001, 0x8000, Rd_SI16, s3_do_sub_rdsi16}, + {"subi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, s3_do_sub_rdsi16}, + {"subis", 0x0a000000, 0x3e0e0001, 0x8000, Rd_SI16, s3_do_sub_rdi16}, + {"subis.c", 0x0a000001, 0x3e0e0001, 0x8000, Rd_SI16, s3_do_sub_rdi16}, + {"subri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, s3_do_sub_rdrssi14}, + {"subri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, s3_do_sub_rdrssi14}, + {"and", 0x00000020, 0x3e0003ff, 0x4b00, Rd_Rs_Rs, s3_do_rdrsrs}, + {"and.c", 0x00000021, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + {"andi", 0x02080000, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16}, + {"andi.c", 0x02080001, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16}, + {"andis", 0x0a080000, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16}, + {"andis.c", 0x0a080001, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16}, + {"andri", 0x18000000, 0x3e000001, 0x8000, Rd_Rs_I14, s3_do_rdrsi14}, + {"andri.c", 0x18000001, 0x3e000001, 0x8000, Rd_Rs_I14, s3_do_rdrsi14}, + + /* and.c <-> and!. */ + {"and!", 0x4b00, 0x7f00, 0x8000, Rd_Rs, s3_do16_rdrs2}, + {"bcs", 0x08000000, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"bcc", 0x08000400, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"bcnz", 0x08003800, 0x3e007c01, 0x3200, PC_DISP19div2, s3_do_branch}, + {"bcsl", 0x08000001, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"bccl", 0x08000401, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"bcnzl", 0x08003801, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"bcnz!", 0x3200, 0x7f00, 0x08003800, PC_DISP8div2, s3_do16_branch}, + {"beq", 0x08001000, 0x3e007c01, 0x3800, PC_DISP19div2, s3_do_branch}, + {"beql", 0x08001001, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"beq!", 0x3800, 0x7e00, 0x08001000, PC_DISP8div2, s3_do16_branch}, + {"bgtu", 0x08000800, 0x3e007c01, 0x3400, PC_DISP19div2, s3_do_branch}, + {"bgt", 0x08001800, 0x3e007c01, 0x3c00, PC_DISP19div2, s3_do_branch}, + {"bge", 0x08002000, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"bgtul", 0x08000801, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"bgtl", 0x08001801, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"bgel", 0x08002001, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"bgtu!", 0x3400, 0x7e00, 0x08000800, PC_DISP8div2, s3_do16_branch}, + {"bgt!", 0x3c00, 0x7e00, 0x08001800, PC_DISP8div2, s3_do16_branch}, + {"bitclr", 0x00000028, 0x3e0003ff, 0x5000, Rd_Rs_I5, s3_do_rdrsi5}, + {"bitclr.c", 0x00000029, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, + + {"mbitclr", 0x00000064, 0x3e00007e, 0x8000, Ra_I9_I5, s3_do_mbitclr}, + {"mbitset", 0x0000006c, 0x3e00007e, 0x8000, Ra_I9_I5, s3_do_mbitset}, + + {"bitrev", 0x3800000c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_dsp2}, + {"bitset", 0x0000002a, 0x3e0003ff, 0x5200, Rd_Rs_I5, s3_do_rdrsi5}, + {"bitset.c", 0x0000002b, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, + {"bittst.c", 0x0000002d, 0x3e0003ff, 0x5400, x_Rs_I5, s3_do_xrsi5}, + {"bittgl", 0x0000002e, 0x3e0003ff, 0x5600, Rd_Rs_I5, s3_do_rdrsi5}, + {"bittgl.c", 0x0000002f, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, + {"bitclr!", 0x5000, 0x7e00, 0x8000, Rd_I5, s3_do16_rdi5}, + {"bitset!", 0x5200, 0x7e00, 0x8000, Rd_I5, s3_do16_rdi5}, + {"bittst!", 0x5400, 0x7e00, 0x8000, Rd_I5, s3_do16_rdi5}, + {"bittgl!", 0x5600, 0x7e00, 0x8000, Rd_I5, s3_do16_rdi5}, + {"bleu", 0x08000c00, 0x3e007c01, 0x3600, PC_DISP19div2, s3_do_branch}, + {"ble", 0x08001c00, 0x3e007c01, 0x3e00, PC_DISP19div2, s3_do_branch}, + {"blt", 0x08002400, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"bleul", 0x08000c01, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"blel", 0x08001c01, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"bltl", 0x08002401, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"bl", 0x08003c01, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"bleu!", 0x3600, 0x7e00, 0x08000c00, PC_DISP8div2, s3_do16_branch}, + {"ble!", 0x3e00, 0x7e00, 0x08001c00, PC_DISP8div2, s3_do16_branch}, + {"bmi", 0x08002800, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"bmil", 0x08002801, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"bne", 0x08001400, 0x3e007c01, 0x3a00, PC_DISP19div2, s3_do_branch}, + {"bnel", 0x08001401, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"bne!", 0x3a00, 0x7e00, 0x08001400, PC_DISP8div2, s3_do16_branch}, + {"bpl", 0x08002c00, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"bpll", 0x08002c01, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"brcs", 0x00000008, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brcc", 0x00000408, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brgtu", 0x00000808, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brleu", 0x00000c08, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"breq", 0x00001008, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brne", 0x00001408, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brgt", 0x00001808, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brle", 0x00001c08, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brge", 0x00002008, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brlt", 0x00002408, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brmi", 0x00002808, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brpl", 0x00002c08, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brvs", 0x00003008, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brvc", 0x00003408, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brcnz", 0x00003808, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"br", 0x00003c08, 0x3e007fff, 0x0080, x_Rs_x, s3_do_rs}, + {"brcsl", 0x00000009, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brccl", 0x00000409, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brgtul", 0x00000809, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brleul", 0x00000c09, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"breql", 0x00001009, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brnel", 0x00001409, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brgtl", 0x00001809, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brlel", 0x00001c09, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brgel", 0x00002009, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brltl", 0x00002409, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brmil", 0x00002809, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brpll", 0x00002c09, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brvsl", 0x00003009, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brvcl", 0x00003409, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brcnzl", 0x00003809, 0x3e007fff, 0x8000, x_Rs_x, s3_do_rs}, + {"brl", 0x00003c09, 0x3e007fff, 0x00a0, x_Rs_x, s3_do_rs}, + {"br!", 0x0080, 0x7fe0, 0x8000, x_Rs, s3_do16_br}, + {"brl!", 0x00a0, 0x7fe0, 0x8000, x_Rs, s3_do16_br}, + {"brr!", 0x00c0, 0x7fe0, 0x8000, x_Rs, s3_do16_brr}, + {"bvs", 0x08003000, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"bvc", 0x08003400, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"bvsl", 0x08003001, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"bvcl", 0x08003401, 0x3e007c01, 0x8000, PC_DISP19div2, s3_do_branch}, + {"b!", 0x3000, 0x7e00, 0x08003c00, PC_DISP8div2, s3_do16_branch}, + {"b", 0x08003c00, 0x3e007c01, 0x3000, PC_DISP19div2, s3_do_branch}, + {"cache", 0x30000000, 0x3ff00000, 0x8000, OP5_rvalueRs_SI15, s3_do_cache}, + {"ceinst", 0x38000000, 0x3e000000, 0x8000, I5_Rs_Rs_I5_OP5, s3_do_ceinst}, + {"clz", 0x0000001c, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"cmp.c", 0x00300019, 0x3ff003ff, 0x4400, x_Rs_Rs, s3_do_rsrs}, + {"cmpz.c", 0x0030001b, 0x3ff07fff, 0x8000, x_Rs_x, s3_do_rs}, + {"cmpi.c", 0x02040001, 0x3e0e0001, 0x6000, Rd_SI16, s3_do_rdsi16}, + + /* cmp.c <-> cmp!. */ + {"cmp!", 0x4400, 0x7c00, 0x8000, Rd_Rs, s3_do16_mv_cmp}, + {"cmpi!", 0x6000, 0x7c00, 0x8000, Rd_SI5, s3_do16_cmpi}, + {"cop1", 0x0c00000c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, s3_do_crdcrscrsimm5}, + {"cop2", 0x0c000014, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, s3_do_crdcrscrsimm5}, + {"cop3", 0x0c00001c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, s3_do_crdcrscrsimm5}, + {"drte", 0x0c0000a4, 0x3e0003ff, 0x8000, NO_OPD, s3_do_empty}, + {"disint!", 0x00e0, 0xffe1, 0x8000, NO16_OPD, s3_do16_int}, + {"enint!", 0x00e1, 0xffe1, 0x8000, NO16_OPD, s3_do16_int}, + {"extsb", 0x00000058, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"extsb.c", 0x00000059, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"extsh", 0x0000005a, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"extsh.c", 0x0000005b, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"extzb", 0x0000005c, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"extzb.c", 0x0000005d, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"extzh", 0x0000005e, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"extzh.c", 0x0000005f, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"jl", 0x04000001, 0x3e000001, 0x8000, PC_DISP24div2, s3_do_jump}, + {"j", 0x04000000, 0x3e000001, 0x8000, PC_DISP24div2, s3_do_jump}, + {"alw", 0x0000000c, 0x3e0003ff, 0x8000, Rd_rvalue32Rs, s3_do_ldst_atomic}, + {"lcb", 0x00000060, 0x3e0003ff, 0x8000, x_rvalueRs_post4, s3_do_ldst_unalign}, + {"lcw", 0x00000062, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, s3_do_ldst_unalign}, + {"lce", 0x00000066, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, s3_do_ldst_unalign}, + {"ldc1", 0x0c00000a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, s3_do_ldst_cop}, + {"ldc2", 0x0c000012, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, s3_do_ldst_cop}, + {"ldc3", 0x0c00001a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, s3_do_ldst_cop}, + + /* s3_inst.relax */ + {"ldi", 0x020c0000, 0x3e0e0000, 0x6400, Rd_SI16, s3_do_rdsi16}, + {"ldis", 0x0a0c0000, 0x3e0e0000, 0x8000, Rd_I16, s3_do_ldis}, + + /* ldi <-> ldiu!. */ + {"ldiu!", 0x6400, 0x7c00, 0x8000, Rd_I5, s3_do16_ldiu}, + + /*ltbb! , ltbh! ltbw! */ + {"ltbw", 0x00000032, 0x03ff, 0x8000, Rd_Rs_Rs, s3_do_ltb}, + {"ltbh", 0x00000132, 0x03ff, 0x8000, Rd_Rs_Rs, s3_do_ltb}, + {"ltbb", 0x00000332, 0x03ff, 0x8000, Rd_Rs_Rs, s3_do_ltb}, + {"lw!", 0x1000, 0x7000, 0x8000, Rd_rvalueRs, s3_do16_ldst_insn}, + {"mfcel", 0x00000448, 0x3e007fff, 0x8000, Rd_x_x, s3_do_rd}, + {"mfcel!", 0x7100, 0x7ff0, 0x00000448, x_Rs, s3_do16_dsp}, + {"mad", 0x38000000, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"mad.f!", 0x7400, 0x7f00, 0x38000080, Rd_Rs, s3_do16_dsp2}, + {"madh", 0x38000203, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"madh.fs", 0x380002c3, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"madh.fs!", 0x7b00, 0x7f00, 0x380002c3, Rd_Rs, s3_do16_dsp2}, + {"madl", 0x38000002, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"madl.fs", 0x380000c2, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"madl.fs!", 0x7a00, 0x7f00, 0x380000c2, Rd_Rs, s3_do16_dsp2}, + {"madu", 0x38000020, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"madu!", 0x7500, 0x7f00, 0x38000020, Rd_Rs, s3_do16_dsp2}, + {"mad.f", 0x38000080, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"max", 0x38000007, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_dsp2}, + {"mazh", 0x38000303, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"mazh.f", 0x38000383, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"mazh.f!", 0x7900, 0x7f00, 0x3800038c, Rd_Rs, s3_do16_dsp2}, + {"mazl", 0x38000102, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"mazl.f", 0x38000182, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"mazl.f!", 0x7800, 0x7f00, 0x38000182, Rd_Rs, s3_do16_dsp2}, + {"mfceh", 0x00000848, 0x3e007fff, 0x8000, Rd_x_x, s3_do_rd}, + {"mfceh!", 0x7110, 0x7ff0, 0x00000848, x_Rs, s3_do16_dsp}, + {"mfcehl", 0x00000c48, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"mfsr", 0x00000050, 0x3e0003ff, 0x8000, Rd_x_I5, s3_do_rdsrs}, + {"mfcr", 0x0c000001, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, + {"mfc1", 0x0c000009, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, + {"mfc2", 0x0c000011, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, + {"mfc3", 0x0c000019, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, + {"mfcc1", 0x0c00000f, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, + {"mfcc2", 0x0c000017, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, + {"mfcc3", 0x0c00001f, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, + {"min", 0x38000006, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_dsp2}, + {"msb", 0x38000001, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"msb.f!", 0x7600, 0x7f00, 0x38000081, Rd_Rs, s3_do16_dsp2}, + {"msbh", 0x38000205, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"msbh.fs", 0x380002c5, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"msbh.fs!", 0x7f00, 0x7f00, 0x380002c5, Rd_Rs, s3_do16_dsp2}, + {"msbl", 0x38000004, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"msbl.fs", 0x380000c4, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"msbl.fs!", 0x7e00, 0x7f00, 0x380000c4, Rd_Rs, s3_do16_dsp2}, + {"msbu", 0x38000021, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"msbu!", 0x7700, 0x7f00, 0x38000021, Rd_Rs, s3_do16_dsp2}, + {"msb.f", 0x38000081, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"mszh", 0x38000305, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"mszh.f", 0x38000385, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"mszh.f!", 0x7d00, 0x7f00, 0x38000385, Rd_Rs, s3_do16_dsp2}, + {"mszl", 0x38000104, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"mszl.f", 0x38000184, 0x3ff003ff, 0x8000, x_Rs_Rs, s3_do_dsp}, + {"mszl.f!", 0x7c00, 0x7f00, 0x38000184, Rd_Rs, s3_do16_dsp2}, + {"mtcel!", 0x7000, 0x7ff0, 0x0000044a, x_Rs, s3_do16_dsp}, + {"mtcel", 0x0000044a, 0x3e007fff, 0x8000, Rd_x_x, s3_do_rd}, + {"mtceh", 0x0000084a, 0x3e007fff, 0x8000, Rd_x_x, s3_do_rd}, + {"mtceh!", 0x7010, 0x7ff0, 0x0000084a, x_Rs, s3_do16_dsp}, + {"mtcehl", 0x00000c4a, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"mtsr", 0x00000052, 0x3e0003ff, 0x8000, x_Rs_I5, s3_do_rdsrs}, + {"mtcr", 0x0c000000, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, + {"mtc1", 0x0c000008, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, + {"mtc2", 0x0c000010, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, + {"mtc3", 0x0c000018, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, + {"mtcc1", 0x0c00000e, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, + {"mtcc2", 0x0c000016, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, + {"mtcc3", 0x0c00001e, 0x3e00001f, 0x8000, Rd_Rs_x, s3_do_rdcrs}, + {"mul.f!", 0x7200, 0x7f00, 0x00000041, Rd_Rs, s3_do16_dsp2}, + {"mulu!", 0x7300, 0x7f00, 0x00000042, Rd_Rs, s3_do16_dsp2}, + {"mulr.l", 0x00000140, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, + {"mulr.h", 0x00000240, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, + {"mulr", 0x00000340, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, + {"mulr.lf", 0x00000141, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, + {"mulr.hf", 0x00000241, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, + {"mulr.f", 0x00000341, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, + {"mulur.l", 0x00000142, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, + {"mulur.h", 0x00000242, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, + {"mulur", 0x00000342, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, + {"divr.q", 0x00000144, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, + {"divr.r", 0x00000244, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, + {"divr", 0x00000344, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, + {"divur.q", 0x00000146, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, + {"divur.r", 0x00000246, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, + {"divur", 0x00000346, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_rdrsrs}, + {"mvcs", 0x00000056, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"mvcc", 0x00000456, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"mvgtu", 0x00000856, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"mvleu", 0x00000c56, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"mveq", 0x00001056, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"mvne", 0x00001456, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"mvgt", 0x00001856, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"mvle", 0x00001c56, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"mvge", 0x00002056, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"mvlt", 0x00002456, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"mvmi", 0x00002856, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"mvpl", 0x00002c56, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"mvvs", 0x00003056, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"mvvc", 0x00003456, 0x3e007fff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + + /* mv <-> mv!. */ + {"mv", 0x00003c56, 0x3e007fff, 0x4000, Rd_Rs_x, s3_do_rdrs}, + {"mv!", 0x4000, 0x7c00, 0x8000, Rd_Rs, s3_do16_mv_cmp}, + {"neg", 0x0000001e, 0x3e0003ff, 0x8000, Rd_x_Rs, s3_do_rdxrs}, + {"neg.c", 0x0000001f, 0x3e0003ff, 0x8000, Rd_x_Rs, s3_do_rdxrs}, + {"nop", 0x00000000, 0x3e0003ff, 0x0000, NO_OPD, s3_do_empty}, + {"not", 0x00000024, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"not.c", 0x00000025, 0x3e0003ff, 0x8000, Rd_Rs_x, s3_do_rdrs}, + {"nop!", 0x0000, 0x7fff, 0x8000, NO16_OPD, s3_do_empty}, + {"or", 0x00000022, 0x3e0003ff, 0x4a00, Rd_Rs_Rs, s3_do_rdrsrs}, + {"or.c", 0x00000023, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + {"ori", 0x020a0000, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16}, + {"ori.c", 0x020a0001, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16}, + {"oris", 0x0a0a0000, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16}, + {"oris.c", 0x0a0a0001, 0x3e0e0001, 0x8000, Rd_I16, s3_do_rdi16}, + {"orri", 0x1a000000, 0x3e000001, 0x8000, Rd_Rs_I14, s3_do_rdrsi14}, + {"orri.c", 0x1a000001, 0x3e000001, 0x8000, Rd_Rs_I14, s3_do_rdrsi14}, + + /* or.c <-> or!. */ + {"or!", 0x4a00, 0x7f00, 0x8000, Rd_Rs, s3_do16_rdrs2}, + {"pflush", 0x0000000a, 0x3e0003ff, 0x8000, NO_OPD, s3_do_empty}, + {"pop!", 0x0040, 0x7fe0, 0x8000, Rd_rvalueRs, s3_do16_push_pop}, + {"push!", 0x0060, 0x7fe0, 0x8000, Rd_lvalueRs, s3_do16_push_pop}, + + {"rpop!", 0x6800, 0x7c00, 0x8000, Rd_I5, s3_do16_rpop}, + {"rpush!", 0x6c00, 0x7c00, 0x8000, Rd_I5, s3_do16_rpush}, + + {"ror", 0x00000038, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + {"ror.c", 0x00000039, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + {"rorc.c", 0x0000003b, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + {"rol", 0x0000003c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + {"rol.c", 0x0000003d, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + {"rolc.c", 0x0000003f, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + {"rori", 0x00000078, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, + {"rori.c", 0x00000079, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, + {"roric.c", 0x0000007b, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, + {"roli", 0x0000007c, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, + {"roli.c", 0x0000007d, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, + {"rolic.c", 0x0000007f, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, + {"rte", 0x0c000084, 0x3e0003ff, 0x8000, NO_OPD, s3_do_empty}, + {"asw", 0x0000000e, 0x3e0003ff, 0x8000, Rd_lvalue32Rs, s3_do_ldst_atomic}, + {"scb", 0x00000068, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, s3_do_ldst_unalign}, + {"scw", 0x0000006a, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, s3_do_ldst_unalign}, + {"sce", 0x0000006e, 0x3e0003ff, 0x8000, x_lvalueRs_post4, s3_do_ldst_unalign}, + {"sdbbp", 0x00000006, 0x3e0003ff, 0x0020, x_I5_x, s3_do_xi5x}, + {"sdbbp!", 0x0020, 0x7fe0, 0x8000, Rd_I5, s3_do16_xi5}, + {"sleep", 0x0c0000c4, 0x3e0003ff, 0x8000, NO_OPD, s3_do_empty}, + {"rti", 0x0c0000e4, 0x3e0003ff, 0x8000, NO_OPD, s3_do_empty}, + {"sll", 0x00000030, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + {"sll.c", 0x00000031, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + {"sll.s", 0x3800004e, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_dsp2}, + {"slli", 0x00000070, 0x3e0003ff, 0x5800, Rd_Rs_I5, s3_do_rdrsi5}, + {"slli.c", 0x00000071, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, + + /* slli.c <-> slli!. */ + {"slli!", 0x5800, 0x7e00, 0x8000, Rd_I5, s3_do16_slli_srli}, + {"srl", 0x00000034, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + {"srl.c", 0x00000035, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + {"sra", 0x00000036, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + {"sra.c", 0x00000037, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + {"srli", 0x00000074, 0x3e0003ff, 0x5a00, Rd_Rs_I5, s3_do_rdrsi5}, + {"srli.c", 0x00000075, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, + {"srai", 0x00000076, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, + {"srai.c", 0x00000077, 0x3e0003ff, 0x8000, Rd_Rs_I5, s3_do_rdrsi5}, + + /* srli.c <-> srli!. */ + {"srli!", 0x5a00, 0x7e00, 0x8000, Rd_Rs, s3_do16_slli_srli}, + {"stc1", 0x0c00000b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, s3_do_ldst_cop}, + {"stc2", 0x0c000013, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, s3_do_ldst_cop}, + {"stc3", 0x0c00001b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, s3_do_ldst_cop}, + {"sub", 0x00000014, 0x3e0003ff, 0x4900, Rd_Rs_Rs, s3_do_rdrsrs}, + {"sub.c", 0x00000015, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + {"sub.s", 0x38000049, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_dsp2}, + {"subc", 0x00000016, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + {"subc.c", 0x00000017, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + + /* sub.c <-> sub!. */ + {"sub!", 0x4900, 0x7f00, 0x8000, Rd_Rs, s3_do16_rdrs2}, + {"sw!", 0x2000, 0x7000, 0x8000, Rd_lvalueRs, s3_do16_ldst_insn}, + {"syscall", 0x00000002, 0x3e0003ff, 0x8000, I15, s3_do_i15}, + {"trapcs", 0x00000004, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, + {"trapcc", 0x00000404, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, + {"trapgtu", 0x00000804, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, + {"trapleu", 0x00000c04, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, + {"trapeq", 0x00001004, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, + {"trapne", 0x00001404, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, + {"trapgt", 0x00001804, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, + {"traple", 0x00001c04, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, + {"trapge", 0x00002004, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, + {"traplt", 0x00002404, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, + {"trapmi", 0x00002804, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, + {"trappl", 0x00002c04, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, + {"trapvs", 0x00003004, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, + {"trapvc", 0x00003404, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, + {"trap", 0x00003c04, 0x3e007fff, 0x8000, x_I5_x, s3_do_xi5x}, + {"xor", 0x00000026, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + {"xor.c", 0x00000027, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s3_do_rdrsrs}, + /* Macro instruction. */ - {"li", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, do_macro_li_rdi32}, + {"li", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, s3_do_macro_li_rdi32}, + /* la reg, imm32 -->(1) ldi reg, simm16 (2) ldis reg, %HI(imm32) ori reg, %LO(imm32) la reg, symbol -->(1) lis reg, %HI(imm32) ori reg, %LO(imm32) */ - {"la", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, do_macro_la_rdi32}, - {"div", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs}, - {"divu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs}, - {"rem", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs}, - {"remu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs}, - {"mul", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs}, - {"mulu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs}, - {"maz", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs}, - {"mazu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs}, - {"mul.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs}, - {"maz.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, do_macro_mul_rdrsrs}, - {"lb", INSN_LB, 0x00000000, 0x8000, Insn_Type_SYN, do_macro_ldst_label}, - {"lbu", INSN_LBU, 0x00000000, 0x200b, Insn_Type_SYN, do_macro_ldst_label}, - {"lh", INSN_LH, 0x00000000, 0x2009, Insn_Type_SYN, do_macro_ldst_label}, - {"lhu", INSN_LHU, 0x00000000, 0x8000, Insn_Type_SYN, do_macro_ldst_label}, - {"lw", INSN_LW, 0x00000000, 0x2008, Insn_Type_SYN, do_macro_ldst_label}, - {"sb", INSN_SB, 0x00000000, 0x200f, Insn_Type_SYN, do_macro_ldst_label}, - {"sh", INSN_SH, 0x00000000, 0x200d, Insn_Type_SYN, do_macro_ldst_label}, - {"sw", INSN_SW, 0x00000000, 0x200c, Insn_Type_SYN, do_macro_ldst_label}, + {"la", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, s3_do_macro_la_rdi32}, + {"bcmpeqz", 0x0000004c, 0x3e00007e, 0x8000, Insn_BCMP, s3_do_macro_bcmpz}, + {"bcmpeq", 0x0000004c, 0x3e00007e, 0x8000, Insn_BCMP, s3_do_macro_bcmp}, + {"bcmpnez", 0x0000004e, 0x3e00007e, 0x8000, Insn_BCMP, s3_do_macro_bcmpz}, + {"bcmpne", 0x0000004e, 0x3e00007e, 0x8000, Insn_BCMP, s3_do_macro_bcmp}, + {"div", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs}, + {"divu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs}, + {"rem", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs}, + {"remu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs}, + {"mul", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs}, + {"mulu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs}, + {"maz", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs}, + {"mazu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs}, + {"mul.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs}, + {"maz.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, s3_do_macro_mul_rdrsrs}, + {"lb", INSN_LB, 0x00000000, 0x8000, Insn_Type_SYN, s3_do_macro_ldst_label}, + {"lbu", INSN_LBU, 0x00000000, 0x8000, Insn_Type_SYN, s3_do_macro_ldst_label}, + {"lh", INSN_LH, 0x00000000, 0x8000, Insn_Type_SYN, s3_do_macro_ldst_label}, + {"lhu", INSN_LHU, 0x00000000, 0x8000, Insn_Type_SYN, s3_do_macro_ldst_label}, + {"lw", INSN_LW, 0x00000000, 0x1000, Insn_Type_SYN, s3_do_macro_ldst_label}, + {"sb", INSN_SB, 0x00000000, 0x8000, Insn_Type_SYN, s3_do_macro_ldst_label}, + {"sh", INSN_SH, 0x00000000, 0x8000, Insn_Type_SYN, s3_do_macro_ldst_label}, + {"sw", INSN_SW, 0x00000000, 0x2000, Insn_Type_SYN, s3_do_macro_ldst_label}, + /* Assembler use internal. */ - {"ld_i32hi", 0x0a0c0000, 0x3e0e0000, 0x8000, Insn_internal, do_macro_rdi32hi}, - {"ld_i32lo", 0x020a0000, 0x3e0e0001, 0x8000, Insn_internal, do_macro_rdi32lo}, - {"ldis_pic", 0x0a0c0000, 0x3e0e0000, 0x5000, Insn_internal, do_rdi16_pic}, - {"addi_s_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal, do_addi_s_pic}, - {"addi_u_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal, do_addi_u_pic}, - {"lw_pic", 0x20000000, 0x3e000000, 0x8000, Insn_internal, do_lw_pic}, + {"ld_i32hi", 0x0a0c0000, 0x3e0e0000, 0x8000, Insn_internal, s3_do_macro_rdi32hi}, + {"ld_i32lo", 0x020a0000, 0x3e0e0001, 0x8000, Insn_internal, s3_do_macro_rdi32lo}, + {"ldis_pic", 0x0a0c0000, 0x3e0e0000, 0x8000, Insn_internal, s3_do_rdi16_pic}, + {"addi_s_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal, s3_do_addi_s_pic}, + {"addi_u_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal, s3_do_addi_u_pic}, + {"lw_pic", 0x20000000, 0x3e000000, 0x8000, Insn_internal, s3_do_lw_pic}, + + /* 48-bit instructions. */ + {"sdbbp48", 0x000000000000LL, 0x1c000000001fLL, 0x8000, Rd_I32, s3_do_sdbbp48}, + {"ldi48", 0x000000000001LL, 0x1c000000001fLL, 0x8000, Rd_I32, s3_do_ldi48}, + {"lw48", 0x000000000002LL, 0x1c000000001fLL, 0x8000, Rd_I30, s3_do_lw48}, + {"sw48", 0x000000000003LL, 0x1c000000001fLL, 0x8000, Rd_I30, s3_do_sw48}, + {"andri48", 0x040000000000LL, 0x1c0000000003LL, 0x8000, Rd_I32, s3_do_and48}, + {"andri48.c", 0x040000000001LL, 0x1c0000000003LL, 0x8000, Rd_I32, s3_do_and48}, + {"orri48", 0x040000000002LL, 0x1c0000000003LL, 0x8000, Rd_I32, s3_do_or48}, + {"orri48.c", 0x040000000003LL, 0x1c0000000003LL, 0x8000, Rd_I32, s3_do_or48}, }; -/* Next free entry in the pool. */ -int next_literal_pool_place = 0; +#define s3_SCORE3_PIPELINE 3 -/* Next literal pool number. */ -int lit_pool_num = 1; -symbolS *current_poolP = NULL; +static int s3_university_version = 0; +static int s3_vector_size = s3_SCORE3_PIPELINE; +static struct s3_score_it s3_dependency_vector[s3_SCORE3_PIPELINE]; +static int s3_score3d = 1; static int -end_of_line (char *str) +s3_end_of_line (char *str) { - int retval = SUCCESS; + int retval = s3_SUCCESS; - skip_whitespace (str); + s3_skip_whitespace (str); if (*str != '\0') { - retval = (int) FAIL; + retval = (int) s3_FAIL; - if (!inst.error) - inst.error = BAD_GARBAGE; + if (!s3_inst.error) + s3_inst.error = s3_BAD_GARBAGE; } return retval; } static int -score_reg_parse (char **ccp, struct hash_control *htab) +s3_score_reg_parse (char **ccp, struct hash_control *htab) { char *start = *ccp; char c; char *p; - struct reg_entry *reg; + struct s3_reg_entry *reg; p = start; if (!ISALPHA (*p) || !is_name_beginner (*p)) - return (int) FAIL; + return (int) s3_FAIL; c = *p++; @@ -824,7 +1045,7 @@ score_reg_parse (char **ccp, struct hash_control *htab) c = *p++; *--p = 0; - reg = (struct reg_entry *) hash_find (htab, start); + reg = (struct s3_reg_entry *) hash_find (htab, start); *p = c; if (reg) @@ -832,52 +1053,52 @@ score_reg_parse (char **ccp, struct hash_control *htab) *ccp = p; return reg->number; } - return (int) FAIL; + return (int) s3_FAIL; } /* If shift <= 0, only return reg. */ static int -reg_required_here (char **str, int shift, enum score_reg_type reg_type) +s3_reg_required_here (char **str, int shift, enum s3_score_reg_type reg_type) { - static char buff[MAX_LITERAL_POOL_SIZE]; - int reg = (int) FAIL; + static char buff[s3_MAX_LITERAL_POOL_SIZE]; + int reg = (int) s3_FAIL; char *start = *str; - if ((reg = score_reg_parse (str, all_reg_maps[reg_type].htab)) != (int) FAIL) + if ((reg = s3_score_reg_parse (str, s3_all_reg_maps[reg_type].htab)) != (int) s3_FAIL) { - if (reg_type == REG_TYPE_SCORE) + if (reg_type == s3_REG_TYPE_SCORE) { - if ((reg == 1) && (nor1 == 1) && (inst.bwarn == 0)) + if ((reg == 1) && (s3_nor1 == 1) && (s3_inst.bwarn == 0)) { as_warn (_("Using temp register(r1)")); - inst.bwarn = 1; + s3_inst.bwarn = 1; } } if (shift >= 0) { - if (reg_type == REG_TYPE_SCORE_CR) - strcpy (inst.reg, score_crn_table[reg].name); - else if (reg_type == REG_TYPE_SCORE_SR) - strcpy (inst.reg, score_srn_table[reg].name); + if (reg_type == s3_REG_TYPE_SCORE_CR) + strcpy (s3_inst.reg, s3_score_crn_table[reg].name); + else if (reg_type == s3_REG_TYPE_SCORE_SR) + strcpy (s3_inst.reg, s3_score_srn_table[reg].name); else - strcpy (inst.reg, ""); + strcpy (s3_inst.reg, ""); - inst.instruction |= reg << shift; + s3_inst.instruction |= (bfd_vma) reg << shift; } } else { *str = start; sprintf (buff, _("register expected, not '%.100s'"), start); - inst.error = buff; + s3_inst.error = buff; } return reg; } static int -skip_past_comma (char **str) +s3_skip_past_comma (char **str) { char *p = *str; char c; @@ -888,166 +1109,174 @@ skip_past_comma (char **str) p++; if (c == ',' && comma++) { - inst.error = BAD_SKIP_COMMA; - return (int) FAIL; + s3_inst.error = s3_BAD_SKIP_COMMA; + return (int) s3_FAIL; } } if ((c == '\0') || (comma == 0)) { - inst.error = BAD_SKIP_COMMA; - return (int) FAIL; + s3_inst.error = s3_BAD_SKIP_COMMA; + return (int) s3_FAIL; } *str = p; - return comma ? SUCCESS : (int) FAIL; + return comma ? s3_SUCCESS : (int) s3_FAIL; } static void -do_rdrsrs (char *str) +s3_do_rdrsrs (char *str) { - skip_whitespace (str); + int reg; + s3_skip_whitespace (str); - if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL - || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL - || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL - || end_of_line (str) == (int) FAIL) + if ((reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) { return; } else { - if ((((inst.instruction >> 15) & 0x10) == 0) - && (((inst.instruction >> 10) & 0x10) == 0) - && (((inst.instruction >> 20) & 0x10) == 0) - && (inst.relax_inst != 0x8000) - && (((inst.instruction >> 20) & 0xf) == ((inst.instruction >> 15) & 0xf))) + /* Check mulr, mulur rd is even number. */ + if (((s3_inst.instruction & 0x3e0003ff) == 0x00000340 + || (s3_inst.instruction & 0x3e0003ff) == 0x00000342) + && (reg % 2)) + { + s3_inst.error = _("rd must be even number."); + return; + } + + if ((((s3_inst.instruction >> 15) & 0x10) == 0) + && (((s3_inst.instruction >> 10) & 0x10) == 0) + && (((s3_inst.instruction >> 20) & 0x10) == 0) + && (s3_inst.relax_inst != 0x8000) + && (((s3_inst.instruction >> 20) & 0xf) == ((s3_inst.instruction >> 15) & 0xf))) { - inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) - | (((inst.instruction >> 15) & 0xf) << 8); - inst.relax_size = 2; + s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0xf) ) + | (((s3_inst.instruction >> 15) & 0xf) << 4); + s3_inst.relax_size = 2; } else { - inst.relax_inst = 0x8000; + s3_inst.relax_inst = 0x8000; } } } static int -walk_no_bignums (symbolS * sp) +s3_walk_no_bignums (symbolS * sp) { if (symbol_get_value_expression (sp)->X_op == O_big) return 1; if (symbol_get_value_expression (sp)->X_add_symbol) - return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol) + return (s3_walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol) || (symbol_get_value_expression (sp)->X_op_symbol - && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol))); + && s3_walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol))); return 0; } static int -my_get_expression (expressionS * ep, char **str) +s3_my_get_expression (expressionS * ep, char **str) { char *save_in; segT seg; save_in = input_line_pointer; input_line_pointer = *str; - in_my_get_expression = 1; + s3_in_my_get_expression = 1; seg = expression (ep); - in_my_get_expression = 0; + s3_in_my_get_expression = 0; if (ep->X_op == O_illegal) { *str = input_line_pointer; input_line_pointer = save_in; - inst.error = _("illegal expression"); - return (int) FAIL; + s3_inst.error = _("illegal expression"); + return (int) s3_FAIL; } /* Get rid of any bignums now, so that we don't generate an error for which we can't establish a line number later on. Big numbers are never valid in instructions, which is where this routine is always called. */ if (ep->X_op == O_big || (ep->X_add_symbol - && (walk_no_bignums (ep->X_add_symbol) - || (ep->X_op_symbol && walk_no_bignums (ep->X_op_symbol))))) + && (s3_walk_no_bignums (ep->X_add_symbol) + || (ep->X_op_symbol && s3_walk_no_bignums (ep->X_op_symbol))))) { - inst.error = _("invalid constant"); + s3_inst.error = _("invalid constant"); *str = input_line_pointer; input_line_pointer = save_in; - return (int) FAIL; + return (int) s3_FAIL; } if ((ep->X_add_symbol != NULL) - && (inst.type != PC_DISP19div2) - && (inst.type != PC_DISP8div2) - && (inst.type != PC_DISP24div2) - && (inst.type != PC_DISP11div2) - && (inst.type != Insn_Type_SYN) - && (inst.type != Rd_rvalueRs_SI15) - && (inst.type != Rd_lvalueRs_SI15) - && (inst.type != Insn_internal)) - { - inst.error = BAD_ARGS; + && (s3_inst.type != PC_DISP19div2) + && (s3_inst.type != PC_DISP8div2) + && (s3_inst.type != PC_DISP24div2) + && (s3_inst.type != PC_DISP11div2) + && (s3_inst.type != Insn_Type_SYN) + && (s3_inst.type != Rd_rvalueRs_SI15) + && (s3_inst.type != Rd_lvalueRs_SI15) + && (s3_inst.type != Insn_internal) + && (s3_inst.type != Rd_I30) + && (s3_inst.type != Rd_I32) + && (s3_inst.type != Insn_BCMP)) + { + s3_inst.error = s3_BAD_ARGS; *str = input_line_pointer; input_line_pointer = save_in; - return (int) FAIL; + return (int) s3_FAIL; } *str = input_line_pointer; input_line_pointer = save_in; - return SUCCESS; + return s3_SUCCESS; } /* Check if an immediate is valid. If so, convert it to the right format. */ - -static int -validate_immediate (int val, unsigned int data_type, int hex_p) +static bfd_signed_vma +s3_validate_immediate (bfd_signed_vma val, unsigned int data_type, int hex_p) { switch (data_type) { case _VALUE_HI16: { - int val_hi = ((val & 0xffff0000) >> 16); + bfd_signed_vma val_hi = ((val & 0xffff0000) >> 16); - if (score_df_range[data_type].range[0] <= val_hi - && val_hi <= score_df_range[data_type].range[1]) + if (s3_score_df_range[data_type].range[0] <= val_hi + && val_hi <= s3_score_df_range[data_type].range[1]) return val_hi; } break; case _VALUE_LO16: { - int val_lo = (val & 0xffff); + bfd_signed_vma val_lo = (val & 0xffff); - if (score_df_range[data_type].range[0] <= val_lo - && val_lo <= score_df_range[data_type].range[1]) + if (s3_score_df_range[data_type].range[0] <= val_lo + && val_lo <= s3_score_df_range[data_type].range[1]) return val_lo; } break; - case _VALUE: - return val; - break; - case _SIMM14: if (hex_p == 1) { if (!(val >= -0x2000 && val <= 0x3fff)) { - return (int) FAIL; + return (int) s3_FAIL; } } else { if (!(val >= -8192 && val <= 8191)) { - return (int) FAIL; + return (int) s3_FAIL; } } @@ -1059,14 +1288,14 @@ validate_immediate (int val, unsigned int data_type, int hex_p) { if (!(val >= -0x7fff && val <= 0xffff && val != 0x8000)) { - return (int) FAIL; + return (int) s3_FAIL; } } else { if (!(val >= -32767 && val <= 32768)) { - return (int) FAIL; + return (int) s3_FAIL; } } @@ -1074,37 +1303,62 @@ validate_immediate (int val, unsigned int data_type, int hex_p) return val; break; + case _IMM5_MULTI_LOAD: + if (val >= 2 && val <= 32) + { + if (val == 32) + { + val = 0; + } + return val; + } + else + { + return (int) s3_FAIL; + } + break; + + case _IMM32: + if (val >= 0 && val <= 0xffffffff) + { + return val; + } + else + { + return (int) s3_FAIL; + } + default: if (data_type == _SIMM14_NEG || data_type == _IMM16_NEG) val = -val; - if (score_df_range[data_type].range[0] <= val - && val <= score_df_range[data_type].range[1]) + if (s3_score_df_range[data_type].range[0] <= val + && val <= s3_score_df_range[data_type].range[1]) return val; break; } - return (int) FAIL; + return (int) s3_FAIL; } static int -data_op2 (char **str, int shift, enum score_data_type data_type) +s3_data_op2 (char **str, int shift, enum score_data_type data_type) { - int value; - char data_exp[MAX_LITERAL_POOL_SIZE]; + bfd_signed_vma value; + char data_exp[s3_MAX_LITERAL_POOL_SIZE]; char *dataptr; int cnt = 0; char *pp = NULL; - skip_whitespace (*str); - inst.error = NULL; + s3_skip_whitespace (*str); + s3_inst.error = NULL; dataptr = * str; /* Set hex_p to zero. */ int hex_p = 0; - while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= MAX_LITERAL_POOL_SIZE)) /* 0x7c = ='|' */ + while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= s3_MAX_LITERAL_POOL_SIZE)) /* 0x7c = ='|' */ { data_exp[cnt] = *dataptr; dataptr++; @@ -1116,18 +1370,18 @@ data_op2 (char **str, int shift, enum score_data_type data_type) if (*dataptr == '|') /* process PCE */ { - if (my_get_expression (&inst.reloc.exp, &pp) == (int) FAIL) - return (int) FAIL; - end_of_line (pp); - if (inst.error != 0) - return (int) FAIL; /* to ouptut_inst to printf out the error */ + if (s3_my_get_expression (&s3_inst.reloc.exp, &pp) == (int) s3_FAIL) + return (int) s3_FAIL; + s3_end_of_line (pp); + if (s3_inst.error != 0) + return (int) s3_FAIL; /* to ouptut_inst to printf out the error */ *str = dataptr; } else /* process 16 bit */ { - if (my_get_expression (&inst.reloc.exp, str) == (int) FAIL) + if (s3_my_get_expression (&s3_inst.reloc.exp, str) == (int) s3_FAIL) { - return (int) FAIL; + return (int) s3_FAIL; } dataptr = (char *)data_exp; @@ -1139,10 +1393,10 @@ data_op2 (char **str, int shift, enum score_data_type data_type) } dataptr = (char *)data_exp; - if ((dataptr != NULL) + if ((dataptr != NULL) && (((strstr (dataptr, "0x")) != NULL) || ((strstr (dataptr, "0X")) != NULL))) - { + { hex_p = 1; if ((data_type != _SIMM16_LA) && (data_type != _VALUE_HI16) @@ -1152,6 +1406,8 @@ data_op2 (char **str, int shift, enum score_data_type data_type) && (data_type != _IMM14) && (data_type != _IMM4) && (data_type != _IMM5) + && (data_type != _IMM5_MULTI_LOAD) + && (data_type != _IMM11) && (data_type != _IMM8) && (data_type != _IMM5_RSHIFT_1) && (data_type != _IMM5_RSHIFT_2) @@ -1159,70 +1415,76 @@ data_op2 (char **str, int shift, enum score_data_type data_type) && (data_type != _SIMM14_NEG) && (data_type != _SIMM16_NEG) && (data_type != _IMM10_RSHIFT_2) - && (data_type != _GP_IMM15)) + && (data_type != _GP_IMM15) + && (data_type != _SIMM5) + && (data_type != _SIMM6) + && (data_type != _IMM32) + && (data_type != _SIMM32)) { data_type += 24; } } - if ((inst.reloc.exp.X_add_number == 0) - && (inst.type != Insn_Type_SYN) - && (inst.type != Rd_rvalueRs_SI15) - && (inst.type != Rd_lvalueRs_SI15) - && (inst.type != Insn_internal) + if ((s3_inst.reloc.exp.X_add_number == 0) + && (s3_inst.type != Insn_Type_SYN) + && (s3_inst.type != Rd_rvalueRs_SI15) + && (s3_inst.type != Rd_lvalueRs_SI15) + && (s3_inst.type != Insn_internal) && (((*dataptr >= 'a') && (*dataptr <= 'z')) || ((*dataptr == '0') && (*(dataptr + 1) == 'x') && (*(dataptr + 2) != '0')) || ((*dataptr == '+') && (*(dataptr + 1) != '0')) || ((*dataptr == '-') && (*(dataptr + 1) != '0')))) { - inst.error = BAD_ARGS; - return (int) FAIL; + s3_inst.error = s3_BAD_ARGS; + return (int) s3_FAIL; } } - if ((inst.reloc.exp.X_add_symbol) + if ((s3_inst.reloc.exp.X_add_symbol) && ((data_type == _SIMM16) || (data_type == _SIMM16_NEG) || (data_type == _IMM16_NEG) || (data_type == _SIMM14) || (data_type == _SIMM14_NEG) || (data_type == _IMM5) + || (data_type == _IMM5_MULTI_LOAD) + || (data_type == _IMM11) || (data_type == _IMM14) || (data_type == _IMM20) || (data_type == _IMM16) || (data_type == _IMM15) || (data_type == _IMM4))) { - inst.error = BAD_ARGS; - return (int) FAIL; + s3_inst.error = s3_BAD_ARGS; + return (int) s3_FAIL; } - if (inst.reloc.exp.X_add_symbol) + if (s3_inst.reloc.exp.X_add_symbol) { switch (data_type) { case _SIMM16_LA: - return (int) FAIL; + return (int) s3_FAIL; case _VALUE_HI16: - inst.reloc.type = BFD_RELOC_HI16_S; - inst.reloc.pc_rel = 0; + s3_inst.reloc.type = BFD_RELOC_HI16_S; + s3_inst.reloc.pc_rel = 0; break; case _VALUE_LO16: - inst.reloc.type = BFD_RELOC_LO16; - inst.reloc.pc_rel = 0; + s3_inst.reloc.type = BFD_RELOC_LO16; + s3_inst.reloc.pc_rel = 0; break; case _GP_IMM15: - inst.reloc.type = BFD_RELOC_SCORE_GPREL15; - inst.reloc.pc_rel = 0; + s3_inst.reloc.type = BFD_RELOC_SCORE_GPREL15; + s3_inst.reloc.pc_rel = 0; break; case _SIMM16_pic: case _IMM16_LO16_pic: - inst.reloc.type = BFD_RELOC_SCORE_GOT_LO16; - inst.reloc.pc_rel = 0; + s3_inst.reloc.type = BFD_RELOC_SCORE_GOT_LO16; + s3_inst.reloc.pc_rel = 0; break; default: - inst.reloc.type = BFD_RELOC_32; - inst.reloc.pc_rel = 0; + s3_inst.reloc.type = BFD_RELOC_32; + s3_inst.reloc.pc_rel = 0; break; } } @@ -1230,533 +1492,591 @@ data_op2 (char **str, int shift, enum score_data_type data_type) { if (data_type == _IMM16_pic) { - inst.reloc.type = BFD_RELOC_SCORE_DUMMY_HI16; - inst.reloc.pc_rel = 0; + s3_inst.reloc.type = BFD_RELOC_SCORE_DUMMY_HI16; + s3_inst.reloc.pc_rel = 0; } - if (data_type == _SIMM16_LA && inst.reloc.exp.X_unsigned == 1) + if (data_type == _SIMM16_LA && s3_inst.reloc.exp.X_unsigned == 1) { - value = validate_immediate (inst.reloc.exp.X_add_number, _SIMM16_LA_POS, hex_p); - if (value == (int) FAIL) /* for advance to check if this is ldis */ - if ((inst.reloc.exp.X_add_number & 0xffff) == 0) + value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _SIMM16_LA_POS, hex_p); + if (value == (int) s3_FAIL) /* for advance to check if this is ldis */ + if ((s3_inst.reloc.exp.X_add_number & 0xffff) == 0) { - inst.instruction |= 0x8000000; - inst.instruction |= ((inst.reloc.exp.X_add_number >> 16) << 1) & 0x1fffe; - return SUCCESS; + s3_inst.instruction |= 0x8000000; + s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number >> 16) << 1) & 0x1fffe; + return s3_SUCCESS; } } else { - value = validate_immediate (inst.reloc.exp.X_add_number, data_type, hex_p); + value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, hex_p); } - if (value == (int) FAIL) + if (value == (int) s3_FAIL) { - if ((data_type != _SIMM14_NEG) && (data_type != _SIMM16_NEG) && (data_type != _IMM16_NEG)) + if (data_type == _IMM32) + { + sprintf (s3_err_msg, + _("invalid constant: %d bit expression not in range %u..%u"), + s3_score_df_range[data_type].bits, + 0, (unsigned)0xffffffff); + } + else if (data_type == _IMM5_MULTI_LOAD) + { + sprintf (s3_err_msg, + _("invalid constant: %d bit expression not in range %u..%u"), + 5, 2, 32); + } + else if ((data_type != _SIMM14_NEG) && (data_type != _SIMM16_NEG) && (data_type != _IMM16_NEG)) { - sprintf (err_msg, + sprintf (s3_err_msg, _("invalid constant: %d bit expression not in range %d..%d"), - score_df_range[data_type].bits, - score_df_range[data_type].range[0], score_df_range[data_type].range[1]); + s3_score_df_range[data_type].bits, + s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]); } else { - sprintf (err_msg, + sprintf (s3_err_msg, _("invalid constant: %d bit expression not in range %d..%d"), - score_df_range[data_type].bits, - -score_df_range[data_type].range[1], -score_df_range[data_type].range[0]); + s3_score_df_range[data_type].bits, + -s3_score_df_range[data_type].range[1], -s3_score_df_range[data_type].range[0]); } - inst.error = err_msg; - return (int) FAIL; + s3_inst.error = s3_err_msg; + return (int) s3_FAIL; } - if ((score_df_range[data_type].range[0] != 0) || (data_type == _IMM5_RANGE_8_31)) + if (((s3_score_df_range[data_type].range[0] != 0) || (data_type == _IMM5_RANGE_8_31)) + && data_type != _IMM5_MULTI_LOAD) { - value &= (1 << score_df_range[data_type].bits) - 1; + value &= (1 << s3_score_df_range[data_type].bits) - 1; } - inst.instruction |= value << shift; - } - - if ((inst.instruction & 0xf0000000) == 0x30000000) - { - if ((((inst.instruction >> 20) & 0x1F) != 0) - && (((inst.instruction >> 20) & 0x1F) != 1) - && (((inst.instruction >> 20) & 0x1F) != 2) - && (((inst.instruction >> 20) & 0x1F) != 3) - && (((inst.instruction >> 20) & 0x1F) != 4) - && (((inst.instruction >> 20) & 0x1F) != 8) - && (((inst.instruction >> 20) & 0x1F) != 9) - && (((inst.instruction >> 20) & 0x1F) != 0xa) - && (((inst.instruction >> 20) & 0x1F) != 0xb) - && (((inst.instruction >> 20) & 0x1F) != 0xc) - && (((inst.instruction >> 20) & 0x1F) != 0xd) - && (((inst.instruction >> 20) & 0x1F) != 0xe) - && (((inst.instruction >> 20) & 0x1F) != 0x10) - && (((inst.instruction >> 20) & 0x1F) != 0x11) - && (((inst.instruction >> 20) & 0x1F) != 0x18) - && (((inst.instruction >> 20) & 0x1F) != 0x1A) - && (((inst.instruction >> 20) & 0x1F) != 0x1B) - && (((inst.instruction >> 20) & 0x1F) != 0x1d) - && (((inst.instruction >> 20) & 0x1F) != 0x1e) - && (((inst.instruction >> 20) & 0x1F) != 0x1f)) + s3_inst.instruction |= value << shift; + } + + if ((s3_inst.instruction & 0x3e000000) == 0x30000000) + { + if ((((s3_inst.instruction >> 20) & 0x1F) != 0) + && (((s3_inst.instruction >> 20) & 0x1F) != 1) + && (((s3_inst.instruction >> 20) & 0x1F) != 2) + && (((s3_inst.instruction >> 20) & 0x1F) != 0x10)) { - inst.error = _("invalid constant: bit expression not defined"); - return (int) FAIL; + s3_inst.error = _("invalid constant: bit expression not defined"); + return (int) s3_FAIL; } } - return SUCCESS; + return s3_SUCCESS; } /* Handle addi/addi.c/addis.c/cmpi.c/addis.c/ldi. */ - static void -do_rdsi16 (char *str) +s3_do_rdsi16 (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL - || data_op2 (&str, 1, _SIMM16) == (int) FAIL - || end_of_line (str) == (int) FAIL) + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_data_op2 (&str, 1, _SIMM16) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) return; - /* ldi. */ - if ((inst.instruction & 0x20c0000) == 0x20c0000) + /* ldi.->ldiu! only for imm5 */ + if ((s3_inst.instruction & 0x20c0000) == 0x20c0000) + { + if ((s3_inst.instruction & 0x1ffc0) != 0) + { + s3_inst.relax_inst = 0x8000; + } + else + { + s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x1f; + s3_inst.relax_inst |= (((s3_inst.instruction >> 20)& 0x1f) <<5); + s3_inst.relax_size = 2; + } + } + /*cmpi.c */ + else if ((s3_inst.instruction & 0x02040001) == 0x02040001) + { + /* imm <=0x3f (5 bit<<1)*/ + if (((s3_inst.instruction & 0x1ffe0)==0)||(((s3_inst.instruction & 0x1ffe0) == 0x1ffe0)&&(s3_inst.instruction & 0x003e) !=0)) + { + s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x1f; + s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0x1f) << 5); + s3_inst.relax_size = 2; + } + else + { + s3_inst.relax_inst =0x8000; + + } + } + /* addi */ + else if (((s3_inst.instruction & 0x2000000) == 0x02000000)&& (s3_inst.relax_inst!=0x8000)) { - if ((((inst.instruction >> 20) & 0x10) == 0x10) || ((inst.instruction & 0x1fe00) != 0)) + /* rd : 0-16 ; imm <=0x7f (6 bit<<1)*/ + if ((((s3_inst.instruction >> 20) & 0x10) != 0x10) && + (((s3_inst.instruction & 0x1ffc0)==0)||(((s3_inst.instruction & 0x1ffc0) == 0x1ffc0)&&(s3_inst.instruction & 0x007e) !=0))) { - inst.relax_inst = 0x8000; + s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x3f; + s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 6); + s3_inst.relax_size = 2; } else { - inst.relax_inst |= (inst.instruction >> 1) & 0xff; - inst.relax_inst |= (((inst.instruction >> 20) & 0xf) << 8); - inst.relax_size = 2; + s3_inst.relax_inst =0x8000; + } } - else if (((inst.instruction >> 20) & 0x10) == 0x10) + + else if (((s3_inst.instruction >> 20) & 0x10) == 0x10) { - inst.relax_inst = 0x8000; + s3_inst.relax_inst = 0x8000; } } +static void +s3_do_ldis (char *str) +{ + s3_skip_whitespace (str); + + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_data_op2 (&str, 1, _IMM16) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) + return; +} + /* Handle subi/subi.c. */ +static void +s3_do_sub_rdsi16 (char *str) +{ + s3_skip_whitespace (str); + + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL + && s3_skip_past_comma (&str) != (int) s3_FAIL + && s3_data_op2 (&str, 1, _SIMM16_NEG) != (int) s3_FAIL) + s3_end_of_line (str); +} +/* Handle subis/subis.c. */ static void -do_sub_rdsi16 (char *str) +s3_do_sub_rdi16 (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL - && skip_past_comma (&str) != (int) FAIL - && data_op2 (&str, 1, _SIMM16_NEG) != (int) FAIL) - end_of_line (str); + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL + && s3_skip_past_comma (&str) != (int) s3_FAIL + && s3_data_op2 (&str, 1, _IMM16_NEG) != (int) s3_FAIL) + s3_end_of_line (str); } /* Handle addri/addri.c. */ - static void -do_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */ +s3_do_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */ { - skip_whitespace (str); + s3_skip_whitespace (str); - if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL - && skip_past_comma (&str) != (int) FAIL - && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL - && skip_past_comma (&str) != (int) FAIL) - data_op2 (&str, 1, _SIMM14); + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL + && s3_skip_past_comma (&str) != (int) s3_FAIL + && s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) != (int) s3_FAIL + && s3_skip_past_comma (&str) != (int) s3_FAIL) + s3_data_op2 (&str, 1, _SIMM14); } /* Handle subri.c/subri. */ static void -do_sub_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */ +s3_do_sub_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */ { - skip_whitespace (str); + s3_skip_whitespace (str); - if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL - && skip_past_comma (&str) != (int) FAIL - && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL - && skip_past_comma (&str) != (int) FAIL - && data_op2 (&str, 1, _SIMM14_NEG) != (int) FAIL) - end_of_line (str); + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL + && s3_skip_past_comma (&str) != (int) s3_FAIL + && s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) != (int) s3_FAIL + && s3_skip_past_comma (&str) != (int) s3_FAIL + && s3_data_op2 (&str, 1, _SIMM14_NEG) != (int) s3_FAIL) + s3_end_of_line (str); } -/* Handle bitclr.c/bitset.c/bittgl.c/slli.c/srai.c/srli.c/roli.c/rori.c/rolic.c. */ +/* Handle bitclr.c/bitset.c/bittgl.c/slli.c/srai.c/srli.c/roli.c/rori.c/rolic.c. + 0~((2^14)-1) */ static void -do_rdrsi5 (char *str) /* 0~((2^14)-1) */ +s3_do_rdrsi5 (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL - || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL - || data_op2 (&str, 10, _IMM5) == (int) FAIL - || end_of_line (str) == (int) FAIL) + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) return; - if ((((inst.instruction >> 20) & 0x1f) == ((inst.instruction >> 15) & 0x1f)) - && (inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0)) + if ((((s3_inst.instruction >> 20) & 0x1f) == ((s3_inst.instruction >> 15) & 0x1f)) + && (s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 15) & 0x10) == 0)) { - inst.relax_inst |= (((inst.instruction >> 10) & 0x1f) << 3) | (((inst.instruction >> 15) & 0xf) << 8); - inst.relax_size = 2; + s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f) ) | (((s3_inst.instruction >> 15) & 0xf) << 5); + s3_inst.relax_size = 2; } else - inst.relax_inst = 0x8000; + s3_inst.relax_inst = 0x8000; } -/* Handle andri/orri/andri.c/orri.c. */ - +/* Handle andri/orri/andri.c/orri.c. + 0 ~ ((2^14)-1) */ static void -do_rdrsi14 (char *str) /* 0 ~ ((2^14)-1) */ +s3_do_rdrsi14 (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL - && skip_past_comma (&str) != (int) FAIL - && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL - && skip_past_comma (&str) != (int) FAIL - && data_op2 (&str, 1, _IMM14) != (int) FAIL) - end_of_line (str); + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL + && s3_skip_past_comma (&str) != (int) s3_FAIL + && s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) != (int) s3_FAIL + && s3_skip_past_comma (&str) != (int) s3_FAIL + && s3_data_op2 (&str, 1, _IMM14) != (int) s3_FAIL) + s3_end_of_line (str); } /* Handle bittst.c. */ static void -do_xrsi5 (char *str) +s3_do_xrsi5 (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL - || data_op2 (&str, 10, _IMM5) == (int) FAIL - || end_of_line (str) == (int) FAIL) + if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) return; - if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0)) + if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 15) & 0x10) == 0)) { - inst.relax_inst |= (((inst.instruction >> 10) & 0x1f) << 3) | (((inst.instruction >> 15) & 0xf) << 8); - inst.relax_size = 2; + s3_inst.relax_inst |= ((s3_inst.instruction >> 10) & 0x1f) | (((s3_inst.instruction >> 15) & 0xf) << 5); + s3_inst.relax_size = 2; } else - inst.relax_inst = 0x8000; + s3_inst.relax_inst = 0x8000; } /* Handle addis/andi/ori/andis/oris/ldis. */ static void -do_rdi16 (char *str) +s3_do_rdi16 (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL - || data_op2 (&str, 1, _IMM16) == (int) FAIL - || end_of_line (str) == (int) FAIL) + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_data_op2 (&str, 1, _IMM16) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) return; - /* - if (((inst.instruction & 0xa0dfffe) != 0xa0c0000) || ((((inst.instruction >> 20) & 0x1f) & 0x10) == 0x10)) - inst.relax_inst = 0x8000; - else - inst.relax_size = 2; - */ + + /* ldis */ + if ((s3_inst.instruction & 0x3e0e0000) == 0x0a0c0000) + { + /* rd : 0-16 ;imm =0 -> can transform to addi!*/ + if ((((s3_inst.instruction >> 20) & 0x10) != 0x10) && ((s3_inst.instruction & 0x1ffff)==0)) + { + s3_inst.relax_inst =0x5400; /* ldiu! */ + s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x1f; + s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 5); + s3_inst.relax_size = 2; + } + else + { + s3_inst.relax_inst =0x8000; + + } + } + + /* addis */ + else if ((s3_inst.instruction & 0x3e0e0001) == 0x0a000000) + { + /* rd : 0-16 ;imm =0 -> can transform to addi!*/ + if ((((s3_inst.instruction >> 20) & 0x10) != 0x10) && ((s3_inst.instruction & 0x1ffff)==0)) + { + s3_inst.relax_inst =0x5c00; /* addi! */ + s3_inst.relax_inst |= (s3_inst.instruction >> 1) & 0x3f; + s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 6); + s3_inst.relax_size = 2; + } + else + { + s3_inst.relax_inst =0x8000; + + } + } } static void -do_macro_rdi32hi (char *str) +s3_do_macro_rdi32hi (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - /* Do not handle end_of_line(). */ - if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL - && skip_past_comma (&str) != (int) FAIL) - data_op2 (&str, 1, _VALUE_HI16); + /* Do not handle s3_end_of_line(). */ + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL + && s3_skip_past_comma (&str) != (int) s3_FAIL) + s3_data_op2 (&str, 1, _VALUE_HI16); } static void -do_macro_rdi32lo (char *str) +s3_do_macro_rdi32lo (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - /* Do not handle end_of_line(). */ - if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL - && skip_past_comma (&str) != (int) FAIL) - data_op2 (&str, 1, _VALUE_LO16); + /* Do not handle s3_end_of_line(). */ + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL + && s3_skip_past_comma (&str) != (int) s3_FAIL) + s3_data_op2 (&str, 1, _VALUE_LO16); } /* Handle ldis_pic. */ - static void -do_rdi16_pic (char *str) +s3_do_rdi16_pic (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL - && skip_past_comma (&str) != (int) FAIL - && data_op2 (&str, 1, _IMM16_pic) != (int) FAIL) - end_of_line (str); + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL + && s3_skip_past_comma (&str) != (int) s3_FAIL + && s3_data_op2 (&str, 1, _IMM16_pic) != (int) s3_FAIL) + s3_end_of_line (str); } /* Handle addi_s_pic to generate R_SCORE_GOT_LO16 . */ - static void -do_addi_s_pic (char *str) +s3_do_addi_s_pic (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL - && skip_past_comma (&str) != (int) FAIL - && data_op2 (&str, 1, _SIMM16_pic) != (int) FAIL) - end_of_line (str); + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL + && s3_skip_past_comma (&str) != (int) s3_FAIL + && s3_data_op2 (&str, 1, _SIMM16_pic) != (int) s3_FAIL) + s3_end_of_line (str); } /* Handle addi_u_pic to generate R_SCORE_GOT_LO16 . */ - static void -do_addi_u_pic (char *str) +s3_do_addi_u_pic (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL - && skip_past_comma (&str) != (int) FAIL - && data_op2 (&str, 1, _IMM16_LO16_pic) != (int) FAIL) - end_of_line (str); + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL + && s3_skip_past_comma (&str) != (int) s3_FAIL + && s3_data_op2 (&str, 1, _IMM16_LO16_pic) != (int) s3_FAIL) + s3_end_of_line (str); } /* Handle mfceh/mfcel/mtceh/mtchl. */ - static void -do_rd (char *str) +s3_do_rd (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL) - end_of_line (str); + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL) + s3_end_of_line (str); } +/* Handle br{cond},cmpzteq.c ,cmpztmi.c ,cmpz.c */ static void -do_rs (char *str) +s3_do_rs (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL - || end_of_line (str) == (int) FAIL) + if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) return; - if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0)) + if ((s3_inst.relax_inst != 0x8000) ) { - inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 8) | (((inst.instruction >> 15) & 0xf) << 4); - inst.relax_size = 2; + s3_inst.relax_inst |= ((s3_inst.instruction >> 15) &0x1f); + s3_inst.relax_size = 2; } else - inst.relax_inst = 0x8000; + s3_inst.relax_inst = 0x8000; } static void -do_i15 (char *str) +s3_do_i15 (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if (data_op2 (&str, 10, _IMM15) != (int) FAIL) - end_of_line (str); + if (s3_data_op2 (&str, 10, _IMM15) != (int) s3_FAIL) + s3_end_of_line (str); } static void -do_xi5x (char *str) +s3_do_xi5x (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if (data_op2 (&str, 15, _IMM5) == (int) FAIL || end_of_line (str) == (int) FAIL) + if (s3_data_op2 (&str, 15, _IMM5) == (int) s3_FAIL || s3_end_of_line (str) == (int) s3_FAIL) return; - if (inst.relax_inst != 0x8000) + if (s3_inst.relax_inst != 0x8000) { - inst.relax_inst |= (((inst.instruction >> 15) & 0x1f) << 3); - inst.relax_size = 2; + s3_inst.relax_inst |= ((s3_inst.instruction >> 15) & 0x1f) ; + s3_inst.relax_size = 2; } } static void -do_rdrs (char *str) +s3_do_rdrs (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL - || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL - || end_of_line (str) == (int) FAIL) + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) return; - if (inst.relax_inst != 0x8000) + if (s3_inst.relax_inst != 0x8000) { - if (((inst.instruction & 0x7f) == 0x56)) /* adjust mv -> mv! / mlfh! / mhfl! */ + if (((s3_inst.instruction & 0x7f) == 0x56)) /* adjust mv -> mv!*/ { - /* mlfh */ - if ((((inst.instruction >> 15) & 0x10) != 0x0) && (((inst.instruction >> 20) & 0x10) == 0)) - { - inst.relax_inst = 0x00000001 | (((inst.instruction >> 15) & 0xf) << 4) - | (((inst.instruction >> 20) & 0xf) << 8); - inst.relax_size = 2; - } - /* mhfl */ - else if ((((inst.instruction >> 15) & 0x10) == 0x0) && ((inst.instruction >> 20) & 0x10) != 0) - { - inst.relax_inst = 0x00000002 | (((inst.instruction >> 15) & 0xf) << 4) - | (((inst.instruction >> 20) & 0xf) << 8); - inst.relax_size = 2; - } - else if ((((inst.instruction >> 15) & 0x10) == 0x0) && (((inst.instruction >> 20) & 0x10) == 0)) - { - inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4) - | (((inst.instruction >> 20) & 0xf) << 8); - inst.relax_size = 2; - } - else - { - inst.relax_inst = 0x8000; - } + /* mv! rd : 5bit , ra : 5bit */ + s3_inst.relax_inst |= ((s3_inst.instruction >> 15) & 0x1f) | (((s3_inst.instruction >> 20) & 0x1f) << 5); + s3_inst.relax_size = 2; + } - else if ((((inst.instruction >> 15) & 0x10) == 0x0) && (((inst.instruction >> 20) & 0x10) == 0)) + else if ((((s3_inst.instruction >> 15) & 0x10) == 0x0) && (((s3_inst.instruction >> 20) & 0x10) == 0)) { - inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4) - | (((inst.instruction >> 20) & 0xf) << 8); - inst.relax_size = 2; + s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0xf) << 4) + | (((s3_inst.instruction >> 20) & 0xf) << 8); + s3_inst.relax_size = 2; } else { - inst.relax_inst = 0x8000; + s3_inst.relax_inst = 0x8000; } } } /* Handle mfcr/mtcr. */ static void -do_rdcrs (char *str) +s3_do_rdcrs (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL - && skip_past_comma (&str) != (int) FAIL - && reg_required_here (&str, 15, REG_TYPE_SCORE_CR) != (int) FAIL) - end_of_line (str); + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL + && s3_skip_past_comma (&str) != (int) s3_FAIL + && s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE_CR) != (int) s3_FAIL) + s3_end_of_line (str); } /* Handle mfsr/mtsr. */ - static void -do_rdsrs (char *str) +s3_do_rdsrs (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); /* mfsr */ - if ((inst.instruction & 0xff) == 0x50) + if ((s3_inst.instruction & 0xff) == 0x50) { - if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL - && skip_past_comma (&str) != (int) FAIL - && reg_required_here (&str, 10, REG_TYPE_SCORE_SR) != (int) FAIL) - end_of_line (str); + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) != (int) s3_FAIL + && s3_skip_past_comma (&str) != (int) s3_FAIL + && s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE_SR) != (int) s3_FAIL) + s3_end_of_line (str); } else { - if (reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL - && skip_past_comma (&str) != (int) FAIL) - reg_required_here (&str, 10, REG_TYPE_SCORE_SR); + if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) != (int) s3_FAIL + && s3_skip_past_comma (&str) != (int) s3_FAIL) + s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE_SR); } } /* Handle neg. */ - static void -do_rdxrs (char *str) +s3_do_rdxrs (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL - || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL - || end_of_line (str) == (int) FAIL) + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) return; - if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 10) & 0x10) == 0) - && (((inst.instruction >> 20) & 0x10) == 0)) + if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 10) & 0x10) == 0) + && (((s3_inst.instruction >> 20) & 0x10) == 0)) { - inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) | (((inst.instruction >> 20) & 0xf) << 8); - inst.relax_size = 2; + s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0xf) << 4) | (((s3_inst.instruction >> 20) & 0xf) << 8); + s3_inst.relax_size = 2; } else - inst.relax_inst = 0x8000; + s3_inst.relax_inst = 0x8000; } /* Handle cmp.c/cmp. */ static void -do_rsrs (char *str) +s3_do_rsrs (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL - || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL - || end_of_line (str) == (int) FAIL) + if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) return; - if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 20) & 0x1f) == 3) - && (((inst.instruction >> 10) & 0x10) == 0) && (((inst.instruction >> 15) & 0x10) == 0)) + if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 20) & 0x1f) == 3) ) { - inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) | (((inst.instruction >> 15) & 0xf) << 8); - inst.relax_size = 2; + s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f)) | (((s3_inst.instruction >> 15) & 0x1f) << 5); + s3_inst.relax_size = 2; } else - inst.relax_inst = 0x8000; + s3_inst.relax_inst = 0x8000; } static void -do_ceinst (char *str) +s3_do_ceinst (char *str) { char *strbak; strbak = str; - skip_whitespace (str); - - if (data_op2 (&str, 20, _IMM5) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL - || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL - || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL - || data_op2 (&str, 5, _IMM5) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL - || data_op2 (&str, 0, _IMM5) == (int) FAIL - || end_of_line (str) == (int) FAIL) + s3_skip_whitespace (str); + + if (s3_data_op2 (&str, 20, _IMM5) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_data_op2 (&str, 5, _IMM5) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) { return; } else { str = strbak; - if (data_op2 (&str, 0, _IMM25) == (int) FAIL) + if (s3_data_op2 (&str, 0, _IMM25) == (int) s3_FAIL) return; } } static int -reglow_required_here (char **str, int shift) +s3_reglow_required_here (char **str, int shift) { - static char buff[MAX_LITERAL_POOL_SIZE]; + static char buff[s3_MAX_LITERAL_POOL_SIZE]; int reg; char *start = *str; - if ((reg = score_reg_parse (str, all_reg_maps[REG_TYPE_SCORE].htab)) != (int) FAIL) + if ((reg = s3_score_reg_parse (str, s3_all_reg_maps[s3_REG_TYPE_SCORE].htab)) != (int) s3_FAIL) { - if ((reg == 1) && (nor1 == 1) && (inst.bwarn == 0)) + if ((reg == 1) && (s3_nor1 == 1) && (s3_inst.bwarn == 0)) { as_warn (_("Using temp register(r1)")); - inst.bwarn = 1; + s3_inst.bwarn = 1; } if (reg < 16) { if (shift >= 0) - inst.instruction |= reg << shift; + s3_inst.instruction |= (bfd_vma) reg << shift; return reg; } @@ -1765,136 +2085,83 @@ reglow_required_here (char **str, int shift) /* Restore the start point, we may have got a reg of the wrong class. */ *str = start; sprintf (buff, _("low register(r0-r15)expected, not '%.100s'"), start); - inst.error = buff; - return (int) FAIL; + s3_inst.error = buff; + return (int) s3_FAIL; } -/* Handle addc!/add!/and!/cmp!/neg!/not!/or!/sll!/srl!/sra!/xor!/sub!. */ +/* Handle add!/and!/or!/sub!. */ static void -do16_rdrs (char *str) +s3_do16_rdrs2 (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if (reglow_required_here (&str, 8) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL - || reglow_required_here (&str, 4) == (int) FAIL - || end_of_line (str) == (int) FAIL) + if (s3_reglow_required_here (&str, 4) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_reglow_required_here (&str, 0) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) { return; } - else +} + +/* Handle br!/brl!. */ +static void +s3_do16_br (char *str) +{ + s3_skip_whitespace (str); + + if (s3_reg_required_here (&str, 0, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) { - if ((inst.instruction & 0x700f) == 0x2003) /* cmp! */ - { - inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 15) - | (((inst.instruction >> 4) & 0xf) << 10); - } - else if ((inst.instruction & 0x700f) == 0x2006) /* not! */ - { - inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20) - | (((inst.instruction >> 4) & 0xf) << 15); - } - else - { - inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20) - | (((inst.instruction >> 8) & 0xf) << 15) | (((inst.instruction >> 4) & 0xf) << 10); - } - inst.relax_size = 4; + return; } } +/* Handle brr!. */ static void -do16_rs (char *str) +s3_do16_brr (char *str) { int rd = 0; - skip_whitespace (str); + s3_skip_whitespace (str); - if ((rd = reglow_required_here (&str, 4)) == (int) FAIL - || end_of_line (str) == (int) FAIL) + if ((rd = s3_reg_required_here (&str, 0,s3_REG_TYPE_SCORE)) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) { return; } - else - { - inst.relax_inst |= rd << 20; - inst.relax_size = 4; - } } -/* Handle br!/brl!. */ +/*Handle ltbw / ltbh / ltbb */ static void -do16_xrs (char *str) +s3_do_ltb (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL) + { + return; + } - if (reglow_required_here (&str, 4) == (int) FAIL || end_of_line (str) == (int) FAIL) + s3_skip_whitespace (str); + if (*str++ != '[') { + s3_inst.error = _("missing ["); return; } - else + + if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL) { - inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 10) - | (((inst.instruction >> 4) & 0xf) << 15); - inst.relax_size = 4; + return; } -} -static int -reghigh_required_here (char **str, int shift) -{ - static char buff[MAX_LITERAL_POOL_SIZE]; - int reg; - char *start = *str; - - if ((reg = score_reg_parse (str, all_reg_maps[REG_TYPE_SCORE].htab)) != (int) FAIL) - { - if (15 < reg && reg < 32) - { - if (shift >= 0) - inst.instruction |= (reg & 0xf) << shift; - - return reg; - } - } - - *str = start; - sprintf (buff, _("high register(r16-r31)expected, not '%.100s'"), start); - inst.error = buff; - return (int) FAIL; -} - -/* Handle mhfl!. */ -static void -do16_hrdrs (char *str) -{ - skip_whitespace (str); - - if (reghigh_required_here (&str, 8) != (int) FAIL - && skip_past_comma (&str) != (int) FAIL - && reglow_required_here (&str, 4) != (int) FAIL - && end_of_line (str) != (int) FAIL) - { - inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20) - | (((inst.instruction >> 4) & 0xf) << 15) | (0xf << 10); - inst.relax_size = 4; - } -} - -/* Handle mlfh!. */ -static void -do16_rdhrs (char *str) -{ - skip_whitespace (str); - - if (reglow_required_here (&str, 8) != (int) FAIL - && skip_past_comma (&str) != (int) FAIL - && reghigh_required_here (&str, 4) != (int) FAIL - && end_of_line (str) != (int) FAIL) + s3_skip_whitespace (str); + if (*str++ != ']') { - inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20) - | ((((inst.instruction >> 4) & 0xf) | 0x10) << 15) | (0xf << 10); - inst.relax_size = 4; + s3_inst.error = _("missing ]"); + return; } } @@ -1905,7 +2172,7 @@ do16_rdhrs (char *str) a data instruction. We do this by pushing the expression into a symbol in the expr_section, and creating a fix for that. */ static fixS * -fix_new_score (fragS * frag, int where, short int size, expressionS * exp, int pc_rel, int reloc) +s3_fix_new_score (fragS * frag, int where, short int size, expressionS * exp, int pc_rel, int reloc) { fixS *new_fix; @@ -1925,55 +2192,55 @@ fix_new_score (fragS * frag, int where, short int size, expressionS * exp, int p } static void -init_dependency_vector (void) +s3_init_dependency_vector (void) { int i; - for (i = 0; i < vector_size; i++) - memset (&dependency_vector[i], '\0', sizeof (dependency_vector[i])); + for (i = 0; i < s3_vector_size; i++) + memset (&s3_dependency_vector[i], '\0', sizeof (s3_dependency_vector[i])); return; } -static enum insn_type_for_dependency -dependency_type_from_insn (char *insn_name) +static enum s3_insn_type_for_dependency +s3_dependency_type_from_insn (char *insn_name) { - char name[INSN_NAME_LEN]; - const struct insn_to_dependency *tmp; + char name[s3_INSN_NAME_LEN]; + const struct s3_insn_to_dependency *tmp; strcpy (name, insn_name); - tmp = (const struct insn_to_dependency *) hash_find (dependency_insn_hsh, name); + tmp = (const struct s3_insn_to_dependency *) hash_find (s3_dependency_insn_hsh, name); if (tmp) return tmp->type; - return D_all_insn; + return s3_D_all_insn; } static int -check_dependency (char *pre_insn, char *pre_reg, +s3_check_dependency (char *pre_insn, char *pre_reg, char *cur_insn, char *cur_reg, int *warn_or_error) { int bubbles = 0; unsigned int i; - enum insn_type_for_dependency pre_insn_type; - enum insn_type_for_dependency cur_insn_type; + enum s3_insn_type_for_dependency pre_insn_type; + enum s3_insn_type_for_dependency cur_insn_type; - pre_insn_type = dependency_type_from_insn (pre_insn); - cur_insn_type = dependency_type_from_insn (cur_insn); + pre_insn_type = s3_dependency_type_from_insn (pre_insn); + cur_insn_type = s3_dependency_type_from_insn (cur_insn); - for (i = 0; i < sizeof (data_dependency_table) / sizeof (data_dependency_table[0]); i++) + for (i = 0; i < sizeof (s3_data_dependency_table) / sizeof (s3_data_dependency_table[0]); i++) { - if ((pre_insn_type == data_dependency_table[i].pre_insn_type) - && (D_all_insn == data_dependency_table[i].cur_insn_type - || cur_insn_type == data_dependency_table[i].cur_insn_type) - && (strcmp (data_dependency_table[i].pre_reg, "") == 0 - || strcmp (data_dependency_table[i].pre_reg, pre_reg) == 0) - && (strcmp (data_dependency_table[i].cur_reg, "") == 0 - || strcmp (data_dependency_table[i].cur_reg, cur_reg) == 0)) + if ((pre_insn_type == s3_data_dependency_table[i].pre_insn_type) + && (s3_D_all_insn == s3_data_dependency_table[i].cur_insn_type + || cur_insn_type == s3_data_dependency_table[i].cur_insn_type) + && (strcmp (s3_data_dependency_table[i].pre_reg, "") == 0 + || strcmp (s3_data_dependency_table[i].pre_reg, pre_reg) == 0) + && (strcmp (s3_data_dependency_table[i].cur_reg, "") == 0 + || strcmp (s3_data_dependency_table[i].cur_reg, cur_reg) == 0)) { - bubbles = (score7) ? data_dependency_table[i].bubblenum_7 : data_dependency_table[i].bubblenum_5; - *warn_or_error = data_dependency_table[i].warn_or_error; + bubbles = s3_data_dependency_table[i].bubblenum_3; + *warn_or_error = s3_data_dependency_table[i].warn_or_error; break; } } @@ -1982,10 +2249,10 @@ check_dependency (char *pre_insn, char *pre_reg, } static void -build_one_frag (struct score_it one_inst) +s3_build_one_frag (struct s3_score_it one_inst) { char *p; - int relaxable_p = g_opt; + int relaxable_p = s3_g_opt; int relax_size = 0; /* Start a new frag if frag_now is not empty. */ @@ -1999,7 +2266,7 @@ build_one_frag (struct score_it one_inst) frag_grow (20); p = frag_more (one_inst.size); - md_number_to_chars (p, one_inst.instruction, one_inst.size); + s3_md_number_to_chars (p, one_inst.instruction, one_inst.size); #ifdef OBJ_ELF dwarf2_emit_insn (one_inst.size); @@ -2008,26 +2275,26 @@ build_one_frag (struct score_it one_inst) relaxable_p &= (one_inst.relax_size != 0); relax_size = relaxable_p ? one_inst.relax_size : 0; - p = frag_var (rs_machine_dependent, relax_size + RELAX_PAD_BYTE, 0, - RELAX_ENCODE (one_inst.size, one_inst.relax_size, + p = frag_var (rs_machine_dependent, relax_size + s3_RELAX_PAD_BYTE, 0, + s3_RELAX_ENCODE (one_inst.size, one_inst.relax_size, one_inst.type, 0, 0, relaxable_p), NULL, 0, NULL); if (relaxable_p) - md_number_to_chars (p, one_inst.relax_inst, relax_size); + s3_md_number_to_chars (p, one_inst.relax_inst, relax_size); } static void -handle_dependency (struct score_it *theinst) +s3_handle_dependency (struct s3_score_it *theinst) { int i; int warn_or_error = 0; /* warn - 0; error - 1 */ int bubbles = 0; int remainder_bubbles = 0; - char cur_insn[INSN_NAME_LEN]; - char pre_insn[INSN_NAME_LEN]; - struct score_it nop_inst; - struct score_it pflush_inst; + char cur_insn[s3_INSN_NAME_LEN]; + char pre_insn[s3_INSN_NAME_LEN]; + struct s3_score_it nop_inst; + struct s3_score_it pflush_inst; nop_inst.instruction = 0x0000; nop_inst.size = 2; @@ -2044,82 +2311,73 @@ handle_dependency (struct score_it *theinst) /* pflush will clear all data dependency. */ if (strcmp (theinst->name, "pflush") == 0) { - init_dependency_vector (); + s3_init_dependency_vector (); return; } - /* Push current instruction to dependency_vector[0]. */ - for (i = vector_size - 1; i > 0; i--) - memcpy (&dependency_vector[i], &dependency_vector[i - 1], sizeof (dependency_vector[i])); + /* Push current instruction to s3_dependency_vector[0]. */ + for (i = s3_vector_size - 1; i > 0; i--) + memcpy (&s3_dependency_vector[i], &s3_dependency_vector[i - 1], sizeof (s3_dependency_vector[i])); - memcpy (&dependency_vector[0], theinst, sizeof (dependency_vector[i])); + memcpy (&s3_dependency_vector[0], theinst, sizeof (s3_dependency_vector[i])); /* There is no dependency between nop and any instruction. */ - if (strcmp (dependency_vector[0].name, "nop") == 0 - || strcmp (dependency_vector[0].name, "nop!") == 0) + if (strcmp (s3_dependency_vector[0].name, "nop") == 0 + || strcmp (s3_dependency_vector[0].name, "nop!") == 0) return; - /* "pce" is defined in insn_to_dependency_table. */ -#define PCE_NAME "pce" - - if (dependency_vector[0].type == Insn_Type_PCE) - strcpy (cur_insn, PCE_NAME); - else - strcpy (cur_insn, dependency_vector[0].name); + strcpy (cur_insn, s3_dependency_vector[0].name); - for (i = 1; i < vector_size; i++) + for (i = 1; i < s3_vector_size; i++) { - /* The element of dependency_vector is NULL. */ - if (dependency_vector[i].name[0] == '\0') + /* The element of s3_dependency_vector is NULL. */ + if (s3_dependency_vector[i].name[0] == '\0') continue; - if (dependency_vector[i].type == Insn_Type_PCE) - strcpy (pre_insn, PCE_NAME); - else - strcpy (pre_insn, dependency_vector[i].name); + strcpy (pre_insn, s3_dependency_vector[i].name); - bubbles = check_dependency (pre_insn, dependency_vector[i].reg, - cur_insn, dependency_vector[0].reg, &warn_or_error); + bubbles = s3_check_dependency (pre_insn, s3_dependency_vector[i].reg, + cur_insn, s3_dependency_vector[0].reg, &warn_or_error); remainder_bubbles = bubbles - i + 1; if (remainder_bubbles > 0) { int j; - if (fix_data_dependency == 1) + if (s3_fix_data_dependency == 1) { if (remainder_bubbles <= 2) { - if (warn_fix_data_dependency) + if (s3_warn_fix_data_dependency) as_warn (_("Fix data dependency: %s %s -- %s %s (insert %d nop!/%d)"), - dependency_vector[i].name, dependency_vector[i].reg, - dependency_vector[0].name, dependency_vector[0].reg, + s3_dependency_vector[i].name, s3_dependency_vector[i].reg, + s3_dependency_vector[0].name, s3_dependency_vector[0].reg, remainder_bubbles, bubbles); - for (j = (vector_size - 1); (j - remainder_bubbles) > 0; j--) - memcpy (&dependency_vector[j], &dependency_vector[j - remainder_bubbles], - sizeof (dependency_vector[j])); + for (j = (s3_vector_size - 1); (j - remainder_bubbles) > 0; j--) + memcpy (&s3_dependency_vector[j], &s3_dependency_vector[j - remainder_bubbles], + sizeof (s3_dependency_vector[j])); for (j = 1; j <= remainder_bubbles; j++) { - memset (&dependency_vector[j], '\0', sizeof (dependency_vector[j])); + memset (&s3_dependency_vector[j], '\0', sizeof (s3_dependency_vector[j])); /* Insert nop!. */ - build_one_frag (nop_inst); + s3_build_one_frag (nop_inst); } } else { - if (warn_fix_data_dependency) + if (s3_warn_fix_data_dependency) as_warn (_("Fix data dependency: %s %s -- %s %s (insert 1 pflush/%d)"), - dependency_vector[i].name, dependency_vector[i].reg, - dependency_vector[0].name, dependency_vector[0].reg, + s3_dependency_vector[i].name, s3_dependency_vector[i].reg, + s3_dependency_vector[0].name, s3_dependency_vector[0].reg, bubbles); - for (j = 1; j < vector_size; j++) - memset (&dependency_vector[j], '\0', sizeof (dependency_vector[j])); + for (j = 1; j < s3_vector_size; j++) + memset (&s3_dependency_vector[j], '\0', sizeof (s3_dependency_vector[j])); /* Insert pflush. */ - build_one_frag (pflush_inst); + s3_build_one_frag (pflush_inst); } } else @@ -2127,15 +2385,15 @@ handle_dependency (struct score_it *theinst) if (warn_or_error) { as_bad (_("data dependency: %s %s -- %s %s (%d/%d bubble)"), - dependency_vector[i].name, dependency_vector[i].reg, - dependency_vector[0].name, dependency_vector[0].reg, + s3_dependency_vector[i].name, s3_dependency_vector[i].reg, + s3_dependency_vector[0].name, s3_dependency_vector[0].reg, remainder_bubbles, bubbles); } else { as_warn (_("data dependency: %s %s -- %s %s (%d/%d bubble)"), - dependency_vector[i].name, dependency_vector[i].reg, - dependency_vector[0].name, dependency_vector[0].reg, + s3_dependency_vector[i].name, s3_dependency_vector[i].reg, + s3_dependency_vector[0].name, s3_dependency_vector[0].reg, remainder_bubbles, bubbles); } } @@ -2144,9 +2402,9 @@ handle_dependency (struct score_it *theinst) } static enum insn_class -get_insn_class_from_type (enum score_insn_type type) +s3_get_insn_class_from_type (enum score_insn_type type) { - enum insn_class retval = (int) FAIL; + enum insn_class retval = (int) s3_FAIL; switch (type) { @@ -2164,6 +2422,8 @@ get_insn_class_from_type (enum score_insn_type type) case x_Rs: case Rd_LowRs: case NO16_OPD: + case Rd_SI5: + case Rd_SI6: retval = INSN_CLASS_16; break; case Rd_Rs_I5: @@ -2204,6 +2464,8 @@ get_insn_class_from_type (enum score_insn_type type) case Insn_GP: case Insn_PIC: case Insn_internal: + case Insn_BCMP: + case Ra_I9_I5: retval = INSN_CLASS_32; break; case Insn_Type_PCE: @@ -2212,6 +2474,10 @@ get_insn_class_from_type (enum score_insn_type type) case Insn_Type_SYN: retval = INSN_CLASS_SYN; break; + case Rd_I30: + case Rd_I32: + retval = INSN_CLASS_48; + break; default: abort (); break; @@ -2219,90 +2485,107 @@ get_insn_class_from_type (enum score_insn_type type) return retval; } -static unsigned long -adjust_paritybit (unsigned long m_code, enum insn_class class) +/* Type of p-bits: + 48-bit instruction: 1, 1, 0. + 32-bit instruction: 1, 0. + 16-bit instruction: 0. */ +static bfd_vma +s3_adjust_paritybit (bfd_vma m_code, enum insn_class class) { - unsigned long result = 0; - unsigned long m_code_high = 0; + bfd_vma result = 0; + bfd_vma m_code_high = 0; + unsigned long m_code_middle = 0; unsigned long m_code_low = 0; - unsigned long pb_high = 0; + bfd_vma pb_high = 0; + unsigned long pb_middle = 0; unsigned long pb_low = 0; - if (class == INSN_CLASS_32) + if (class == INSN_CLASS_48) + { + pb_high = 0x800000000000LL; + pb_middle = 0x80000000; + pb_low = 0x00000000; + m_code_high = m_code & 0x1fffc0000000LL; + m_code_middle = m_code & 0x3fff8000; + m_code_low = m_code & 0x00007fff; + result = pb_high | (m_code_high << 2) | + pb_middle | (m_code_middle << 1) | + pb_low | m_code_low; + } + else if (class == INSN_CLASS_32 || class == INSN_CLASS_SYN) { pb_high = 0x80000000; - pb_low = 0x00008000; + pb_low = 0x00000000; + m_code_high = m_code & 0x3fff8000; + m_code_low = m_code & 0x00007fff; + result = pb_high | (m_code_high << 1) | pb_low | m_code_low; } else if (class == INSN_CLASS_16) { pb_high = 0; pb_low = 0; + m_code_high = m_code & 0x3fff8000; + m_code_low = m_code & 0x00007fff; + result = pb_high | (m_code_high << 1) | pb_low | m_code_low; } else if (class == INSN_CLASS_PCE) { + /* Keep original. */ pb_high = 0; pb_low = 0x00008000; - } - else if (class == INSN_CLASS_SYN) - { - /* FIXME. at this time, INSN_CLASS_SYN must be 32 bit, but, instruction type should - be changed if macro instruction has been expanded. */ - pb_high = 0x80000000; - pb_low = 0x00008000; + m_code_high = m_code & 0x3fff8000; + m_code_low = m_code & 0x00007fff; + result = pb_high | (m_code_high << 1) | pb_low | m_code_low; } else { abort (); } - m_code_high = m_code & 0x3fff8000; - m_code_low = m_code & 0x00007fff; - result = pb_high | (m_code_high << 1) | pb_low | m_code_low; return result; - } static void -gen_insn_frag (struct score_it *part_1, struct score_it *part_2) +s3_gen_insn_frag (struct s3_score_it *part_1, struct s3_score_it *part_2) { char *p; bfd_boolean pce_p = FALSE; - int relaxable_p = g_opt; + int relaxable_p = s3_g_opt; int relax_size = 0; - struct score_it *inst1 = part_1; - struct score_it *inst2 = part_2; - struct score_it backup_inst1; + struct s3_score_it *inst1 = part_1; + struct s3_score_it *inst2 = part_2; + struct s3_score_it backup_inst1; pce_p = (inst2) ? TRUE : FALSE; - memcpy (&backup_inst1, inst1, sizeof (struct score_it)); + memcpy (&backup_inst1, inst1, sizeof (struct s3_score_it)); /* Adjust instruction opcode and to be relaxed instruction opcode. */ if (pce_p) { backup_inst1.instruction = ((backup_inst1.instruction & 0x7FFF) << 15) | (inst2->instruction & 0x7FFF); - backup_inst1.instruction = adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE); + backup_inst1.instruction = s3_adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE); backup_inst1.relax_inst = 0x8000; - backup_inst1.size = INSN_SIZE; + backup_inst1.size = s3_INSN_SIZE; backup_inst1.relax_size = 0; backup_inst1.type = Insn_Type_PCE; } else { - backup_inst1.instruction = adjust_paritybit (backup_inst1.instruction, - GET_INSN_CLASS (backup_inst1.type)); + backup_inst1.instruction = s3_adjust_paritybit (backup_inst1.instruction, + s3_GET_INSN_CLASS (backup_inst1.type)); } if (backup_inst1.relax_size != 0) { enum insn_class tmp; - tmp = (backup_inst1.size == INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32; - backup_inst1.relax_inst = adjust_paritybit (backup_inst1.relax_inst, tmp); + tmp = (backup_inst1.size == s3_INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32; + backup_inst1.relax_inst = s3_adjust_paritybit (backup_inst1.relax_inst, tmp); } /* Check data dependency. */ - handle_dependency (&backup_inst1); + s3_handle_dependency (&backup_inst1); /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains data produced by .ascii etc. Doing this is to make one instruction per frag. */ @@ -2323,7 +2606,7 @@ gen_insn_frag (struct score_it *part_1, struct score_it *part_2) frag_grow (20); p = frag_more (backup_inst1.size); - md_number_to_chars (p, backup_inst1.instruction, backup_inst1.size); + s3_md_number_to_chars (p, backup_inst1.instruction, backup_inst1.size); #ifdef OBJ_ELF dwarf2_emit_insn (backup_inst1.size); @@ -2333,18 +2616,18 @@ gen_insn_frag (struct score_it *part_1, struct score_it *part_2) if (pce_p) { if (inst1->reloc.type != BFD_RELOC_NONE) - fix_new_score (frag_now, p - frag_now->fr_literal, + s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst1->size, &inst1->reloc.exp, inst1->reloc.pc_rel, inst1->reloc.type); if (inst2->reloc.type != BFD_RELOC_NONE) - fix_new_score (frag_now, p - frag_now->fr_literal + 2, + s3_fix_new_score (frag_now, p - frag_now->fr_literal + 2, inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type); } else { if (backup_inst1.reloc.type != BFD_RELOC_NONE) - fix_new_score (frag_now, p - frag_now->fr_literal, + s3_fix_new_score (frag_now, p - frag_now->fr_literal, backup_inst1.size, &backup_inst1.reloc.exp, backup_inst1.reloc.pc_rel, backup_inst1.reloc.type); } @@ -2353,27 +2636,27 @@ gen_insn_frag (struct score_it *part_1, struct score_it *part_2) relaxable_p &= (backup_inst1.relax_size != 0); relax_size = relaxable_p ? backup_inst1.relax_size : 0; - p = frag_var (rs_machine_dependent, relax_size + RELAX_PAD_BYTE, 0, - RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size, + p = frag_var (rs_machine_dependent, relax_size + s3_RELAX_PAD_BYTE, 0, + s3_RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size, backup_inst1.type, 0, 0, relaxable_p), backup_inst1.reloc.exp.X_add_symbol, 0, NULL); if (relaxable_p) - md_number_to_chars (p, backup_inst1.relax_inst, relax_size); + s3_md_number_to_chars (p, backup_inst1.relax_inst, relax_size); - memcpy (inst1, &backup_inst1, sizeof (struct score_it)); + memcpy (inst1, &backup_inst1, sizeof (struct s3_score_it)); } static void -parse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p) +s3_parse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p) { char c; char *p; char *operator = insnstr; - const struct asm_opcode *opcode; + const struct s3_asm_opcode *opcode; /* Parse operator and operands. */ - skip_whitespace (operator); + s3_skip_whitespace (operator); for (p = operator; *p != '\0'; p++) if ((*p == ' ') || (*p == '!')) @@ -2385,219 +2668,196 @@ parse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p) c = *p; *p = '\0'; - opcode = (const struct asm_opcode *) hash_find (score_ops_hsh, operator); + opcode = (const struct s3_asm_opcode *) hash_find (s3_score_ops_hsh, operator); + *p = c; + + memset (&s3_inst, '\0', sizeof (s3_inst)); + sprintf (s3_inst.str, "%s", insnstr); + if (opcode) + { + s3_inst.instruction = opcode->value; + s3_inst.relax_inst = opcode->relax_value; + s3_inst.type = opcode->type; + s3_inst.size = s3_GET_INSN_SIZE (s3_inst.type); + s3_inst.relax_size = 0; + s3_inst.bwarn = 0; + sprintf (s3_inst.name, "%s", opcode->template); + strcpy (s3_inst.reg, ""); + s3_inst.error = NULL; + s3_inst.reloc.type = BFD_RELOC_NONE; + + (*opcode->parms) (p); + + /* It indicates current instruction is a macro instruction if s3_inst.bwarn equals -1. */ + if ((s3_inst.bwarn != -1) && (!s3_inst.error) && (gen_frag_p)) + s3_gen_insn_frag (&s3_inst, NULL); + } + else + s3_inst.error = _("unrecognized opcode"); +} + +static void +s3_parse_48_inst (char *insnstr, bfd_boolean gen_frag_p) +{ + char c; + char *p; + char *operator = insnstr; + const struct s3_asm_opcode *opcode; + + /* Parse operator and operands. */ + s3_skip_whitespace (operator); + + for (p = operator; *p != '\0'; p++) + if (*p == ' ') + break; + + c = *p; + *p = '\0'; + + opcode = (const struct s3_asm_opcode *) hash_find (s3_score_ops_hsh, operator); *p = c; - memset (&inst, '\0', sizeof (inst)); - sprintf (inst.str, "%s", insnstr); + memset (&s3_inst, '\0', sizeof (s3_inst)); + sprintf (s3_inst.str, "%s", insnstr); if (opcode) { - inst.instruction = opcode->value; - inst.relax_inst = opcode->relax_value; - inst.type = opcode->type; - inst.size = GET_INSN_SIZE (inst.type); - inst.relax_size = 0; - inst.bwarn = 0; - sprintf (inst.name, "%s", opcode->template); - strcpy (inst.reg, ""); - inst.error = NULL; - inst.reloc.type = BFD_RELOC_NONE; + s3_inst.instruction = opcode->value; + s3_inst.relax_inst = opcode->relax_value; + s3_inst.type = opcode->type; + s3_inst.size = s3_GET_INSN_SIZE (s3_inst.type); + s3_inst.relax_size = 0; + s3_inst.bwarn = 0; + sprintf (s3_inst.name, "%s", opcode->template); + strcpy (s3_inst.reg, ""); + s3_inst.error = NULL; + s3_inst.reloc.type = BFD_RELOC_NONE; (*opcode->parms) (p); - /* It indicates current instruction is a macro instruction if inst.bwarn equals -1. */ - if ((inst.bwarn != -1) && (!inst.error) && (gen_frag_p)) - gen_insn_frag (&inst, NULL); + /* It indicates current instruction is a macro instruction if s3_inst.bwarn equals -1. */ + if ((s3_inst.bwarn != -1) && (!s3_inst.error) && (gen_frag_p)) + s3_gen_insn_frag (&s3_inst, NULL); } else - inst.error = _("unrecognized opcode"); + s3_inst.error = _("unrecognized opcode"); } static int -append_insn (char *str, bfd_boolean gen_frag_p) +s3_append_insn (char *str, bfd_boolean gen_frag_p) { - int retval = SUCCESS; + int retval = s3_SUCCESS; - parse_16_32_inst (str, gen_frag_p); + s3_parse_16_32_inst (str, gen_frag_p); - if (inst.error) + if (s3_inst.error) { - retval = (int) FAIL; - as_bad (_("%s -- `%s'"), inst.error, inst.str); - inst.error = NULL; + retval = (int) s3_FAIL; + as_bad (_("%s -- `%s'"), s3_inst.error, s3_inst.str); + s3_inst.error = NULL; } return retval; } -/* Handle mv! reg_high, reg_low; - mv! reg_low, reg_high; - mv! reg_low, reg_low; */ static void -do16_mv_rdrs (char *str) +s3_do16_mv_cmp (char *str) { - int reg_rd; - int reg_rs; - char *backupstr = NULL; + s3_skip_whitespace (str); - backupstr = str; - skip_whitespace (str); - - if ((reg_rd = reg_required_here (&str, 8, REG_TYPE_SCORE)) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL - || (reg_rs = reg_required_here (&str, 4, REG_TYPE_SCORE)) == (int) FAIL - || end_of_line (str) == (int) FAIL) + if (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_reg_required_here (&str, 0, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) { return; } - else - { - /* Case 1 : mv! or mlfh!. */ - if (reg_rd < 16) - { - if (reg_rs < 16) - { - inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20) - | (((inst.instruction >> 4) & 0xf) << 15) | (0xf << 10); - inst.relax_size = 4; - } - else - { - char append_str[MAX_LITERAL_POOL_SIZE]; - - sprintf (append_str, "mlfh! %s", backupstr); - if (append_insn (append_str, TRUE) == (int) FAIL) - return; - /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ - inst.bwarn = -1; - } - } - /* Case 2 : mhfl!. */ - else - { - if (reg_rs > 16) - { - SET_INSN_ERROR (BAD_ARGS); - return; - } - else - { - char append_str[MAX_LITERAL_POOL_SIZE]; +} - sprintf (append_str, "mhfl! %s", backupstr); - if (append_insn (append_str, TRUE) == (int) FAIL) - return; +static void +s3_do16_cmpi (char *str) +{ + s3_skip_whitespace (str); - /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ - inst.bwarn = -1; - } - } + if (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_data_op2 (&str, 0, _SIMM5) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) + { + return; } } static void -do16_rdi4 (char *str) +s3_do16_addi (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if (reglow_required_here (&str, 8) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL - || data_op2 (&str, 3, _IMM4) == (int) FAIL - || end_of_line (str) == (int) FAIL) + if (s3_reglow_required_here (&str, 6) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_data_op2 (&str, 0, _SIMM6) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) { return; } - else - { - if (((inst.instruction >> 3) & 0x10) == 0) /* for judge is addei or subei : bit 5 =0 : addei */ - { - if (((inst.instruction >> 3) & 0xf) != 0xf) - { - inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20) - | ((1 << ((inst.instruction >> 3) & 0xf)) << 1); - inst.relax_size = 4; - } - else - { - inst.relax_inst = 0x8000; - } - } - else - { - if (((inst.instruction >> 3) & 0xf) != 0xf) - { - inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20) - | (((-(1 << ((inst.instruction >> 3) & 0xf))) & 0xffff) << 1); - inst.relax_size = 4; - } - else - { - inst.relax_inst = 0x8000; - } - } - } } +/* Handle bitclr! / bitset! / bittst! / bittgl! */ static void -do16_rdi5 (char *str) +s3_do16_rdi5 (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if (reglow_required_here (&str, 8) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL - || data_op2 (&str, 3, _IMM5) == (int) FAIL - || end_of_line (str) == (int) FAIL) + if (s3_reglow_required_here (&str, 5) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) return; else { - inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20) - | (((inst.instruction >> 8) & 0xf) << 15) | (((inst.instruction >> 3) & 0x1f) << 10); - inst.relax_size = 4; + s3_inst.relax_inst |= (((s3_inst.instruction >>5) & 0xf) << 20) + | (((s3_inst.instruction >> 5) & 0xf) << 15) | (((s3_inst.instruction ) & 0x1f) << 10); + s3_inst.relax_size = 4; } } -/* Handle sdbbp. */ + +/* Handle sdbbp!. */ static void -do16_xi5 (char *str) +s3_do16_xi5 (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if (data_op2 (&str, 3, _IMM5) == (int) FAIL || end_of_line (str) == (int) FAIL) + if (s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL || s3_end_of_line (str) == (int) s3_FAIL) return; - else - { - inst.relax_inst |= (((inst.instruction >> 3) & 0x1f) << 15); - inst.relax_size = 4; - } } /* Check that an immediate is word alignment or half word alignment. If so, convert it to the right format. */ static int -validate_immediate_align (int val, unsigned int data_type) +s3_validate_immediate_align (int val, unsigned int data_type) { if (data_type == _IMM5_RSHIFT_1) { if (val % 2) { - inst.error = _("address offset must be half word alignment"); - return (int) FAIL; + s3_inst.error = _("address offset must be half word alignment"); + return (int) s3_FAIL; } } else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2)) { if (val % 4) { - inst.error = _("address offset must be word alignment"); - return (int) FAIL; + s3_inst.error = _("address offset must be word alignment"); + return (int) s3_FAIL; } } - return SUCCESS; + return s3_SUCCESS; } static int -exp_ldst_offset (char **str, int shift, unsigned int data_type) +s3_exp_ldst_offset (char **str, int shift, unsigned int data_type) { char *dataptr; @@ -2621,32 +2881,32 @@ exp_ldst_offset (char **str, int shift, unsigned int data_type) data_type += 24; } - if (my_get_expression (&inst.reloc.exp, str) == (int) FAIL) - return (int) FAIL; + if (s3_my_get_expression (&s3_inst.reloc.exp, str) == (int) s3_FAIL) + return (int) s3_FAIL; - if (inst.reloc.exp.X_op == O_constant) + if (s3_inst.reloc.exp.X_op == O_constant) { /* Need to check the immediate align. */ - int value = validate_immediate_align (inst.reloc.exp.X_add_number, data_type); + int value = s3_validate_immediate_align (s3_inst.reloc.exp.X_add_number, data_type); - if (value == (int) FAIL) - return (int) FAIL; + if (value == (int) s3_FAIL) + return (int) s3_FAIL; - value = validate_immediate (inst.reloc.exp.X_add_number, data_type, 0); - if (value == (int) FAIL) + value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0); + if (value == (int) s3_FAIL) { if (data_type < 30) - sprintf (err_msg, + sprintf (s3_err_msg, _("invalid constant: %d bit expression not in range %d..%d"), - score_df_range[data_type].bits, - score_df_range[data_type].range[0], score_df_range[data_type].range[1]); + s3_score_df_range[data_type].bits, + s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]); else - sprintf (err_msg, + sprintf (s3_err_msg, _("invalid constant: %d bit expression not in range %d..%d"), - score_df_range[data_type - 24].bits, - score_df_range[data_type - 24].range[0], score_df_range[data_type - 24].range[1]); - inst.error = err_msg; - return (int) FAIL; + s3_score_df_range[data_type - 24].bits, + s3_score_df_range[data_type - 24].range[0], s3_score_df_range[data_type - 24].range[1]); + s3_inst.error = s3_err_msg; + return (int) s3_FAIL; } if (data_type == _IMM5_RSHIFT_1) @@ -2658,23 +2918,23 @@ exp_ldst_offset (char **str, int shift, unsigned int data_type) value >>= 2; } - if (score_df_range[data_type].range[0] != 0) + if (s3_score_df_range[data_type].range[0] != 0) { - value &= (1 << score_df_range[data_type].bits) - 1; + value &= (1 << s3_score_df_range[data_type].bits) - 1; } - inst.instruction |= value << shift; + s3_inst.instruction |= value << shift; } else { - inst.reloc.pc_rel = 0; + s3_inst.reloc.pc_rel = 0; } - return SUCCESS; + return s3_SUCCESS; } static void -do_ldst_insn (char *str) +s3_do_ldst_insn (char *str) { int pre_inc = 0; int conflict_reg; @@ -2686,24 +2946,24 @@ do_ldst_insn (char *str) int ldst_idx = 0; strbak = str; - skip_whitespace (str); + s3_skip_whitespace (str); - if (((conflict_reg = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL) - || (skip_past_comma (&str) == (int) FAIL)) + if (((conflict_reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) + || (s3_skip_past_comma (&str) == (int) s3_FAIL)) return; /* ld/sw rD, [rA, simm15] ld/sw rD, [rA]+, simm12 ld/sw rD, [rA, simm12]+. */ if (*str == '[') { str++; - skip_whitespace (str); + s3_skip_whitespace (str); - if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL) + if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) return; /* Conflicts can occur on stores as well as loads. */ conflict_reg = (conflict_reg == reg); - skip_whitespace (str); + s3_skip_whitespace (str); temp = str + 1; /* The latter will process decimal/hex expression. */ /* ld/sw rD, [rA]+, simm12 ld/sw rD, [rA]+. */ @@ -2714,15 +2974,15 @@ do_ldst_insn (char *str) { str++; /* ld/sw rD, [rA]+, simm12. */ - if (skip_past_comma (&str) == SUCCESS) + if (s3_skip_past_comma (&str) == s3_SUCCESS) { - if ((exp_ldst_offset (&str, 3, _SIMM12) == (int) FAIL) - || (end_of_line (str) == (int) FAIL)) + if ((s3_exp_ldst_offset (&str, 3, _SIMM12) == (int) s3_FAIL) + || (s3_end_of_line (str) == (int) s3_FAIL)) return; if (conflict_reg) { - unsigned int ldst_func = inst.instruction & OPC_PSEUDOLDST_MASK; + unsigned int ldst_func = s3_inst.instruction & OPC_PSEUDOLDST_MASK; if ((ldst_func == INSN_LH) || (ldst_func == INSN_LHU) @@ -2730,37 +2990,25 @@ do_ldst_insn (char *str) || (ldst_func == INSN_LB) || (ldst_func == INSN_LBU)) { - inst.error = _("register same as write-back base"); + s3_inst.error = _("register same as write-back base"); return; } } - ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK; - inst.instruction &= ~OPC_PSEUDOLDST_MASK; - inst.instruction |= score_ldst_insns[ldst_idx * 3 + LDST_POST].value; + ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK; + s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK; + s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + LDST_POST].value; /* lw rD, [rA]+, 4 convert to pop rD, [rA]. */ - if ((inst.instruction & 0x3e000007) == 0x0e000000) + if ((s3_inst.instruction & 0x3e000007) == 0x0e000000) { - /* rs = r0-r7, offset = 4 */ - if ((((inst.instruction >> 15) & 0x18) == 0) - && (((inst.instruction >> 3) & 0xfff) == 4)) + /* rs = r0, offset = 4 */ + if ((((s3_inst.instruction >> 15) & 0x1f) == 0) + && (((s3_inst.instruction >> 3) & 0xfff) == 4)) { - /* Relax to pophi. */ - if ((((inst.instruction >> 20) & 0x10) == 0x10)) - { - inst.relax_inst = 0x0000200a | (((inst.instruction >> 20) & 0xf) - << 8) | 1 << 7 | - (((inst.instruction >> 15) & 0x7) << 4); - } - /* Relax to pop. */ - else - { - inst.relax_inst = 0x0000200a | (((inst.instruction >> 20) & 0xf) - << 8) | 0 << 7 | - (((inst.instruction >> 15) & 0x7) << 4); - } - inst.relax_size = 2; + /* Relax to pop!. */ + s3_inst.relax_inst = 0x0040 | ((s3_inst.instruction >> 20) & 0x1f); + s3_inst.relax_size = 2; } } return; @@ -2768,74 +3016,76 @@ do_ldst_insn (char *str) /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+. */ else { - SET_INSN_ERROR (NULL); - if (end_of_line (str) == (int) FAIL) + s3_SET_INSN_ERROR (NULL); + if (s3_end_of_line (str) == (int) s3_FAIL) { return; } pre_inc = 1; - value = validate_immediate (inst.reloc.exp.X_add_number, _SIMM12, 0); - value &= (1 << score_df_range[_SIMM12].bits) - 1; - ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK; - inst.instruction &= ~OPC_PSEUDOLDST_MASK; - inst.instruction |= score_ldst_insns[ldst_idx * 3 + pre_inc].value; - inst.instruction |= value << 3; - inst.relax_inst = 0x8000; + value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _SIMM12, 0); + value &= (1 << s3_score_df_range[_SIMM12].bits) - 1; + ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK; + s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK; + s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + pre_inc].value; + s3_inst.instruction |= value << 3; + s3_inst.relax_inst = 0x8000; return; } } /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15]. */ else { - if (end_of_line (str) == (int) FAIL) + if (s3_end_of_line (str) == (int) s3_FAIL) return; - ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK; - inst.instruction &= ~OPC_PSEUDOLDST_MASK; - inst.instruction |= score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value; + ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK; + s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK; + s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value; /* lbu rd, [rs] -> lbu! rd, [rs] */ if (ldst_idx == INSN_LBU) { - inst.relax_inst = INSN16_LBU; + s3_inst.relax_inst = INSN16_LBU; } else if (ldst_idx == INSN_LH) { - inst.relax_inst = INSN16_LH; + s3_inst.relax_inst = INSN16_LH; } else if (ldst_idx == INSN_LW) { - inst.relax_inst = INSN16_LW; + s3_inst.relax_inst = INSN16_LW; } else if (ldst_idx == INSN_SB) { - inst.relax_inst = INSN16_SB; + s3_inst.relax_inst = INSN16_SB; } else if (ldst_idx == INSN_SH) { - inst.relax_inst = INSN16_SH; + s3_inst.relax_inst = INSN16_SH; } else if (ldst_idx == INSN_SW) { - inst.relax_inst = INSN16_SW; + s3_inst.relax_inst = INSN16_SW; } else { - inst.relax_inst = 0x8000; + s3_inst.relax_inst = 0x8000; } /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction. */ - if ((ldst_idx == INSN_LBU) + /* if ((ldst_idx == INSN_LBU) || (ldst_idx == INSN_LH) || (ldst_idx == INSN_LW) - || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW)) + || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))*/ + if ( (ldst_idx == INSN_LW)|| (ldst_idx == INSN_SW)) { - if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0)) + /* ra only 3 bit , rd only 4 bit for lw! and sw! */ + if ((((s3_inst.instruction >> 15) & 0x18) == 0) && (((s3_inst.instruction >> 20) & 0x10) == 0)) { - inst.relax_inst |= (2 << 12) | (((inst.instruction >> 20) & 0xf) << 8) | - (((inst.instruction >> 15) & 0xf) << 4); - inst.relax_size = 2; + s3_inst.relax_inst |= (((s3_inst.instruction >> 20) & 0xf) << 8) | + (((s3_inst.instruction >> 15) & 0x7) << 5); + s3_inst.relax_size = 2; } } @@ -2845,23 +3095,23 @@ do_ldst_insn (char *str) /* ld/sw rD, [rA, simm15] ld/sw rD, [rA, simm12]+. */ else { - if (skip_past_comma (&str) == (int) FAIL) + if (s3_skip_past_comma (&str) == (int) s3_FAIL) { - inst.error = _("pre-indexed expression expected"); + s3_inst.error = _("pre-indexed expression expected"); return; } - if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL) + if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL) return; - skip_whitespace (str); + s3_skip_whitespace (str); if (*str++ != ']') { - inst.error = _("missing ]"); + s3_inst.error = _("missing ]"); return; } - skip_whitespace (str); + s3_skip_whitespace (str); /* ld/sw rD, [rA, simm12]+. */ if (*str == '+') { @@ -2869,7 +3119,7 @@ do_ldst_insn (char *str) pre_inc = 1; if (conflict_reg) { - unsigned int ldst_func = inst.instruction & OPC_PSEUDOLDST_MASK; + unsigned int ldst_func = s3_inst.instruction & OPC_PSEUDOLDST_MASK; if ((ldst_func == INSN_LH) || (ldst_func == INSN_LHU) @@ -2877,16 +3127,16 @@ do_ldst_insn (char *str) || (ldst_func == INSN_LB) || (ldst_func == INSN_LBU)) { - inst.error = _("register same as write-back base"); + s3_inst.error = _("register same as write-back base"); return; } } } - if (end_of_line (str) == (int) FAIL) + if (s3_end_of_line (str) == (int) s3_FAIL) return; - if (inst.reloc.exp.X_op == O_constant) + if (s3_inst.reloc.exp.X_op == O_constant) { int value; unsigned int data_type; @@ -2915,254 +3165,100 @@ do_ldst_insn (char *str) data_type += 24; } - value = validate_immediate (inst.reloc.exp.X_add_number, data_type, 0); - if (value == (int) FAIL) + value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0); + if (value == (int) s3_FAIL) { if (data_type < 30) - sprintf (err_msg, + sprintf (s3_err_msg, _("invalid constant: %d bit expression not in range %d..%d"), - score_df_range[data_type].bits, - score_df_range[data_type].range[0], score_df_range[data_type].range[1]); + s3_score_df_range[data_type].bits, + s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]); else - sprintf (err_msg, + sprintf (s3_err_msg, _("invalid constant: %d bit expression not in range %d..%d"), - score_df_range[data_type - 24].bits, - score_df_range[data_type - 24].range[0], - score_df_range[data_type - 24].range[1]); - inst.error = err_msg; + s3_score_df_range[data_type - 24].bits, + s3_score_df_range[data_type - 24].range[0], + s3_score_df_range[data_type - 24].range[1]); + s3_inst.error = s3_err_msg; return; } - value &= (1 << score_df_range[data_type].bits) - 1; - ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK; - inst.instruction &= ~OPC_PSEUDOLDST_MASK; - inst.instruction |= score_ldst_insns[ldst_idx * 3 + pre_inc].value; + value &= (1 << s3_score_df_range[data_type].bits) - 1; + ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK; + s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK; + s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + pre_inc].value; if (pre_inc == 1) - inst.instruction |= value << 3; + s3_inst.instruction |= value << 3; else - inst.instruction |= value; + s3_inst.instruction |= value; /* lw rD, [rA, simm15] */ - if ((inst.instruction & 0x3e000000) == 0x20000000) + if ((s3_inst.instruction & 0x3e000000) == 0x20000000) { - /* Both rD and rA are in [r0 - r15]. */ - if ((((inst.instruction >> 15) & 0x10) == 0) - && (((inst.instruction >> 20) & 0x10) == 0)) + /* rD in [r0 - r15]. , ra in [r0-r7] */ + if ((((s3_inst.instruction >> 15) & 0x18) == 0) + && (((s3_inst.instruction >> 20) & 0x10) == 0)) { - /* simm15 = 0, lw -> lw!. */ - if ((inst.instruction & 0x7fff) == 0) - { - inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4) - | (((inst.instruction >> 20) & 0xf) << 8); - inst.relax_size = 2; - } - /* rA = r2, lw -> lwp!. */ - else if ((((inst.instruction >> 15) & 0xf) == 2) - && ((inst.instruction & 0x3) == 0) - && ((inst.instruction & 0x7fff) < 128)) + /* simm = [bit 7], lw -> lw!. */ + if (((s3_inst.instruction & 0x7f80) == 0)&&((s3_inst.instruction &0x3)==0)) { - inst.relax_inst = 0x7000 | (((inst.instruction >> 20) & 0xf) << 8) - | (((inst.instruction & 0x7fff) >> 2) << 3); - inst.relax_size = 2; + s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0x7) << 5) + | (((s3_inst.instruction >> 20) & 0xf) << 8)|(value>>2); + s3_inst.relax_size = 2; } else { - inst.relax_inst = 0x8000; + s3_inst.relax_inst = 0x8000; } } else { - inst.relax_inst = 0x8000; + s3_inst.relax_inst = 0x8000; } } /* sw rD, [rA, simm15] */ - else if ((inst.instruction & 0x3e000000) == 0x28000000) + else if ((s3_inst.instruction & 0x3e000000) == 0x28000000) { - /* Both rD and rA are in [r0 - r15]. */ - if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0)) + /* rD is in [r0 - r15] and ra in [r0-r7] */ + if ((((s3_inst.instruction >> 15) & 0x18) == 0) && (((s3_inst.instruction >> 20) & 0x10) == 0)) { - /* simm15 = 0, sw -> sw!. */ - if ((inst.instruction & 0x7fff) == 0) + /* simm15 =7 bit , sw -> sw!. */ + if (((s3_inst.instruction & 0x7f80) == 0)&&((s3_inst.instruction &0x3)==0)) { - inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4) - | (((inst.instruction >> 20) & 0xf) << 8); - inst.relax_size = 2; + s3_inst.relax_inst |= (((s3_inst.instruction >> 15) & 0xf) << 5) + | (((s3_inst.instruction >> 20) & 0xf) << 8)|(value>>2); + s3_inst.relax_size = 2; } /* rA = r2, sw -> swp!. */ - else if ((((inst.instruction >> 15) & 0xf) == 2) - && ((inst.instruction & 0x3) == 0) - && ((inst.instruction & 0x7fff) < 128)) - { - inst.relax_inst = 0x7004 | (((inst.instruction >> 20) & 0xf) << 8) - | (((inst.instruction & 0x7fff) >> 2) << 3); - inst.relax_size = 2; - } else { - inst.relax_inst = 0x8000; + s3_inst.relax_inst = 0x8000; } } else { - inst.relax_inst = 0x8000; + s3_inst.relax_inst = 0x8000; } } /* sw rD, [rA, simm15]+ sw pre. */ - else if ((inst.instruction & 0x3e000007) == 0x06000004) + else if ((s3_inst.instruction & 0x3e000007) == 0x06000004) { - /* rA is in [r0 - r7], and simm15 = -4. */ - if ((((inst.instruction >> 15) & 0x18) == 0) - && (((inst.instruction >> 3) & 0xfff) == 0xffc)) + /* simm15 = -4. and ra==r0 */ + if ((((s3_inst.instruction >> 15) & 0x1f) == 0) + && (((s3_inst.instruction >> 3) & 0xfff) == 0xffc)) { - /* sw -> pushhi!. */ - if ((((inst.instruction >> 20) & 0x10) == 0x10)) - { - inst.relax_inst = 0x0000200e | (((inst.instruction >> 20) & 0xf) << 8) - | 1 << 7 | (((inst.instruction >> 15) & 0x7) << 4); - inst.relax_size = 2; - } /* sw -> push!. */ - else - { - inst.relax_inst = 0x0000200e | (((inst.instruction >> 20) & 0xf) << 8) - | 0 << 7 | (((inst.instruction >> 15) & 0x7) << 4); - inst.relax_size = 2; - } - } - else - { - inst.relax_inst = 0x8000; - } - } - /* lh rD, [rA, simm15] */ - else if ((inst.instruction & 0x3e000000) == 0x22000000) - { - /* Both rD and rA are in [r0 - r15]. */ - if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0)) - { - /* simm15 = 0, lh -> lh!. */ - if ((inst.instruction & 0x7fff) == 0) - { - inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4) - | (((inst.instruction >> 20) & 0xf) << 8); - inst.relax_size = 2; - } - /* rA = r2, lh -> lhp!. */ - else if ((((inst.instruction >> 15) & 0xf) == 2) - && ((inst.instruction & 0x1) == 0) - && ((inst.instruction & 0x7fff) < 64)) - { - inst.relax_inst = 0x7001 | (((inst.instruction >> 20) & 0xf) << 8) - | (((inst.instruction & 0x7fff) >> 1) << 3); - inst.relax_size = 2; - } - else - { - inst.relax_inst = 0x8000; - } - } - else - { - inst.relax_inst = 0x8000; - } - } - /* sh rD, [rA, simm15] */ - else if ((inst.instruction & 0x3e000000) == 0x2a000000) - { - /* Both rD and rA are in [r0 - r15]. */ - if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0)) - { - /* simm15 = 0, sh -> sh!. */ - if ((inst.instruction & 0x7fff) == 0) - { - inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4) - | (((inst.instruction >> 20) & 0xf) << 8); - inst.relax_size = 2; - } - /* rA = r2, sh -> shp!. */ - else if ((((inst.instruction >> 15) & 0xf) == 2) - && ((inst.instruction & 0x1) == 0) - && ((inst.instruction & 0x7fff) < 64)) - { - inst.relax_inst = 0x7005 | (((inst.instruction >> 20) & 0xf) << 8) - | (((inst.instruction & 0x7fff) >> 1) << 3); - inst.relax_size = 2; - } - else - { - inst.relax_inst = 0x8000; - } - } - else - { - inst.relax_inst = 0x8000; - } - } - /* lbu rD, [rA, simm15] */ - else if ((inst.instruction & 0x3e000000) == 0x2c000000) - { - /* Both rD and rA are in [r0 - r15]. */ - if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0)) - { - /* simm15 = 0, lbu -> lbu!. */ - if ((inst.instruction & 0x7fff) == 0) - { - inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4) - | (((inst.instruction >> 20) & 0xf) << 8); - inst.relax_size = 2; - } - /* rA = r2, lbu -> lbup!. */ - else if ((((inst.instruction >> 15) & 0xf) == 2) - && ((inst.instruction & 0x7fff) < 32)) - { - inst.relax_inst = 0x7003 | (((inst.instruction >> 20) & 0xf) << 8) - | ((inst.instruction & 0x7fff) << 3); - inst.relax_size = 2; - } - else - { - inst.relax_inst = 0x8000; - } - } - else - { - inst.relax_inst = 0x8000; - } - } - /* sb rD, [rA, simm15] */ - else if ((inst.instruction & 0x3e000000) == 0x2e000000) - { - /* Both rD and rA are in [r0 - r15]. */ - if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0)) - { - /* simm15 = 0, sb -> sb!. */ - if ((inst.instruction & 0x7fff) == 0) - { - inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4) - | (((inst.instruction >> 20) & 0xf) << 8); - inst.relax_size = 2; - } - /* rA = r2, sb -> sb!. */ - else if ((((inst.instruction >> 15) & 0xf) == 2) - && ((inst.instruction & 0x7fff) < 32)) - { - inst.relax_inst = 0x7007 | (((inst.instruction >> 20) & 0xf) << 8) - | ((inst.instruction & 0x7fff) << 3); - inst.relax_size = 2; - } - else - { - inst.relax_inst = 0x8000; - } + s3_inst.relax_inst = 0x0060 | ((s3_inst.instruction >> 20) & 0x1f); + s3_inst.relax_size = 2; } else { - inst.relax_inst = 0x8000; + s3_inst.relax_inst = 0x8000; } } else { - inst.relax_inst = 0x8000; + s3_inst.relax_inst = 0x8000; } return; @@ -3170,24 +3266,23 @@ do_ldst_insn (char *str) else { /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */ - inst.reloc.pc_rel = 0; + s3_inst.reloc.pc_rel = 0; } } } else { - inst.error = BAD_ARGS; + s3_inst.error = s3_BAD_ARGS; } } /* Handle cache. */ - static void -do_cache (char *str) +s3_do_cache (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if ((data_op2 (&str, 20, _IMM5) == (int) FAIL) || (skip_past_comma (&str) == (int) FAIL)) + if ((s3_data_op2 (&str, 20, _IMM5) == (int) s3_FAIL) || (s3_skip_past_comma (&str) == (int) s3_FAIL)) { return; } @@ -3195,27 +3290,27 @@ do_cache (char *str) { int cache_op; - cache_op = (inst.instruction >> 20) & 0x1F; - sprintf (inst.name, "cache %d", cache_op); + cache_op = (s3_inst.instruction >> 20) & 0x1F; + sprintf (s3_inst.name, "cache %d", cache_op); } if (*str == '[') { str++; - skip_whitespace (str); + s3_skip_whitespace (str); - if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL) + if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL) return; - skip_whitespace (str); + s3_skip_whitespace (str); /* cache op, [rA] */ - if (skip_past_comma (&str) == (int) FAIL) + if (s3_skip_past_comma (&str) == (int) s3_FAIL) { - SET_INSN_ERROR (NULL); + s3_SET_INSN_ERROR (NULL); if (*str != ']') { - inst.error = _("missing ]"); + s3_inst.error = _("missing ]"); return; } str++; @@ -3223,357 +3318,593 @@ do_cache (char *str) /* cache op, [rA, simm15] */ else { - if (exp_ldst_offset (&str, 0, _SIMM15) == (int) FAIL) + if (s3_exp_ldst_offset (&str, 0, _SIMM15) == (int) s3_FAIL) { return; } - skip_whitespace (str); + s3_skip_whitespace (str); if (*str++ != ']') { - inst.error = _("missing ]"); + s3_inst.error = _("missing ]"); return; } } - if (end_of_line (str) == (int) FAIL) + if (s3_end_of_line (str) == (int) s3_FAIL) return; } else { - inst.error = BAD_ARGS; + s3_inst.error = s3_BAD_ARGS; } } static void -do_crdcrscrsimm5 (char *str) +s3_do_crdcrscrsimm5 (char *str) { char *strbak; strbak = str; - skip_whitespace (str); + s3_skip_whitespace (str); - if (reg_required_here (&str, 20, REG_TYPE_SCORE_CR) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL - || reg_required_here (&str, 15, REG_TYPE_SCORE_CR) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL - || reg_required_here (&str, 10, REG_TYPE_SCORE_CR) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL) + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL) { str = strbak; /* cop1 cop_code20. */ - if (data_op2 (&str, 5, _IMM20) == (int) FAIL) + if (s3_data_op2 (&str, 5, _IMM20) == (int) s3_FAIL) return; } else { - if (data_op2 (&str, 5, _IMM5) == (int) FAIL) + if (s3_data_op2 (&str, 5, _IMM5) == (int) s3_FAIL) return; } - end_of_line (str); + s3_end_of_line (str); } /* Handle ldc/stc. */ static void -do_ldst_cop (char *str) +s3_do_ldst_cop (char *str) { - skip_whitespace (str); + s3_skip_whitespace (str); - if ((reg_required_here (&str, 15, REG_TYPE_SCORE_CR) == (int) FAIL) - || (skip_past_comma (&str) == (int) FAIL)) + if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE_CR) == (int) s3_FAIL) + || (s3_skip_past_comma (&str) == (int) s3_FAIL)) return; if (*str == '[') { str++; - skip_whitespace (str); + s3_skip_whitespace (str); - if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL) + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL) return; - skip_whitespace (str); + s3_skip_whitespace (str); if (*str++ != ']') { - if (exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) FAIL) + if (s3_exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) s3_FAIL) return; - skip_whitespace (str); + s3_skip_whitespace (str); if (*str++ != ']') { - inst.error = _("missing ]"); + s3_inst.error = _("missing ]"); return; } } - end_of_line (str); + s3_end_of_line (str); } else - inst.error = BAD_ARGS; + s3_inst.error = s3_BAD_ARGS; } static void -do16_ldst_insn (char *str) +s3_do16_ldst_insn (char *str) { - skip_whitespace (str); + int conflict_reg=0; + char * temp; + s3_skip_whitespace (str); - if ((reglow_required_here (&str, 8) == (int) FAIL) || (skip_past_comma (&str) == (int) FAIL)) + if ((s3_reglow_required_here (&str, 8) == (int) s3_FAIL) || (s3_skip_past_comma (&str) == (int) s3_FAIL)) return; if (*str == '[') { - int reg; str++; - skip_whitespace (str); + s3_skip_whitespace (str); - if ((reg = reglow_required_here (&str, 4)) == (int) FAIL) + if ((conflict_reg = s3_reglow_required_here (&str, 5)) == (int) s3_FAIL) return; + if (conflict_reg&0x8) + { + sprintf (s3_err_msg, _("invalid register number: %d is not in [r0--r7]"),conflict_reg); + s3_inst.error=s3_err_msg; + return ; + } - skip_whitespace (str); - if (*str++ == ']') + s3_skip_whitespace (str); + temp = str + 1; /* The latter will process decimal/hex expression. */ + if (*str == ']') { - if (end_of_line (str) == (int) FAIL) + str++; + if (s3_end_of_line (str) == (int) s3_FAIL) return; - else - { - inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20) - | (((inst.instruction >> 4) & 0xf) << 15); - inst.relax_size = 4; - } } else { - inst.error = _("missing ]"); + if (s3_skip_past_comma (&str) == (int) s3_FAIL) + { + s3_inst.error = _("comma is expected"); + return; + } + if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL) + return; + s3_skip_whitespace (str); + if (*str++ != ']') + { + s3_inst.error = _("missing ]"); + return; + } + if (s3_end_of_line (str) == (int) s3_FAIL) + return; + if (s3_inst.reloc.exp.X_op == O_constant) + { + int value; + unsigned int data_type; + data_type = _IMM5_RSHIFT_2; + value = s3_validate_immediate (s3_inst.reloc.exp.X_add_number, data_type, 0); + if (value == (int) s3_FAIL) + { + if (data_type < 30) + sprintf (s3_err_msg, + _("invalid constant: %d bit expression not in range %d..%d"), + s3_score_df_range[data_type].bits, + s3_score_df_range[data_type].range[0], s3_score_df_range[data_type].range[1]); + s3_inst.error = s3_err_msg; + return; + } + if (value &0x3) + { + sprintf (s3_err_msg, _("invalid constant: %d is not word align integer"),value); + s3_inst.error=s3_err_msg; + return ; + } + + value >>=2; + s3_inst.instruction |= value; + } } + } else { - inst.error = BAD_ARGS; + sprintf (s3_err_msg, _("missing [")); + s3_inst.error=s3_err_msg; + return ; } } -/* Handle lbup!/lhp!/ldiu!/lwp!/sbp!/shp!/swp!. */ static void -do16_ldst_imm_insn (char *str) +s3_do_lw48 (char *str) { - char data_exp[MAX_LITERAL_POOL_SIZE]; - int reg_rd; - char *dataptr = NULL, *pp = NULL; - int cnt = 0; - int assign_data = (int) FAIL; - unsigned int ldst_func; + bfd_signed_vma val = 0; - skip_whitespace (str); + s3_skip_whitespace (str); - if (((reg_rd = reglow_required_here (&str, 8)) == (int) FAIL) - || (skip_past_comma (&str) == (int) FAIL)) + if ((s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL) + || (s3_skip_past_comma (&str) == (int) s3_FAIL)) return; - skip_whitespace (str); - dataptr = str; - - while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= MAX_LITERAL_POOL_SIZE)) + if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) { - data_exp[cnt] = *dataptr; - dataptr++; - cnt++; + return; } - data_exp[cnt] = '\0'; - pp = &data_exp[0]; + /* Check word align for lw48 rd, value. */ + if ((s3_inst.reloc.exp.X_add_symbol == NULL) + && ((s3_inst.reloc.exp.X_add_number & 0x3) != 0)) + { + s3_inst.error = _("invalid constant: 32 bit expression not word align"); + return; + } - str = dataptr; + /* Check and set offset. */ + val = s3_inst.reloc.exp.X_add_number; + if ((s3_inst.reloc.exp.X_add_symbol == NULL) + && (!(val >= 0 && val <= 0xffffffffLL))) + { + s3_inst.error = _("invalid constant: 32 bit expression not in range [0, 0xffffffff]"); + return; + } - ldst_func = inst.instruction & LDST16_RI_MASK; - if (ldst_func == N16_LIU) - assign_data = exp_ldst_offset (&pp, 0, _IMM8); - else if (ldst_func == N16_LHP || ldst_func == N16_SHP) - assign_data = exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_1); - else if (ldst_func == N16_LWP || ldst_func == N16_SWP) - assign_data = exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_2); - else - assign_data = exp_ldst_offset (&pp, 3, _IMM5); + val &= 0xffffffff; + val >>= 2; + s3_inst.instruction |= (val << 7); - if ((assign_data == (int) FAIL) || (end_of_line (pp) == (int) FAIL)) - return; - else - { - if ((inst.instruction & 0x7000) == N16_LIU) - { - inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 - | ((inst.instruction & 0xff) << 1); - } - else if (((inst.instruction & 0x7007) == N16_LHP) - || ((inst.instruction & 0x7007) == N16_SHP)) - { - inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15 - | (((inst.instruction >> 3) & 0x1f) << 1); - } - else if (((inst.instruction & 0x7007) == N16_LWP) - || ((inst.instruction & 0x7007) == N16_SWP)) - { - inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15 - | (((inst.instruction >> 3) & 0x1f) << 2); - } - else if (((inst.instruction & 0x7007) == N16_LBUP) - || ((inst.instruction & 0x7007) == N16_SBP)) - { - inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15 - | (((inst.instruction >> 3) & 0x1f)); - } + /* Set reloc type. */ + s3_inst.reloc.type = BFD_RELOC_SCORE_IMM30; - inst.relax_size = 4; - } } static void -do16_push_pop (char *str) +s3_do_sw48 (char *str) { - int reg_rd; - int H_bit_mask = 0; + bfd_signed_vma val = 0; - skip_whitespace (str); - if (((reg_rd = reg_required_here (&str, 8, REG_TYPE_SCORE)) == (int) FAIL) - || (skip_past_comma (&str) == (int) FAIL)) - return; + s3_skip_whitespace (str); - if (reg_rd >= 16) - H_bit_mask = 1; + if ((s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL) + || (s3_skip_past_comma (&str) == (int) s3_FAIL)) + return; - /* reg_required_here will change bit 12 of opcode, so we must restore bit 12. */ - inst.instruction &= ~(1 << 12); + if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) + { + return; + } - inst.instruction |= H_bit_mask << 7; + /* Check word align for lw48 rd, value. */ + if ((s3_inst.reloc.exp.X_add_symbol == NULL) + && ((s3_inst.reloc.exp.X_add_number & 0x3) != 0)) + { + s3_inst.error = _("invalid constant: 32 bit expression not word align"); + return; + } - if (*str == '[') + /* Check and set offset. */ + val = s3_inst.reloc.exp.X_add_number; + if ((s3_inst.reloc.exp.X_add_symbol == NULL) + && (!(val >= 0 && val <= 0xffffffffLL))) { - int reg; + s3_inst.error = _("invalid constant: 32 bit expression not in range [0, 0xffffffff]"); + return; + } - str++; - skip_whitespace (str); - if ((reg = reg_required_here (&str, 4, REG_TYPE_SCORE)) == (int) FAIL) - return; - else if (reg > 7) - { - if (!inst.error) - inst.error = _("base register nums are over 3 bit"); + val &= 0xffffffff; + val >>= 2; + s3_inst.instruction |= (val << 7); - return; - } + /* Set reloc type. */ + s3_inst.reloc.type = BFD_RELOC_SCORE_IMM30; +} - skip_whitespace (str); - if ((*str++ != ']') || (end_of_line (str) == (int) FAIL)) - { - if (!inst.error) - inst.error = _("missing ]"); +static void +s3_do_ldi48 (char *str) +{ + bfd_signed_vma val; - return; - } + s3_skip_whitespace (str); - /* pop! */ - if ((inst.instruction & 0xf) == 0xa) - { - if (H_bit_mask) - { - inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20) - | (((inst.instruction >> 4) & 0x7) << 15) | (4 << 3); - } - else - { - inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20) - | (((inst.instruction >> 4) & 0x7) << 15) | (4 << 3); - } - } - /* push! */ - else - { - if (H_bit_mask) - { - inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20) - | (((inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3); - } - else - { - inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20) - | (((inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3); - } - } - inst.relax_size = 4; + if (s3_reg_required_here (&str, 37, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL) + return; + + if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) + { + return; } - else + + /* Check and set offset. */ + val = s3_inst.reloc.exp.X_add_number; + if (!(val >= -0xffffffffLL && val <= 0xffffffffLL)) + { + s3_inst.error = _("invalid constant: 32 bit expression not in range [-0x80000000, 0x7fffffff]"); + return; + } + + val &= 0xffffffff; + s3_inst.instruction |= (val << 5); + + /* Set reloc type. */ + s3_inst.reloc.type = BFD_RELOC_SCORE_IMM32; +} + +static void +s3_do_sdbbp48 (char *str) +{ + s3_skip_whitespace (str); + + if (s3_data_op2 (&str, 5, _IMM5) == (int) s3_FAIL || s3_end_of_line (str) == (int) s3_FAIL) + return; +} + +static void +s3_do_and48 (char *str) +{ + s3_skip_whitespace (str); + + if (s3_reglow_required_here (&str, 38) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_reglow_required_here (&str, 34) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_data_op2 (&str, 2, _IMM32) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) + return; +} + +static void +s3_do_or48 (char *str) +{ + s3_skip_whitespace (str); + + if (s3_reglow_required_here (&str, 38) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_reglow_required_here (&str, 34) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_data_op2 (&str, 2, _IMM32) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) + return; +} + +static void +s3_do_mbitclr (char *str) +{ + int val; + s3_skip_whitespace (str); + + if (*str != '[') + { + sprintf (s3_err_msg, _("missing [")); + s3_inst.error=s3_err_msg; + return; + } + str++; + + s3_inst.instruction &= 0x0; + + if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL) + || (s3_skip_past_comma (&str) == (int) s3_FAIL) + || (s3_data_op2 (&str, 0, _IMM11) == (int) s3_FAIL)) + return; + + /* Get imm11 and refill opcode. */ + val = s3_inst.instruction & 0x7ff; + val >>= 2; + s3_inst.instruction &= 0x000f8000; + s3_inst.instruction |= 0x00000064; + + if (*str != ']') + { + sprintf (s3_err_msg, _("missing ]")); + s3_inst.error=s3_err_msg; + return; + } + str++; + + if ((s3_skip_past_comma (&str) == (int) s3_FAIL) + || (s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL)) + return; + + /* Set imm11 to opcode. */ + s3_inst.instruction |= (val & 0x1) + | (((val >> 1 ) & 0x7) << 7) + | (((val >> 4 ) & 0x1f) << 20); +} + +static void +s3_do_mbitset (char *str) +{ + int val; + s3_skip_whitespace (str); + + if (*str != '[') { - inst.error = BAD_ARGS; + sprintf (s3_err_msg, _("missing [")); + s3_inst.error=s3_err_msg; + return; + } + str++; + + s3_inst.instruction &= 0x0; + + if ((s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL) + || (s3_skip_past_comma (&str) == (int) s3_FAIL) + || (s3_data_op2 (&str, 0, _IMM11) == (int) s3_FAIL)) + return; + + /* Get imm11 and refill opcode. */ + val = s3_inst.instruction & 0x7ff; + val >>= 2; + s3_inst.instruction &= 0x000f8000; + s3_inst.instruction |= 0x0000006c; + + if (*str != ']') + { + sprintf (s3_err_msg, _("missing ]")); + s3_inst.error=s3_err_msg; + return; + } + str++; + + if ((s3_skip_past_comma (&str) == (int) s3_FAIL) + || (s3_data_op2 (&str, 10, _IMM5) == (int) s3_FAIL)) + return; + + /* Set imm11 to opcode. */ + s3_inst.instruction |= (val & 0x1) + | (((val >> 1 ) & 0x7) << 7) + | (((val >> 4 ) & 0x1f) << 20); +} + +static void +s3_do16_slli_srli (char *str) +{ + s3_skip_whitespace (str); + + if ((s3_reglow_required_here (&str, 5) == (int) s3_FAIL) + || (s3_skip_past_comma (&str) == (int) s3_FAIL) + || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) + return; +} + +static void +s3_do16_ldiu (char *str) +{ + s3_skip_whitespace (str); + + if ((s3_reg_required_here (&str, 5,s3_REG_TYPE_SCORE) == (int) s3_FAIL) + || (s3_skip_past_comma (&str) == (int) s3_FAIL) + || s3_data_op2 (&str, 0, _IMM5) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) + return; +} + +static void +s3_do16_push_pop (char *str) +{ + s3_skip_whitespace (str); + if ((s3_reg_required_here (&str, 0, s3_REG_TYPE_SCORE)) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) + return; +} + +static void +s3_do16_rpush (char *str) +{ + int reg; + int val; + s3_skip_whitespace (str); + if ((reg = (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE))) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_data_op2 (&str, 0, _IMM5_MULTI_LOAD) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) + return; + + /* 0: indicate 32. + 1: invalide value. + 2: to 31: normal value. */ + val = s3_inst.instruction & 0x1f; + if (val == 1) + { + s3_inst.error = _("imm5 should >= 2"); + return; + } + if (reg >= 32) + { + s3_inst.error = _("reg should <= 31"); + return; + } +} + +static void +s3_do16_rpop (char *str) +{ + int reg; + int val; + s3_skip_whitespace (str); + if ((reg = (s3_reg_required_here (&str, 5, s3_REG_TYPE_SCORE))) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_data_op2 (&str, 0, _IMM5_MULTI_LOAD) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) + return; + + /* 0: indicate 32. + 1: invalide value. + 2: to 31: normal value. */ + val = s3_inst.instruction & 0x1f; + if (val == 1) + { + s3_inst.error = _("imm5 should >= 2"); + return; + } + + if (reg >= 32) + { + s3_inst.error = _("reg should <= 31"); + return; + } + else + { + if ((reg + val) <= 32) + reg = reg + val - 1; + else + reg = reg + val - 33; + s3_inst.instruction &= 0x7c1f; + s3_inst.instruction |= (reg << 5); + return; } } /* Handle lcb/lcw/lce/scb/scw/sce. */ static void -do_ldst_unalign (char *str) +s3_do_ldst_unalign (char *str) { int conflict_reg; - if (university_version == 1) + if (s3_university_version == 1) { - inst.error = ERR_FOR_SCORE5U_ATOMIC; + s3_inst.error = s3_ERR_FOR_SCORE5U_ATOMIC; return; } - skip_whitespace (str); + s3_skip_whitespace (str); /* lcb/scb [rA]+. */ if (*str == '[') { str++; - skip_whitespace (str); + s3_skip_whitespace (str); - if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL) + if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL) return; if (*str++ == ']') { if (*str++ != '+') { - inst.error = _("missing +"); + s3_inst.error = _("missing +"); return; } } else { - inst.error = _("missing ]"); + s3_inst.error = _("missing ]"); return; } - if (end_of_line (str) == (int) FAIL) + if (s3_end_of_line (str) == (int) s3_FAIL) return; } /* lcw/lce/scb/sce rD, [rA]+. */ else { - if (((conflict_reg = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL) - || (skip_past_comma (&str) == (int) FAIL)) + if (((conflict_reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) + || (s3_skip_past_comma (&str) == (int) s3_FAIL)) { return; } - skip_whitespace (str); + s3_skip_whitespace (str); if (*str++ == '[') { int reg; - skip_whitespace (str); - if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL) + s3_skip_whitespace (str); + if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) { return; } /* Conflicts can occur on stores as well as loads. */ conflict_reg = (conflict_reg == reg); - skip_whitespace (str); + s3_skip_whitespace (str); if (*str++ == ']') { - unsigned int ldst_func = inst.instruction & LDST_UNALIGN_MASK; + unsigned int ldst_func = s3_inst.instruction & LDST_UNALIGN_MASK; if (*str++ == '+') { @@ -3586,22 +3917,22 @@ do_ldst_unalign (char *str) } else { - inst.error = _("missing +"); + s3_inst.error = _("missing +"); return; } - if (end_of_line (str) == (int) FAIL) + if (s3_end_of_line (str) == (int) s3_FAIL) return; } else { - inst.error = _("missing ]"); + s3_inst.error = _("missing ]"); return; } } else { - inst.error = BAD_ARGS; + s3_inst.error = s3_BAD_ARGS; return; } } @@ -3609,52 +3940,52 @@ do_ldst_unalign (char *str) /* Handle alw/asw. */ static void -do_ldst_atomic (char *str) +s3_do_ldst_atomic (char *str) { - if (university_version == 1) + if (s3_university_version == 1) { - inst.error = ERR_FOR_SCORE5U_ATOMIC; + s3_inst.error = s3_ERR_FOR_SCORE5U_ATOMIC; return; } - skip_whitespace (str); + s3_skip_whitespace (str); - if ((reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL) - || (skip_past_comma (&str) == (int) FAIL)) + if ((s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL) + || (s3_skip_past_comma (&str) == (int) s3_FAIL)) { return; } else { - skip_whitespace (str); + s3_skip_whitespace (str); if (*str++ == '[') { int reg; - skip_whitespace (str); - if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL) + s3_skip_whitespace (str); + if ((reg = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) { return; } - skip_whitespace (str); + s3_skip_whitespace (str); if (*str++ != ']') { - inst.error = _("missing ]"); + s3_inst.error = _("missing ]"); return; } - end_of_line (str); + s3_end_of_line (str); } else - inst.error = BAD_ARGS; + s3_inst.error = s3_BAD_ARGS; } } static void -build_relax_frag (struct score_it fix_insts[RELAX_INST_NUM], int fix_num ATTRIBUTE_UNUSED, - struct score_it var_insts[RELAX_INST_NUM], int var_num, +s3_build_relax_frag (struct s3_score_it fix_insts[s3_RELAX_INST_NUM], int fix_num ATTRIBUTE_UNUSED, + struct s3_score_it var_insts[s3_RELAX_INST_NUM], int var_num, symbolS *add_symbol) { int i; @@ -3662,23 +3993,23 @@ build_relax_frag (struct score_it fix_insts[RELAX_INST_NUM], int fix_num ATTRIBU fixS *fixp = NULL; fixS *cur_fixp = NULL; long where; - struct score_it inst_main; + struct s3_score_it inst_main; - memcpy (&inst_main, &fix_insts[0], sizeof (struct score_it)); + memcpy (&inst_main, &fix_insts[0], sizeof (struct s3_score_it)); /* Adjust instruction opcode and to be relaxed instruction opcode. */ - inst_main.instruction = adjust_paritybit (inst_main.instruction, GET_INSN_CLASS (inst_main.type)); + inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type)); inst_main.type = Insn_PIC; for (i = 0; i < var_num; i++) { inst_main.relax_size += var_insts[i].size; - var_insts[i].instruction = adjust_paritybit (var_insts[i].instruction, - GET_INSN_CLASS (var_insts[i].type)); + var_insts[i].instruction = s3_adjust_paritybit (var_insts[i].instruction, + s3_GET_INSN_CLASS (var_insts[i].type)); } /* Check data dependency. */ - handle_dependency (&inst_main); + s3_handle_dependency (&inst_main); /* Start a new frag if frag_now is not empty. */ if (frag_now_fix () != 0) @@ -3693,10 +4024,10 @@ build_relax_frag (struct score_it fix_insts[RELAX_INST_NUM], int fix_num ATTRIBU /* Write fr_fix part. */ p = frag_more (inst_main.size); - md_number_to_chars (p, inst_main.instruction, inst_main.size); + s3_md_number_to_chars (p, inst_main.instruction, inst_main.size); if (inst_main.reloc.type != BFD_RELOC_NONE) - fixp = fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size, + fixp = s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size, &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type); frag_now->tc_frag_data.fixp = fixp; @@ -3714,7 +4045,7 @@ build_relax_frag (struct score_it fix_insts[RELAX_INST_NUM], int fix_num ATTRIBU if (var_insts[i].reloc.type != BFD_RELOC_NONE) { - fixp = fix_new_score (frag_now, where, var_insts[i].size, + fixp = s3_fix_new_score (frag_now, where, var_insts[i].size, &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel, var_insts[i].reloc.type); if (fixp) @@ -3733,38 +4064,37 @@ build_relax_frag (struct score_it fix_insts[RELAX_INST_NUM], int fix_num ATTRIBU } } - p = frag_var (rs_machine_dependent, inst_main.relax_size + RELAX_PAD_BYTE, 0, - RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, + p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0, + s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, inst_main.size, 0), add_symbol, 0, NULL); /* Write fr_var part. - no calling gen_insn_frag, no fixS will be generated. */ + no calling s3_gen_insn_frag, no fixS will be generated. */ for (i = 0; i < var_num; i++) { - md_number_to_chars (p, var_insts[i].instruction, var_insts[i].size); + s3_md_number_to_chars (p, var_insts[i].instruction, var_insts[i].size); p += var_insts[i].size; } /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ - inst.bwarn = -1; + s3_inst.bwarn = -1; } -/* Build a relax frag for la instruction when generating PIC, +/* Build a relax frag for la instruction when generating s3_PIC, external symbol first and local symbol second. */ - static void -build_la_pic (int reg_rd, expressionS exp) +s3_build_la_pic (int reg_rd, expressionS exp) { symbolS *add_symbol = exp.X_add_symbol; offsetT add_number = exp.X_add_number; - struct score_it fix_insts[RELAX_INST_NUM]; - struct score_it var_insts[RELAX_INST_NUM]; + struct s3_score_it fix_insts[s3_RELAX_INST_NUM]; + struct s3_score_it var_insts[s3_RELAX_INST_NUM]; int fix_num = 0; int var_num = 0; - char tmp[MAX_LITERAL_POOL_SIZE]; + char tmp[s3_MAX_LITERAL_POOL_SIZE]; int r1_bak; - r1_bak = nor1; - nor1 = 0; + r1_bak = s3_nor1; + s3_nor1 = 0; if (add_number == 0) { @@ -3777,31 +4107,31 @@ build_la_pic (int reg_rd, expressionS exp) For an external symbol: lw rD, ($gp) (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15) */ sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name); - if (append_insn (tmp, FALSE) == (int) FAIL) + if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL) return; - if (reg_rd == PIC_CALL_REG) - inst.reloc.type = BFD_RELOC_SCORE_CALL15; - memcpy (&fix_insts[0], &inst, sizeof (struct score_it)); + if (reg_rd == s3_PIC_CALL_REG) + s3_inst.reloc.type = BFD_RELOC_SCORE_CALL15; + memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it)); /* Var part For a local symbol : lw rD, ($gp) (BFD_RELOC_SCORE_GOT15) addi rD, (BFD_RELOC_GOT_LO16) */ - inst.reloc.type = BFD_RELOC_SCORE_GOT15; - memcpy (&var_insts[0], &inst, sizeof (struct score_it)); + s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15; + memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it)); sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, add_symbol->bsym->name); - if (append_insn (tmp, FALSE) == (int) FAIL) + if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL) return; - memcpy (&var_insts[1], &inst, sizeof (struct score_it)); - build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); + memcpy (&var_insts[1], &s3_inst, sizeof (struct s3_score_it)); + s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); } else if (add_number >= -0x8000 && add_number <= 0x7fff) { /* Insn 1: lw rD, ($gp) (BFD_RELOC_SCORE_GOT15) */ sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name); - if (append_insn (tmp, TRUE) == (int) FAIL) + if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL) return; /* Insn 2 */ @@ -3810,19 +4140,19 @@ build_la_pic (int reg_rd, expressionS exp) /* Fix part For an external symbol: addi rD, */ sprintf (tmp, "addi r%d, %d", reg_rd, (int)add_number); - if (append_insn (tmp, FALSE) == (int) FAIL) + if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL) return; - memcpy (&fix_insts[0], &inst, sizeof (struct score_it)); + memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it)); /* Var part For a local symbol: addi rD, + (BFD_RELOC_GOT_LO16) */ sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd, add_symbol->bsym->name, (int)add_number); - if (append_insn (tmp, FALSE) == (int) FAIL) + if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL) return; - memcpy (&var_insts[0], &inst, sizeof (struct score_it)); - build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); + memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it)); + s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); } else { @@ -3831,7 +4161,7 @@ build_la_pic (int reg_rd, expressionS exp) /* Insn 1: lw rD, ($gp) (BFD_RELOC_SCORE_GOT15) */ sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name); - if (append_insn (tmp, TRUE) == (int) FAIL) + if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL) return; /* Insn 2 */ @@ -3840,10 +4170,10 @@ build_la_pic (int reg_rd, expressionS exp) /* Fix part For an external symbol: ldis r1, HI% */ sprintf (tmp, "ldis r1, %d", hi); - if (append_insn (tmp, FALSE) == (int) FAIL) + if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL) return; - memcpy (&fix_insts[0], &inst, sizeof (struct score_it)); + memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it)); /* Var part For a local symbol: ldis r1, HI% @@ -3853,11 +4183,11 @@ build_la_pic (int reg_rd, expressionS exp) hi += 1; } sprintf (tmp, "ldis_pic r1, %d", hi); - if (append_insn (tmp, FALSE) == (int) FAIL) + if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL) return; - memcpy (&var_insts[0], &inst, sizeof (struct score_it)); - build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); + memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it)); + s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); /* Insn 3 */ fix_num = 1; @@ -3865,85 +4195,103 @@ build_la_pic (int reg_rd, expressionS exp) /* Fix part For an external symbol: ori r1, LO% */ sprintf (tmp, "ori r1, %d", lo); - if (append_insn (tmp, FALSE) == (int) FAIL) + if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL) return; - memcpy (&fix_insts[0], &inst, sizeof (struct score_it)); + memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it)); /* Var part For a local symbol: addi r1, +LO% (BFD_RELOC_GOT_LO16) */ sprintf (tmp, "addi_u_pic r1, %s + %d", add_symbol->bsym->name, lo); - if (append_insn (tmp, FALSE) == (int) FAIL) + if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL) return; - memcpy (&var_insts[0], &inst, sizeof (struct score_it)); - build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); + memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it)); + s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); /* Insn 4: add rD, rD, r1 */ sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd); - if (append_insn (tmp, TRUE) == (int) FAIL) + if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL) return; /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ - inst.bwarn = -1; + s3_inst.bwarn = -1; } - nor1 = r1_bak; + s3_nor1 = r1_bak; } /* Handle la. */ static void -do_macro_la_rdi32 (char *str) +s3_do_macro_la_rdi32 (char *str) { int reg_rd; - skip_whitespace (str); - if ((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL) + s3_skip_whitespace (str); + if ((reg_rd = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL) { return; } else { - char append_str[MAX_LITERAL_POOL_SIZE]; + /* Save str. */ char *keep_data = str; + char append_str[s3_MAX_LITERAL_POOL_SIZE]; + + /* Check immediate value. */ + if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL) + { + s3_inst.error = _("expression error"); + return; + } + else if ((s3_inst.reloc.exp.X_add_symbol == NULL) + && (s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _IMM32, 0) == (int) s3_FAIL)) + { + s3_inst.error = _("value not in range [0, 0xffffffff]"); + return; + } + + /* Reset str. */ + str = keep_data; /* la rd, simm16. */ - if (data_op2 (&str, 1, _SIMM16_LA) != (int) FAIL) + if (s3_data_op2 (&str, 1, _SIMM16_LA) != (int) s3_FAIL) { - end_of_line (str); + s3_end_of_line (str); return; } /* la rd, imm32 or la rd, label. */ else { - SET_INSN_ERROR (NULL); + s3_SET_INSN_ERROR (NULL); + /* Reset str. */ str = keep_data; - if ((data_op2 (&str, 1, _VALUE_HI16) == (int) FAIL) - || (end_of_line (str) == (int) FAIL)) + if ((s3_data_op2 (&str, 1, _VALUE_HI16) == (int) s3_FAIL) + || (s3_end_of_line (str) == (int) s3_FAIL)) { return; } else { - if ((score_pic == NO_PIC) || (!inst.reloc.exp.X_add_symbol)) + if ((s3_score_pic == s3_NO_PIC) || (!s3_inst.reloc.exp.X_add_symbol)) { sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data); - if (append_insn (append_str, TRUE) == (int) FAIL) + if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL) return; sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data); - if (append_insn (append_str, TRUE) == (int) FAIL) + if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL) return; } else { - assert (inst.reloc.exp.X_add_symbol); - build_la_pic (reg_rd, inst.reloc.exp); + assert (s3_inst.reloc.exp.X_add_symbol); + s3_build_la_pic (reg_rd, s3_inst.reloc.exp); } /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ - inst.bwarn = -1; + s3_inst.bwarn = -1; } } } @@ -3951,57 +4299,76 @@ do_macro_la_rdi32 (char *str) /* Handle li. */ static void -do_macro_li_rdi32 (char *str){ +s3_do_macro_li_rdi32 (char *str) +{ int reg_rd; - skip_whitespace (str); - if ((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL - || skip_past_comma (&str) == (int) FAIL) + s3_skip_whitespace (str); + if ((reg_rd = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL) { return; } else { + /* Save str. */ char *keep_data = str; + /* Check immediate value. */ + if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL) + { + s3_inst.error = _("expression error"); + return; + } + else if (!(s3_inst.reloc.exp.X_add_number >= -0xffffffffLL + && s3_inst.reloc.exp.X_add_number <= 0xffffffffLL)) + { + s3_inst.error = _("value not in range [-0xffffffff, 0xffffffff]"); + return; + } + + /* Reset str. */ + str = keep_data; + /* li rd, simm16. */ - if (data_op2 (&str, 1, _SIMM16_LA) != (int) FAIL) + if (s3_data_op2 (&str, 1, _SIMM16_LA) != (int) s3_FAIL) { - end_of_line (str); + s3_end_of_line (str); return; } /* li rd, imm32. */ else { - char append_str[MAX_LITERAL_POOL_SIZE]; + char append_str[s3_MAX_LITERAL_POOL_SIZE]; + /* Reset str. */ str = keep_data; - if ((data_op2 (&str, 1, _VALUE_HI16) == (int) FAIL) - || (end_of_line (str) == (int) FAIL)) + if ((s3_data_op2 (&str, 1, _VALUE_HI16) == (int) s3_FAIL) + || (s3_end_of_line (str) == (int) s3_FAIL)) { return; } - else if (inst.reloc.exp.X_add_symbol) + else if (s3_inst.reloc.exp.X_add_symbol) { - inst.error = _("li rd label isn't correct instruction form"); + s3_inst.error = _("li rd label isn't correct instruction form"); return; } else { sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data); - if (append_insn (append_str, TRUE) == (int) FAIL) + if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL) return; else { sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data); - if (append_insn (append_str, TRUE) == (int) FAIL) + if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL) return; /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ - inst.bwarn = -1; + s3_inst.bwarn = -1; } } } @@ -4010,236 +4377,535 @@ do_macro_li_rdi32 (char *str){ /* Handle mul/mulu/div/divu/rem/remu. */ static void -do_macro_mul_rdrsrs (char *str) +s3_do_macro_mul_rdrsrs (char *str) { int reg_rd; int reg_rs1; int reg_rs2; char *backupstr; - char append_str[MAX_LITERAL_POOL_SIZE]; + char append_str[s3_MAX_LITERAL_POOL_SIZE]; - if (university_version == 1) - as_warn ("%s", ERR_FOR_SCORE5U_MUL_DIV); + if (s3_university_version == 1) + as_warn ("%s", s3_ERR_FOR_SCORE5U_MUL_DIV); strcpy (append_str, str); backupstr = append_str; - skip_whitespace (backupstr); - if (((reg_rd = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL) - || (skip_past_comma (&backupstr) == (int) FAIL) - || ((reg_rs1 = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)) + s3_skip_whitespace (backupstr); + if (((reg_rd = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) + || (s3_skip_past_comma (&backupstr) == (int) s3_FAIL) + || ((reg_rs1 = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL)) { - inst.error = BAD_ARGS; + s3_inst.error = s3_BAD_ARGS; return; } - if (skip_past_comma (&backupstr) == (int) FAIL) + if (s3_skip_past_comma (&backupstr) == (int) s3_FAIL) { /* rem/remu rA, rB is error format. */ - if (strcmp (inst.name, "rem") == 0 || strcmp (inst.name, "remu") == 0) + if (strcmp (s3_inst.name, "rem") == 0 || strcmp (s3_inst.name, "remu") == 0) { - SET_INSN_ERROR (BAD_ARGS); + s3_SET_INSN_ERROR (s3_BAD_ARGS); } else { - SET_INSN_ERROR (NULL); - do_rsrs (str); + s3_SET_INSN_ERROR (NULL); + s3_do_rsrs (str); } return; } else { - SET_INSN_ERROR (NULL); - if (((reg_rs2 = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL) - || (end_of_line (backupstr) == (int) FAIL)) + s3_SET_INSN_ERROR (NULL); + if (((reg_rs2 = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) + || (s3_end_of_line (backupstr) == (int) s3_FAIL)) { return; } else { - char append_str1[MAX_LITERAL_POOL_SIZE]; + char append_str1[s3_MAX_LITERAL_POOL_SIZE]; - if (strcmp (inst.name, "rem") == 0) + if (strcmp (s3_inst.name, "rem") == 0) { sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2); sprintf (append_str1, "mfceh r%d", reg_rd); } - else if (strcmp (inst.name, "remu") == 0) + else if (strcmp (s3_inst.name, "remu") == 0) { sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2); sprintf (append_str1, "mfceh r%d", reg_rd); } else { - sprintf (append_str, "%s r%d, r%d", inst.name, reg_rs1, reg_rs2); + sprintf (append_str, "%s r%d, r%d", s3_inst.name, reg_rs1, reg_rs2); sprintf (append_str1, "mfcel r%d", reg_rd); } /* Output mul/mulu or div/divu or rem/remu. */ - if (append_insn (append_str, TRUE) == (int) FAIL) + if (s3_append_insn (append_str, TRUE) == (int) s3_FAIL) return; /* Output mfcel or mfceh. */ - if (append_insn (append_str1, TRUE) == (int) FAIL) + if (s3_append_insn (append_str1, TRUE) == (int) s3_FAIL) return; /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ - inst.bwarn = -1; + s3_inst.bwarn = -1; } } } static void -exp_macro_ldst_abs (char *str) +s3_exp_macro_ldst_abs (char *str) { int reg_rd; char *backupstr, *tmp; - char append_str[MAX_LITERAL_POOL_SIZE]; - char verifystr[MAX_LITERAL_POOL_SIZE]; - struct score_it inst_backup; + char append_str[s3_MAX_LITERAL_POOL_SIZE]; + char verifystr[s3_MAX_LITERAL_POOL_SIZE]; + struct s3_score_it inst_backup; int r1_bak = 0; - r1_bak = nor1; - nor1 = 0; - memcpy (&inst_backup, &inst, sizeof (struct score_it)); + r1_bak = s3_nor1; + s3_nor1 = 0; + memcpy (&inst_backup, &s3_inst, sizeof (struct s3_score_it)); strcpy (verifystr, str); backupstr = verifystr; - skip_whitespace (backupstr); - if ((reg_rd = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL) + s3_skip_whitespace (backupstr); + if ((reg_rd = s3_reg_required_here (&backupstr, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) return; tmp = backupstr; - if (skip_past_comma (&backupstr) == (int) FAIL) + if (s3_skip_past_comma (&backupstr) == (int) s3_FAIL) return; backupstr = tmp; sprintf (append_str, "li r1 %s", backupstr); - append_insn (append_str, TRUE); + s3_append_insn (append_str, TRUE); - memcpy (&inst, &inst_backup, sizeof (struct score_it)); + memcpy (&s3_inst, &inst_backup, sizeof (struct s3_score_it)); sprintf (append_str, " r%d, [r1,0]", reg_rd); - do_ldst_insn (append_str); + s3_do_ldst_insn (append_str); - nor1 = r1_bak; + s3_nor1 = r1_bak; } - -static int -nopic_need_relax (symbolS * sym, int before_relaxing) +/* Handle bcmpeq / bcmpne */ +static void +s3_do_macro_bcmp (char *str) { - if (sym == NULL) - return 0; - else if (USE_GLOBAL_POINTER_OPT && g_switch_value > 0) + int reg_a , reg_b; + char keep_data[s3_MAX_LITERAL_POOL_SIZE]; + char* ptemp; + int i=0; + struct s3_score_it inst_expand[2]; + struct s3_score_it inst_main; + + + s3_skip_whitespace (str); + if (( reg_a = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + ||(reg_b = s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE)) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL) + return; + ptemp =str; + while(*ptemp!=0) + { + keep_data[i]=*ptemp; + i++; + ptemp++; + } + keep_data[i]=0; + if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL + ||reg_b ==0 + || s3_end_of_line (str) == (int) s3_FAIL) + return ; + else if (s3_inst.reloc.exp.X_add_symbol == 0) + { + s3_inst.error = _("lacking label "); + return; + } + else { - const char *symname; - const char *segname; + char append_str[s3_MAX_LITERAL_POOL_SIZE]; + s3_SET_INSN_ERROR (NULL); + + s3_inst.reloc.type = BFD_RELOC_SCORE_BCMP; + s3_inst.reloc.pc_rel = 1; + bfd_signed_vma val = s3_inst.reloc.exp.X_add_number; - /* Find out whether this symbol can be referenced off the $gp - register. It can be if it is smaller than the -G size or if - it is in the .sdata or .sbss section. Certain symbols can - not be referenced off the $gp, although it appears as though - they can. */ - symname = S_GET_NAME (sym); - if (symname != (const char *)NULL - && (strcmp (symname, "eprol") == 0 - || strcmp (symname, "etext") == 0 - || strcmp (symname, "_gp") == 0 - || strcmp (symname, "edata") == 0 - || strcmp (symname, "_fbss") == 0 - || strcmp (symname, "_fdata") == 0 - || strcmp (symname, "_ftext") == 0 - || strcmp (symname, "end") == 0 - || strcmp (symname, GP_DISP_LABEL) == 0)) + /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */ + s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number>>1) & 0x1) | ((s3_inst.reloc.exp.X_add_number>>2) & 0x7)<<7 |((s3_inst.reloc.exp.X_add_number>>5) & 0x1f)<<20; + + /* Check and set offset. */ + if (((val & 0xfffffe00) != 0) + && ((val & 0xfffffe00) != 0xfffffe00)) { - return 1; + /* support bcmp --> cmp!+beq (bne) */ + if (s3_score_pic == s3_NO_PIC) + { + sprintf (&append_str[0], "cmp! r%d, r%d", reg_a, reg_b); + if (s3_append_insn (&append_str[0], TRUE) == (int) s3_FAIL) + return; + if ((inst_main.instruction & 0x3e00007e) == 0x0000004c) + sprintf (&append_str[1], "beq %s", keep_data); + else + sprintf (&append_str[1], "bne %s", keep_data); + if (s3_append_insn (&append_str[1], TRUE) == (int) s3_FAIL) + return; + } + else + { + assert (s3_inst.reloc.exp.X_add_symbol); + } + /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ + s3_inst.bwarn = -1; + return; } - else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0 - /* We must defer this decision until after the whole file has been read, - since there might be a .extern after the first use of this symbol. */ - || (before_relaxing - && S_GET_VALUE (sym) == 0) - || (S_GET_VALUE (sym) != 0 - && S_GET_VALUE (sym) <= g_switch_value))) + else { - return 0; + val >>= 1; + s3_inst.instruction |= (val & 0x1) + | (((val >> 1) & 0x7) << 7) + | (((val >> 4) & 0x1f) << 20); } - segname = segment_name (S_GET_SEGMENT (sym)); - return (strcmp (segname, ".sdata") != 0 - && strcmp (segname, ".sbss") != 0 - && strncmp (segname, ".sdata.", 7) != 0 - && strncmp (segname, ".gnu.linkonce.s.", 16) != 0); - } - /* We are not optimizing for the $gp register. */ - else - return 1; -} - -/* Build a relax frag for lw/st instruction when generating PIC, - external symbol first and local symbol second. */ - -static void -build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name) -{ - symbolS *add_symbol = exp.X_add_symbol; - int add_number = exp.X_add_number; - struct score_it fix_insts[RELAX_INST_NUM]; - struct score_it var_insts[RELAX_INST_NUM]; - int fix_num = 0; - int var_num = 0; - char tmp[MAX_LITERAL_POOL_SIZE]; - int r1_bak; + /* Backup s3_inst. */ + memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it)); - r1_bak = nor1; - nor1 = 0; + if (s3_score_pic == s3_NO_PIC) + { + sprintf (&append_str[0], "cmp! r%d, r%d", reg_a, reg_b); + if (s3_append_insn (&append_str[0], FALSE) == (int) s3_FAIL) + return; + memcpy (&inst_expand[0], &s3_inst, sizeof (struct s3_score_it)); + + if ((inst_main.instruction & 0x3e00007e) == 0x0000004c) + sprintf (&append_str[1], "beq %s", keep_data); + else + sprintf (&append_str[1], "bne %s", keep_data); + if (s3_append_insn (&append_str[1], FALSE) == (int) s3_FAIL) + return; + memcpy (&inst_expand[1], &s3_inst, sizeof (struct s3_score_it)); + } + else + { + assert (s3_inst.reloc.exp.X_add_symbol); + } + inst_main.relax_size = inst_expand[0].size + inst_expand[1].size; + inst_main.type = Insn_BCMP; - if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff)) - { - fix_num = 1; - var_num = 2; + /* Adjust instruction opcode and to be relaxed instruction opcode. */ + inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type)); - /* For an external symbol, two insns are generated; - For a local symbol, three insns are generated. */ - /* Fix part - For an external symbol: lw rD, ($gp) - (BFD_RELOC_SCORE_GOT15) */ - sprintf (tmp, "lw_pic r1, %s", add_symbol->bsym->name); - if (append_insn (tmp, FALSE) == (int) FAIL) - return; + for (i = 0; i < 2; i++) + inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction, + s3_GET_INSN_CLASS (inst_expand[i].type)); + /* Check data dependency. */ + s3_handle_dependency (&inst_main); + /* Start a new frag if frag_now is not empty. */ + if (frag_now_fix () != 0) + { + if (!frag_now->tc_frag_data.is_insn) + frag_wane (frag_now); + frag_new (0); + } + frag_grow (20); - memcpy (&fix_insts[0], &inst, sizeof (struct score_it)); + /* Write fr_fix part. */ + char *p; + p = frag_more (inst_main.size); + s3_md_number_to_chars (p, inst_main.instruction, inst_main.size); - /* Var part - For a local symbol : - lw rD, ($gp) (BFD_RELOC_SCORE_GOT15) - addi rD, (BFD_RELOC_GOT_LO16) */ - inst.reloc.type = BFD_RELOC_SCORE_GOT15; - memcpy (&var_insts[0], &inst, sizeof (struct score_it)); - sprintf (tmp, "addi_s_pic r1, %s", add_symbol->bsym->name); - if (append_insn (tmp, FALSE) == (int) FAIL) - return; + if (inst_main.reloc.type != BFD_RELOC_NONE) + { + s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size, + &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type); + } +#ifdef OBJ_ELF + dwarf2_emit_insn (inst_main.size); +#endif - memcpy (&var_insts[1], &inst, sizeof (struct score_it)); - build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); + /* s3_GP instruction can not do optimization, only can do relax between + 1 instruction and 3 instructions. */ + p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0, + s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 1), + inst_main.reloc.exp.X_add_symbol, 0, NULL); - /* Insn 2 or Insn 3: lw/st rD, [r1, constant] */ - sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number); - if (append_insn (tmp, TRUE) == (int) FAIL) - return; + /* Write fr_var part. + no calling s3_gen_insn_frag, no fixS will be generated. */ + s3_md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size); + p += inst_expand[0].size; + s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size); + p += inst_expand[1].size; /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ - inst.bwarn = -1; - } - else - { - inst.error = _("PIC code offset overflow (max 16 signed bits)"); + s3_inst.bwarn = -1; + } +} + +/* Handle bcmpeqz / bcmpnez */ +static void +s3_do_macro_bcmpz (char *str) +{ + int reg_a ; + char keep_data[s3_MAX_LITERAL_POOL_SIZE]; + char* ptemp; + int i=0; + struct s3_score_it inst_expand[2]; + struct s3_score_it inst_main; + + s3_skip_whitespace (str); + if (( reg_a = s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE)) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL ) + return; + ptemp =str; + while(*ptemp!=0) + { + keep_data[i]=*ptemp; + i++; + ptemp++; + } + keep_data[i]=0; + if ( s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) + return ; + + else if (s3_inst.reloc.exp.X_add_symbol == 0) + { + s3_inst.error = _("lacking label "); + return; + } + else + { + char append_str[s3_MAX_LITERAL_POOL_SIZE]; + s3_SET_INSN_ERROR (NULL); + s3_inst.reloc.type = BFD_RELOC_SCORE_BCMP; + s3_inst.reloc.pc_rel = 1; + bfd_signed_vma val = s3_inst.reloc.exp.X_add_number; + + /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */ + s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number>>1) & 0x1) | ((s3_inst.reloc.exp.X_add_number>>2) & 0x7)<<7 |((s3_inst.reloc.exp.X_add_number>>5) & 0x1f)<<20; + + /* Check and set offset. */ + if (((val & 0xfffffe00) != 0) + && ((val & 0xfffffe00) != 0xfffffe00)) + { + if (s3_score_pic == s3_NO_PIC) + { + sprintf (&append_str[0], "cmpi! r%d,0", reg_a); + if (s3_append_insn (&append_str[0], TRUE) == (int) s3_FAIL) + return; + if ((inst_main.instruction & 0x3e00007e) == 0x0000004c) + sprintf (&append_str[1], "beq %s", keep_data); + else + sprintf (&append_str[1], "bne %s", keep_data); + if (s3_append_insn (&append_str[1], TRUE) == (int) s3_FAIL) + return; + } + else + { + assert (s3_inst.reloc.exp.X_add_symbol); + } + /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ + s3_inst.bwarn = -1; + return; + } + else + { + val >>= 1; + s3_inst.instruction |= (val & 0x1) + | (((val >> 1) & 0x7) << 7) + | (((val >> 4) & 0x1f) << 20); + } + + /* Backup s3_inst. */ + memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it)); + + if (s3_score_pic == s3_NO_PIC) + { + sprintf (&append_str[0], "cmpi! r%d, 0", reg_a); + if (s3_append_insn (&append_str[0], FALSE) == (int) s3_FAIL) + return; + memcpy (&inst_expand[0], &s3_inst, sizeof (struct s3_score_it)); + if ((inst_main.instruction & 0x3e00007e) == 0x0000004c) + sprintf (&append_str[1], "beq %s", keep_data); + else + sprintf (&append_str[1], "bne %s", keep_data); + if (s3_append_insn (&append_str[1], FALSE) == (int) s3_FAIL) + return; + memcpy (&inst_expand[1], &s3_inst, sizeof (struct s3_score_it)); + } + else + { + assert (s3_inst.reloc.exp.X_add_symbol); + } + inst_main.relax_size = inst_expand[0].size + inst_expand[1].size; + inst_main.type = Insn_BCMP; + + /* Adjust instruction opcode and to be relaxed instruction opcode. */ + inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type)); + + for (i = 0; i < 2; i++) + inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction , s3_GET_INSN_CLASS (inst_expand[i].type)); + /* Check data dependency. */ + s3_handle_dependency (&inst_main); + /* Start a new frag if frag_now is not empty. */ + if (frag_now_fix () != 0) + { + if (!frag_now->tc_frag_data.is_insn) + frag_wane (frag_now); + frag_new (0); + } + frag_grow (20); + + /* Write fr_fix part. */ + char *p; + p = frag_more (inst_main.size); + s3_md_number_to_chars (p, inst_main.instruction, inst_main.size); + + if (inst_main.reloc.type != BFD_RELOC_NONE) + { + s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size, + &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type); + } +#ifdef OBJ_ELF + dwarf2_emit_insn (inst_main.size); +#endif + + /* s3_GP instruction can not do optimization, only can do relax between + 1 instruction and 3 instructions. */ + p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0, + s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 1), + inst_main.reloc.exp.X_add_symbol, 0, NULL); + + /* Write fr_var part. + no calling s3_gen_insn_frag, no fixS will be generated. */ + s3_md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size); + p += inst_expand[0].size; + s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size); + p += inst_expand[1].size; + + /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ + s3_inst.bwarn = -1; + } +} + +static int +s3_nopic_need_relax (symbolS * sym, int before_relaxing) +{ + if (sym == NULL) + return 0; + else if (s3_USE_GLOBAL_POINTER_OPT && s3_g_switch_value > 0) + { + const char *symname; + const char *segname; + + /* Find out whether this symbol can be referenced off the $gp + register. It can be if it is smaller than the -G size or if + it is in the .sdata or .sbss section. Certain symbols can + not be referenced off the $gp, although it appears as though + they can. */ + symname = S_GET_NAME (sym); + if (symname != (const char *)NULL + && (strcmp (symname, "eprol") == 0 + || strcmp (symname, "etext") == 0 + || strcmp (symname, "_gp") == 0 + || strcmp (symname, "edata") == 0 + || strcmp (symname, "_fbss") == 0 + || strcmp (symname, "_fdata") == 0 + || strcmp (symname, "_ftext") == 0 + || strcmp (symname, "end") == 0 + || strcmp (symname, GP_DISP_LABEL) == 0)) + { + return 1; + } + else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0 + /* We must defer this decision until after the whole file has been read, + since there might be a .extern after the first use of this symbol. */ + || (before_relaxing + && S_GET_VALUE (sym) == 0) + || (S_GET_VALUE (sym) != 0 + && S_GET_VALUE (sym) <= s3_g_switch_value))) + { + return 0; + } + + segname = segment_name (S_GET_SEGMENT (sym)); + return (strcmp (segname, ".sdata") != 0 + && strcmp (segname, ".sbss") != 0 + && strncmp (segname, ".sdata.", 7) != 0 + && strncmp (segname, ".gnu.linkonce.s.", 16) != 0); + } + /* We are not optimizing for the $gp register. */ + else + return 1; +} + +/* Build a relax frag for lw/st instruction when generating s3_PIC, + external symbol first and local symbol second. */ +static void +s3_build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name) +{ + symbolS *add_symbol = exp.X_add_symbol; + int add_number = exp.X_add_number; + struct s3_score_it fix_insts[s3_RELAX_INST_NUM]; + struct s3_score_it var_insts[s3_RELAX_INST_NUM]; + int fix_num = 0; + int var_num = 0; + char tmp[s3_MAX_LITERAL_POOL_SIZE]; + int r1_bak; + + r1_bak = s3_nor1; + s3_nor1 = 0; + + if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff)) + { + fix_num = 1; + var_num = 2; + + /* For an external symbol, two insns are generated; + For a local symbol, three insns are generated. */ + /* Fix part + For an external symbol: lw rD, ($gp) + (BFD_RELOC_SCORE_GOT15) */ + sprintf (tmp, "lw_pic r1, %s", add_symbol->bsym->name); + if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL) + return; + + memcpy (&fix_insts[0], &s3_inst, sizeof (struct s3_score_it)); + + /* Var part + For a local symbol : + lw rD, ($gp) (BFD_RELOC_SCORE_GOT15) + addi rD, (BFD_RELOC_GOT_LO16) */ + s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15; + memcpy (&var_insts[0], &s3_inst, sizeof (struct s3_score_it)); + sprintf (tmp, "addi_s_pic r1, %s", add_symbol->bsym->name); + if (s3_append_insn (tmp, FALSE) == (int) s3_FAIL) + return; + + memcpy (&var_insts[1], &s3_inst, sizeof (struct s3_score_it)); + s3_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); + + /* Insn 2 or Insn 3: lw/st rD, [r1, constant] */ + sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number); + if (s3_append_insn (tmp, TRUE) == (int) s3_FAIL) + return; + + /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ + s3_inst.bwarn = -1; + } + else + { + s3_inst.error = _("s3_PIC code offset overflow (max 16 signed bits)"); return; } - nor1 = r1_bak; + s3_nor1 = r1_bak; } static void -do_macro_ldst_label (char *str) +s3_do_macro_ldst_label (char *str) { int i; int ldst_gp_p = 0; @@ -4248,21 +4914,21 @@ do_macro_ldst_label (char *str) char *backup_str; char *label_str; char *absolute_value; - char append_str[3][MAX_LITERAL_POOL_SIZE]; - char verifystr[MAX_LITERAL_POOL_SIZE]; - struct score_it inst_backup; - struct score_it inst_expand[3]; - struct score_it inst_main; + char append_str[3][s3_MAX_LITERAL_POOL_SIZE]; + char verifystr[s3_MAX_LITERAL_POOL_SIZE]; + struct s3_score_it inst_backup; + struct s3_score_it inst_expand[3]; + struct s3_score_it inst_main; - memcpy (&inst_backup, &inst, sizeof (struct score_it)); + memcpy (&inst_backup, &s3_inst, sizeof (struct s3_score_it)); strcpy (verifystr, str); backup_str = verifystr; - skip_whitespace (backup_str); - if ((reg_rd = reg_required_here (&backup_str, -1, REG_TYPE_SCORE)) == (int) FAIL) + s3_skip_whitespace (backup_str); + if ((reg_rd = s3_reg_required_here (&backup_str, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) return; - if (skip_past_comma (&backup_str) == (int) FAIL) + if (s3_skip_past_comma (&backup_str) == (int) s3_FAIL) return; label_str = backup_str; @@ -4270,80 +4936,91 @@ do_macro_ldst_label (char *str) /* Ld/st rD, [rA, imm] ld/st rD, [rA]+, imm ld/st rD, [rA, imm]+. */ if (*backup_str == '[') { - inst.type = Rd_rvalueRs_preSI12; - do_ldst_insn (str); + s3_inst.type = Rd_rvalueRs_preSI12; + s3_do_ldst_insn (str); return; } /* Ld/st rD, imm. */ absolute_value = backup_str; - inst.type = Rd_rvalueRs_SI15; - if ((my_get_expression (&inst.reloc.exp, &backup_str) == (int) FAIL) - || (validate_immediate (inst.reloc.exp.X_add_number, _VALUE, 0) == (int) FAIL) - || (end_of_line (backup_str) == (int) FAIL)) + s3_inst.type = Rd_rvalueRs_SI15; + + if (s3_my_get_expression (&s3_inst.reloc.exp, &backup_str) == (int) s3_FAIL) + { + s3_inst.error = _("expression error"); + return; + } + else if ((s3_inst.reloc.exp.X_add_symbol == NULL) + && (s3_validate_immediate (s3_inst.reloc.exp.X_add_number, _VALUE, 0) == (int) s3_FAIL)) + { + s3_inst.error = _("value not in range [0, 0x7fffffff]"); + return; + } + else if (s3_end_of_line (backup_str) == (int) s3_FAIL) { + s3_inst.error = _("end on line error"); return; } else { - if (inst.reloc.exp.X_add_symbol == 0) + if (s3_inst.reloc.exp.X_add_symbol == 0) { - memcpy (&inst, &inst_backup, sizeof (struct score_it)); - exp_macro_ldst_abs (str); + memcpy (&s3_inst, &inst_backup, sizeof (struct s3_score_it)); + s3_exp_macro_ldst_abs (str); return; } } /* Ld/st rD, label. */ - inst.type = Rd_rvalueRs_SI15; + s3_inst.type = Rd_rvalueRs_SI15; backup_str = absolute_value; - if ((data_op2 (&backup_str, 1, _GP_IMM15) == (int) FAIL) - || (end_of_line (backup_str) == (int) FAIL)) + if ((s3_data_op2 (&backup_str, 1, _GP_IMM15) == (int) s3_FAIL) + || (s3_end_of_line (backup_str) == (int) s3_FAIL)) { return; } else { - if (inst.reloc.exp.X_add_symbol == 0) + if (s3_inst.reloc.exp.X_add_symbol == 0) { - if (!inst.error) - inst.error = BAD_ARGS; + if (!s3_inst.error) + s3_inst.error = s3_BAD_ARGS; return; } - if (score_pic == PIC) + if (s3_score_pic == s3_PIC) { int ldst_idx = 0; - ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK; - build_lwst_pic (reg_rd, inst.reloc.exp, score_ldst_insns[ldst_idx * 3 + 0].template); + ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK; + s3_build_lwst_pic (reg_rd, s3_inst.reloc.exp, s3_score_ldst_insns[ldst_idx * 3 + 0].template); return; } else { - if ((inst.reloc.exp.X_add_number <= 0x3fff) - && (inst.reloc.exp.X_add_number >= -0x4000) - && (!nopic_need_relax (inst.reloc.exp.X_add_symbol, 1))) + if ((s3_inst.reloc.exp.X_add_number <= 0x3fff) + && (s3_inst.reloc.exp.X_add_number >= -0x4000) + && (!s3_nopic_need_relax (s3_inst.reloc.exp.X_add_symbol, 1))) { int ldst_idx = 0; /* Assign the real opcode. */ - ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK; - inst.instruction &= ~OPC_PSEUDOLDST_MASK; - inst.instruction |= score_ldst_insns[ldst_idx * 3 + 0].value; - inst.instruction |= reg_rd << 20; - inst.instruction |= GP << 15; - inst.relax_inst = 0x8000; - inst.relax_size = 0; + ldst_idx = s3_inst.instruction & OPC_PSEUDOLDST_MASK; + s3_inst.instruction &= ~OPC_PSEUDOLDST_MASK; + s3_inst.instruction |= s3_score_ldst_insns[ldst_idx * 3 + 0].value; + s3_inst.instruction |= reg_rd << 20; + s3_inst.instruction |= s3_GP << 15; + s3_inst.relax_inst = 0x8000; + s3_inst.relax_size = 0; ldst_gp_p = 1; } } } - /* Backup inst. */ - memcpy (&inst_main, &inst, sizeof (struct score_it)); - r1_bak = nor1; - nor1 = 0; + /* Backup s3_inst. */ + memcpy (&inst_main, &s3_inst, sizeof (struct s3_score_it)); + r1_bak = s3_nor1; + s3_nor1 = 0; /* Determine which instructions should be output. */ sprintf (append_str[0], "ld_i32hi r1, %s", label_str); @@ -4355,10 +5032,10 @@ do_macro_ldst_label (char *str) ld/st rd, [r1, 0] */ for (i = 0; i < 3; i++) { - if (append_insn (append_str[i], FALSE) == (int) FAIL) + if (s3_append_insn (append_str[i], FALSE) == (int) s3_FAIL) return; - memcpy (&inst_expand[i], &inst, sizeof (struct score_it)); + memcpy (&inst_expand[i], &s3_inst, sizeof (struct s3_score_it)); } if (ldst_gp_p) @@ -4366,16 +5043,24 @@ do_macro_ldst_label (char *str) char *p; /* Adjust instruction opcode and to be relaxed instruction opcode. */ - inst_main.instruction = adjust_paritybit (inst_main.instruction, GET_INSN_CLASS (inst_main.type)); - inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size; + inst_main.instruction = s3_adjust_paritybit (inst_main.instruction, s3_GET_INSN_CLASS (inst_main.type)); + + /* relax lw rd, label -> ldis rs, imm16 + ori rd, imm16 + lw rd, [rs, imm15] or lw! rd, [rs, imm5]. */ + if (inst_expand[2].relax_size == 0) + inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size; + else + inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].relax_size; + inst_main.type = Insn_GP; for (i = 0; i < 3; i++) - inst_expand[i].instruction = adjust_paritybit (inst_expand[i].instruction - , GET_INSN_CLASS (inst_expand[i].type)); + inst_expand[i].instruction = s3_adjust_paritybit (inst_expand[i].instruction, + s3_GET_INSN_CLASS (inst_expand[i].type)); /* Check data dependency. */ - handle_dependency (&inst_main); + s3_handle_dependency (&inst_main); /* Start a new frag if frag_now is not empty. */ if (frag_now_fix () != 0) @@ -4389,11 +5074,11 @@ do_macro_ldst_label (char *str) /* Write fr_fix part. */ p = frag_more (inst_main.size); - md_number_to_chars (p, inst_main.instruction, inst_main.size); + s3_md_number_to_chars (p, inst_main.instruction, inst_main.size); if (inst_main.reloc.type != BFD_RELOC_NONE) { - fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size, + s3_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size, &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type); } @@ -4401,2191 +5086,2757 @@ do_macro_ldst_label (char *str) dwarf2_emit_insn (inst_main.size); #endif - /* GP instruction can not do optimization, only can do relax between + /* s3_GP instruction can not do optimization, only can do relax between 1 instruction and 3 instructions. */ - p = frag_var (rs_machine_dependent, inst_main.relax_size + RELAX_PAD_BYTE, 0, - RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0), + p = frag_var (rs_machine_dependent, inst_main.relax_size + s3_RELAX_PAD_BYTE, 0, + s3_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0), inst_main.reloc.exp.X_add_symbol, 0, NULL); /* Write fr_var part. - no calling gen_insn_frag, no fixS will be generated. */ - md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size); + no calling s3_gen_insn_frag, no fixS will be generated. */ + s3_md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size); p += inst_expand[0].size; - md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size); + s3_md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size); p += inst_expand[1].size; - md_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size); + + /* relax lw rd, label -> ldis rs, imm16 + ori rd, imm16 + lw rd, [rs, imm15] or lw! rd, [rs, imm5]. */ + if (inst_expand[2].relax_size == 0) + s3_md_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size); + else + s3_md_number_to_chars (p, inst_expand[2].relax_inst, inst_expand[2].relax_size); } else { - gen_insn_frag (&inst_expand[0], NULL); - gen_insn_frag (&inst_expand[1], NULL); - gen_insn_frag (&inst_expand[2], NULL); + s3_gen_insn_frag (&inst_expand[0], NULL); + s3_gen_insn_frag (&inst_expand[1], NULL); + s3_gen_insn_frag (&inst_expand[2], NULL); } - nor1 = r1_bak; + s3_nor1 = r1_bak; /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ - inst.bwarn = -1; + s3_inst.bwarn = -1; } static void -do_lw_pic (char *str) +s3_do_lw_pic (char *str) { int reg_rd; - skip_whitespace (str); - if (((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL) - || (skip_past_comma (&str) == (int) FAIL) - || (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL) - || (end_of_line (str) == (int) FAIL)) + s3_skip_whitespace (str); + if (((reg_rd = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) + || (s3_skip_past_comma (&str) == (int) s3_FAIL) + || (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL) + || (s3_end_of_line (str) == (int) s3_FAIL)) { return; } else { - if (inst.reloc.exp.X_add_symbol == 0) + if (s3_inst.reloc.exp.X_add_symbol == 0) { - if (!inst.error) - inst.error = BAD_ARGS; + if (!s3_inst.error) + s3_inst.error = s3_BAD_ARGS; return; } - inst.instruction |= GP << 15; - inst.reloc.type = BFD_RELOC_SCORE_GOT15; + s3_inst.instruction |= s3_GP << 15; + s3_inst.reloc.type = BFD_RELOC_SCORE_GOT15; } } static void -do_empty (char *str) +s3_do_empty (char *str) { str = str; - if (university_version == 1) + if (s3_university_version == 1) { - if (((inst.instruction & 0x3e0003ff) == 0x0c000004) - || ((inst.instruction & 0x3e0003ff) == 0x0c000024) - || ((inst.instruction & 0x3e0003ff) == 0x0c000044) - || ((inst.instruction & 0x3e0003ff) == 0x0c000064)) + if (((s3_inst.instruction & 0x3e0003ff) == 0x0c000004) + || ((s3_inst.instruction & 0x3e0003ff) == 0x0c000024) + || ((s3_inst.instruction & 0x3e0003ff) == 0x0c000044) + || ((s3_inst.instruction & 0x3e0003ff) == 0x0c000064)) { - inst.error = ERR_FOR_SCORE5U_MMU; + s3_inst.error = s3_ERR_FOR_SCORE5U_MMU; return; } } - if (end_of_line (str) == (int) FAIL) + if (s3_end_of_line (str) == (int) s3_FAIL) return; - if (inst.relax_inst != 0x8000) + if (s3_inst.relax_inst != 0x8000) { - if (inst.type == NO_OPD) + if (s3_inst.type == NO_OPD) { - inst.relax_size = 2; + s3_inst.relax_size = 2; } else { - inst.relax_size = 4; + s3_inst.relax_size = 4; } } } static void -do_jump (char *str) +s3_do16_int (char *str) +{ + s3_skip_whitespace (str); + return; +} + +static void +s3_do_jump (char *str) { char *save_in; - skip_whitespace (str); - if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL - || end_of_line (str) == (int) FAIL) + s3_skip_whitespace (str); + if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) return; - if (inst.reloc.exp.X_add_symbol == 0) + if (s3_inst.reloc.exp.X_add_symbol == 0) { - inst.error = _("lacking label "); + s3_inst.error = _("lacking label "); return; } - if (((inst.reloc.exp.X_add_number & 0xff000000) != 0) - && ((inst.reloc.exp.X_add_number & 0xff000000) != 0xff000000)) + if (!(s3_inst.reloc.exp.X_add_number >= -16777216 + && s3_inst.reloc.exp.X_add_number <= 16777215)) { - inst.error = _("invalid constant: 25 bit expression not in range -2^24..2^24"); + s3_inst.error = _("invalid constant: 25 bit expression not in range [-16777216, 16777215]"); return; } save_in = input_line_pointer; input_line_pointer = str; - inst.reloc.type = BFD_RELOC_SCORE_JMP; - inst.reloc.pc_rel = 1; + s3_inst.reloc.type = BFD_RELOC_SCORE_JMP; + s3_inst.reloc.pc_rel = 1; input_line_pointer = save_in; } static void -do16_jump (char *str) -{ - skip_whitespace (str); - if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL - || end_of_line (str) == (int) FAIL) - { - return; - } - else if (inst.reloc.exp.X_add_symbol == 0) - { - inst.error = _("lacking label "); - return; - } - else if (((inst.reloc.exp.X_add_number & 0xfffff800) != 0) - && ((inst.reloc.exp.X_add_number & 0xfffff800) != 0xfffff800)) - { - inst.error = _("invalid constant: 12 bit expression not in range -2^11..2^11"); - return; - } - - inst.reloc.type = BFD_RELOC_SCORE16_JMP; - inst.reloc.pc_rel = 1; -} - -static void -do_branch (char *str) +s3_do_branch (char *str) { - unsigned long abs_value = 0; - - if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL - || end_of_line (str) == (int) FAIL) + if (s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) { return; } - else if (inst.reloc.exp.X_add_symbol == 0) + else if (s3_inst.reloc.exp.X_add_symbol == 0) { - inst.error = _("lacking label "); + s3_inst.error = _("lacking label "); return; } - else if (((inst.reloc.exp.X_add_number & 0xff000000) != 0) - && ((inst.reloc.exp.X_add_number & 0xff000000) != 0xff000000)) + else if (!(s3_inst.reloc.exp.X_add_number >= -524288 + && s3_inst.reloc.exp.X_add_number <= 524287)) { - inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19"); + s3_inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19"); return; } - inst.reloc.type = BFD_RELOC_SCORE_BRANCH; - inst.reloc.pc_rel = 1; + s3_inst.reloc.type = BFD_RELOC_SCORE_BRANCH; + s3_inst.reloc.pc_rel = 1; /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */ - inst.instruction |= (inst.reloc.exp.X_add_number & 0x3fe) | ((inst.reloc.exp.X_add_number & 0xffc00) << 5); + s3_inst.instruction |= (s3_inst.reloc.exp.X_add_number & 0x3fe) | ((s3_inst.reloc.exp.X_add_number & 0xffc00) << 5); /* Compute 16 bit branch instruction. */ - if ((inst.relax_inst != 0x8000) && (abs_value & 0xfffffe00) == 0) + if ((s3_inst.relax_inst != 0x8000) + && (s3_inst.reloc.exp.X_add_number >= -512 && s3_inst.reloc.exp.X_add_number <= 511)) { - inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 8); - inst.relax_inst |= ((inst.reloc.exp.X_add_number >> 1) & 0xff); - inst.relax_size = 2; + s3_inst.relax_inst |= ((s3_inst.reloc.exp.X_add_number >> 1) & 0x1ff);/*b! :disp 9 bit */ + s3_inst.relax_size = 2; } else { - inst.relax_inst = 0x8000; + s3_inst.relax_inst = 0x8000; } } static void -do16_branch (char *str) +s3_do16_branch (char *str) { - if ((my_get_expression (&inst.reloc.exp, &str) == (int) FAIL - || end_of_line (str) == (int) FAIL)) + if ((s3_my_get_expression (&s3_inst.reloc.exp, &str) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL)) { ; } - else if (inst.reloc.exp.X_add_symbol == 0) + else if (s3_inst.reloc.exp.X_add_symbol == 0) { - inst.error = _("lacking label"); + s3_inst.error = _("lacking label"); } - else if (((inst.reloc.exp.X_add_number & 0xffffff00) != 0) - && ((inst.reloc.exp.X_add_number & 0xffffff00) != 0xffffff00)) + else if (!(s3_inst.reloc.exp.X_add_number >= -512 + && s3_inst.reloc.exp.X_add_number <= 511)) { - inst.error = _("invalid constant: 9 bit expression not in range -2^8..2^8"); + s3_inst.error = _("invalid constant: 10 bit expression not in range [-2^9, 2^9-1]"); } else { - inst.reloc.type = BFD_RELOC_SCORE16_BRANCH; - inst.reloc.pc_rel = 1; - inst.instruction |= ((inst.reloc.exp.X_add_number >> 1) & 0xff); + s3_inst.reloc.type = BFD_RELOC_SCORE16_BRANCH; + s3_inst.reloc.pc_rel = 1; + s3_inst.instruction |= ((s3_inst.reloc.exp.X_add_number >> 1) & 0x1ff); + s3_inst.relax_inst |= ((s3_inst.reloc.exp.X_add_number ) & 0x1ff); + s3_inst.relax_size = 4; } } -/* Iterate over the base tables to create the instruction patterns. */ -static void -build_score_ops_hsh (void) +/* Return true if the given symbol should be considered local for s3_PIC. */ +static bfd_boolean +s3_pic_need_relax (symbolS *sym, asection *segtype) { - unsigned int i; - static struct obstack insn_obstack; + asection *symsec; + bfd_boolean linkonce; - obstack_begin (&insn_obstack, 4000); - for (i = 0; i < sizeof (score_insns) / sizeof (struct asm_opcode); i++) + /* Handle the case of a symbol equated to another symbol. */ + while (symbol_equated_reloc_p (sym)) { - const struct asm_opcode *insn = score_insns + i; - unsigned len = strlen (insn->template); - struct asm_opcode *new; - char *template; - new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode)); - template = obstack_alloc (&insn_obstack, len + 1); + symbolS *n; - strcpy (template, insn->template); - new->template = template; - new->parms = insn->parms; - new->value = insn->value; - new->relax_value = insn->relax_value; - new->type = insn->type; - new->bitmask = insn->bitmask; - hash_insert (score_ops_hsh, new->template, (void *) new); + /* It's possible to get a loop here in a badly written + program. */ + n = symbol_get_value_expression (sym)->X_add_symbol; + if (n == sym) + break; + sym = n; } -} -static void -build_dependency_insn_hsh (void) -{ - unsigned int i; - static struct obstack dependency_obstack; + symsec = S_GET_SEGMENT (sym); - obstack_begin (&dependency_obstack, 4000); - for (i = 0; i < sizeof (insn_to_dependency_table) / sizeof (insn_to_dependency_table[0]); i++) + /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */ + linkonce = FALSE; + if (symsec != segtype && ! S_IS_LOCAL (sym)) { - const struct insn_to_dependency *tmp = insn_to_dependency_table + i; - unsigned len = strlen (tmp->insn_name); - struct insn_to_dependency *new; - - new = obstack_alloc (&dependency_obstack, sizeof (struct insn_to_dependency)); - new->insn_name = obstack_alloc (&dependency_obstack, len + 1); + if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE) != 0) + linkonce = TRUE; - strcpy (new->insn_name, tmp->insn_name); - new->type = tmp->type; - hash_insert (dependency_insn_hsh, new->insn_name, (void *) new); + /* The GNU toolchain uses an extension for ELF: a section + beginning with the magic string .gnu.linkonce is a linkonce + section. */ + if (strncmp (segment_name (symsec), ".gnu.linkonce", + sizeof ".gnu.linkonce" - 1) == 0) + linkonce = TRUE; } -} -/* Turn an integer of n bytes (in val) into a stream of bytes appropriate - for use in the a.out file, and stores them in the array pointed to by buf. - This knows about the endian-ness of the target machine and does - THE RIGHT THING, whatever it is. Possible values for n are 1 (byte) - 2 (short) and 4 (long) Floating numbers are put out as a series of - LITTLENUMS (shorts, here at least). */ + /* This must duplicate the test in adjust_reloc_syms. */ + return (symsec != &bfd_und_section + && symsec != &bfd_abs_section + && ! bfd_is_com_section (symsec) + && !linkonce +#ifdef OBJ_ELF + /* A global or weak symbol is treated as external. */ + && (OUTPUT_FLAVOR != bfd_target_elf_flavour + || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym))) +#endif + ); +} -void -md_number_to_chars (char *buf, valueT val, int n) +static void +s3_parse_pce_inst (char *insnstr) { - if (target_big_endian) - number_to_chars_bigendian (buf, val, n); - else - number_to_chars_littleendian (buf, val, n); -} + char c; + char *p; + char first[s3_MAX_LITERAL_POOL_SIZE]; + char second[s3_MAX_LITERAL_POOL_SIZE]; + struct s3_score_it pec_part_1; -static valueT -md_chars_to_number (char *buf, int n) -{ - valueT result = 0; - unsigned char *where = (unsigned char *)buf; + /* Get first part string of PCE. */ + p = strstr (insnstr, "||"); + c = *p; + *p = '\0'; + sprintf (first, "%s", insnstr); - if (target_big_endian) - { - while (n--) - { - result <<= 8; - result |= (*where++ & 255); - } - } - else + /* Get second part string of PCE. */ + *p = c; + p += 2; + sprintf (second, "%s", p); + + s3_parse_16_32_inst (first, FALSE); + if (s3_inst.error) + return; + + memcpy (&pec_part_1, &s3_inst, sizeof (s3_inst)); + + s3_parse_16_32_inst (second, FALSE); + if (s3_inst.error) + return; + + if ( ((pec_part_1.size == s3_INSN_SIZE) && (s3_inst.size == s3_INSN_SIZE)) + || ((pec_part_1.size == s3_INSN_SIZE) && (s3_inst.size == s3_INSN16_SIZE)) + || ((pec_part_1.size == s3_INSN16_SIZE) && (s3_inst.size == s3_INSN_SIZE))) { - while (n--) - { - result <<= 8; - result |= (where[n] & 255); - } + s3_inst.error = _("pce instruction error (16 bit || 16 bit)'"); + sprintf (s3_inst.str, insnstr); + return; } - return result; -} - -char * -md_atof (int type, char *litP, int *sizeP) -{ - return ieee_md_atof (type, litP, sizeP, target_big_endian); + if (!s3_inst.error) + s3_gen_insn_frag (&pec_part_1, &s3_inst); } -/* Return true if the given symbol should be considered local for PIC. */ - -static bfd_boolean -pic_need_relax (symbolS *sym, asection *segtype) +/* s3: dsp. */ +static void +s3_do16_dsp (char *str) { - asection *symsec; - bfd_boolean linkonce; + int rd = 0; - /* Handle the case of a symbol equated to another symbol. */ - while (symbol_equated_reloc_p (sym)) + /* Check 3d. */ + if (s3_score3d == 0) { - symbolS *n; - - /* It's possible to get a loop here in a badly written - program. */ - n = symbol_get_value_expression (sym)->X_add_symbol; - if (n == sym) - break; - sym = n; + s3_inst.error = _("score3d instruction."); + return; } - symsec = S_GET_SEGMENT (sym); + s3_skip_whitespace (str); - /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */ - linkonce = FALSE; - if (symsec != segtype && ! S_IS_LOCAL (sym)) + if ((rd = s3_reglow_required_here (&str, 0)) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) { - if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE) != 0) - linkonce = TRUE; - - /* The GNU toolchain uses an extension for ELF: a section - beginning with the magic string .gnu.linkonce is a linkonce - section. */ - if (strncmp (segment_name (symsec), ".gnu.linkonce", - sizeof ".gnu.linkonce" - 1) == 0) - linkonce = TRUE; + return; } - - /* This must duplicate the test in adjust_reloc_syms. */ - return (symsec != &bfd_und_section - && symsec != &bfd_abs_section - && ! bfd_is_com_section (symsec) - && !linkonce -#ifdef OBJ_ELF - /* A global or weak symbol is treated as external. */ - && (OUTPUT_FLAVOR != bfd_target_elf_flavour - || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym))) -#endif - ); -} - -static int -judge_size_before_relax (fragS * fragp, asection *sec) -{ - int change = 0; - - if (score_pic == NO_PIC) - change = nopic_need_relax (fragp->fr_symbol, 0); else - change = pic_need_relax (fragp->fr_symbol, sec); - - if (change == 1) { - /* Only at the first time determining whether GP instruction relax should be done, - return the difference between insntruction size and instruction relax size. */ - if (fragp->fr_opcode == NULL) - { - fragp->fr_fix = RELAX_NEW (fragp->fr_subtype); - fragp->fr_opcode = fragp->fr_literal + RELAX_RELOC1 (fragp->fr_subtype); - return RELAX_NEW (fragp->fr_subtype) - RELAX_OLD (fragp->fr_subtype); - } + s3_inst.relax_inst |= rd << 20; + s3_inst.relax_size = 4; } - - return 0; -} - -/* In this function, we determine whether GP instruction should do relaxation, - for the label being against was known now. - Doing this here but not in md_relax_frag() can induce iteration times - in stage of doing relax. */ -int -md_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED) -{ - if ((RELAX_TYPE (fragp->fr_subtype) == Insn_GP) - || (RELAX_TYPE (fragp->fr_subtype) == Insn_PIC)) - return judge_size_before_relax (fragp, sec); - - return 0; } -static int -b32_relax_to_b16 (fragS * fragp) +static void +s3_do16_dsp2 (char *str) { - int grows = 0; - int relaxable_p = 0; - int old; - int new; - int frag_addr = fragp->fr_address + fragp->insn_addr; - - addressT symbol_address = 0; - symbolS *s; - offsetT offset; - unsigned long value; - unsigned long abs_value; - - /* FIXME : here may be able to modify better . - I don't know how to get the fragp's section , - so in relax stage , it may be wrong to calculate the symbol's offset when the frag's section - is different from the symbol's. */ - - old = RELAX_OLD (fragp->fr_subtype); - new = RELAX_NEW (fragp->fr_subtype); - relaxable_p = RELAX_OPT (fragp->fr_subtype); - - s = fragp->fr_symbol; - /* b/bl immediate */ - if (s == NULL) - frag_addr = 0; - else + /* Check 3d. */ + if (s3_score3d == 0) { - if (s->bsym != 0) - symbol_address = (addressT) s->sy_frag->fr_address; + s3_inst.error = _("score3d instruction."); + return; } - value = md_chars_to_number (fragp->fr_literal, INSN_SIZE); - - /* b 32's offset : 20 bit, b 16's tolerate field : 0xff. */ - offset = ((value & 0x3ff0000) >> 6) | (value & 0x3fe); - if ((offset & 0x80000) == 0x80000) - offset |= 0xfff00000; - - abs_value = offset + symbol_address - frag_addr; - if ((abs_value & 0x80000000) == 0x80000000) - abs_value = 0xffffffff - abs_value + 1; + s3_skip_whitespace (str); - /* Relax branch 32 to branch 16. */ - if (relaxable_p && (s->bsym != NULL) && ((abs_value & 0xffffff00) == 0) - && (S_IS_DEFINED (s) && !S_IS_COMMON (s) && !S_IS_EXTERNAL (s))) + if (s3_reglow_required_here (&str, 4) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_reglow_required_here (&str, 0) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) { - /* do nothing. */ + return; } else { - /* Branch 32 can not be relaxed to b 16, so clear OPT bit. */ - fragp->fr_opcode = NULL; - fragp->fr_subtype = RELAX_OPT_CLEAR (fragp->fr_subtype); + s3_inst.relax_inst |= (((s3_inst.instruction >> 8) & 0xf) << 20) + | (((s3_inst.instruction >> 8) & 0xf) << 15) | (((s3_inst.instruction >> 4) & 0xf) << 10); + s3_inst.relax_size = 4; } - - return grows; } -/* Main purpose is to determine whether one frag should do relax. - frag->fr_opcode indicates this point. */ - -int -score_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED) +static void +s3_do_dsp (char *str) { - int grows = 0; - int insn_size; - int insn_relax_size; - int do_relax_p = 0; /* Indicate doing relaxation for this frag. */ - int relaxable_p = 0; - bfd_boolean word_align_p = FALSE; - fragS *next_fragp; - - /* If the instruction address is odd, make it half word align first. */ - if ((fragp->fr_address) % 2 != 0) + /* Check 3d. */ + if (s3_score3d == 0) { - if ((fragp->fr_address + fragp->insn_addr) % 2 != 0) - { - fragp->insn_addr = 1; - grows += 1; - } + s3_inst.error = _("score3d instruction."); + return; } - word_align_p = ((fragp->fr_address + fragp->insn_addr) % 4 == 0) ? TRUE : FALSE; + s3_skip_whitespace (str); + + if (s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) + return; - /* Get instruction size and relax size after the last relaxation. */ - if (fragp->fr_opcode) + if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 20) & 0x1f) == 3) ) { - insn_size = RELAX_NEW (fragp->fr_subtype); - insn_relax_size = RELAX_OLD (fragp->fr_subtype); + s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f)) | (((s3_inst.instruction >> 15) & 0x1f) << 5); + s3_inst.relax_size = 2; } else + s3_inst.relax_inst = 0x8000; +} + +static void +s3_do_dsp2 (char *str) +{ + int reg; + + /* Check 3d. */ + if (s3_score3d == 0) { - insn_size = RELAX_OLD (fragp->fr_subtype); - insn_relax_size = RELAX_NEW (fragp->fr_subtype); + s3_inst.error = _("score3d instruction."); + return; } - /* Handle specially for GP instruction. for, judge_size_before_relax() has already determine - whether the GP instruction should do relax. */ - if ((RELAX_TYPE (fragp->fr_subtype) == Insn_GP) - || (RELAX_TYPE (fragp->fr_subtype) == Insn_PIC)) - { - if (!word_align_p) - { - if (fragp->insn_addr < 2) - { - fragp->insn_addr += 2; - grows += 2; - } - else - { - fragp->insn_addr -= 2; - grows -= 2; - } - } + s3_skip_whitespace (str); - if (fragp->fr_opcode) - fragp->fr_fix = RELAX_NEW (fragp->fr_subtype) + fragp->insn_addr; - else - fragp->fr_fix = RELAX_OLD (fragp->fr_subtype) + fragp->insn_addr; + if ((reg = s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE)) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_reg_required_here (&str, 10, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) + { + return; } else { - if (RELAX_TYPE (fragp->fr_subtype) == PC_DISP19div2) - b32_relax_to_b16 (fragp); - - relaxable_p = RELAX_OPT (fragp->fr_subtype); - next_fragp = fragp->fr_next; - while ((next_fragp) && (next_fragp->fr_type != rs_machine_dependent)) - { - next_fragp = next_fragp->fr_next; - } - - if (next_fragp) - { - int n_insn_size; - int n_relaxable_p = 0; - - if (next_fragp->fr_opcode) - { - n_insn_size = RELAX_NEW (next_fragp->fr_subtype); - } - else - { - n_insn_size = RELAX_OLD (next_fragp->fr_subtype); - } - - if (RELAX_TYPE (next_fragp->fr_subtype) == PC_DISP19div2) - b32_relax_to_b16 (next_fragp); - n_relaxable_p = RELAX_OPT (next_fragp->fr_subtype); - - if (word_align_p) - { - if (insn_size == 4) - { - /* 32 -> 16. */ - if (relaxable_p && ((n_insn_size == 2) || n_relaxable_p)) - { - grows -= 2; - do_relax_p = 1; - } - } - else if (insn_size == 2) - { - /* 16 -> 32. */ - if (relaxable_p && (((n_insn_size == 4) && !n_relaxable_p) || (n_insn_size > 4))) - { - grows += 2; - do_relax_p = 1; - } - } - else - { - abort (); - } - } - else - { - if (insn_size == 4) - { - /* 32 -> 16. */ - if (relaxable_p) - { - grows -= 2; - do_relax_p = 1; - } - /* Make the 32 bit insturction word align. */ - else - { - fragp->insn_addr += 2; - grows += 2; - } - } - else if (insn_size == 2) - { - /* Do nothing. */ - } - else - { - abort (); - } - } - } - else + /* Check mulr, mulur rd is even number. */ + if (((s3_inst.instruction & 0x3e0003ff) == 0x00000340 + || (s3_inst.instruction & 0x3e0003ff) == 0x00000342) + && (reg % 2)) { - /* Here, try best to do relax regardless fragp->fr_next->fr_type. */ - if (word_align_p == FALSE) - { - if (insn_size % 4 == 0) - { - /* 32 -> 16. */ - if (relaxable_p) - { - grows -= 2; - do_relax_p = 1; - } - else - { - fragp->insn_addr += 2; - grows += 2; - } - } - } - else - { - /* Do nothing. */ - } + s3_inst.error = _("rd must be even number."); + return; } - /* fragp->fr_opcode indicates whether this frag should be relaxed. */ - if (do_relax_p) + if ((((s3_inst.instruction >> 15) & 0x10) == 0) + && (((s3_inst.instruction >> 10) & 0x10) == 0) + && (((s3_inst.instruction >> 20) & 0x10) == 0) + && (s3_inst.relax_inst != 0x8000) + && (((s3_inst.instruction >> 20) & 0xf) == ((s3_inst.instruction >> 15) & 0xf))) { - if (fragp->fr_opcode) - { - fragp->fr_opcode = NULL; - /* Guarantee estimate stage is correct. */ - fragp->fr_fix = RELAX_OLD (fragp->fr_subtype); - fragp->fr_fix += fragp->insn_addr; - } - else - { - fragp->fr_opcode = fragp->fr_literal + RELAX_RELOC1 (fragp->fr_subtype); - /* Guarantee estimate stage is correct. */ - fragp->fr_fix = RELAX_NEW (fragp->fr_subtype); - fragp->fr_fix += fragp->insn_addr; - } + s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0xf) ) + | (((s3_inst.instruction >> 15) & 0xf) << 4); + s3_inst.relax_size = 2; } else - { - if (fragp->fr_opcode) - { - /* Guarantee estimate stage is correct. */ - fragp->fr_fix = RELAX_NEW (fragp->fr_subtype); - fragp->fr_fix += fragp->insn_addr; - } - else - { - /* Guarantee estimate stage is correct. */ - fragp->fr_fix = RELAX_OLD (fragp->fr_subtype); - fragp->fr_fix += fragp->insn_addr; - } - } + { + s3_inst.relax_inst = 0x8000; + } } - - return grows; } -void -md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp) +static void +s3_do_dsp3 (char *str) { - int old; - int new; - char backup[20]; - fixS *fixp; + /* Check 3d. */ + if (s3_score3d == 0) + { + s3_inst.error = _("score3d instruction."); + return; + } - old = RELAX_OLD (fragp->fr_subtype); - new = RELAX_NEW (fragp->fr_subtype); + s3_skip_whitespace (str); - /* fragp->fr_opcode indicates whether this frag should be relaxed. */ - if (fragp->fr_opcode == NULL) - { - memcpy (backup, fragp->fr_literal, old); - fragp->fr_fix = old; - } - else - { - memcpy (backup, fragp->fr_literal + old, new); - fragp->fr_fix = new; - } - - fixp = fragp->tc_frag_data.fixp; - while (fixp && fixp->fx_frag == fragp && fixp->fx_where < old) - { - if (fragp->fr_opcode) - fixp->fx_done = 1; - fixp = fixp->fx_next; - } - while (fixp && fixp->fx_frag == fragp) - { - if (fragp->fr_opcode) - fixp->fx_where -= old + fragp->insn_addr; - else - fixp->fx_done = 1; - fixp = fixp->fx_next; - } + if (s3_reg_required_here (&str, 20, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_skip_past_comma (&str) == (int) s3_FAIL + || s3_reg_required_here (&str, 15, s3_REG_TYPE_SCORE) == (int) s3_FAIL + || s3_end_of_line (str) == (int) s3_FAIL) + return; - if (fragp->insn_addr) + if ((s3_inst.relax_inst != 0x8000) && (((s3_inst.instruction >> 20) & 0x1f) == 3) ) { - md_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr); + s3_inst.relax_inst |= (((s3_inst.instruction >> 10) & 0x1f)) | (((s3_inst.instruction >> 15) & 0x1f) << 5); + s3_inst.relax_size = 2; } - memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix); - fragp->fr_fix += fragp->insn_addr; + else + s3_inst.relax_inst = 0x8000; } -/* Implementation of md_frag_check. - Called after md_convert_frag(). */ -void -score_frag_check (fragS * fragp ATTRIBUTE_UNUSED) +/* If we change section we must dump the literal pool first. */ +static void +s3_s_score_bss (int ignore ATTRIBUTE_UNUSED) { - know (fragp->insn_addr <= RELAX_PAD_BYTE); + subseg_set (bss_section, (subsegT) get_absolute_expression ()); + demand_empty_rest_of_line (); } -bfd_boolean -score_fix_adjustable (fixS * fixP) +static void +s3_s_score_text (int ignore) { - if (fixP->fx_addsy == NULL) - { - return 1; - } - else if (OUTPUT_FLAVOR == bfd_target_elf_flavour - && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy))) - { - return 0; - } - else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT - || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY) - { - return 0; - } - - return 1; + obj_elf_text (ignore); + record_alignment (now_seg, 2); } -/* Implementation of TC_VALIDATE_FIX. - Called before md_apply_fix() and after md_convert_frag(). */ -void -score_validate_fix (fixS *fixP) +static void +s3_score_s_section (int ignore) { - fixP->fx_where += fixP->fx_frag->insn_addr; + obj_elf_section (ignore); + if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0) + record_alignment (now_seg, 2); + } -long -md_pcrel_from (fixS * fixP) +static void +s3_s_change_sec (int sec) { - long retval = 0; + segT seg; - if (fixP->fx_addsy - && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section) - && (fixP->fx_subsy == NULL)) - { - retval = 0; - } - else +#ifdef OBJ_ELF + /* The ELF backend needs to know that we are changing sections, so + that .previous works correctly. We could do something like check + for an obj_section_change_hook macro, but that might be confusing + as it would not be appropriate to use it in the section changing + functions in read.c, since obj-elf.c intercepts those. FIXME: + This should be cleaner, somehow. */ + obj_elf_section_change_hook (); +#endif + switch (sec) { - retval = fixP->fx_where + fixP->fx_frag->fr_address; + case 'r': + seg = subseg_new (s3_RDATA_SECTION_NAME, (subsegT) get_absolute_expression ()); + bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA)); + if (strcmp (TARGET_OS, "elf") != 0) + record_alignment (seg, 4); + demand_empty_rest_of_line (); + break; + case 's': + seg = subseg_new (".sdata", (subsegT) get_absolute_expression ()); + bfd_set_section_flags (stdoutput, seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA); + if (strcmp (TARGET_OS, "elf") != 0) + record_alignment (seg, 4); + demand_empty_rest_of_line (); + break; } - - return retval; } -int -score_force_relocation (struct fix *fixp) +static void +s3_s_score_mask (int reg_type ATTRIBUTE_UNUSED) { - int retval = 0; + long mask, off; - if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT - || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY - || fixp->fx_r_type == BFD_RELOC_SCORE_JMP - || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH - || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP - || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH) + if (s3_cur_proc_ptr == (s3_procS *) NULL) { - retval = 1; + as_warn (_(".mask outside of .ent")); + demand_empty_rest_of_line (); + return; } - - return retval; + if (get_absolute_expression_and_terminator (&mask) != ',') + { + as_warn (_("Bad .mask directive")); + --input_line_pointer; + demand_empty_rest_of_line (); + return; + } + off = get_absolute_expression (); + s3_cur_proc_ptr->reg_mask = mask; + s3_cur_proc_ptr->reg_offset = off; + demand_empty_rest_of_line (); } -/* Round up a section size to the appropriate boundary. */ -valueT -md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size) +static symbolS * +s3_get_symbol (void) { - int align = bfd_get_section_alignment (stdoutput, segment); + int c; + char *name; + symbolS *p; - return ((size + (1 << align) - 1) & (-1 << align)); + name = input_line_pointer; + c = get_symbol_end (); + p = (symbolS *) symbol_find_or_make (name); + *input_line_pointer = c; + return p; } -void -md_apply_fix (fixS *fixP, valueT *valP, segT seg) +static long +s3_get_number (void) { - offsetT value = *valP; - offsetT abs_value = 0; - offsetT newval; - offsetT content; - unsigned short HI, LO; - - char *buf = fixP->fx_frag->fr_literal + fixP->fx_where; - - assert (fixP->fx_r_type < BFD_RELOC_UNUSED); - if (fixP->fx_addsy == 0 && !fixP->fx_pcrel) - { - if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16) - fixP->fx_done = 1; - } + int negative = 0; + long val = 0; - /* If this symbol is in a different section then we need to leave it for - the linker to deal with. Unfortunately, md_pcrel_from can't tell, - so we have to undo it's effects here. */ - if (fixP->fx_pcrel) + if (*input_line_pointer == '-') { - if (fixP->fx_addsy != NULL - && S_IS_DEFINED (fixP->fx_addsy) - && S_GET_SEGMENT (fixP->fx_addsy) != seg) - value += md_pcrel_from (fixP); + ++input_line_pointer; + negative = 1; } - - /* Remember value for emit_reloc. */ - fixP->fx_addnumber = value; - - switch (fixP->fx_r_type) + if (!ISDIGIT (*input_line_pointer)) + as_bad (_("expected simple number")); + if (input_line_pointer[0] == '0') { - case BFD_RELOC_HI16_S: - if (fixP->fx_done) - { /* For la rd, imm32. */ - newval = md_chars_to_number (buf, INSN_SIZE); - HI = (value) >> 16; /* mul to 2, then take the hi 16 bit. */ - newval |= (HI & 0x3fff) << 1; - newval |= ((HI >> 14) & 0x3) << 16; - md_number_to_chars (buf, newval, INSN_SIZE); - } - break; - case BFD_RELOC_LO16: - if (fixP->fx_done) /* For la rd, imm32. */ - { - newval = md_chars_to_number (buf, INSN_SIZE); - LO = (value) & 0xffff; - newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi. */ - newval |= ((LO >> 14) & 0x3) << 16; - md_number_to_chars (buf, newval, INSN_SIZE); - } - break; - case BFD_RELOC_SCORE_JMP: - { - content = md_chars_to_number (buf, INSN_SIZE); - value = fixP->fx_offset; - content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff); - md_number_to_chars (buf, content, INSN_SIZE); - } - break; - case BFD_RELOC_SCORE_BRANCH: - if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) - value = fixP->fx_offset; - else - fixP->fx_done = 1; - - content = md_chars_to_number (buf, INSN_SIZE); - if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) != 0x80008000)) + if (input_line_pointer[1] == 'x') { - if ((value & 0x80000000) == 0x80000000) - abs_value = 0xffffffff - value + 1; - if ((abs_value & 0xffffff00) != 0) + input_line_pointer += 2; + while (ISXDIGIT (*input_line_pointer)) { - as_bad_where (fixP->fx_file, fixP->fx_line, - _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int)value); - return; + val <<= 4; + val |= hex_value (*input_line_pointer++); } - content = md_chars_to_number (buf, INSN16_SIZE); - content &= 0xff00; - content = (content & 0xff00) | ((value >> 1) & 0xff); - md_number_to_chars (buf, content, INSN16_SIZE); - fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH; - fixP->fx_size = 2; + return negative ? -val : val; } else { - if ((value & 0x80000000) == 0x80000000) - abs_value = 0xffffffff - value + 1; - if ((abs_value & 0xfff80000) != 0) - { - as_bad_where (fixP->fx_file, fixP->fx_line, - _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value); - return; - } - content = md_chars_to_number (buf, INSN_SIZE); - content &= 0xfc00fc01; - content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000); - md_number_to_chars (buf, content, INSN_SIZE); - } - break; - case BFD_RELOC_SCORE16_JMP: - content = md_chars_to_number (buf, INSN16_SIZE); - content &= 0xf001; - value = fixP->fx_offset & 0xfff; - content = (content & 0xfc01) | (value & 0xffe); - md_number_to_chars (buf, content, INSN16_SIZE); - break; - case BFD_RELOC_SCORE16_BRANCH: - content = md_chars_to_number (buf, INSN_SIZE); - if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) == 0x80008000)) - { - if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || - (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) - value = fixP->fx_offset; - else - fixP->fx_done = 1; - if ((value & 0x80000000) == 0x80000000) - abs_value = 0xffffffff - value + 1; - if ((abs_value & 0xfff80000) != 0) + ++input_line_pointer; + while (ISDIGIT (*input_line_pointer)) { - as_bad_where (fixP->fx_file, fixP->fx_line, - _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value); - return; + val <<= 3; + val |= *input_line_pointer++ - '0'; } - content = md_chars_to_number (buf, INSN_SIZE); - content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000); - md_number_to_chars (buf, content, INSN_SIZE); - fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH; - fixP->fx_size = 4; - break; + return negative ? -val : val; } - else - { - /* In differnt section. */ - if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || - (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) - value = fixP->fx_offset; - else - fixP->fx_done = 1; + } + if (!ISDIGIT (*input_line_pointer)) + { + printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer); + as_warn (_("invalid number")); + return -1; + } + while (ISDIGIT (*input_line_pointer)) + { + val *= 10; + val += *input_line_pointer++ - '0'; + } + return negative ? -val : val; +} + +/* The .aent and .ent directives. */ +static void +s3_s_score_ent (int aent) +{ + symbolS *symbolP; + int maybe_text; + + symbolP = s3_get_symbol (); + if (*input_line_pointer == ',') + ++input_line_pointer; + SKIP_WHITESPACE (); + if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-') + s3_get_number (); + +#ifdef BFD_ASSEMBLER + if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0) + maybe_text = 1; + else + maybe_text = 0; +#else + if (now_seg != data_section && now_seg != bss_section) + maybe_text = 1; + else + maybe_text = 0; +#endif + if (!maybe_text) + as_warn (_(".ent or .aent not in text section.")); + if (!aent && s3_cur_proc_ptr) + as_warn (_("missing .end")); + if (!aent) + { + s3_cur_proc_ptr = &s3_cur_proc; + s3_cur_proc_ptr->reg_mask = 0xdeadbeaf; + s3_cur_proc_ptr->reg_offset = 0xdeadbeaf; + s3_cur_proc_ptr->fpreg_mask = 0xdeafbeaf; + s3_cur_proc_ptr->leaf = 0xdeafbeaf; + s3_cur_proc_ptr->frame_offset = 0xdeafbeaf; + s3_cur_proc_ptr->frame_reg = 0xdeafbeaf; + s3_cur_proc_ptr->pc_reg = 0xdeafbeaf; + s3_cur_proc_ptr->isym = symbolP; + symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION; + ++s3_numprocs; + if (debug_type == DEBUG_STABS) + stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP)); + } + demand_empty_rest_of_line (); +} + +static void +s3_s_score_frame (int ignore ATTRIBUTE_UNUSED) +{ + char *backupstr; + char str[30]; + long val; + int i = 0; + + backupstr = input_line_pointer; + +#ifdef OBJ_ELF + if (s3_cur_proc_ptr == (s3_procS *) NULL) + { + as_warn (_(".frame outside of .ent")); + demand_empty_rest_of_line (); + return; + } + s3_cur_proc_ptr->frame_reg = s3_reg_required_here ((&backupstr), 0, s3_REG_TYPE_SCORE); + SKIP_WHITESPACE (); + s3_skip_past_comma (&backupstr); + while (*backupstr != ',') + { + str[i] = *backupstr; + i++; + backupstr++; + } + str[i] = '\0'; + val = atoi (str); + + SKIP_WHITESPACE (); + s3_skip_past_comma (&backupstr); + s3_cur_proc_ptr->frame_offset = val; + s3_cur_proc_ptr->pc_reg = s3_reg_required_here ((&backupstr), 0, s3_REG_TYPE_SCORE); + + SKIP_WHITESPACE (); + s3_skip_past_comma (&backupstr); + i = 0; + while (*backupstr != '\n') + { + str[i] = *backupstr; + i++; + backupstr++; + } + str[i] = '\0'; + val = atoi (str); + s3_cur_proc_ptr->leaf = val; + SKIP_WHITESPACE (); + s3_skip_past_comma (&backupstr); + +#endif /* OBJ_ELF */ + while (input_line_pointer != backupstr) + input_line_pointer++; +} + +/* The .end directive. */ +static void +s3_s_score_end (int x ATTRIBUTE_UNUSED) +{ + symbolS *p; + int maybe_text; + + /* Generate a .pdr section. */ + segT saved_seg = now_seg; + subsegT saved_subseg = now_subseg; + valueT dot; + expressionS exp; + char *fragp; + + if (!is_end_of_line[(unsigned char)*input_line_pointer]) + { + p = s3_get_symbol (); + demand_empty_rest_of_line (); + } + else + p = NULL; + +#ifdef BFD_ASSEMBLER + if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0) + maybe_text = 1; + else + maybe_text = 0; +#else + if (now_seg != data_section && now_seg != bss_section) + maybe_text = 1; + else + maybe_text = 0; +#endif + + if (!maybe_text) + as_warn (_(".end not in text section")); + if (!s3_cur_proc_ptr) + { + as_warn (_(".end directive without a preceding .ent directive.")); + demand_empty_rest_of_line (); + return; + } + if (p != NULL) + { + assert (S_GET_NAME (p)); + if (strcmp (S_GET_NAME (p), S_GET_NAME (s3_cur_proc_ptr->isym))) + as_warn (_(".end symbol does not match .ent symbol.")); + if (debug_type == DEBUG_STABS) + stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p)); + } + else + as_warn (_(".end directive missing or unknown symbol")); + + if ((s3_cur_proc_ptr->reg_mask == 0xdeadbeaf) || + (s3_cur_proc_ptr->reg_offset == 0xdeadbeaf) || + (s3_cur_proc_ptr->leaf == 0xdeafbeaf) || + (s3_cur_proc_ptr->frame_offset == 0xdeafbeaf) || + (s3_cur_proc_ptr->frame_reg == 0xdeafbeaf) || (s3_cur_proc_ptr->pc_reg == 0xdeafbeaf)); + + else + { + dot = frag_now_fix (); + assert (s3_pdr_seg); + subseg_set (s3_pdr_seg, 0); + /* Write the symbol. */ + exp.X_op = O_symbol; + exp.X_add_symbol = p; + exp.X_add_number = 0; + emit_expr (&exp, 4); + fragp = frag_more (7 * 4); + md_number_to_chars (fragp, (valueT) s3_cur_proc_ptr->reg_mask, 4); + md_number_to_chars (fragp + 4, (valueT) s3_cur_proc_ptr->reg_offset, 4); + md_number_to_chars (fragp + 8, (valueT) s3_cur_proc_ptr->fpreg_mask, 4); + md_number_to_chars (fragp + 12, (valueT) s3_cur_proc_ptr->leaf, 4); + md_number_to_chars (fragp + 16, (valueT) s3_cur_proc_ptr->frame_offset, 4); + md_number_to_chars (fragp + 20, (valueT) s3_cur_proc_ptr->frame_reg, 4); + md_number_to_chars (fragp + 24, (valueT) s3_cur_proc_ptr->pc_reg, 4); + subseg_set (saved_seg, saved_subseg); + + } + s3_cur_proc_ptr = NULL; +} + +/* Handle the .set pseudo-op. */ +static void +s3_s_score_set (int x ATTRIBUTE_UNUSED) +{ + int i = 0; + char name[s3_MAX_LITERAL_POOL_SIZE]; + char * orig_ilp = input_line_pointer; + + while (!is_end_of_line[(unsigned char)*input_line_pointer]) + { + name[i] = (char) * input_line_pointer; + i++; + ++input_line_pointer; + } + + name[i] = '\0'; + + if (strcmp (name, "nwarn") == 0) + { + s3_warn_fix_data_dependency = 0; + } + else if (strcmp (name, "fixdd") == 0) + { + s3_fix_data_dependency = 1; + } + else if (strcmp (name, "nofixdd") == 0) + { + s3_fix_data_dependency = 0; + } + else if (strcmp (name, "r1") == 0) + { + s3_nor1 = 0; + } + else if (strcmp (name, "nor1") == 0) + { + s3_nor1 = 1; + } + else if (strcmp (name, "optimize") == 0) + { + s3_g_opt = 1; + } + else if (strcmp (name, "volatile") == 0) + { + s3_g_opt = 0; + } + else if (strcmp (name, "pic") == 0) + { + s3_score_pic = s3_PIC; + } + else + { + input_line_pointer = orig_ilp; + s_set (0); + } +} + +/* Handle the .cpload pseudo-op. This is used when generating s3_PIC code. It sets the + $gp register for the function based on the function address, which is in the register + named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled + specially by the linker. The result is: + ldis gp, %hi(GP_DISP_LABEL) + ori gp, %low(GP_DISP_LABEL) + add gp, gp, .cpload argument + The .cpload argument is normally r29. */ +static void +s3_s_score_cpload (int ignore ATTRIBUTE_UNUSED) +{ + int reg; + char insn_str[s3_MAX_LITERAL_POOL_SIZE]; + + /* If we are not generating s3_PIC code, .cpload is ignored. */ + if (s3_score_pic == s3_NO_PIC) + { + s_ignore (0); + return; + } + + if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) + return; + + demand_empty_rest_of_line (); + + sprintf (insn_str, "ld_i32hi r%d, %s", s3_GP, GP_DISP_LABEL); + if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL) + return; + + sprintf (insn_str, "ld_i32lo r%d, %s", s3_GP, GP_DISP_LABEL); + if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL) + return; + + sprintf (insn_str, "add r%d, r%d, r%d", s3_GP, s3_GP, reg); + if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL) + return; +} + +/* Handle the .cprestore pseudo-op. This stores $gp into a given + offset from $sp. The offset is remembered, and after making a s3_PIC + call $gp is restored from that location. */ +static void +s3_s_score_cprestore (int ignore ATTRIBUTE_UNUSED) +{ + int reg; + int cprestore_offset; + char insn_str[s3_MAX_LITERAL_POOL_SIZE]; + + /* If we are not generating s3_PIC code, .cprestore is ignored. */ + if (s3_score_pic == s3_NO_PIC) + { + s_ignore (0); + return; + } + + if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL + || s3_skip_past_comma (&input_line_pointer) == (int) s3_FAIL) + { + return; + } + + cprestore_offset = get_absolute_expression (); + + if (cprestore_offset <= 0x3fff) + { + sprintf (insn_str, "sw r%d, [r%d, %d]", s3_GP, reg, cprestore_offset); + if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL) + return; + } + else + { + int r1_bak; + + r1_bak = s3_nor1; + s3_nor1 = 0; + + sprintf (insn_str, "li r1, %d", cprestore_offset); + if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL) + return; + + sprintf (insn_str, "add r1, r1, r%d", reg); + if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL) + return; + + sprintf (insn_str, "sw r%d, [r1]", s3_GP); + if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL) + return; + + s3_nor1 = r1_bak; + } + + demand_empty_rest_of_line (); +} + +/* Handle the .gpword pseudo-op. This is used when generating s3_PIC + code. It generates a 32 bit s3_GP relative reloc. */ +static void +s3_s_score_gpword (int ignore ATTRIBUTE_UNUSED) +{ + expressionS ex; + char *p; + + /* When not generating s3_PIC code, this is treated as .word. */ + if (s3_score_pic == s3_NO_PIC) + { + cons (4); + return; + } + expression (&ex); + if (ex.X_op != O_symbol || ex.X_add_number != 0) + { + as_bad (_("Unsupported use of .gpword")); + ignore_rest_of_line (); + } + p = frag_more (4); + s3_md_number_to_chars (p, (valueT) 0, 4); + fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32); + demand_empty_rest_of_line (); +} + +/* Handle the .cpadd pseudo-op. This is used when dealing with switch + tables in s3_PIC code. */ +static void +s3_s_score_cpadd (int ignore ATTRIBUTE_UNUSED) +{ + int reg; + char insn_str[s3_MAX_LITERAL_POOL_SIZE]; + + /* If we are not generating s3_PIC code, .cpload is ignored. */ + if (s3_score_pic == s3_NO_PIC) + { + s_ignore (0); + return; + } + + if ((reg = s3_reg_required_here (&input_line_pointer, -1, s3_REG_TYPE_SCORE)) == (int) s3_FAIL) + { + return; + } + demand_empty_rest_of_line (); + + /* Add $gp to the register named as an argument. */ + sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, s3_GP); + if (s3_append_insn (insn_str, TRUE) == (int) s3_FAIL) + return; +} + +#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT +#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \ + do \ + { \ + if ((SIZE) >= 8) \ + (P2VAR) = 3; \ + else if ((SIZE) >= 4) \ + (P2VAR) = 2; \ + else if ((SIZE) >= 2) \ + (P2VAR) = 1; \ + else \ + (P2VAR) = 0; \ + } \ + while (0) +#endif - if ((value & 0x80000000) == 0x80000000) - abs_value = 0xffffffff - value + 1; - if ((abs_value & 0xffffff00) != 0) - { - as_bad_where (fixP->fx_file, fixP->fx_line, - _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int)value); - return; - } - content = md_chars_to_number (buf, INSN16_SIZE); - content = (content & 0xff00) | ((value >> 1) & 0xff); - md_number_to_chars (buf, content, INSN16_SIZE); - break; - } - case BFD_RELOC_8: - if (fixP->fx_done || fixP->fx_pcrel) - md_number_to_chars (buf, value, 1); -#ifdef OBJ_ELF - else +static void +s3_s_score_lcomm (int bytes_p) +{ + char *name; + char c; + char *p; + int temp; + symbolS *symbolP; + segT current_seg = now_seg; + subsegT current_subseg = now_subseg; + const int max_alignment = 15; + int align = 0; + segT bss_seg = bss_section; + int needs_align = 0; + + name = input_line_pointer; + c = get_symbol_end (); + p = input_line_pointer; + *p = c; + + if (name == p) + { + as_bad (_("expected symbol name")); + discard_rest_of_line (); + return; + } + + SKIP_WHITESPACE (); + + /* Accept an optional comma after the name. The comma used to be + required, but Irix 5 cc does not generate it. */ + if (*input_line_pointer == ',') + { + ++input_line_pointer; + SKIP_WHITESPACE (); + } + + if (is_end_of_line[(unsigned char)*input_line_pointer]) + { + as_bad (_("missing size expression")); + return; + } + + if ((temp = get_absolute_expression ()) < 0) + { + as_warn (_("BSS length (%d) < 0 ignored"), temp); + ignore_rest_of_line (); + return; + } + +#if defined (TC_SCORE) + if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour) + { + /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss. */ + if ((unsigned)temp <= bfd_get_gp_size (stdoutput)) { - value = fixP->fx_offset; - md_number_to_chars (buf, value, 1); + bss_seg = subseg_new (".sbss", 1); + seg_info (bss_seg)->bss = 1; +#ifdef BFD_ASSEMBLER + if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC)) + as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ())); +#endif } + } #endif - break; - case BFD_RELOC_16: - if (fixP->fx_done || fixP->fx_pcrel) - md_number_to_chars (buf, value, 2); -#ifdef OBJ_ELF - else + SKIP_WHITESPACE (); + if (*input_line_pointer == ',') + { + ++input_line_pointer; + SKIP_WHITESPACE (); + + if (is_end_of_line[(unsigned char)*input_line_pointer]) { - value = fixP->fx_offset; - md_number_to_chars (buf, value, 2); + as_bad (_("missing alignment")); + return; } -#endif - break; - case BFD_RELOC_RVA: - case BFD_RELOC_32: - if (fixP->fx_done || fixP->fx_pcrel) - md_number_to_chars (buf, value, 4); -#ifdef OBJ_ELF else { - value = fixP->fx_offset; - md_number_to_chars (buf, value, 4); + align = get_absolute_expression (); + needs_align = 1; } -#endif - break; - case BFD_RELOC_VTABLE_INHERIT: - fixP->fx_done = 0; - if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy)) - S_SET_WEAK (fixP->fx_addsy); - break; - case BFD_RELOC_VTABLE_ENTRY: - fixP->fx_done = 0; - break; - case BFD_RELOC_SCORE_GPREL15: - content = md_chars_to_number (buf, INSN_SIZE); - if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94188000)) - fixP->fx_r_type = BFD_RELOC_NONE; - fixP->fx_done = 0; - break; - case BFD_RELOC_SCORE_GOT15: - case BFD_RELOC_SCORE_DUMMY_HI16: - case BFD_RELOC_SCORE_GOT_LO16: - case BFD_RELOC_SCORE_CALL15: - case BFD_RELOC_GPREL32: - break; - case BFD_RELOC_NONE: - default: - as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type); } -} -/* Translate internal representation of relocation info to BFD target format. */ -arelent ** -tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp) -{ - static arelent *retval[MAX_RELOC_EXPANSION + 1]; /* MAX_RELOC_EXPANSION equals 2. */ - arelent *reloc; - bfd_reloc_code_real_type code; - char *type; - fragS *f; - symbolS *s; - expressionS e; + if (!needs_align) + { + TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align); - reloc = retval[0] = xmalloc (sizeof (arelent)); - retval[1] = NULL; + /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it. */ + if (align) + record_alignment (bss_seg, align); + } - reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); - *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); - reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; - reloc->addend = fixp->fx_offset; + if (needs_align) + { + if (bytes_p) + { + /* Convert to a power of 2. */ + if (align != 0) + { + unsigned int i; - /* If this is a variant frag, we may need to adjust the existing - reloc and generate a new one. */ - if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15)) + for (i = 0; align != 0; align >>= 1, ++i) + ; + align = i - 1; + } + } + + if (align > max_alignment) + { + align = max_alignment; + as_warn (_("alignment too large; %d assumed"), align); + } + else if (align < 0) + { + align = 0; + as_warn (_("alignment negative; 0 assumed")); + } + + record_alignment (bss_seg, align); + } + else { - /* Update instruction imm bit. */ - offsetT newval; - unsigned short off; - char *buf; + /* Assume some objects may require alignment on some systems. */ +#if defined (TC_ALPHA) && ! defined (VMS) + if (temp > 1) + { + align = ffs (temp) - 1; + if (temp % (1 << align)) + abort (); + } +#endif + } - buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr; - newval = md_chars_to_number (buf, INSN_SIZE); - off = fixp->fx_offset >> 16; - newval |= (off & 0x3fff) << 1; - newval |= ((off >> 14) & 0x3) << 16; - md_number_to_chars (buf, newval, INSN_SIZE); + *p = 0; + symbolP = symbol_find_or_make (name); + *p = c; - buf += INSN_SIZE; - newval = md_chars_to_number (buf, INSN_SIZE); - off = fixp->fx_offset & 0xffff; - newval |= ((off & 0x3fff) << 1); - newval |= (((off >> 14) & 0x3) << 16); - md_number_to_chars (buf, newval, INSN_SIZE); + if ( +#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \ + || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT)) +#ifdef BFD_ASSEMBLER + (OUTPUT_FLAVOR != bfd_target_aout_flavour + || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) && +#else + (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) && +#endif +#endif + (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0))) + { + char *pfrag; - retval[1] = xmalloc (sizeof (arelent)); - retval[2] = NULL; - retval[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); - *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); - retval[1]->address = (reloc->address + RELAX_RELOC2 (fixp->fx_frag->fr_subtype)); + subseg_set (bss_seg, 1); - f = fixp->fx_frag; - s = f->fr_symbol; - e = s->sy_value; + if (align) + frag_align (align, 0, 0); - retval[1]->addend = 0; - retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16); - assert (retval[1]->howto != NULL); + /* Detach from old frag. */ + if (S_GET_SEGMENT (symbolP) == bss_seg) + symbol_get_frag (symbolP)->fr_symbol = NULL; - fixp->fx_r_type = BFD_RELOC_HI16_S; - } + symbol_set_frag (symbolP, frag_now); + pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL); + *pfrag = 0; - code = fixp->fx_r_type; - switch (fixp->fx_r_type) - { - case BFD_RELOC_32: - if (fixp->fx_pcrel) + + S_SET_SEGMENT (symbolP, bss_seg); + +#ifdef OBJ_COFF + /* The symbol may already have been created with a preceding + ".globl" directive -- be careful not to step on storage class + in that case. Otherwise, set it to static. */ + if (S_GET_STORAGE_CLASS (symbolP) != C_EXT) { - code = BFD_RELOC_32_PCREL; - break; + S_SET_STORAGE_CLASS (symbolP, C_STAT); } - case BFD_RELOC_HI16_S: - case BFD_RELOC_LO16: - case BFD_RELOC_SCORE_JMP: - case BFD_RELOC_SCORE_BRANCH: - case BFD_RELOC_SCORE16_JMP: - case BFD_RELOC_SCORE16_BRANCH: - case BFD_RELOC_VTABLE_ENTRY: - case BFD_RELOC_VTABLE_INHERIT: - case BFD_RELOC_SCORE_GPREL15: - case BFD_RELOC_SCORE_GOT15: - case BFD_RELOC_SCORE_DUMMY_HI16: - case BFD_RELOC_SCORE_GOT_LO16: - case BFD_RELOC_SCORE_CALL15: - case BFD_RELOC_GPREL32: - case BFD_RELOC_NONE: - code = fixp->fx_r_type; - break; - default: - type = _(""); - as_bad_where (fixp->fx_file, fixp->fx_line, - _("cannot represent %s relocation in this object file format"), type); - return NULL; +#endif /* OBJ_COFF */ + +#ifdef S_SET_SIZE + S_SET_SIZE (symbolP, temp); +#endif } + else + as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP)); - reloc->howto = bfd_reloc_type_lookup (stdoutput, code); - if (reloc->howto == NULL) + subseg_set (current_seg, current_subseg); + + demand_empty_rest_of_line (); +} + +static void +s3_insert_reg (const struct s3_reg_entry *r, struct hash_control *htab) +{ + int i = 0; + int len = strlen (r->name) + 2; + char *buf = xmalloc (len); + char *buf2 = xmalloc (len); + + strcpy (buf + i, r->name); + for (i = 0; buf[i]; i++) { - as_bad_where (fixp->fx_file, fixp->fx_line, - _("cannot represent %s relocation in this object file format1"), - bfd_get_reloc_code_name (code)); - return NULL; + buf2[i] = TOUPPER (buf[i]); } - /* HACK: Since arm ELF uses Rel instead of Rela, encode the - vtable entry to be used in the relocation's section offset. */ - if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) - reloc->address = fixp->fx_offset; + buf2[i] = '\0'; - return retval; + hash_insert (htab, buf, (void *) r); + hash_insert (htab, buf2, (void *) r); } -void -score_elf_final_processing (void) +static void +s3_build_reg_hsh (struct s3_reg_map *map) { - if (fix_data_dependency == 1) + const struct s3_reg_entry *r; + + if ((map->htab = hash_new ()) == NULL) { - elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP; + as_fatal (_("virtual memory exhausted")); } - if (score_pic == PIC) + for (r = map->names; r->name != NULL; r++) { - elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC; + s3_insert_reg (r, map->htab); } } +/* Iterate over the base tables to create the instruction patterns. */ static void -parse_pce_inst (char *insnstr) +s3_build_score_ops_hsh (void) { - char c; - char *p; - char first[MAX_LITERAL_POOL_SIZE]; - char second[MAX_LITERAL_POOL_SIZE]; - struct score_it pec_part_1; + unsigned int i; + static struct obstack insn_obstack; - /* Get first part string of PCE. */ - p = strstr (insnstr, "||"); - c = *p; - *p = '\0'; - sprintf (first, "%s", insnstr); + obstack_begin (&insn_obstack, 4000); + for (i = 0; i < sizeof (s3_score_insns) / sizeof (struct s3_asm_opcode); i++) + { + const struct s3_asm_opcode *insn = s3_score_insns + i; + unsigned len = strlen (insn->template); + struct s3_asm_opcode *new; + char *template; + new = obstack_alloc (&insn_obstack, sizeof (struct s3_asm_opcode)); + template = obstack_alloc (&insn_obstack, len + 1); - /* Get second part string of PCE. */ - *p = c; - p += 2; - sprintf (second, "%s", p); + strcpy (template, insn->template); + new->template = template; + new->parms = insn->parms; + new->value = insn->value; + new->relax_value = insn->relax_value; + new->type = insn->type; + new->bitmask = insn->bitmask; + hash_insert (s3_score_ops_hsh, new->template, (void *) new); + } +} - parse_16_32_inst (first, FALSE); - if (inst.error) - return; +static void +s3_build_dependency_insn_hsh (void) +{ + unsigned int i; + static struct obstack dependency_obstack; - memcpy (&pec_part_1, &inst, sizeof (inst)); + obstack_begin (&dependency_obstack, 4000); + for (i = 0; i < sizeof (s3_insn_to_dependency_table) / sizeof (s3_insn_to_dependency_table[0]); i++) + { + const struct s3_insn_to_dependency *tmp = s3_insn_to_dependency_table + i; + unsigned len = strlen (tmp->insn_name); + struct s3_insn_to_dependency *new; - parse_16_32_inst (second, FALSE); - if (inst.error) - return; + new = obstack_alloc (&dependency_obstack, sizeof (struct s3_insn_to_dependency)); + new->insn_name = obstack_alloc (&dependency_obstack, len + 1); - if ( ((pec_part_1.size == INSN_SIZE) && (inst.size == INSN_SIZE)) - || ((pec_part_1.size == INSN_SIZE) && (inst.size == INSN16_SIZE)) - || ((pec_part_1.size == INSN16_SIZE) && (inst.size == INSN_SIZE))) - { - inst.error = _("pce instruction error (16 bit || 16 bit)'"); - sprintf (inst.str, insnstr); - return; + strcpy (new->insn_name, tmp->insn_name); + new->type = tmp->type; + hash_insert (s3_dependency_insn_hsh, new->insn_name, (void *) new); } +} - if (!inst.error) - gen_insn_frag (&pec_part_1, &inst); +static void +s_score_bss (int ignore ATTRIBUTE_UNUSED) +{ + if (score3) + return s3_s_score_bss (ignore); + else + return s7_s_score_bss (ignore); } -void -md_assemble (char *str) +static void +s_score_text (int ignore) { - know (str); - know (strlen (str) < MAX_LITERAL_POOL_SIZE); + if (score3) + return s3_s_score_text (ignore); + else + return s7_s_score_text (ignore); +} + +static void +s_section (int ignore) +{ + if (score3) + return s3_score_s_section (ignore); + else + return s7_s_section (ignore); +} - memset (&inst, '\0', sizeof (inst)); - if (INSN_IS_PCE_P (str)) - parse_pce_inst (str); +static void +s_change_sec (int sec) +{ + if (score3) + return s3_s_change_sec (sec); else - parse_16_32_inst (str, TRUE); + return s7_s_change_sec (sec); +} - if (inst.error) - as_bad (_("%s -- `%s'"), inst.error, inst.str); +static void +s_score_mask (int reg_type ATTRIBUTE_UNUSED) +{ + if (score3) + return s3_s_score_mask (reg_type); + else + return s7_s_score_mask (reg_type); } -/* We handle all bad expressions here, so that we can report the faulty - instruction in the error message. */ -void -md_operand (expressionS * expr) +static void +s_score_ent (int aent) { - if (in_my_get_expression) - { - expr->X_op = O_illegal; - if (inst.error == NULL) - { - inst.error = _("bad expression"); - } - } + if (score3) + return s3_s_score_ent (aent); + else + return s7_s_score_ent (aent); } -const char *md_shortopts = "nO::g::G:"; +static void +s_score_frame (int ignore ATTRIBUTE_UNUSED) +{ + if (score3) + return s3_s_score_frame (ignore); + else + return s7_s_score_frame (ignore); +} -#ifdef SCORE_BI_ENDIAN -#define OPTION_EB (OPTION_MD_BASE + 0) -#define OPTION_EL (OPTION_MD_BASE + 1) -#else -#if TARGET_BYTES_BIG_ENDIAN -#define OPTION_EB (OPTION_MD_BASE + 0) -#else -#define OPTION_EL (OPTION_MD_BASE + 1) -#endif -#endif -#define OPTION_FIXDD (OPTION_MD_BASE + 2) -#define OPTION_NWARN (OPTION_MD_BASE + 3) -#define OPTION_SCORE5 (OPTION_MD_BASE + 4) -#define OPTION_SCORE5U (OPTION_MD_BASE + 5) -#define OPTION_SCORE7 (OPTION_MD_BASE + 6) -#define OPTION_R1 (OPTION_MD_BASE + 7) -#define OPTION_O0 (OPTION_MD_BASE + 8) -#define OPTION_SCORE_VERSION (OPTION_MD_BASE + 9) -#define OPTION_PIC (OPTION_MD_BASE + 10) +static void +s_score_end (int x ATTRIBUTE_UNUSED) +{ + if (score3) + return s3_s_score_end (x); + else + return s7_s_score_end (x); +} -struct option md_longopts[] = +static void +s_score_set (int x ATTRIBUTE_UNUSED) { -#ifdef OPTION_EB - {"EB" , no_argument, NULL, OPTION_EB}, -#endif -#ifdef OPTION_EL - {"EL" , no_argument, NULL, OPTION_EL}, -#endif - {"FIXDD" , no_argument, NULL, OPTION_FIXDD}, - {"NWARN" , no_argument, NULL, OPTION_NWARN}, - {"SCORE5" , no_argument, NULL, OPTION_SCORE5}, - {"SCORE5U", no_argument, NULL, OPTION_SCORE5U}, - {"SCORE7" , no_argument, NULL, OPTION_SCORE7}, - {"USE_R1" , no_argument, NULL, OPTION_R1}, - {"O0" , no_argument, NULL, OPTION_O0}, - {"V" , no_argument, NULL, OPTION_SCORE_VERSION}, - {"KPIC" , no_argument, NULL, OPTION_PIC}, - {NULL , no_argument, NULL, 0} -}; + if (score3) + return s3_s_score_set (x); + else + return s7_s_score_set (x); +} -size_t md_longopts_size = sizeof (md_longopts); +static void +s_score_cpload (int ignore ATTRIBUTE_UNUSED) +{ + if (score3) + return s3_s_score_cpload (ignore); + else + return s7_s_score_cpload (ignore); +} -int -md_parse_option (int c, char *arg) +static void +s_score_cprestore (int ignore ATTRIBUTE_UNUSED) { - switch (c) - { -#ifdef OPTION_EB - case OPTION_EB: - target_big_endian = 1; - break; -#endif -#ifdef OPTION_EL - case OPTION_EL: - target_big_endian = 0; - break; -#endif - case OPTION_FIXDD: - fix_data_dependency = 1; - break; - case OPTION_NWARN: - warn_fix_data_dependency = 0; - break; - case OPTION_SCORE5: - score7 = 0; - university_version = 0; - vector_size = SCORE5_PIPELINE; - break; - case OPTION_SCORE5U: - score7 = 0; - university_version = 1; - vector_size = SCORE5_PIPELINE; - break; - case OPTION_SCORE7: - score7 = 1; - university_version = 0; - vector_size = SCORE7_PIPELINE; - break; - case OPTION_R1: - nor1 = 0; - break; - case 'G': - g_switch_value = atoi (arg); - break; - case OPTION_O0: - g_opt = 0; - break; - case OPTION_SCORE_VERSION: - printf (_("Sunplus-v2-0-0-20060510\n")); - break; - case OPTION_PIC: - score_pic = PIC; - g_switch_value = 0; /* Must set -G num as 0 to generate PIC code. */ - break; - default: - /* as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : ""); */ - return 0; - } - return 1; + if (score3) + return s3_s_score_cprestore (ignore); + else + return s7_s_score_cprestore (ignore); +} + +static void +s_score_gpword (int ignore ATTRIBUTE_UNUSED) +{ + if (score3) + return s3_s_score_gpword (ignore); + else + return s7_s_score_gpword (ignore); } -void -md_show_usage (FILE * fp) +static void +s_score_cpadd (int ignore ATTRIBUTE_UNUSED) { - fprintf (fp, _(" Score-specific assembler options:\n")); -#ifdef OPTION_EB - fprintf (fp, _("\ - -EB\t\tassemble code for a big-endian cpu\n")); -#endif - -#ifdef OPTION_EL - fprintf (fp, _("\ - -EL\t\tassemble code for a little-endian cpu\n")); -#endif + if (score3) + return s3_s_score_cpadd (ignore); + else + return s7_s_score_cpadd (ignore); +} - fprintf (fp, _("\ - -FIXDD\t\tassemble code for fix data dependency\n")); - fprintf (fp, _("\ - -NWARN\t\tassemble code for no warning message for fix data dependency\n")); - fprintf (fp, _("\ - -SCORE5\t\tassemble code for target is SCORE5\n")); - fprintf (fp, _("\ - -SCORE5U\tassemble code for target is SCORE5U\n")); - fprintf (fp, _("\ - -SCORE7\t\tassemble code for target is SCORE7, this is default setting\n")); - fprintf (fp, _("\ - -USE_R1\t\tassemble code for no warning message when using temp register r1\n")); - fprintf (fp, _("\ - -KPIC\t\tassemble code for PIC\n")); - fprintf (fp, _("\ - -O0\t\tassembler will not perform any optimizations\n")); - fprintf (fp, _("\ - -G gpnum\tassemble code for setting gpsize and default is 8 byte\n")); - fprintf (fp, _("\ - -V \t\tSunplus release version \n")); +static void +s_score_lcomm (int bytes_p) +{ + if (score3) + return s3_s_score_lcomm (bytes_p); + else + return s7_s_score_lcomm (bytes_p); } +static void +s3_assemble (char *str) +{ + know (str); + know (strlen (str) < s3_MAX_LITERAL_POOL_SIZE); + + memset (&s3_inst, '\0', sizeof (s3_inst)); + if (s3_INSN_IS_PCE_P (str)) + s3_parse_pce_inst (str); + else if (s3_INSN_IS_48_P (str)) + s3_parse_48_inst (str, TRUE); + else + s3_parse_16_32_inst (str, TRUE); -/* Pesudo handling functions. */ + if (s3_inst.error) + as_bad (_("%s -- `%s'"), s3_inst.error, s3_inst.str); +} -/* If we change section we must dump the literal pool first. */ static void -s_score_bss (int ignore ATTRIBUTE_UNUSED) +s3_operand (expressionS * expr) { - subseg_set (bss_section, (subsegT) get_absolute_expression ()); - demand_empty_rest_of_line (); + if (s3_in_my_get_expression) + { + expr->X_op = O_illegal; + if (s3_inst.error == NULL) + { + s3_inst.error = _("bad expression"); + } + } } static void -s_score_text (int ignore) +s3_begin (void) { - obj_elf_text (ignore); - record_alignment (now_seg, 2); + unsigned int i; + segT seg; + subsegT subseg; + + if ((s3_score_ops_hsh = hash_new ()) == NULL) + as_fatal (_("virtual memory exhausted")); + + s3_build_score_ops_hsh (); + + if ((s3_dependency_insn_hsh = hash_new ()) == NULL) + as_fatal (_("virtual memory exhausted")); + + s3_build_dependency_insn_hsh (); + + for (i = (int)s3_REG_TYPE_FIRST; i < (int)s3_REG_TYPE_MAX; i++) + s3_build_reg_hsh (s3_all_reg_maps + i); + + /* Initialize dependency vector. */ + s3_init_dependency_vector (); + + bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0); + seg = now_seg; + subseg = now_subseg; + s3_pdr_seg = subseg_new (".pdr", (subsegT) 0); + (void)bfd_set_section_flags (stdoutput, s3_pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING); + (void)bfd_set_section_alignment (stdoutput, s3_pdr_seg, 2); + subseg_set (seg, subseg); + + if (s3_USE_GLOBAL_POINTER_OPT) + bfd_set_gp_size (stdoutput, s3_g_switch_value); } static void -score_s_section (int ignore) +s3_number_to_chars (char *buf, valueT val, int n) { - obj_elf_section (ignore); - if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0) - record_alignment (now_seg, 2); + if (target_big_endian) + number_to_chars_bigendian (buf, val, n); + else + number_to_chars_littleendian (buf, val, n); +} + +static valueT +s3_normal_chars_to_number (char *buf, int n) +{ + valueT result = 0; + unsigned char *where = (unsigned char *)buf; + + if (target_big_endian) + { + while (n--) + { + result <<= 8; + result |= (*where++ & 255); + } + } + else + { + while (n--) + { + result <<= 8; + result |= (where[n] & 255); + } + } + return result; } static void -s_change_sec (int sec) +s3_number_to_chars_littleendian (void *p, valueT data, int n) { - segT seg; + char *buf = (char *) p; -#ifdef OBJ_ELF - /* The ELF backend needs to know that we are changing sections, so - that .previous works correctly. We could do something like check - for an obj_section_change_hook macro, but that might be confusing - as it would not be appropriate to use it in the section changing - functions in read.c, since obj-elf.c intercepts those. FIXME: - This should be cleaner, somehow. */ - obj_elf_section_change_hook (); -#endif - switch (sec) + switch (n) { - case 'r': - seg = subseg_new (RDATA_SECTION_NAME, (subsegT) get_absolute_expression ()); - bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA)); - if (strcmp (TARGET_OS, "elf") != 0) - record_alignment (seg, 4); - demand_empty_rest_of_line (); + case 4: + md_number_to_chars (buf, data >> 16, 2); + md_number_to_chars (buf + 2, data, 2); break; - case 's': - seg = subseg_new (".sdata", (subsegT) get_absolute_expression ()); - bfd_set_section_flags (stdoutput, seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA); - if (strcmp (TARGET_OS, "elf") != 0) - record_alignment (seg, 4); - demand_empty_rest_of_line (); + case 6: + md_number_to_chars (buf, data >> 32, 2); + md_number_to_chars (buf + 2, data >> 16, 2); + md_number_to_chars (buf + 4, data, 2); + break; + default: + /* Error routine. */ + as_bad_where (__FILE__, __LINE__, _("size is not 4 or 6")); break; } } -static void -s_score_mask (int reg_type ATTRIBUTE_UNUSED) +static valueT +s3_chars_to_number_littleendian (const void *p, int n) { - long mask, off; + char *buf = (char *) p; + valueT result = 0; - if (cur_proc_ptr == (procS *) NULL) - { - as_warn (_(".mask outside of .ent")); - demand_empty_rest_of_line (); - return; - } - if (get_absolute_expression_and_terminator (&mask) != ',') + switch (n) { - as_warn (_("Bad .mask directive")); - --input_line_pointer; - demand_empty_rest_of_line (); - return; + case 4: + result = s3_normal_chars_to_number (buf, 2) << 16; + result |= s3_normal_chars_to_number (buf + 2, 2); + break; + case 6: + result = s3_normal_chars_to_number (buf, 2) << 32; + result |= s3_normal_chars_to_number (buf + 2, 2) << 16; + result |= s3_normal_chars_to_number (buf + 4, 2); + break; + default: + /* Error routine. */ + as_bad_where (__FILE__, __LINE__, _("size is not 4 or 6")); + break; } - off = get_absolute_expression (); - cur_proc_ptr->reg_mask = mask; - cur_proc_ptr->reg_offset = off; - demand_empty_rest_of_line (); + + return result; } -static symbolS * -get_symbol (void) +static void +s3_md_number_to_chars (char *buf, valueT val, int n) { - int c; - char *name; - symbolS *p; + if (!target_big_endian && n >= 4) + s3_number_to_chars_littleendian (buf, val, n); + else + md_number_to_chars (buf, val, n); +} - name = input_line_pointer; - c = get_symbol_end (); - p = (symbolS *) symbol_find_or_make (name); - *input_line_pointer = c; - return p; +static valueT +s3_md_chars_to_number (char *buf, int n) +{ + valueT result = 0; + + if (!target_big_endian && n >= 4) + result = s3_chars_to_number_littleendian (buf, n); + else + result = s3_normal_chars_to_number (buf, n); + + return result; } -static long -get_number (void) +static char * +s3_atof (int type, char *litP, int *sizeP) { - int negative = 0; - long val = 0; + int prec; + LITTLENUM_TYPE words[s3_MAX_LITTLENUMS]; + char *t; + int i; - if (*input_line_pointer == '-') + switch (type) { - ++input_line_pointer; - negative = 1; + case 'f': + case 'F': + case 's': + case 'S': + prec = 2; + break; + case 'd': + case 'D': + case 'r': + case 'R': + prec = 4; + break; + case 'x': + case 'X': + case 'p': + case 'P': + prec = 6; + break; + default: + *sizeP = 0; + return _("bad call to MD_ATOF()"); } - if (!ISDIGIT (*input_line_pointer)) - as_bad (_("expected simple number")); - if (input_line_pointer[0] == '0') + + t = atof_ieee (input_line_pointer, type, words); + if (t) + input_line_pointer = t; + *sizeP = prec * 2; + + if (target_big_endian) { - if (input_line_pointer[1] == 'x') - { - input_line_pointer += 2; - while (ISXDIGIT (*input_line_pointer)) - { - val <<= 4; - val |= hex_value (*input_line_pointer++); - } - return negative ? -val : val; - } - else + for (i = 0; i < prec; i++) { - ++input_line_pointer; - while (ISDIGIT (*input_line_pointer)) - { - val <<= 3; - val |= *input_line_pointer++ - '0'; - } - return negative ? -val : val; + s3_md_number_to_chars (litP, (valueT) words[i], 2); + litP += 2; } } - if (!ISDIGIT (*input_line_pointer)) - { - printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer); - as_warn (_("invalid number")); - return -1; - } - while (ISDIGIT (*input_line_pointer)) + else { - val *= 10; - val += *input_line_pointer++ - '0'; + for (i = 0; i < prec; i += 2) + { + s3_md_number_to_chars (litP, (valueT) words[i + 1], 2); + s3_md_number_to_chars (litP + 2, (valueT) words[i], 2); + litP += 4; + } } - return negative ? -val : val; + + return 0; } -/* The .aent and .ent directives. */ +static void +s3_frag_check (fragS * fragp ATTRIBUTE_UNUSED) +{ + know (fragp->insn_addr <= s3_RELAX_PAD_BYTE); +} static void -s_score_ent (int aent) +s3_validate_fix (fixS *fixP) { - symbolS *symbolP; - int maybe_text; + fixP->fx_where += fixP->fx_frag->insn_addr; +} - symbolP = get_symbol (); - if (*input_line_pointer == ',') - ++input_line_pointer; - SKIP_WHITESPACE (); - if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-') - get_number (); +static int +s3_force_relocation (struct fix *fixp) +{ + int retval = 0; -#ifdef BFD_ASSEMBLER - if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0) - maybe_text = 1; - else - maybe_text = 0; -#else - if (now_seg != data_section && now_seg != bss_section) - maybe_text = 1; - else - maybe_text = 0; -#endif - if (!maybe_text) - as_warn (_(".ent or .aent not in text section.")); - if (!aent && cur_proc_ptr) - as_warn (_("missing .end")); - if (!aent) + if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT + || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY + || fixp->fx_r_type == BFD_RELOC_SCORE_JMP + || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH + || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP + || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH + || fixp->fx_r_type == BFD_RELOC_SCORE_BCMP) { - cur_proc_ptr = &cur_proc; - cur_proc_ptr->reg_mask = 0xdeadbeaf; - cur_proc_ptr->reg_offset = 0xdeadbeaf; - cur_proc_ptr->fpreg_mask = 0xdeafbeaf; - cur_proc_ptr->leaf = 0xdeafbeaf; - cur_proc_ptr->frame_offset = 0xdeafbeaf; - cur_proc_ptr->frame_reg = 0xdeafbeaf; - cur_proc_ptr->pc_reg = 0xdeafbeaf; - cur_proc_ptr->isym = symbolP; - symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION; - ++numprocs; - if (debug_type == DEBUG_STABS) - stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP)); + retval = 1; } - demand_empty_rest_of_line (); + return retval; } -static void -s_score_frame (int ignore ATTRIBUTE_UNUSED) +static bfd_boolean +s3_fix_adjustable (fixS * fixP) { - char *backupstr; - char str[30]; - long val; - int i = 0; - - backupstr = input_line_pointer; - -#ifdef OBJ_ELF - if (cur_proc_ptr == (procS *) NULL) + if (fixP->fx_addsy == NULL) { - as_warn (_(".frame outside of .ent")); - demand_empty_rest_of_line (); - return; + return 1; } - cur_proc_ptr->frame_reg = reg_required_here ((&backupstr), 0, REG_TYPE_SCORE); - SKIP_WHITESPACE (); - skip_past_comma (&backupstr); - while (*backupstr != ',') + else if (OUTPUT_FLAVOR == bfd_target_elf_flavour + && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy))) { - str[i] = *backupstr; - i++; - backupstr++; + return 0; } - str[i] = '\0'; - val = atoi (str); - - SKIP_WHITESPACE (); - skip_past_comma (&backupstr); - cur_proc_ptr->frame_offset = val; - cur_proc_ptr->pc_reg = reg_required_here ((&backupstr), 0, REG_TYPE_SCORE); - - SKIP_WHITESPACE (); - skip_past_comma (&backupstr); - i = 0; - while (*backupstr != '\n') + else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT + || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY + || fixP->fx_r_type == BFD_RELOC_SCORE_JMP + || fixP->fx_r_type == BFD_RELOC_SCORE16_JMP) { - str[i] = *backupstr; - i++; - backupstr++; + return 0; } - str[i] = '\0'; - val = atoi (str); - cur_proc_ptr->leaf = val; - SKIP_WHITESPACE (); - skip_past_comma (&backupstr); -#endif /* OBJ_ELF */ - while (input_line_pointer != backupstr) - input_line_pointer++; + return 1; } -/* The .end directive. */ static void -s_score_end (int x ATTRIBUTE_UNUSED) +s3_elf_final_processing (void) { - symbolS *p; - int maybe_text; - - /* Generate a .pdr section. */ - segT saved_seg = now_seg; - subsegT saved_subseg = now_subseg; - valueT dot; - expressionS exp; - char *fragp; + unsigned long val = 0; - if (!is_end_of_line[(unsigned char)*input_line_pointer]) - { - p = get_symbol (); - demand_empty_rest_of_line (); - } - else - p = NULL; + if (score3) + val = E_SCORE_MACH_SCORE3; + else if (score7) + val = E_SCORE_MACH_SCORE7; -#ifdef BFD_ASSEMBLER - if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0) - maybe_text = 1; - else - maybe_text = 0; -#else - if (now_seg != data_section && now_seg != bss_section) - maybe_text = 1; - else - maybe_text = 0; -#endif + elf_elfheader (stdoutput)->e_machine = EM_SCORE; + elf_elfheader (stdoutput)->e_flags &= ~EF_SCORE_MACH; + elf_elfheader (stdoutput)->e_flags |= val; - if (!maybe_text) - as_warn (_(".end not in text section")); - if (!cur_proc_ptr) + if (s3_fix_data_dependency == 1) { - as_warn (_(".end directive without a preceding .ent directive.")); - demand_empty_rest_of_line (); - return; + elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP; } - if (p != NULL) + if (s3_score_pic == s3_PIC) { - assert (S_GET_NAME (p)); - if (strcmp (S_GET_NAME (p), S_GET_NAME (cur_proc_ptr->isym))) - as_warn (_(".end symbol does not match .ent symbol.")); - if (debug_type == DEBUG_STABS) - stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p)); + elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC; } - else - as_warn (_(".end directive missing or unknown symbol")); +} - if ((cur_proc_ptr->reg_mask == 0xdeadbeaf) || - (cur_proc_ptr->reg_offset == 0xdeadbeaf) || - (cur_proc_ptr->leaf == 0xdeafbeaf) || - (cur_proc_ptr->frame_offset == 0xdeafbeaf) || - (cur_proc_ptr->frame_reg == 0xdeafbeaf) || (cur_proc_ptr->pc_reg == 0xdeafbeaf)); +static int +s3_judge_size_before_relax (fragS * fragp, asection *sec) +{ + int change = 0; + if (s3_score_pic == s3_NO_PIC) + change = s3_nopic_need_relax (fragp->fr_symbol, 0); else - { - dot = frag_now_fix (); - assert (pdr_seg); - subseg_set (pdr_seg, 0); - /* Write the symbol. */ - exp.X_op = O_symbol; - exp.X_add_symbol = p; - exp.X_add_number = 0; - emit_expr (&exp, 4); - fragp = frag_more (7 * 4); - md_number_to_chars (fragp, (valueT) cur_proc_ptr->reg_mask, 4); - md_number_to_chars (fragp + 4, (valueT) cur_proc_ptr->reg_offset, 4); - md_number_to_chars (fragp + 8, (valueT) cur_proc_ptr->fpreg_mask, 4); - md_number_to_chars (fragp + 12, (valueT) cur_proc_ptr->leaf, 4); - md_number_to_chars (fragp + 16, (valueT) cur_proc_ptr->frame_offset, 4); - md_number_to_chars (fragp + 20, (valueT) cur_proc_ptr->frame_reg, 4); - md_number_to_chars (fragp + 24, (valueT) cur_proc_ptr->pc_reg, 4); - subseg_set (saved_seg, saved_subseg); + change = s3_pic_need_relax (fragp->fr_symbol, sec); + if (change == 1) + { + /* Only at the first time determining whether s3_GP instruction relax should be done, + return the difference between insntruction size and instruction relax size. */ + if (fragp->fr_opcode == NULL) + { + fragp->fr_fix = s3_RELAX_NEW (fragp->fr_subtype); + fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype); + return s3_RELAX_NEW (fragp->fr_subtype) - s3_RELAX_OLD (fragp->fr_subtype); + } } - cur_proc_ptr = NULL; + + return 0; } -/* Handle the .set pseudo-op. */ -static void -s_score_set (int x ATTRIBUTE_UNUSED) +static int +s3_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED) { - int i = 0; - char name[MAX_LITERAL_POOL_SIZE]; - char * orig_ilp = input_line_pointer; + if ((s3_RELAX_TYPE (fragp->fr_subtype) == Insn_GP) + || (s3_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC)) + return s3_judge_size_before_relax (fragp, sec); - while (!is_end_of_line[(unsigned char)*input_line_pointer]) - { - name[i] = (char) * input_line_pointer; - i++; - ++input_line_pointer; - } + return 0; +} - name[i] = '\0'; +static int +s3_relax_branch_inst32 (fragS * fragp) +{ + fragp->fr_opcode = NULL; + return 0; +} - if (strcmp (name, "nwarn") == 0) - { - warn_fix_data_dependency = 0; - } - else if (strcmp (name, "fixdd") == 0) - { - fix_data_dependency = 1; - } - else if (strcmp (name, "nofixdd") == 0) - { - fix_data_dependency = 0; - } - else if (strcmp (name, "r1") == 0) - { - nor1 = 0; - } - else if (strcmp (name, "nor1") == 0) +static int +s3_relax_branch_inst16 (fragS * fragp) +{ + int relaxable_p = 0; + int frag_addr = fragp->fr_address + fragp->insn_addr; + addressT symbol_address = 0; + symbolS *s; + offsetT offset; + long value; + unsigned long inst_value; + + relaxable_p = s3_RELAX_OPT (fragp->fr_subtype); + + s = fragp->fr_symbol; + if (s == NULL) + frag_addr = 0; + else { - nor1 = 1; + if (s->bsym != 0) + symbol_address = (addressT) s->sy_frag->fr_address; } - else if (strcmp (name, "optimize") == 0) + + inst_value = s3_md_chars_to_number (fragp->fr_literal, s3_INSN16_SIZE); + offset = (inst_value & 0x1ff) << 1; + if ((offset & 0x200) == 0x200) + offset |= 0xfffffc00; + + value = offset + symbol_address - frag_addr; + + if (relaxable_p + && (!((value & 0xfffffe00) == 0 || (value & 0xfffffe00) == 0xfffffe00)) + && fragp->fr_fix == 2 + && (s->bsym != NULL) + && (S_IS_DEFINED (s) + && !S_IS_COMMON (s) + && !S_IS_EXTERNAL (s))) { - g_opt = 1; + /* Relax branch 32 to branch 16. */ + fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype); + fragp->fr_fix = 4; + return 2; } - else if (strcmp (name, "volatile") == 0) + else + return 0; +} + +static int +s3_relax_cmpbranch_inst32 (fragS * fragp) +{ + int relaxable_p = 0; + symbolS *s; + /* For sign bit. */ + long offset; + long frag_addr = fragp->fr_address + fragp->insn_addr; + long symbol_address = 0; + long value; + unsigned long inst_value; + + relaxable_p = s3_RELAX_OPT (fragp->fr_subtype); + + s = fragp->fr_symbol; + if (s == NULL) + frag_addr = 0; + else { - g_opt = 0; + if (s->bsym != 0) + symbol_address = (addressT) s->sy_frag->fr_address; + } + + inst_value = s3_md_chars_to_number (fragp->fr_literal, s3_INSN_SIZE); + offset = (inst_value & 0x1) + | (((inst_value >> 7) & 0x7) << 1) + | (((inst_value >> 21) & 0x1f) << 4); + offset <<= 1; + if ((offset & 0x200) == 0x200) + offset |= 0xfffffe00; + + value = offset + symbol_address - frag_addr; + /* change the order of judging rule is because + 1.not defined symbol or common sysbol or external symbol will change + bcmp to cmp!+beq/bne ,here need to record fragp->fr_opcode + 2.if the flow is as before : it will results to recursive loop + */ + if (fragp->fr_fix == 6) + { + /* Have already relaxed! Just return 0 to terminate the loop. */ + return 0; } - else if (strcmp (name, "pic") == 0) + /* need to translate when extern or not defind or common sysbol */ + else if ((relaxable_p + && (!((value & 0xfffffe00) == 0 || (value & 0xfffffe00) == 0xfffffe00)) + && fragp->fr_fix == 4 + && (s->bsym != NULL)) + || !S_IS_DEFINED (s) + ||S_IS_COMMON (s) + ||S_IS_EXTERNAL (s)) { - score_pic = PIC; + fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype); + fragp->fr_fix = 6; + return 2; } + else - { - input_line_pointer = orig_ilp; - s_set (0); + { + /* Never relax. Modify fr_opcode to NULL to verify it's value in + md_apply_fix. */ + fragp->fr_opcode = NULL; + return 0; } } -/* Handle the .cpload pseudo-op. This is used when generating PIC code. It sets the - $gp register for the function based on the function address, which is in the register - named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled - specially by the linker. The result is: - ldis gp, %hi(GP_DISP_LABEL) - ori gp, %low(GP_DISP_LABEL) - add gp, gp, .cpload argument - The .cpload argument is normally r29. */ -static void -s_score_cpload (int ignore ATTRIBUTE_UNUSED) +static int +s3_relax_other_inst32 (fragS * fragp) { - int reg; - char insn_str[MAX_LITERAL_POOL_SIZE]; + int relaxable_p = s3_RELAX_OPT (fragp->fr_subtype); - /* If we are not generating PIC code, .cpload is ignored. */ - if (score_pic == NO_PIC) + if (relaxable_p + && fragp->fr_fix == 4) { - s_ignore (0); - return; + fragp->fr_opcode = fragp->fr_literal + s3_RELAX_RELOC1 (fragp->fr_subtype); + fragp->fr_fix = 2; + return -2; } + else + return 0; +} - if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL) - return; +static int +s3_relax_gp_and_pic_inst32 (void) +{ + /* md_estimate_size_before_relax has already relaxed s3_GP and s3_PIC + instructions. We don't change relax size here. */ + return 0; +} - demand_empty_rest_of_line (); +static int +s3_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED) +{ + int grows = 0; + int adjust_align_p = 0; - sprintf (insn_str, "ld_i32hi r%d, %s", GP, GP_DISP_LABEL); - if (append_insn (insn_str, TRUE) == (int) FAIL) - return; + /* If the instruction address is odd, make it half word align first. */ + if ((fragp->fr_address) % 2 != 0) + { + if ((fragp->fr_address + fragp->insn_addr) % 2 != 0) + { + fragp->insn_addr = 1; + grows += 1; + adjust_align_p = 1; + } + } - sprintf (insn_str, "ld_i32lo r%d, %s", GP, GP_DISP_LABEL); - if (append_insn (insn_str, TRUE) == (int) FAIL) - return; + switch (s3_RELAX_TYPE (fragp->fr_subtype)) + { + case PC_DISP19div2: + grows += s3_relax_branch_inst32 (fragp); + break; - sprintf (insn_str, "add r%d, r%d, r%d", GP, GP, reg); - if (append_insn (insn_str, TRUE) == (int) FAIL) - return; -} + case PC_DISP8div2: + grows += s3_relax_branch_inst16 (fragp); + break; -/* Handle the .cprestore pseudo-op. This stores $gp into a given - offset from $sp. The offset is remembered, and after making a PIC - call $gp is restored from that location. */ + case Insn_BCMP : + grows += s3_relax_cmpbranch_inst32 (fragp); + break; -static void -s_score_cprestore (int ignore ATTRIBUTE_UNUSED) -{ - int reg; - int cprestore_offset; - char insn_str[MAX_LITERAL_POOL_SIZE]; + case Insn_GP: + case Insn_PIC: + grows += s3_relax_gp_and_pic_inst32 (); + break; - /* If we are not generating PIC code, .cprestore is ignored. */ - if (score_pic == NO_PIC) - { - s_ignore (0); - return; + default: + grows += s3_relax_other_inst32 (fragp); + break; } - if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL - || skip_past_comma (&input_line_pointer) == (int) FAIL) + /* newly added */ + if (adjust_align_p && fragp->insn_addr) { - return; + fragp->fr_fix += fragp->insn_addr; } - cprestore_offset = get_absolute_expression (); + return grows; +} + +static void +s3_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp) +{ + int old; + int new; + char backup[20]; + fixS *fixp; + + old = s3_RELAX_OLD (fragp->fr_subtype); + new = s3_RELAX_NEW (fragp->fr_subtype); - if (cprestore_offset <= 0x3fff) + /* fragp->fr_opcode indicates whether this frag should be relaxed. */ + if (fragp->fr_opcode == NULL) { - sprintf (insn_str, "sw r%d, [r%d, %d]", GP, reg, cprestore_offset); - if (append_insn (insn_str, TRUE) == (int) FAIL) - return; + memcpy (backup, fragp->fr_literal, old); + fragp->fr_fix = old; } else { - int r1_bak; - - r1_bak = nor1; - nor1 = 0; - - sprintf (insn_str, "li r1, %d", cprestore_offset); - if (append_insn (insn_str, TRUE) == (int) FAIL) - return; - - sprintf (insn_str, "add r1, r1, r%d", reg); - if (append_insn (insn_str, TRUE) == (int) FAIL) - return; - - sprintf (insn_str, "sw r%d, [r1]", GP); - if (append_insn (insn_str, TRUE) == (int) FAIL) - return; + memcpy (backup, fragp->fr_literal + old, new); + fragp->fr_fix = new; + } - nor1 = r1_bak; + fixp = fragp->tc_frag_data.fixp; + while (fixp && fixp->fx_frag == fragp && fixp->fx_where < old) + { + if (fragp->fr_opcode) + fixp->fx_done = 1; + fixp = fixp->fx_next; + } + while (fixp && fixp->fx_frag == fragp) + { + if (fragp->fr_opcode) + fixp->fx_where -= old + fragp->insn_addr; + else + fixp->fx_done = 1; + fixp = fixp->fx_next; } - demand_empty_rest_of_line (); + if (fragp->insn_addr) + { + s3_md_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr); + } + memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix); + fragp->fr_fix += fragp->insn_addr; } -/* Handle the .gpword pseudo-op. This is used when generating PIC - code. It generates a 32 bit GP relative reloc. */ -static void -s_score_gpword (int ignore ATTRIBUTE_UNUSED) +static long +s3_pcrel_from (fixS * fixP) { - expressionS ex; - char *p; + long retval = 0; - /* When not generating PIC code, this is treated as .word. */ - if (score_pic == NO_PIC) + if (fixP->fx_addsy + && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section) + && (fixP->fx_subsy == NULL)) { - cons (4); - return; + retval = 0; } - expression (&ex); - if (ex.X_op != O_symbol || ex.X_add_number != 0) + else { - as_bad (_("Unsupported use of .gpword")); - ignore_rest_of_line (); + retval = fixP->fx_where + fixP->fx_frag->fr_address; } - p = frag_more (4); - md_number_to_chars (p, (valueT) 0, 4); - fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32); - demand_empty_rest_of_line (); + + return retval; } -/* Handle the .cpadd pseudo-op. This is used when dealing with switch - tables in PIC code. */ +static valueT +s3_section_align (segT segment ATTRIBUTE_UNUSED, valueT size) +{ + int align = bfd_get_section_alignment (stdoutput, segment); + return ((size + (1 << align) - 1) & (-1 << align)); +} static void -s_score_cpadd (int ignore ATTRIBUTE_UNUSED) +s3_apply_fix (fixS *fixP, valueT *valP, segT seg) { - int reg; - char insn_str[MAX_LITERAL_POOL_SIZE]; + offsetT value = *valP; + offsetT newval; + offsetT content; + unsigned short HI, LO; - /* If we are not generating PIC code, .cpload is ignored. */ - if (score_pic == NO_PIC) + char *buf = fixP->fx_frag->fr_literal + fixP->fx_where; + + assert (fixP->fx_r_type < BFD_RELOC_UNUSED); + if (fixP->fx_addsy == 0 && !fixP->fx_pcrel) { - s_ignore (0); - return; + if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16) + fixP->fx_done = 1; } - if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL) + /* If this symbol is in a different section then we need to leave it for + the linker to deal with. Unfortunately, md_pcrel_from can't tell, + so we have to undo it's effects here. */ + if (fixP->fx_pcrel) { - return; + if (fixP->fx_addsy != NULL + && S_IS_DEFINED (fixP->fx_addsy) + && S_GET_SEGMENT (fixP->fx_addsy) != seg) + value += md_pcrel_from (fixP); } - demand_empty_rest_of_line (); - /* Add $gp to the register named as an argument. */ - sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, GP); - if (append_insn (insn_str, TRUE) == (int) FAIL) - return; -} + /* Remember value for emit_reloc. */ + fixP->fx_addnumber = value; -#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT -#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \ - do \ - { \ - if ((SIZE) >= 8) \ - (P2VAR) = 3; \ - else if ((SIZE) >= 4) \ - (P2VAR) = 2; \ - else if ((SIZE) >= 2) \ - (P2VAR) = 1; \ - else \ - (P2VAR) = 0; \ - } \ - while (0) -#endif + switch (fixP->fx_r_type) + { + case BFD_RELOC_HI16_S: + if (fixP->fx_done) /* For la rd, imm32. */ + { + newval = s3_md_chars_to_number (buf, s3_INSN_SIZE); + HI = (value) >> 16; /* mul to 2, then take the hi 16 bit. */ + newval |= (HI & 0x3fff) << 1; + newval |= ((HI >> 14) & 0x3) << 16; + s3_md_number_to_chars (buf, newval, s3_INSN_SIZE); + } + break; + case BFD_RELOC_LO16: + if (fixP->fx_done) /* For la rd, imm32. */ + { + newval = s3_md_chars_to_number (buf, s3_INSN_SIZE); + LO = (value) & 0xffff; + newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi. */ + newval |= ((LO >> 14) & 0x3) << 16; + s3_md_number_to_chars (buf, newval, s3_INSN_SIZE); + } + break; + case BFD_RELOC_SCORE_JMP: + { + content = s3_md_chars_to_number (buf, s3_INSN_SIZE); + value = fixP->fx_offset; + content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff); + s3_md_number_to_chars (buf, content, s3_INSN_SIZE); + } + break; -static void -s_score_lcomm (int bytes_p) -{ - char *name; - char c; - char *p; - int temp; - symbolS *symbolP; - segT current_seg = now_seg; - subsegT current_subseg = now_subseg; - const int max_alignment = 15; - int align = 0; - segT bss_seg = bss_section; - int needs_align = 0; + case BFD_RELOC_SCORE_IMM30: + { + content = s3_md_chars_to_number (buf, s3_INSN48_SIZE); + value = fixP->fx_offset; + value >>= 2; + content = (content & ~0x7f7fff7f80LL) + | (((value & 0xff) >> 0) << 7) + | (((value & 0x7fff00) >> 8) << 16) + | (((value & 0x3f800000) >> 23) << 32); + s3_md_number_to_chars (buf, content, s3_INSN48_SIZE); + break; + } - name = input_line_pointer; - c = get_symbol_end (); - p = input_line_pointer; - *p = c; + case BFD_RELOC_SCORE_IMM32: + { + content = s3_md_chars_to_number (buf, s3_INSN48_SIZE); + value = fixP->fx_offset; + content = (content & ~0x7f7fff7fe0LL) + | ((value & 0x3ff) << 5) + | (((value >> 10) & 0x7fff) << 16) + | (((value >> 25) & 0x7f) << 32); + s3_md_number_to_chars (buf, content, s3_INSN48_SIZE); + break; + } - if (name == p) - { - as_bad (_("expected symbol name")); - discard_rest_of_line (); - return; - } + case BFD_RELOC_SCORE_BRANCH: + if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) + value = fixP->fx_offset; + else + fixP->fx_done = 1; + + content = s3_md_chars_to_number (buf, s3_INSN_SIZE); + + /* Don't check c-bit. */ + if (fixP->fx_frag->fr_opcode != 0) + { + if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9]"), (unsigned int)value); + return; + } + content = s3_md_chars_to_number (buf, s3_INSN16_SIZE); + content &= 0xfe00; + content = (content & 0xfe00) | ((value >> 1) & 0x1ff); + s3_md_number_to_chars (buf, content, s3_INSN16_SIZE); + fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH; + fixP->fx_size = 2; + } + else + { + if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value); + return; + } + content = s3_md_chars_to_number (buf, s3_INSN_SIZE); + content &= 0xfc00fc01; + content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000); + s3_md_number_to_chars (buf, content, s3_INSN_SIZE); + } + break; + case BFD_RELOC_SCORE16_JMP: + content = s3_md_chars_to_number (buf, s3_INSN16_SIZE); + content &= 0xf001; + value = fixP->fx_offset & 0xfff; + content = (content & 0xfc01) | (value & 0xffe); + s3_md_number_to_chars (buf, content, s3_INSN16_SIZE); + break; + case BFD_RELOC_SCORE16_BRANCH: + content = s3_md_chars_to_number (buf, s3_INSN_SIZE); + /* Don't check c-bit. */ + if (fixP->fx_frag->fr_opcode != 0) + { + if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || + (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) + value = fixP->fx_offset; + else + fixP->fx_done = 1; + if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value); + return; + } + content = s3_md_chars_to_number (buf, s3_INSN_SIZE); + content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000); + s3_md_number_to_chars (buf, content, s3_INSN_SIZE); + fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH; + fixP->fx_size = 4; + break; + } + else + { + /* In differnt section. */ + if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || + (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) + value = fixP->fx_offset; + else + fixP->fx_done = 1; + + if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9]"), (unsigned int)value); + return; + } + + content = s3_md_chars_to_number (buf, s3_INSN16_SIZE); + content = (content & 0xfe00) | ((value >> 1) & 0x1ff); + s3_md_number_to_chars (buf, content, s3_INSN16_SIZE); + break; + } + + break; + + case BFD_RELOC_SCORE_BCMP: + if (fixP->fx_frag->fr_opcode != 0) + { + char *buf_ptr = buf; + buf_ptr += 2; + + if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) + value = fixP->fx_offset; + else + fixP->fx_done = 1; + + /* NOTE!!! + bcmp -> cmp! and branch, so value -= 2. */ + value -= 2; + + if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value); + return; + } + + content = s3_md_chars_to_number (buf_ptr, s3_INSN_SIZE); + content &= 0xfc00fc01; + content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000); + s3_md_number_to_chars (buf_ptr, content, s3_INSN_SIZE); + /* change relocation type to BFD_RELOC_SCORE_BRANCH */ + fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH; + fixP->fx_where+=2; /* first insn is cmp! , the second insn is beq/bne */ + break; + } + else + { + if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) + value = fixP->fx_offset; + else + fixP->fx_done = 1; - SKIP_WHITESPACE (); + content = s3_md_chars_to_number (buf, s3_INSN_SIZE); - /* Accept an optional comma after the name. The comma used to be - required, but Irix 5 cc does not generate it. */ - if (*input_line_pointer == ',') - { - ++input_line_pointer; - SKIP_WHITESPACE (); - } + if ((value & 0xfffffe00) != 0 && (value & 0xfffffe00) != 0xfffffe00) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + _(" branch relocation truncate (0x%x) [-2^9 ~ 2^9]"), (unsigned int)value); + return; + } - if (is_end_of_line[(unsigned char)*input_line_pointer]) - { - as_bad (_("missing size expression")); - return; - } + value >>= 1; + content &= ~0x03e00381; + content = content + | (value & 0x1) + | (((value & 0xe) >> 1) << 7) + | (((value & 0x1f0) >> 4) << 21); - if ((temp = get_absolute_expression ()) < 0) - { - as_warn (_("BSS length (%d) < 0 ignored"), temp); - ignore_rest_of_line (); - return; - } + s3_md_number_to_chars (buf, content, s3_INSN_SIZE); + break; + } -#if defined (TC_SCORE) - if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour) - { - /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss. */ - if ((unsigned)temp <= bfd_get_gp_size (stdoutput)) + case BFD_RELOC_8: + if (fixP->fx_done || fixP->fx_pcrel) + s3_md_number_to_chars (buf, value, 1); +#ifdef OBJ_ELF + else { - bss_seg = subseg_new (".sbss", 1); - seg_info (bss_seg)->bss = 1; -#ifdef BFD_ASSEMBLER - if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC)) - as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ())); -#endif + value = fixP->fx_offset; + s3_md_number_to_chars (buf, value, 1); } - } #endif + break; - SKIP_WHITESPACE (); - if (*input_line_pointer == ',') - { - ++input_line_pointer; - SKIP_WHITESPACE (); - - if (is_end_of_line[(unsigned char)*input_line_pointer]) + case BFD_RELOC_16: + if (fixP->fx_done || fixP->fx_pcrel) + s3_md_number_to_chars (buf, value, 2); +#ifdef OBJ_ELF + else { - as_bad (_("missing alignment")); - return; + value = fixP->fx_offset; + s3_md_number_to_chars (buf, value, 2); } +#endif + break; + case BFD_RELOC_RVA: + case BFD_RELOC_32: + if (fixP->fx_done || fixP->fx_pcrel) + md_number_to_chars (buf, value, 4); +#ifdef OBJ_ELF else { - align = get_absolute_expression (); - needs_align = 1; + value = fixP->fx_offset; + md_number_to_chars (buf, value, 4); } +#endif + break; + case BFD_RELOC_VTABLE_INHERIT: + fixP->fx_done = 0; + if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy)) + S_SET_WEAK (fixP->fx_addsy); + break; + case BFD_RELOC_VTABLE_ENTRY: + fixP->fx_done = 0; + break; + case BFD_RELOC_SCORE_GPREL15: + content = s3_md_chars_to_number (buf, s3_INSN_SIZE); + /* c-bit. */ + if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94180000)) + fixP->fx_r_type = BFD_RELOC_NONE; + fixP->fx_done = 0; + break; + case BFD_RELOC_SCORE_GOT15: + case BFD_RELOC_SCORE_DUMMY_HI16: + case BFD_RELOC_SCORE_GOT_LO16: + case BFD_RELOC_SCORE_CALL15: + case BFD_RELOC_GPREL32: + break; + case BFD_RELOC_NONE: + default: + as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type); } +} - if (!needs_align) - { - TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align); +static arelent ** +s3_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp) +{ + static arelent *retval[MAX_RELOC_EXPANSION + 1]; /* MAX_RELOC_EXPANSION equals 2. */ + arelent *reloc; + bfd_reloc_code_real_type code; + char *type; + fragS *f; + symbolS *s; + expressionS e; - /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it. */ - if (align) - record_alignment (bss_seg, align); - } + reloc = retval[0] = xmalloc (sizeof (arelent)); + retval[1] = NULL; - if (needs_align) + reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); + *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); + reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; + reloc->addend = fixp->fx_offset; + + /* If this is a variant frag, we may need to adjust the existing + reloc and generate a new one. */ + if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15)) { - if (bytes_p) - { - /* Convert to a power of 2. */ - if (align != 0) - { - unsigned int i; + /* Update instruction imm bit. */ + offsetT newval; + unsigned short off; + char *buf; - for (i = 0; align != 0; align >>= 1, ++i) - ; - align = i - 1; - } - } + buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr; + newval = s3_md_chars_to_number (buf, s3_INSN_SIZE); + off = fixp->fx_offset >> 16; + newval |= (off & 0x3fff) << 1; + newval |= ((off >> 14) & 0x3) << 16; + s3_md_number_to_chars (buf, newval, s3_INSN_SIZE); - if (align > max_alignment) - { - align = max_alignment; - as_warn (_("alignment too large; %d assumed"), align); - } - else if (align < 0) - { - align = 0; - as_warn (_("alignment negative; 0 assumed")); - } + buf += s3_INSN_SIZE; + newval = s3_md_chars_to_number (buf, s3_INSN_SIZE); + off = fixp->fx_offset & 0xffff; + newval |= ((off & 0x3fff) << 1); + newval |= (((off >> 14) & 0x3) << 16); + s3_md_number_to_chars (buf, newval, s3_INSN_SIZE); - record_alignment (bss_seg, align); + retval[1] = xmalloc (sizeof (arelent)); + retval[2] = NULL; + retval[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); + *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); + retval[1]->address = (reloc->address + s3_RELAX_RELOC2 (fixp->fx_frag->fr_subtype)); + + f = fixp->fx_frag; + s = f->fr_symbol; + e = s->sy_value; + + retval[1]->addend = 0; + retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16); + assert (retval[1]->howto != NULL); + + fixp->fx_r_type = BFD_RELOC_HI16_S; } - else + + code = fixp->fx_r_type; + switch (fixp->fx_r_type) { - /* Assume some objects may require alignment on some systems. */ -#if defined (TC_ALPHA) && ! defined (VMS) - if (temp > 1) + case BFD_RELOC_32: + if (fixp->fx_pcrel) { - align = ffs (temp) - 1; - if (temp % (1 << align)) - abort (); + code = BFD_RELOC_32_PCREL; + break; } -#endif + case BFD_RELOC_HI16_S: + case BFD_RELOC_LO16: + case BFD_RELOC_SCORE_JMP: + case BFD_RELOC_SCORE_BRANCH: + case BFD_RELOC_SCORE16_JMP: + case BFD_RELOC_SCORE16_BRANCH: + case BFD_RELOC_SCORE_BCMP: + case BFD_RELOC_VTABLE_ENTRY: + case BFD_RELOC_VTABLE_INHERIT: + case BFD_RELOC_SCORE_GPREL15: + case BFD_RELOC_SCORE_GOT15: + case BFD_RELOC_SCORE_DUMMY_HI16: + case BFD_RELOC_SCORE_GOT_LO16: + case BFD_RELOC_SCORE_CALL15: + case BFD_RELOC_GPREL32: + case BFD_RELOC_NONE: + case BFD_RELOC_SCORE_IMM30: + case BFD_RELOC_SCORE_IMM32: + code = fixp->fx_r_type; + break; + default: + type = _(""); + as_bad_where (fixp->fx_file, fixp->fx_line, + _("cannot represent %s relocation in this object file format"), type); + return NULL; } - *p = 0; - symbolP = symbol_find_or_make (name); - *p = c; - - if ( -#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \ - || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT)) -#ifdef BFD_ASSEMBLER - (OUTPUT_FLAVOR != bfd_target_aout_flavour - || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) && -#else - (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) && -#endif -#endif - (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0))) + reloc->howto = bfd_reloc_type_lookup (stdoutput, code); + if (reloc->howto == NULL) { - char *pfrag; + as_bad_where (fixp->fx_file, fixp->fx_line, + _("cannot represent %s relocation in this object file format1"), + bfd_get_reloc_code_name (code)); + return NULL; + } + /* HACK: Since arm ELF uses Rel instead of Rela, encode the + vtable entry to be used in the relocation's section offset. */ + if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) + reloc->address = fixp->fx_offset; + + return retval; +} + +void +md_assemble (char *str) +{ + if (score3) + s3_assemble (str); + else + s7_assemble (str); +} + +/* We handle all bad expressions here, so that we can report the faulty + instruction in the error message. */ +void +md_operand (expressionS * expr) +{ + if (score3) + s3_operand (expr); + else + s7_operand (expr); +} + +/* Turn an integer of n bytes (in val) into a stream of bytes appropriate + for use in the a.out file, and stores them in the array pointed to by buf. + This knows about the endian-ness of the target machine and does + THE RIGHT THING, whatever it is. Possible values for n are 1 (byte) + 2 (short) and 4 (long) Floating numbers are put out as a series of + LITTLENUMS (shorts, here at least). */ +void +md_number_to_chars (char *buf, valueT val, int n) +{ + if (score3) + s3_number_to_chars (buf, val, n); + else + s7_number_to_chars (buf, val, n); +} - subseg_set (bss_seg, 1); +/* Turn a string in input_line_pointer into a floating point constant + of type TYPE, and store the appropriate bytes in *LITP. The number + of LITTLENUMS emitted is stored in *SIZEP. An error message is + returned, or NULL on OK. + + Note that fp constants aren't represent in the normal way on the ARM. + In big endian mode, things are as expected. However, in little endian + mode fp constants are big-endian word-wise, and little-endian byte-wise + within the words. For example, (double) 1.1 in big endian mode is + the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is + the byte sequence 99 99 f1 3f 9a 99 99 99. */ +char * +md_atof (int type, char *litP, int *sizeP) +{ + if (score3) + return s3_atof (type, litP, sizeP); + else + return s7_atof (type, litP, sizeP); +} - if (align) - frag_align (align, 0, 0); +void +score_frag_check (fragS * fragp ATTRIBUTE_UNUSED) +{ + if (score3) + s3_frag_check (fragp); + else + s7_frag_check (fragp); +} - /* Detach from old frag. */ - if (S_GET_SEGMENT (symbolP) == bss_seg) - symbol_get_frag (symbolP)->fr_symbol = NULL; +/* Implementation of TC_VALIDATE_FIX. + Called before md_apply_fix() and after md_convert_frag(). */ +void +score_validate_fix (fixS *fixP) +{ + if (score3) + s3_validate_fix (fixP); + else + s7_validate_fix (fixP); +} - symbol_set_frag (symbolP, frag_now); - pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL); - *pfrag = 0; +int +score_force_relocation (struct fix *fixp) +{ + if (score3) + return s3_force_relocation (fixp); + else + return s7_force_relocation (fixp); +} +/* Implementation of md_frag_check. + Called after md_convert_frag(). */ +bfd_boolean +score_fix_adjustable (fixS * fixP) +{ + if (score3) + return s3_fix_adjustable (fixP); + else + return s7_fix_adjustable (fixP); +} - S_SET_SEGMENT (symbolP, bss_seg); +void +score_elf_final_processing (void) +{ + if (score3) + s3_elf_final_processing (); + else + s7_elf_final_processing (); +} -#ifdef OBJ_COFF - /* The symbol may already have been created with a preceding - ".globl" directive -- be careful not to step on storage class - in that case. Otherwise, set it to static. */ - if (S_GET_STORAGE_CLASS (symbolP) != C_EXT) - { - S_SET_STORAGE_CLASS (symbolP, C_STAT); - } -#endif /* OBJ_COFF */ +/* In this function, we determine whether s3_GP instruction should do relaxation, + for the label being against was known now. + Doing this here but not in md_relax_frag() can induce iteration times + in stage of doing relax. */ +int +md_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED) +{ + if (score3) + return s3_estimate_size_before_relax (fragp, sec); + else + return s7_estimate_size_before_relax (fragp, sec); +} -#ifdef S_SET_SIZE - S_SET_SIZE (symbolP, temp); -#endif - } +int +score_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED) +{ + if (score3) + return s3_relax_frag (sec, fragp, stretch); + else + return s7_relax_frag (sec, fragp, stretch); +} + +void +md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp) +{ + if (score3) + return s3_convert_frag (abfd, sec, fragp); else - as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP)); + return s7_convert_frag (abfd, sec, fragp); +} - subseg_set (current_seg, current_subseg); +long +md_pcrel_from (fixS * fixP) +{ + if (score3) + return s3_pcrel_from (fixP); + else + return s7_pcrel_from (fixP); +} - demand_empty_rest_of_line (); +/* Round up a section size to the appropriate boundary. */ +valueT +md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size) +{ + if (score3) + return s3_section_align (segment, size); + else + return s7_section_align (segment, size); } -static void -insert_reg (const struct reg_entry *r, struct hash_control *htab) +void +md_apply_fix (fixS *fixP, valueT *valP, segT seg) { - int i = 0; - int len = strlen (r->name) + 2; - char *buf = xmalloc (len); - char *buf2 = xmalloc (len); + if (score3) + return s3_apply_fix (fixP, valP, seg); + else + return s7_apply_fix (fixP, valP, seg); +} - strcpy (buf + i, r->name); - for (i = 0; buf[i]; i++) - { - buf2[i] = TOUPPER (buf[i]); - } - buf2[i] = '\0'; +/* Translate internal representation of relocation info to BFD target format. */ +arelent ** +tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp) +{ + if (score3) + return s3_gen_reloc (section, fixp); + else + return s7_gen_reloc (section, fixp); +} - hash_insert (htab, buf, (void *) r); - hash_insert (htab, buf2, (void *) r); +void +md_begin (void) +{ + s3_begin (); + s7_begin (); } static void -build_reg_hsh (struct reg_map *map) +score_set_mach (const char *arg) { - const struct reg_entry *r; - - if ((map->htab = hash_new ()) == NULL) + if (strcmp (arg, MARCH_SCORE3) == 0) { - as_fatal (_("virtual memory exhausted")); + score3 = 1; + score7 = 0; + s3_score3d = 1; } - for (r = map->names; r->name != NULL; r++) + else if (strcmp (arg, MARCH_SCORE7) == 0) + { + score3 = 0; + score7 = 1; + s7_score7d = 1; + s7_university_version = 0; + s7_vector_size = s7_SCORE7_PIPELINE; + } + else if (strcmp (arg, MARCH_SCORE5) == 0) + { + score3 = 0; + score7 = 1; + s7_score7d = 1; + s7_university_version = 0; + s7_vector_size = s7_SCORE5_PIPELINE; + } + else if (strcmp (arg, MARCH_SCORE5U) == 0) + { + score3 = 0; + score7 = 1; + s7_score7d = 1; + s7_university_version = 1; + s7_vector_size = s7_SCORE5_PIPELINE; + } + else { - insert_reg (r, map->htab); + as_bad (_("unknown architecture `%s'\n"), arg); } } -void -md_begin (void) +int +md_parse_option (int c, char *arg) { - unsigned int i; - segT seg; - subsegT subseg; - - if ((score_ops_hsh = hash_new ()) == NULL) - as_fatal (_("virtual memory exhausted")); - - build_score_ops_hsh (); - - if ((dependency_insn_hsh = hash_new ()) == NULL) - as_fatal (_("virtual memory exhausted")); - - build_dependency_insn_hsh (); - - for (i = (int)REG_TYPE_FIRST; i < (int)REG_TYPE_MAX; i++) - build_reg_hsh (all_reg_maps + i); - - /* Initialize dependency vector. */ - init_dependency_vector (); - - bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0); - seg = now_seg; - subseg = now_subseg; - pdr_seg = subseg_new (".pdr", (subsegT) 0); - (void)bfd_set_section_flags (stdoutput, pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING); - (void)bfd_set_section_alignment (stdoutput, pdr_seg, 2); - subseg_set (seg, subseg); - - if (USE_GLOBAL_POINTER_OPT) - bfd_set_gp_size (stdoutput, g_switch_value); + switch (c) + { +#ifdef OPTION_EB + case OPTION_EB: + target_big_endian = 1; + break; +#endif +#ifdef OPTION_EL + case OPTION_EL: + target_big_endian = 0; + break; +#endif + case OPTION_FIXDD: + s3_fix_data_dependency = 1; + s7_fix_data_dependency = 1; + break; + case OPTION_NWARN: + s3_warn_fix_data_dependency = 0; + s7_warn_fix_data_dependency = 0; + break; + case OPTION_SCORE5: + score3 = 0; + score7 = 1; + s7_university_version = 0; + s7_vector_size = s7_SCORE5_PIPELINE; + break; + case OPTION_SCORE5U: + score3 = 0; + score7 = 1; + s7_university_version = 1; + s7_vector_size = s7_SCORE5_PIPELINE; + break; + case OPTION_SCORE7: + score3 = 0; + score7 = 1; + s7_score7d = 1; + s7_university_version = 0; + s7_vector_size = s7_SCORE7_PIPELINE; + break; + case OPTION_SCORE3: + score3 = 1; + score7 = 0; + s3_score3d = 1; + break; + case OPTION_R1: + s3_nor1 = 0; + s7_nor1 = 0; + break; + case 'G': + s3_g_switch_value = atoi (arg); + s7_g_switch_value = atoi (arg); + break; + case OPTION_O0: + s3_g_opt = 0; + s7_g_opt = 0; + break; + case OPTION_SCORE_VERSION: + printf (_("Sunplus-v2-0-0-20060510\n")); + break; + case OPTION_PIC: + s3_score_pic = s3_NO_PIC; /* Score3 doesn't support PIC now. */ + s7_score_pic = s7_PIC; + s3_g_switch_value = 0; /* Must set -G num as 0 to generate s3_PIC code. */ + s7_g_switch_value = 0; /* Must set -G num as 0 to generate s7_PIC code. */ + break; + case OPTION_MARCH: + score_set_mach (arg); + break; + default: + return 0; + } + return 1; } - -const pseudo_typeS md_pseudo_table[] = +void +md_show_usage (FILE * fp) { - {"bss", s_score_bss, 0}, - {"text", s_score_text, 0}, - {"word", cons, 4}, - {"long", cons, 4}, - {"extend", float_cons, 'x'}, - {"ldouble", float_cons, 'x'}, - {"packed", float_cons, 'p'}, - {"end", s_score_end, 0}, - {"ent", s_score_ent, 0}, - {"frame", s_score_frame, 0}, - {"rdata", s_change_sec, 'r'}, - {"sdata", s_change_sec, 's'}, - {"set", s_score_set, 0}, - {"mask", s_score_mask, 'R'}, - {"dword", cons, 8}, - {"lcomm", s_score_lcomm, 1}, - {"section", score_s_section, 0}, - {"cpload", s_score_cpload, 0}, - {"cprestore", s_score_cprestore, 0}, - {"gpword", s_score_gpword, 0}, - {"cpadd", s_score_cpadd, 0}, - {0, 0, 0} -}; + fprintf (fp, _(" Score-specific assembler options:\n")); +#ifdef OPTION_EB + fprintf (fp, _("\ + -EB\t\tassemble code for a big-endian cpu\n")); +#endif + +#ifdef OPTION_EL + fprintf (fp, _("\ + -EL\t\tassemble code for a little-endian cpu\n")); +#endif + fprintf (fp, _("\ + -FIXDD\t\tassemble code for fix data dependency\n")); + fprintf (fp, _("\ + -NWARN\t\tassemble code for no warning message for fix data dependency\n")); + fprintf (fp, _("\ + -SCORE5\t\tassemble code for target is SCORE5\n")); + fprintf (fp, _("\ + -SCORE5U\tassemble code for target is SCORE5U\n")); + fprintf (fp, _("\ + -SCORE7\t\tassemble code for target is SCORE7, this is default setting\n")); + fprintf (fp, _("\ + -SCORE3\t\tassemble code for target is SCORE3\n")); + fprintf (fp, _("\ + -march=score7\tassemble code for target is SCORE7, this is default setting\n")); + fprintf (fp, _("\ + -march=score3\tassemble code for target is SCORE3\n")); + fprintf (fp, _("\ + -USE_R1\t\tassemble code for no warning message when using temp register r1\n")); + fprintf (fp, _("\ + -KPIC\t\tassemble code for PIC\n")); + fprintf (fp, _("\ + -O0\t\tassembler will not perform any optimizations\n")); + fprintf (fp, _("\ + -G gpnum\tassemble code for setting gpsize and default is 8 byte\n")); + fprintf (fp, _("\ + -V \t\tSunplus release version \n")); +} diff --git a/gas/config/tc-score.h b/gas/config/tc-score.h index 1f3e0f3b249..b46ef7986c0 100644 --- a/gas/config/tc-score.h +++ b/gas/config/tc-score.h @@ -1,6 +1,7 @@ /* tc-score.h -- Score specific file for assembler - Copyright 2006, 2007 Free Software Foundation, Inc. + Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by: + Brain.lin (brain.lin@sunplusct.com) Mei Ligang (ligang@sunnorth.com.cn) Pei-Lin Tsai (pltsai@sunplus.com) @@ -38,7 +39,7 @@ #define md_relax_frag(segment, fragp, stretch) score_relax_frag (segment, fragp, stretch) extern int score_relax_frag (asection *, struct frag *, long); -#define md_frag_check(fragp) score_frag_check (fragp) +/* #define md_frag_check(fragp) score_frag_check (fragp) */ extern void score_frag_check (fragS *); #define TC_VALIDATE_FIX(FIXP, SEGTYPE, SKIP) score_validate_fix (FIXP) @@ -74,10 +75,4 @@ struct score_tc_frag_data #define GLOBAL_OFFSET_TABLE_NAME "__GLOBAL_OFFSET_TABLE_" #endif -enum score_pic_level -{ - NO_PIC, - PIC -}; - #endif /*TC_SCORE */ diff --git a/gas/config/tc-score7.c b/gas/config/tc-score7.c new file mode 100644 index 00000000000..b282b1d9a31 --- /dev/null +++ b/gas/config/tc-score7.c @@ -0,0 +1,6987 @@ +/* tc-score7.c -- Assembler for Score7 + Copyright 2009 Free Software Foundation, Inc. + Contributed by: + Brain.lin (brain.lin@sunplusct.com) + Mei Ligang (ligang@sunnorth.com.cn) + Pei-Lin Tsai (pltsai@sunplus.com) + + This file is part of GAS, the GNU Assembler. + + GAS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GAS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to the Free + Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "as.h" +#include "config.h" +#include "subsegs.h" +#include "safe-ctype.h" +#include "opcode/score-inst.h" +#include "struc-symbol.h" +#include "libiberty.h" + +#ifdef OBJ_ELF +#include "elf/score.h" +#include "dwarf2dbg.h" +#endif + +static void s7_do_ldst_insn (char *); +static void s7_do_crdcrscrsimm5 (char *); +static void s7_do_ldst_unalign (char *); +static void s7_do_ldst_atomic (char *); +static void s7_do_ldst_cop (char *); +static void s7_do_macro_li_rdi32 (char *); +static void s7_do_macro_la_rdi32 (char *); +static void s7_do_macro_rdi32hi (char *); +static void s7_do_macro_rdi32lo (char *); +static void s7_do_macro_mul_rdrsrs (char *); +static void s7_do_macro_ldst_label (char *); +static void s7_do_branch (char *); +static void s7_do_jump (char *); +static void s7_do_empty (char *); +static void s7_do_rdrsrs (char *); +static void s7_do_rdsi16 (char *); +static void s7_do_rdrssi14 (char *); +static void s7_do_sub_rdsi16 (char *); +static void s7_do_sub_rdrssi14 (char *); +static void s7_do_rdrsi5 (char *); +static void s7_do_rdrsi14 (char *); +static void s7_do_rdi16 (char *); +static void s7_do_xrsi5 (char *); +static void s7_do_rdrs (char *); +static void s7_do_rdxrs (char *); +static void s7_do_rsrs (char *); +static void s7_do_rdcrs (char *); +static void s7_do_rdsrs (char *); +static void s7_do_rd (char *); +static void s7_do_rs (char *); +static void s7_do_i15 (char *); +static void s7_do_xi5x (char *); +static void s7_do_ceinst (char *); +static void s7_do_cache (char *); +static void s7_do16_rdrs (char *); +static void s7_do16_rs (char *); +static void s7_do16_xrs (char *); +static void s7_do16_mv_rdrs (char *); +static void s7_do16_hrdrs (char *); +static void s7_do16_rdhrs (char *); +static void s7_do16_rdi4 (char *); +static void s7_do16_rdi5 (char *); +static void s7_do16_xi5 (char *); +static void s7_do16_ldst_insn (char *); +static void s7_do16_ldst_imm_insn (char *); +static void s7_do16_push_pop (char *); +static void s7_do16_branch (char *); +static void s7_do16_jump (char *); +static void s7_do_rdi16_pic (char *); +static void s7_do_addi_s_pic (char *); +static void s7_do_addi_u_pic (char *); +static void s7_do_lw_pic (char *); + +#define s7_GP 28 +#define s7_PIC_CALL_REG 29 +#define s7_MAX_LITERAL_POOL_SIZE 1024 +#define s7_FAIL 0x80000000 +#define s7_SUCCESS 0 +#define s7_INSN_SIZE 4 +#define s7_INSN16_SIZE 2 +#define s7_RELAX_INST_NUM 3 + +/* For score5u : div/mul will pop warning message, mmu/alw/asw will pop error message. */ +#define s7_BAD_ARGS _("bad arguments to instruction") +#define s7_ERR_FOR_SCORE5U_MUL_DIV _("div / mul are reserved instructions") +#define s7_ERR_FOR_SCORE5U_MMU _("This architecture doesn't support mmu") +#define s7_ERR_FOR_SCORE5U_ATOMIC _("This architecture doesn't support atomic instruction") +#define s7_BAD_SKIP_COMMA s7_BAD_ARGS +#define s7_BAD_GARBAGE _("garbage following instruction"); + +#define s7_skip_whitespace(str) while (*(str) == ' ') ++(str) + +/* The name of the readonly data section. */ +#define s7_RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \ + ? ".data" \ + : OUTPUT_FLAVOR == bfd_target_ecoff_flavour \ + ? ".rdata" \ + : OUTPUT_FLAVOR == bfd_target_coff_flavour \ + ? ".rdata" \ + : OUTPUT_FLAVOR == bfd_target_elf_flavour \ + ? ".rodata" \ + : (abort (), "")) + +#define s7_RELAX_ENCODE(old, new, type, reloc1, reloc2, opt) \ + ((relax_substateT) \ + (((old) << 23) \ + | ((new) << 16) \ + | ((type) << 9) \ + | ((reloc1) << 5) \ + | ((reloc2) << 1) \ + | ((opt) ? 1 : 0))) + +#define s7_RELAX_OLD(i) (((i) >> 23) & 0x7f) +#define s7_RELAX_NEW(i) (((i) >> 16) & 0x7f) +#define s7_RELAX_TYPE(i) (((i) >> 9) & 0x7f) +#define s7_RELAX_RELOC1(i) ((valueT) ((i) >> 5) & 0xf) +#define s7_RELAX_RELOC2(i) ((valueT) ((i) >> 1) & 0xf) +#define s7_RELAX_OPT(i) ((i) & 1) +#define s7_RELAX_OPT_CLEAR(i) ((i) & ~1) + +#define s7_SET_INSN_ERROR(s) (s7_inst.error = (s)) +#define s7_INSN_IS_PCE_P(s) (strstr (str, "||") != NULL) + +#define s7_GET_INSN_CLASS(type) (s7_get_insn_class_from_type (type)) + +#define s7_GET_INSN_SIZE(type) ((s7_GET_INSN_CLASS (type) == INSN_CLASS_16) \ + ? s7_INSN16_SIZE : s7_INSN_SIZE) + +#define s7_MAX_LITTLENUMS 6 +#define s7_INSN_NAME_LEN 16 + +/* Relax will need some padding for alignment. */ +#define s7_RELAX_PAD_BYTE 3 + +#define s7_USE_GLOBAL_POINTER_OPT 1 + + + +/* Enumeration matching entries in table above. */ +enum s7_score_reg_type +{ + s7_REG_TYPE_SCORE = 0, +#define REG_TYPE_FIRST s7_REG_TYPE_SCORE + s7_REG_TYPE_SCORE_SR = 1, + s7_REG_TYPE_SCORE_CR = 2, + s7_REG_TYPE_MAX = 3 +}; + +enum s7_score_pic_level +{ + s7_NO_PIC, + s7_PIC +}; +static enum s7_score_pic_level s7_score_pic = s7_NO_PIC; + +enum s7_insn_type_for_dependency +{ + s7_D_pce, + s7_D_cond_br, + s7_D_cond_mv, + s7_D_cached, + s7_D_cachei, + s7_D_ldst, + s7_D_ldcombine, + s7_D_mtcr, + s7_D_mfcr, + s7_D_mfsr, + s7_D_mftlb, + s7_D_mtptlb, + s7_D_mtrtlb, + s7_D_stlb, + s7_D_all_insn +}; + +struct s7_insn_to_dependency +{ + char *insn_name; + enum s7_insn_type_for_dependency type; +}; + +struct s7_data_dependency +{ + enum s7_insn_type_for_dependency pre_insn_type; + char pre_reg[6]; + enum s7_insn_type_for_dependency cur_insn_type; + char cur_reg[6]; + int bubblenum_7; + int bubblenum_5; + int warn_or_error; /* warning - 0; error - 1 */ +}; + +static const struct s7_insn_to_dependency s7_insn_to_dependency_table[] = +{ + /* pce instruction. */ + {"pce", s7_D_pce}, + /* conditional branch instruction. */ + {"bcs", s7_D_cond_br}, + {"bcc", s7_D_cond_br}, + {"bgtu", s7_D_cond_br}, + {"bleu", s7_D_cond_br}, + {"beq", s7_D_cond_br}, + {"bne", s7_D_cond_br}, + {"bgt", s7_D_cond_br}, + {"ble", s7_D_cond_br}, + {"bge", s7_D_cond_br}, + {"blt", s7_D_cond_br}, + {"bmi", s7_D_cond_br}, + {"bpl", s7_D_cond_br}, + {"bvs", s7_D_cond_br}, + {"bvc", s7_D_cond_br}, + {"bcsl", s7_D_cond_br}, + {"bccl", s7_D_cond_br}, + {"bgtul", s7_D_cond_br}, + {"bleul", s7_D_cond_br}, + {"beql", s7_D_cond_br}, + {"bnel", s7_D_cond_br}, + {"bgtl", s7_D_cond_br}, + {"blel", s7_D_cond_br}, + {"bgel", s7_D_cond_br}, + {"bltl", s7_D_cond_br}, + {"bmil", s7_D_cond_br}, + {"bpll", s7_D_cond_br}, + {"bvsl", s7_D_cond_br}, + {"bvcl", s7_D_cond_br}, + {"bcs!", s7_D_cond_br}, + {"bcc!", s7_D_cond_br}, + {"bgtu!", s7_D_cond_br}, + {"bleu!", s7_D_cond_br}, + {"beq!", s7_D_cond_br}, + {"bne!", s7_D_cond_br}, + {"bgt!", s7_D_cond_br}, + {"ble!", s7_D_cond_br}, + {"bge!", s7_D_cond_br}, + {"blt!", s7_D_cond_br}, + {"bmi!", s7_D_cond_br}, + {"bpl!", s7_D_cond_br}, + {"bvs!", s7_D_cond_br}, + {"bvc!", s7_D_cond_br}, + {"brcs", s7_D_cond_br}, + {"brcc", s7_D_cond_br}, + {"brgtu", s7_D_cond_br}, + {"brleu", s7_D_cond_br}, + {"breq", s7_D_cond_br}, + {"brne", s7_D_cond_br}, + {"brgt", s7_D_cond_br}, + {"brle", s7_D_cond_br}, + {"brge", s7_D_cond_br}, + {"brlt", s7_D_cond_br}, + {"brmi", s7_D_cond_br}, + {"brpl", s7_D_cond_br}, + {"brvs", s7_D_cond_br}, + {"brvc", s7_D_cond_br}, + {"brcsl", s7_D_cond_br}, + {"brccl", s7_D_cond_br}, + {"brgtul", s7_D_cond_br}, + {"brleul", s7_D_cond_br}, + {"breql", s7_D_cond_br}, + {"brnel", s7_D_cond_br}, + {"brgtl", s7_D_cond_br}, + {"brlel", s7_D_cond_br}, + {"brgel", s7_D_cond_br}, + {"brltl", s7_D_cond_br}, + {"brmil", s7_D_cond_br}, + {"brpll", s7_D_cond_br}, + {"brvsl", s7_D_cond_br}, + {"brvcl", s7_D_cond_br}, + {"brcs!", s7_D_cond_br}, + {"brcc!", s7_D_cond_br}, + {"brgtu!", s7_D_cond_br}, + {"brleu!", s7_D_cond_br}, + {"breq!", s7_D_cond_br}, + {"brne!", s7_D_cond_br}, + {"brgt!", s7_D_cond_br}, + {"brle!", s7_D_cond_br}, + {"brge!", s7_D_cond_br}, + {"brlt!", s7_D_cond_br}, + {"brmi!", s7_D_cond_br}, + {"brpl!", s7_D_cond_br}, + {"brvs!", s7_D_cond_br}, + {"brvc!", s7_D_cond_br}, + {"brcsl!", s7_D_cond_br}, + {"brccl!", s7_D_cond_br}, + {"brgtul!", s7_D_cond_br}, + {"brleul!", s7_D_cond_br}, + {"breql!", s7_D_cond_br}, + {"brnel!", s7_D_cond_br}, + {"brgtl!", s7_D_cond_br}, + {"brlel!", s7_D_cond_br}, + {"brgel!", s7_D_cond_br}, + {"brltl!", s7_D_cond_br}, + {"brmil!", s7_D_cond_br}, + {"brpll!", s7_D_cond_br}, + {"brvsl!", s7_D_cond_br}, + {"brvcl!", s7_D_cond_br}, + /* conditional move instruction. */ + {"mvcs", s7_D_cond_mv}, + {"mvcc", s7_D_cond_mv}, + {"mvgtu", s7_D_cond_mv}, + {"mvleu", s7_D_cond_mv}, + {"mveq", s7_D_cond_mv}, + {"mvne", s7_D_cond_mv}, + {"mvgt", s7_D_cond_mv}, + {"mvle", s7_D_cond_mv}, + {"mvge", s7_D_cond_mv}, + {"mvlt", s7_D_cond_mv}, + {"mvmi", s7_D_cond_mv}, + {"mvpl", s7_D_cond_mv}, + {"mvvs", s7_D_cond_mv}, + {"mvvc", s7_D_cond_mv}, + /* move spectial instruction. */ + {"mtcr", s7_D_mtcr}, + {"mftlb", s7_D_mftlb}, + {"mtptlb", s7_D_mtptlb}, + {"mtrtlb", s7_D_mtrtlb}, + {"stlb", s7_D_stlb}, + {"mfcr", s7_D_mfcr}, + {"mfsr", s7_D_mfsr}, + /* cache instruction. */ + {"cache 8", s7_D_cached}, + {"cache 9", s7_D_cached}, + {"cache 10", s7_D_cached}, + {"cache 11", s7_D_cached}, + {"cache 12", s7_D_cached}, + {"cache 13", s7_D_cached}, + {"cache 14", s7_D_cached}, + {"cache 24", s7_D_cached}, + {"cache 26", s7_D_cached}, + {"cache 27", s7_D_cached}, + {"cache 29", s7_D_cached}, + {"cache 30", s7_D_cached}, + {"cache 31", s7_D_cached}, + {"cache 0", s7_D_cachei}, + {"cache 1", s7_D_cachei}, + {"cache 2", s7_D_cachei}, + {"cache 3", s7_D_cachei}, + {"cache 4", s7_D_cachei}, + {"cache 16", s7_D_cachei}, + {"cache 17", s7_D_cachei}, + /* load/store instruction. */ + {"lb", s7_D_ldst}, + {"lbu", s7_D_ldst}, + {"lbu!", s7_D_ldst}, + {"lbup!", s7_D_ldst}, + {"lh", s7_D_ldst}, + {"lhu", s7_D_ldst}, + {"lh!", s7_D_ldst}, + {"lhp!", s7_D_ldst}, + {"lw", s7_D_ldst}, + {"lw!", s7_D_ldst}, + {"lwp!", s7_D_ldst}, + {"sb", s7_D_ldst}, + {"sb!", s7_D_ldst}, + {"sbp!", s7_D_ldst}, + {"sh", s7_D_ldst}, + {"sh!", s7_D_ldst}, + {"shp!", s7_D_ldst}, + {"sw", s7_D_ldst}, + {"sw!", s7_D_ldst}, + {"swp!", s7_D_ldst}, + {"alw", s7_D_ldst}, + {"asw", s7_D_ldst}, + {"push!", s7_D_ldst}, + {"pushhi!", s7_D_ldst}, + {"pop!", s7_D_ldst}, + {"pophi!", s7_D_ldst}, + {"ldc1", s7_D_ldst}, + {"ldc2", s7_D_ldst}, + {"ldc3", s7_D_ldst}, + {"stc1", s7_D_ldst}, + {"stc2", s7_D_ldst}, + {"stc3", s7_D_ldst}, + {"scb", s7_D_ldst}, + {"scw", s7_D_ldst}, + {"sce", s7_D_ldst}, + /* load combine instruction. */ + {"lcb", s7_D_ldcombine}, + {"lcw", s7_D_ldcombine}, + {"lce", s7_D_ldcombine}, +}; + +static const struct s7_data_dependency s7_data_dependency_table[] = +{ + /* Condition register. */ + {s7_D_mtcr, "cr1", s7_D_pce, "", 2, 1, 0}, + {s7_D_mtcr, "cr1", s7_D_cond_br, "", 1, 0, 1}, + {s7_D_mtcr, "cr1", s7_D_cond_mv, "", 1, 0, 1}, + /* Status regiser. */ + {s7_D_mtcr, "cr0", s7_D_all_insn, "", 5, 4, 0}, + /* CCR regiser. */ + {s7_D_mtcr, "cr4", s7_D_all_insn, "", 6, 5, 0}, + /* EntryHi/EntryLo register. */ + {s7_D_mftlb, "", s7_D_mtptlb, "", 1, 1, 1}, + {s7_D_mftlb, "", s7_D_mtrtlb, "", 1, 1, 1}, + {s7_D_mftlb, "", s7_D_stlb, "", 1, 1,1}, + {s7_D_mftlb, "", s7_D_mfcr, "cr11", 1, 1, 1}, + {s7_D_mftlb, "", s7_D_mfcr, "cr12", 1, 1, 1}, + /* Index register. */ + {s7_D_stlb, "", s7_D_mtptlb, "", 1, 1, 1}, + {s7_D_stlb, "", s7_D_mftlb, "", 1, 1, 1}, + {s7_D_stlb, "", s7_D_mfcr, "cr8", 2, 2, 1}, + /* Cache. */ + {s7_D_cached, "", s7_D_ldst, "", 1, 1, 0}, + {s7_D_cached, "", s7_D_ldcombine, "", 1, 1, 0}, + {s7_D_cachei, "", s7_D_all_insn, "", 5, 4, 0}, + /* Load combine. */ + {s7_D_ldcombine, "", s7_D_mfsr, "sr1", 3, 3, 1}, +}; + + + +/* Used to contain constructed error messages. */ +static char s7_err_msg[255]; +static int s7_fix_data_dependency = 0; +static int s7_warn_fix_data_dependency = 1; + +static int s7_in_my_get_expression = 0; + +/* Default, pop warning message when using r1. */ +static int s7_nor1 = 1; + +/* Default will do instruction relax, -O0 will set s7_g_opt = 0. */ +static unsigned int s7_g_opt = 1; + +/* The size of the small data section. */ +static unsigned int s7_g_switch_value = 8; + +static segT s7_pdr_seg; + +struct s7_score_it +{ + char name[s7_INSN_NAME_LEN]; + unsigned long instruction; + unsigned long relax_inst; + int size; + int relax_size; + enum score_insn_type type; + char str[s7_MAX_LITERAL_POOL_SIZE]; + const char *error; + int bwarn; + char reg[s7_INSN_NAME_LEN]; + struct + { + bfd_reloc_code_real_type type; + expressionS exp; + int pc_rel; + }reloc; +}; +static struct s7_score_it s7_inst; + +typedef struct proc +{ + symbolS *isym; + unsigned long reg_mask; + unsigned long reg_offset; + unsigned long fpreg_mask; + unsigned long leaf; + unsigned long frame_offset; + unsigned long frame_reg; + unsigned long pc_reg; +} s7_procS; +static s7_procS s7_cur_proc; +static s7_procS *s7_cur_proc_ptr; +static int s7_numprocs; + +/* Structure for a hash table entry for a register. */ +struct s7_reg_entry +{ + const char *name; + int number; +}; + +static const struct s7_reg_entry s7_score_rn_table[] = +{ + {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3}, + {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7}, + {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11}, + {"r12", 12}, {"r13", 13}, {"r14", 14}, {"r15", 15}, + {"r16", 16}, {"r17", 17}, {"r18", 18}, {"r19", 19}, + {"r20", 20}, {"r21", 21}, {"r22", 22}, {"r23", 23}, + {"r24", 24}, {"r25", 25}, {"r26", 26}, {"r27", 27}, + {"r28", 28}, {"r29", 29}, {"r30", 30}, {"r31", 31}, + {NULL, 0} +}; + +static const struct s7_reg_entry s7_score_srn_table[] = +{ + {"sr0", 0}, {"sr1", 1}, {"sr2", 2}, + {NULL, 0} +}; + +static const struct s7_reg_entry s7_score_crn_table[] = +{ + {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3}, + {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7}, + {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11}, + {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15}, + {"cr16", 16}, {"cr17", 17}, {"cr18", 18}, {"cr19", 19}, + {"cr20", 20}, {"cr21", 21}, {"cr22", 22}, {"cr23", 23}, + {"cr24", 24}, {"cr25", 25}, {"cr26", 26}, {"cr27", 27}, + {"cr28", 28}, {"cr29", 29}, {"cr30", 30}, {"cr31", 31}, + {NULL, 0} +}; + +struct s7_reg_map +{ + const struct s7_reg_entry *names; + int max_regno; + struct hash_control *htab; + const char *expected; +}; + +static struct s7_reg_map s7_all_reg_maps[] = +{ + {s7_score_rn_table, 31, NULL, N_("S+core register expected")}, + {s7_score_srn_table, 2, NULL, N_("S+core special-register expected")}, + {s7_score_crn_table, 31, NULL, N_("S+core co-processor register expected")}, +}; + +static struct hash_control *s7_score_ops_hsh = NULL; +static struct hash_control *s7_dependency_insn_hsh = NULL; + + +struct s7_datafield_range +{ + int data_type; + int bits; + int range[2]; +}; + +static struct s7_datafield_range s7_score_df_range[] = +{ + {_IMM4, 4, {0, (1 << 4) - 1}}, /* ( 0 ~ 15 ) */ + {_IMM5, 5, {0, (1 << 5) - 1}}, /* ( 0 ~ 31 ) */ + {_IMM8, 8, {0, (1 << 8) - 1}}, /* ( 0 ~ 255 ) */ + {_IMM14, 14, {0, (1 << 14) - 1}}, /* ( 0 ~ 16383) */ + {_IMM15, 15, {0, (1 << 15) - 1}}, /* ( 0 ~ 32767) */ + {_IMM16, 16, {0, (1 << 16) - 1}}, /* ( 0 ~ 65535) */ + {_SIMM10, 10, {-(1 << 9), (1 << 9) - 1}}, /* ( -512 ~ 511 ) */ + {_SIMM12, 12, {-(1 << 11), (1 << 11) - 1}}, /* ( -2048 ~ 2047 ) */ + {_SIMM14, 14, {-(1 << 13), (1 << 13) - 1}}, /* ( -8192 ~ 8191 ) */ + {_SIMM15, 15, {-(1 << 14), (1 << 14) - 1}}, /* (-16384 ~ 16383) */ + {_SIMM16, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */ + {_SIMM14_NEG, 14, {-(1 << 13), (1 << 13) - 1}}, /* ( -8191 ~ 8192 ) */ + {_IMM16_NEG, 16, {0, (1 << 16) - 1}}, /* (-65535 ~ 0 ) */ + {_SIMM16_NEG, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */ + {_IMM20, 20, {0, (1 << 20) - 1}}, + {_IMM25, 25, {0, (1 << 25) - 1}}, + {_DISP8div2, 8, {-(1 << 8), (1 << 8) - 1}}, /* ( -256 ~ 255 ) */ + {_DISP11div2, 11, {0, 0}}, + {_DISP19div2, 19, {-(1 << 19), (1 << 19) - 1}}, /* (-524288 ~ 524287) */ + {_DISP24div2, 24, {0, 0}}, + {_VALUE, 32, {0, ((unsigned int)1 << 31) - 1}}, + {_VALUE_HI16, 16, {0, (1 << 16) - 1}}, + {_VALUE_LO16, 16, {0, (1 << 16) - 1}}, + {_VALUE_LDST_LO16, 16, {0, (1 << 16) - 1}}, + {_SIMM16_LA, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */ + {_IMM5_RSHIFT_1, 5, {0, (1 << 6) - 1}}, /* ( 0 ~ 63 ) */ + {_IMM5_RSHIFT_2, 5, {0, (1 << 7) - 1}}, /* ( 0 ~ 127 ) */ + {_SIMM16_LA_POS, 16, {0, (1 << 15) - 1}}, /* ( 0 ~ 32767) */ + {_IMM5_RANGE_8_31, 5, {8, 31}}, /* But for cop0 the valid data : (8 ~ 31). */ + {_IMM10_RSHIFT_2, 10, {-(1 << 11), (1 << 11) - 1}}, /* For ldc#, stc#. */ + {_SIMM10, 10, {0, (1 << 10) - 1}}, /* ( -1024 ~ 1023 ) */ + {_SIMM12, 12, {0, (1 << 12) - 1}}, /* ( -2048 ~ 2047 ) */ + {_SIMM14, 14, {0, (1 << 14) - 1}}, /* ( -8192 ~ 8191 ) */ + {_SIMM15, 15, {0, (1 << 15) - 1}}, /* (-16384 ~ 16383) */ + {_SIMM16, 16, {0, (1 << 16) - 1}}, /* (-65536 ~ 65536) */ + {_SIMM14_NEG, 14, {0, (1 << 16) - 1}}, /* ( -8191 ~ 8192 ) */ + {_IMM16_NEG, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */ + {_SIMM16_NEG, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */ + {_IMM20, 20, {0, (1 << 20) - 1}}, /* (-32768 ~ 32767) */ + {_IMM25, 25, {0, (1 << 25) - 1}}, /* (-32768 ~ 32767) */ + {_GP_IMM15, 15, {0, (1 << 15) - 1}}, /* ( 0 ~ 65535) */ + {_GP_IMM14, 14, {0, (1 << 14) - 1}}, /* ( 0 ~ 65535) */ + {_SIMM16_pic, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */ + {_IMM16_LO16_pic, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */ + {_IMM16_pic, 16, {0, (1 << 16) - 1}}, /* ( 0 ~ 65535) */ +}; + + +struct s7_asm_opcode +{ + /* Instruction name. */ + const char *template; + + /* Instruction Opcode. */ + bfd_vma value; + + /* Instruction bit mask. */ + bfd_vma bitmask; + + /* Relax instruction opcode. 0x8000 imply no relaxation. */ + bfd_vma relax_value; + + /* Instruction type. */ + enum score_insn_type type; + + /* Function to call to parse args. */ + void (*parms) (char *); +}; + +static const struct s7_asm_opcode s7_score_ldst_insns[] = +{ + {"lw", 0x20000000, 0x3e000000, 0x2008, Rd_rvalueRs_SI15, s7_do_ldst_insn}, + {"lw", 0x06000000, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s7_do_ldst_insn}, + {"lw", 0x0e000000, 0x3e000007, 0x200a, Rd_rvalueRs_postSI12, s7_do_ldst_insn}, + {"lh", 0x22000000, 0x3e000000, 0x2009, Rd_rvalueRs_SI15, s7_do_ldst_insn}, + {"lh", 0x06000001, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s7_do_ldst_insn}, + {"lh", 0x0e000001, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s7_do_ldst_insn}, + {"lhu", 0x24000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, s7_do_ldst_insn}, + {"lhu", 0x06000002, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s7_do_ldst_insn}, + {"lhu", 0x0e000002, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s7_do_ldst_insn}, + {"lb", 0x26000000, 0x3e000000, 0x8000, Rd_rvalueRs_SI15, s7_do_ldst_insn}, + {"lb", 0x06000003, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s7_do_ldst_insn}, + {"lb", 0x0e000003, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s7_do_ldst_insn}, + {"sw", 0x28000000, 0x3e000000, 0x200c, Rd_lvalueRs_SI15, s7_do_ldst_insn}, + {"sw", 0x06000004, 0x3e000007, 0x200e, Rd_lvalueRs_preSI12, s7_do_ldst_insn}, + {"sw", 0x0e000004, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, s7_do_ldst_insn}, + {"sh", 0x2a000000, 0x3e000000, 0x200d, Rd_lvalueRs_SI15, s7_do_ldst_insn}, + {"sh", 0x06000005, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, s7_do_ldst_insn}, + {"sh", 0x0e000005, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, s7_do_ldst_insn}, + {"lbu", 0x2c000000, 0x3e000000, 0x200b, Rd_rvalueRs_SI15, s7_do_ldst_insn}, + {"lbu", 0x06000006, 0x3e000007, 0x8000, Rd_rvalueRs_preSI12, s7_do_ldst_insn}, + {"lbu", 0x0e000006, 0x3e000007, 0x8000, Rd_rvalueRs_postSI12, s7_do_ldst_insn}, + {"sb", 0x2e000000, 0x3e000000, 0x200f, Rd_lvalueRs_SI15, s7_do_ldst_insn}, + {"sb", 0x06000007, 0x3e000007, 0x8000, Rd_lvalueRs_preSI12, s7_do_ldst_insn}, + {"sb", 0x0e000007, 0x3e000007, 0x8000, Rd_lvalueRs_postSI12, s7_do_ldst_insn}, +}; + +static const struct s7_asm_opcode s7_score_insns[] = +{ + {"abs", 0x3800000a, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"abs.s", 0x3800004b, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"add", 0x00000010, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"add.c", 0x00000011, 0x3e0003ff, 0x2000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"add.s", 0x38000048, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"addc", 0x00000012, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"addc.c", 0x00000013, 0x3e0003ff, 0x0009, Rd_Rs_Rs, s7_do_rdrsrs}, + {"addi", 0x02000000, 0x3e0e0001, 0x8000, Rd_SI16, s7_do_rdsi16}, + {"addi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, s7_do_rdsi16}, + {"addis", 0x0a000000, 0x3e0e0001, 0x8000, Rd_SI16, s7_do_rdi16}, + {"addis.c", 0x0a000001, 0x3e0e0001, 0x8000, Rd_SI16, s7_do_rdi16}, + {"addri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, s7_do_rdrssi14}, + {"addri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, s7_do_rdrssi14}, + {"addc!", 0x0009, 0x700f, 0x00000013, Rd_Rs, s7_do16_rdrs}, + {"add!", 0x2000, 0x700f, 0x00000011, Rd_Rs, s7_do16_rdrs}, + {"addei!", 0x6000 , 0x7087, 0x02000001, Rd_I4, s7_do16_rdi4}, + {"subi", 0x02000000, 0x3e0e0001, 0x8000, Rd_SI16, s7_do_sub_rdsi16}, + {"subi.c", 0x02000001, 0x3e0e0001, 0x8000, Rd_SI16, s7_do_sub_rdsi16}, + {"subri", 0x10000000, 0x3e000001, 0x8000, Rd_Rs_SI14, s7_do_sub_rdrssi14}, + {"subri.c", 0x10000001, 0x3e000001, 0x8000, Rd_Rs_SI14, s7_do_sub_rdrssi14}, + {"and", 0x00000020, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"and.c", 0x00000021, 0x3e0003ff, 0x2004, Rd_Rs_Rs, s7_do_rdrsrs}, + {"andi", 0x02080000, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16}, + {"andi.c", 0x02080001, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16}, + {"andis", 0x0a080000, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16}, + {"andis.c", 0x0a080001, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16}, + {"andri", 0x18000000, 0x3e000001, 0x8000, Rd_Rs_I14, s7_do_rdrsi14}, + {"andri.c", 0x18000001, 0x3e000001, 0x8000, Rd_Rs_I14, s7_do_rdrsi14}, + {"and!", 0x2004, 0x700f, 0x00000021, Rd_Rs, s7_do16_rdrs}, + {"bcs", 0x08000000, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch}, + {"bcc", 0x08000400, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch}, + {"bcnz", 0x08003800, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch}, + {"bcsl", 0x08000001, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch}, + {"bccl", 0x08000401, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch}, + {"bcnzl", 0x08003801, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch}, + {"bcs!", 0x4000, 0x7f00, 0x08000000, PC_DISP8div2, s7_do16_branch}, + {"bcc!", 0x4100, 0x7f00, 0x08000400, PC_DISP8div2, s7_do16_branch}, + {"bcnz!", 0x4e00, 0x7f00, 0x08003800, PC_DISP8div2, s7_do16_branch}, + {"beq", 0x08001000, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch}, + {"beql", 0x08001001, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch}, + {"beq!", 0x4400, 0x7f00, 0x08001000, PC_DISP8div2, s7_do16_branch}, + {"bgtu", 0x08000800, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch}, + {"bgt", 0x08001800, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch}, + {"bge", 0x08002000, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch}, + {"bgtul", 0x08000801, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch}, + {"bgtl", 0x08001801, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch}, + {"bgel", 0x08002001, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch}, + {"bgtu!", 0x4200, 0x7f00, 0x08000800, PC_DISP8div2, s7_do16_branch}, + {"bgt!", 0x4600, 0x7f00, 0x08001800, PC_DISP8div2, s7_do16_branch}, + {"bge!", 0x4800, 0x7f00, 0x08002000, PC_DISP8div2, s7_do16_branch}, + {"bitclr.c", 0x00000029, 0x3e0003ff, 0x6004, Rd_Rs_I5, s7_do_rdrsi5}, + {"bitrev", 0x3800000c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"bitset.c", 0x0000002b, 0x3e0003ff, 0x6005, Rd_Rs_I5, s7_do_rdrsi5}, + {"bittst.c", 0x0000002d, 0x3e0003ff, 0x6006, x_Rs_I5, s7_do_xrsi5}, + {"bittgl.c", 0x0000002f, 0x3e0003ff, 0x6007, Rd_Rs_I5, s7_do_rdrsi5}, + {"bitclr!", 0x6004, 0x7007, 0x00000029, Rd_I5, s7_do16_rdi5}, + {"bitset!", 0x6005, 0x7007, 0x0000002b, Rd_I5, s7_do16_rdi5}, + {"bittst!", 0x6006, 0x7007, 0x0000002d, Rd_I5, s7_do16_rdi5}, + {"bittgl!", 0x6007, 0x7007, 0x0000002f, Rd_I5, s7_do16_rdi5}, + {"bleu", 0x08000c00, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch}, + {"ble", 0x08001c00, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch}, + {"blt", 0x08002400, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch}, + {"bleul", 0x08000c01, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch}, + {"blel", 0x08001c01, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch}, + {"bltl", 0x08002401, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch}, + {"bl", 0x08003c01, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch}, + {"bleu!", 0x4300, 0x7f00, 0x08000c00, PC_DISP8div2, s7_do16_branch}, + {"ble!", 0x4700, 0x7f00, 0x08001c00, PC_DISP8div2, s7_do16_branch}, + {"blt!", 0x4900, 0x7f00, 0x08002400, PC_DISP8div2, s7_do16_branch}, + {"bmi", 0x08002800, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch}, + {"bmil", 0x08002801, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch}, + {"bmi!", 0x00004a00, 0x00007f00, 0x08002800, PC_DISP8div2, s7_do16_branch}, + {"bne", 0x08001400, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch}, + {"bnel", 0x08001401, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch}, + {"bne!", 0x4500, 0x7f00, 0x08001400, PC_DISP8div2, s7_do16_branch}, + {"bpl", 0x08002c00, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch}, + {"bpll", 0x08002c01, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch}, + {"bpl!", 0x4b00, 0x7f00, 0x08002c00, PC_DISP8div2, s7_do16_branch}, + {"brcs", 0x00000008, 0x3e007fff, 0x0004, x_Rs_x, s7_do_rs}, + {"brcc", 0x00000408, 0x3e007fff, 0x0104, x_Rs_x, s7_do_rs}, + {"brgtu", 0x00000808, 0x3e007fff, 0x0204, x_Rs_x, s7_do_rs}, + {"brleu", 0x00000c08, 0x3e007fff, 0x0304, x_Rs_x, s7_do_rs}, + {"breq", 0x00001008, 0x3e007fff, 0x0404, x_Rs_x, s7_do_rs}, + {"brne", 0x00001408, 0x3e007fff, 0x0504, x_Rs_x, s7_do_rs}, + {"brgt", 0x00001808, 0x3e007fff, 0x0604, x_Rs_x, s7_do_rs}, + {"brle", 0x00001c08, 0x3e007fff, 0x0704, x_Rs_x, s7_do_rs}, + {"brge", 0x00002008, 0x3e007fff, 0x0804, x_Rs_x, s7_do_rs}, + {"brlt", 0x00002408, 0x3e007fff, 0x0904, x_Rs_x, s7_do_rs}, + {"brmi", 0x00002808, 0x3e007fff, 0x0a04, x_Rs_x, s7_do_rs}, + {"brpl", 0x00002c08, 0x3e007fff, 0x0b04, x_Rs_x, s7_do_rs}, + {"brvs", 0x00003008, 0x3e007fff, 0x0c04, x_Rs_x, s7_do_rs}, + {"brvc", 0x00003408, 0x3e007fff, 0x0d04, x_Rs_x, s7_do_rs}, + {"brcnz", 0x00003808, 0x3e007fff, 0x0e04, x_Rs_x, s7_do_rs}, + {"br", 0x00003c08, 0x3e007fff, 0x0f04, x_Rs_x, s7_do_rs}, + {"brcsl", 0x00000009, 0x3e007fff, 0x000c, x_Rs_x, s7_do_rs}, + {"brccl", 0x00000409, 0x3e007fff, 0x010c, x_Rs_x, s7_do_rs}, + {"brgtul", 0x00000809, 0x3e007fff, 0x020c, x_Rs_x, s7_do_rs}, + {"brleul", 0x00000c09, 0x3e007fff, 0x030c, x_Rs_x, s7_do_rs}, + {"breql", 0x00001009, 0x3e007fff, 0x040c, x_Rs_x, s7_do_rs}, + {"brnel", 0x00001409, 0x3e007fff, 0x050c, x_Rs_x, s7_do_rs}, + {"brgtl", 0x00001809, 0x3e007fff, 0x060c, x_Rs_x, s7_do_rs}, + {"brlel", 0x00001c09, 0x3e007fff, 0x070c, x_Rs_x, s7_do_rs}, + {"brgel", 0x00002009, 0x3e007fff, 0x080c, x_Rs_x, s7_do_rs}, + {"brltl", 0x00002409, 0x3e007fff, 0x090c, x_Rs_x, s7_do_rs}, + {"brmil", 0x00002809, 0x3e007fff, 0x0a0c, x_Rs_x, s7_do_rs}, + {"brpll", 0x00002c09, 0x3e007fff, 0x0b0c, x_Rs_x, s7_do_rs}, + {"brvsl", 0x00003009, 0x3e007fff, 0x0c0c, x_Rs_x, s7_do_rs}, + {"brvcl", 0x00003409, 0x3e007fff, 0x0d0c, x_Rs_x, s7_do_rs}, + {"brcnzl", 0x00003809, 0x3e007fff, 0x0e0c, x_Rs_x, s7_do_rs}, + {"brl", 0x00003c09, 0x3e007fff, 0x0f0c, x_Rs_x, s7_do_rs}, + {"brcs!", 0x0004, 0x7f0f, 0x00000008, x_Rs, s7_do16_xrs}, + {"brcc!", 0x0104, 0x7f0f, 0x00000408, x_Rs, s7_do16_xrs}, + {"brgtu!", 0x0204, 0x7f0f, 0x00000808, x_Rs, s7_do16_xrs}, + {"brleu!", 0x0304, 0x7f0f, 0x00000c08, x_Rs, s7_do16_xrs}, + {"breq!", 0x0404, 0x7f0f, 0x00001008, x_Rs, s7_do16_xrs}, + {"brne!", 0x0504, 0x7f0f, 0x00001408, x_Rs, s7_do16_xrs}, + {"brgt!", 0x0604, 0x7f0f, 0x00001808, x_Rs, s7_do16_xrs}, + {"brle!", 0x0704, 0x7f0f, 0x00001c08, x_Rs, s7_do16_xrs}, + {"brge!", 0x0804, 0x7f0f, 0x00002008, x_Rs, s7_do16_xrs}, + {"brlt!", 0x0904, 0x7f0f, 0x00002408, x_Rs, s7_do16_xrs}, + {"brmi!", 0x0a04, 0x7f0f, 0x00002808, x_Rs, s7_do16_xrs}, + {"brpl!", 0x0b04, 0x7f0f, 0x00002c08, x_Rs, s7_do16_xrs}, + {"brvs!", 0x0c04, 0x7f0f, 0x00003008, x_Rs, s7_do16_xrs}, + {"brvc!", 0x0d04, 0x7f0f, 0x00003408, x_Rs, s7_do16_xrs}, + {"brcnz!", 0x0e04, 0x7f0f, 0x00003808, x_Rs, s7_do16_xrs}, + {"br!", 0x0f04, 0x7f0f, 0x00003c08, x_Rs, s7_do16_xrs}, + {"brcsl!", 0x000c, 0x7f0f, 0x00000009, x_Rs, s7_do16_xrs}, + {"brccl!", 0x010c, 0x7f0f, 0x00000409, x_Rs, s7_do16_xrs}, + {"brgtul!", 0x020c, 0x7f0f, 0x00000809, x_Rs, s7_do16_xrs}, + {"brleul!", 0x030c, 0x7f0f, 0x00000c09, x_Rs, s7_do16_xrs}, + {"breql!", 0x040c, 0x7f0f, 0x00001009, x_Rs, s7_do16_xrs}, + {"brnel!", 0x050c, 0x7f0f, 0x00001409, x_Rs, s7_do16_xrs}, + {"brgtl!", 0x060c, 0x7f0f, 0x00001809, x_Rs, s7_do16_xrs}, + {"brlel!", 0x070c, 0x7f0f, 0x00001c09, x_Rs, s7_do16_xrs}, + {"brgel!", 0x080c, 0x7f0f, 0x00002009, x_Rs, s7_do16_xrs}, + {"brltl!", 0x090c, 0x7f0f, 0x00002409, x_Rs, s7_do16_xrs}, + {"brmil!", 0x0a0c, 0x7f0f, 0x00002809, x_Rs, s7_do16_xrs}, + {"brpll!", 0x0b0c, 0x7f0f, 0x00002c09, x_Rs, s7_do16_xrs}, + {"brvsl!", 0x0c0c, 0x7f0f, 0x00003009, x_Rs, s7_do16_xrs}, + {"brvcl!", 0x0d0c, 0x7f0f, 0x00003409, x_Rs, s7_do16_xrs}, + {"brcnzl!", 0x0e0c, 0x7f0f, 0x00003809, x_Rs, s7_do16_xrs}, + {"brl!", 0x0f0c, 0x7f0f, 0x00003c09, x_Rs, s7_do16_xrs}, + {"bvs", 0x08003000, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch}, + {"bvc", 0x08003400, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch}, + {"bvsl", 0x08003001, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch}, + {"bvcl", 0x08003401, 0x3e007c01, 0x8000, PC_DISP19div2, s7_do_branch}, + {"bvs!", 0x4c00, 0x7f00, 0x08003000, PC_DISP8div2, s7_do16_branch}, + {"bvc!", 0x4d00, 0x7f00, 0x08003400, PC_DISP8div2, s7_do16_branch}, + {"b!", 0x4f00, 0x7f00, 0x08003c00, PC_DISP8div2, s7_do16_branch}, + {"b", 0x08003c00, 0x3e007c01, 0x4000, PC_DISP19div2, s7_do_branch}, + {"cache", 0x30000000, 0x3ff00000, 0x8000, OP5_rvalueRs_SI15, s7_do_cache}, + {"ceinst", 0x38000000, 0x3e000000, 0x8000, I5_Rs_Rs_I5_OP5, s7_do_ceinst}, + {"clz", 0x3800000d, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"cmpteq.c", 0x00000019, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"cmptmi.c", 0x00100019, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"cmp.c", 0x00300019, 0x3ff003ff, 0x2003, x_Rs_Rs, s7_do_rsrs}, + {"cmpzteq.c", 0x0000001b, 0x3ff07fff, 0x8000, x_Rs_x, s7_do_rs}, + {"cmpztmi.c", 0x0010001b, 0x3ff07fff, 0x8000, x_Rs_x, s7_do_rs}, + {"cmpz.c", 0x0030001b, 0x3ff07fff, 0x8000, x_Rs_x, s7_do_rs}, + {"cmpi.c", 0x02040001, 0x3e0e0001, 0x8000, Rd_SI16, s7_do_rdsi16}, + {"cmp!", 0x2003, 0x700f, 0x00300019, Rd_Rs, s7_do16_rdrs}, + {"cop1", 0x0c00000c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, s7_do_crdcrscrsimm5}, + {"cop2", 0x0c000014, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, s7_do_crdcrscrsimm5}, + {"cop3", 0x0c00001c, 0x3e00001f, 0x8000, Rd_Rs_Rs_imm, s7_do_crdcrscrsimm5}, + {"drte", 0x0c0000a4, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty}, + {"extsb", 0x00000058, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"extsb.c", 0x00000059, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"extsh", 0x0000005a, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"extsh.c", 0x0000005b, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"extzb", 0x0000005c, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"extzb.c", 0x0000005d, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"extzh", 0x0000005e, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"extzh.c", 0x0000005f, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"jl", 0x04000001, 0x3e000001, 0x8000, PC_DISP24div2, s7_do_jump}, + {"jl!", 0x3001, 0x7001, 0x04000001, PC_DISP11div2, s7_do16_jump}, + {"j!", 0x3000, 0x7001, 0x04000000, PC_DISP11div2, s7_do16_jump}, + {"j", 0x04000000, 0x3e000001, 0x8000, PC_DISP24div2, s7_do_jump}, + {"lbu!", 0x200b, 0x0000700f, 0x2c000000, Rd_rvalueRs, s7_do16_ldst_insn}, + {"lbup!", 0x7003, 0x7007, 0x2c000000, Rd_rvalueBP_I5, s7_do16_ldst_imm_insn}, + {"alw", 0x0000000c, 0x3e0003ff, 0x8000, Rd_rvalue32Rs, s7_do_ldst_atomic}, + {"lcb", 0x00000060, 0x3e0003ff, 0x8000, x_rvalueRs_post4, s7_do_ldst_unalign}, + {"lcw", 0x00000062, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, s7_do_ldst_unalign}, + {"lce", 0x00000066, 0x3e0003ff, 0x8000, Rd_rvalueRs_post4, s7_do_ldst_unalign}, + {"ldc1", 0x0c00000a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, s7_do_ldst_cop}, + {"ldc2", 0x0c000012, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, s7_do_ldst_cop}, + {"ldc3", 0x0c00001a, 0x3e00001f, 0x8000, Rd_rvalueRs_SI10, s7_do_ldst_cop}, + {"lh!", 0x2009, 0x700f, 0x22000000, Rd_rvalueRs, s7_do16_ldst_insn}, + {"lhp!", 0x7001, 0x7007, 0x22000000, Rd_rvalueBP_I5, s7_do16_ldst_imm_insn}, + {"ldi", 0x020c0000, 0x3e0e0000, 0x5000, Rd_SI16, s7_do_rdsi16}, + {"ldis", 0x0a0c0000, 0x3e0e0000, 0x8000, Rd_I16, s7_do_rdi16}, + {"ldiu!", 0x5000, 0x7000, 0x020c0000, Rd_I8, s7_do16_ldst_imm_insn}, + {"lw!", 0x2008, 0x700f, 0x20000000, Rd_rvalueRs, s7_do16_ldst_insn}, + {"lwp!", 0x7000, 0x7007, 0x20000000, Rd_rvalueBP_I5, s7_do16_ldst_imm_insn}, + {"mfcel", 0x00000448, 0x3e007fff, 0x8000, Rd_x_x, s7_do_rd}, + {"mfcel!", 0x1001, 0x7f0f, 0x00000448, x_Rs, s7_do16_rs}, + {"mad", 0x38000000, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"mad.f!", 0x1004, 0x700f, 0x38000080, Rd_Rs, s7_do16_rdrs}, + {"madh", 0x38000203, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"madh.fs", 0x380002c3, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"madh.fs!", 0x100b, 0x700f, 0x380002c3, Rd_Rs, s7_do16_rdrs}, + {"madl", 0x38000002, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"madl.fs", 0x380000c2, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"madl.fs!", 0x100a, 0x700f, 0x380000c2, Rd_Rs, s7_do16_rdrs}, + {"madu", 0x38000020, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"madu!", 0x1005, 0x700f, 0x38000020, Rd_Rs, s7_do16_rdrs}, + {"mad.f", 0x38000080, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"max", 0x38000007, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"mazh", 0x38000303, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"mazh.f", 0x38000383, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"mazh.f!", 0x1009, 0x700f, 0x38000383, Rd_Rs, s7_do16_rdrs}, + {"mazl", 0x38000102, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"mazl.f", 0x38000182, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"mazl.f!", 0x1008, 0x700f, 0x38000182, Rd_Rs, s7_do16_rdrs}, + {"mfceh", 0x00000848, 0x3e007fff, 0x8000, Rd_x_x, s7_do_rd}, + {"mfceh!", 0x1101, 0x7f0f, 0x00000848, x_Rs, s7_do16_rs}, + {"mfcehl", 0x00000c48, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"mfsr", 0x00000050, 0x3e0003ff, 0x8000, Rd_x_I5, s7_do_rdsrs}, + {"mfcr", 0x0c000001, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs}, + {"mfc1", 0x0c000009, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs}, + {"mfc2", 0x0c000011, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs}, + {"mfc3", 0x0c000019, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs}, + {"mfcc1", 0x0c00000f, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs}, + {"mfcc2", 0x0c000017, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs}, + {"mfcc3", 0x0c00001f, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs}, + {"mhfl!", 0x0002, 0x700f, 0x00003c56, Rd_LowRs, s7_do16_hrdrs}, + {"min", 0x38000006, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"mlfh!", 0x0001, 0x700f, 0x00003c56, Rd_HighRs, s7_do16_rdhrs}, + {"msb", 0x38000001, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"msb.f!", 0x1006, 0x700f, 0x38000081, Rd_Rs, s7_do16_rdrs}, + {"msbh", 0x38000205, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"msbh.fs", 0x380002c5, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"msbh.fs!", 0x100f, 0x700f, 0x380002c5, Rd_Rs, s7_do16_rdrs}, + {"msbl", 0x38000004, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"msbl.fs", 0x380000c4, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"msbl.fs!", 0x100e, 0x700f, 0x380000c4, Rd_Rs, s7_do16_rdrs}, + {"msbu", 0x38000021, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"msbu!", 0x1007, 0x700f, 0x38000021, Rd_Rs, s7_do16_rdrs}, + {"msb.f", 0x38000081, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"mszh", 0x38000305, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"mszh.f", 0x38000385, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"mszh.f!", 0x100d, 0x700f, 0x38000385, Rd_Rs, s7_do16_rdrs}, + {"mszl", 0x38000104, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"mszl.f", 0x38000184, 0x3ff003ff, 0x8000, x_Rs_Rs, s7_do_rsrs}, + {"mszl.f!", 0x100c, 0x700f, 0x38000184, Rd_Rs, s7_do16_rdrs}, + {"mtcel!", 0x1000, 0x7f0f, 0x0000044a, x_Rs, s7_do16_rs}, + {"mtcel", 0x0000044a, 0x3e007fff, 0x8000, Rd_x_x, s7_do_rd}, + {"mtceh", 0x0000084a, 0x3e007fff, 0x8000, Rd_x_x, s7_do_rd}, + {"mtceh!", 0x1100, 0x7f0f, 0x0000084a, x_Rs, s7_do16_rs}, + {"mtcehl", 0x00000c4a, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"mtsr", 0x00000052, 0x3e0003ff, 0x8000, x_Rs_I5, s7_do_rdsrs}, + {"mtcr", 0x0c000000, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs}, + {"mtc1", 0x0c000008, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs}, + {"mtc2", 0x0c000010, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs}, + {"mtc3", 0x0c000018, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs}, + {"mtcc1", 0x0c00000e, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs}, + {"mtcc2", 0x0c000016, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs}, + {"mtcc3", 0x0c00001e, 0x3e00001f, 0x8000, Rd_Rs_x, s7_do_rdcrs}, + {"mul.f!", 0x1002, 0x700f, 0x00000041, Rd_Rs, s7_do16_rdrs}, + {"mulu!", 0x1003, 0x700f, 0x00000042, Rd_Rs, s7_do16_rdrs}, + {"mvcs", 0x00000056, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"mvcc", 0x00000456, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"mvgtu", 0x00000856, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"mvleu", 0x00000c56, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"mveq", 0x00001056, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"mvne", 0x00001456, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"mvgt", 0x00001856, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"mvle", 0x00001c56, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"mvge", 0x00002056, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"mvlt", 0x00002456, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"mvmi", 0x00002856, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"mvpl", 0x00002c56, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"mvvs", 0x00003056, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"mvvc", 0x00003456, 0x3e007fff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"mv", 0x00003c56, 0x3e007fff, 0x0003, Rd_Rs_x, s7_do_rdrs}, + {"mv!", 0x0003, 0x700f, 0x00003c56, Rd_Rs, s7_do16_mv_rdrs}, + {"neg", 0x0000001e, 0x3e0003ff, 0x8000, Rd_x_Rs, s7_do_rdxrs}, + {"neg.c", 0x0000001f, 0x3e0003ff, 0x2002, Rd_x_Rs, s7_do_rdxrs}, + {"neg!", 0x2002, 0x700f, 0x0000001f, Rd_Rs, s7_do16_rdrs}, + {"nop", 0x00000000, 0x3e0003ff, 0x0000, NO_OPD, s7_do_empty}, + {"not", 0x00000024, 0x3e0003ff, 0x8000, Rd_Rs_x, s7_do_rdrs}, + {"not.c", 0x00000025, 0x3e0003ff, 0x2006, Rd_Rs_x, s7_do_rdrs}, + {"nop!", 0x0000, 0x700f, 0x00000000, NO16_OPD, s7_do_empty}, + {"not!", 0x2006, 0x700f, 0x00000025, Rd_Rs, s7_do16_rdrs}, + {"or", 0x00000022, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"or.c", 0x00000023, 0x3e0003ff, 0x2005, Rd_Rs_Rs, s7_do_rdrsrs}, + {"ori", 0x020a0000, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16}, + {"ori.c", 0x020a0001, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16}, + {"oris", 0x0a0a0000, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16}, + {"oris.c", 0x0a0a0001, 0x3e0e0001, 0x8000, Rd_I16, s7_do_rdi16}, + {"orri", 0x1a000000, 0x3e000001, 0x8000, Rd_Rs_I14, s7_do_rdrsi14}, + {"orri.c", 0x1a000001, 0x3e000001, 0x8000, Rd_Rs_I14, s7_do_rdrsi14}, + {"or!", 0x2005, 0x700f, 0x00000023, Rd_Rs, s7_do16_rdrs}, + {"pflush", 0x0000000a, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty}, + {"pop!", 0x200a, 0x700f, 0x0e000000, Rd_rvalueRs, s7_do16_push_pop}, + {"push!", 0x200e, 0x700f, 0x06000004, Rd_lvalueRs, s7_do16_push_pop}, + {"ror", 0x00000038, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"ror.c", 0x00000039, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"rorc.c", 0x0000003b, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"rol", 0x0000003c, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"rol.c", 0x0000003d, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"rolc.c", 0x0000003f, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"rori", 0x00000078, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5}, + {"rori.c", 0x00000079, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5}, + {"roric.c", 0x0000007b, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5}, + {"roli", 0x0000007c, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5}, + {"roli.c", 0x0000007d, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5}, + {"rolic.c", 0x0000007f, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5}, + {"rte", 0x0c000084, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty}, + {"sb!", 0x200f, 0x700f, 0x2e000000, Rd_lvalueRs, s7_do16_ldst_insn}, + {"sbp!", 0x7007, 0x7007, 0x2e000000, Rd_lvalueBP_I5, s7_do16_ldst_imm_insn}, + {"asw", 0x0000000e, 0x3e0003ff, 0x8000, Rd_lvalue32Rs, s7_do_ldst_atomic}, + {"scb", 0x00000068, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, s7_do_ldst_unalign}, + {"scw", 0x0000006a, 0x3e0003ff, 0x8000, Rd_lvalueRs_post4, s7_do_ldst_unalign}, + {"sce", 0x0000006e, 0x3e0003ff, 0x8000, x_lvalueRs_post4, s7_do_ldst_unalign}, + {"sdbbp", 0x00000006, 0x3e0003ff, 0x6002, x_I5_x, s7_do_xi5x}, + {"sdbbp!", 0x6002, 0x7007, 0x00000006, Rd_I5, s7_do16_xi5}, + {"sh!", 0x200d, 0x700f, 0x2a000000, Rd_lvalueRs, s7_do16_ldst_insn}, + {"shp!", 0x7005, 0x7007, 0x2a000000, Rd_lvalueBP_I5, s7_do16_ldst_imm_insn}, + {"sleep", 0x0c0000c4, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty}, + {"sll", 0x00000030, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"sll.c", 0x00000031, 0x3e0003ff, 0x0008, Rd_Rs_Rs, s7_do_rdrsrs}, + {"sll.s", 0x3800004e, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"slli", 0x00000070, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5}, + {"slli.c", 0x00000071, 0x3e0003ff, 0x6001, Rd_Rs_I5, s7_do_rdrsi5}, + {"sll!", 0x0008, 0x700f, 0x00000031, Rd_Rs, s7_do16_rdrs}, + {"slli!", 0x6001, 0x7007, 0x00000071, Rd_I5, s7_do16_rdi5}, + {"srl", 0x00000034, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"srl.c", 0x00000035, 0x3e0003ff, 0x000a, Rd_Rs_Rs, s7_do_rdrsrs}, + {"sra", 0x00000036, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"sra.c", 0x00000037, 0x3e0003ff, 0x000b, Rd_Rs_Rs, s7_do_rdrsrs}, + {"srli", 0x00000074, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5}, + {"srli.c", 0x00000075, 0x3e0003ff, 0x6003, Rd_Rs_I5, s7_do_rdrsi5}, + {"srai", 0x00000076, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5}, + {"srai.c", 0x00000077, 0x3e0003ff, 0x8000, Rd_Rs_I5, s7_do_rdrsi5}, + {"srl!", 0x000a, 0x700f, 0x00000035, Rd_Rs, s7_do16_rdrs}, + {"sra!", 0x000b, 0x700f, 0x00000037, Rd_Rs, s7_do16_rdrs}, + {"srli!", 0x6003, 0x7007, 0x00000075, Rd_Rs, s7_do16_rdi5}, + {"stc1", 0x0c00000b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, s7_do_ldst_cop}, + {"stc2", 0x0c000013, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, s7_do_ldst_cop}, + {"stc3", 0x0c00001b, 0x3e00001f, 0x8000, Rd_lvalueRs_SI10, s7_do_ldst_cop}, + {"sub", 0x00000014, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"sub.c", 0x00000015, 0x3e0003ff, 0x2001, Rd_Rs_Rs, s7_do_rdrsrs}, + {"sub.s", 0x38000049, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"subc", 0x00000016, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"subc.c", 0x00000017, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"sub!", 0x2001, 0x700f, 0x00000015, Rd_Rs, s7_do16_rdrs}, + {"subei!", 0x6080, 0x7087, 0x02000001, Rd_I4, s7_do16_rdi4}, + {"sw!", 0x200c, 0x700f, 0x28000000, Rd_lvalueRs, s7_do16_ldst_insn}, + {"swp!", 0x7004, 0x7007, 0x28000000, Rd_lvalueBP_I5, s7_do16_ldst_imm_insn}, + {"syscall", 0x00000002, 0x3e0003ff, 0x8000, I15, s7_do_i15}, + {"tcs", 0x00000054, 0x3e007fff, 0x0005, NO_OPD, s7_do_empty}, + {"tcc", 0x00000454, 0x3e007fff, 0x0105, NO_OPD, s7_do_empty}, + {"tcnz", 0x00003854, 0x3e007fff, 0x0e05, NO_OPD, s7_do_empty}, + {"tcs!", 0x0005, 0x7f0f, 0x00000054, NO16_OPD, s7_do_empty}, + {"tcc!", 0x0105, 0x7f0f, 0x00000454, NO16_OPD, s7_do_empty}, + {"tcnz!", 0x0e05, 0x7f0f, 0x00003854, NO16_OPD, s7_do_empty}, + {"teq", 0x00001054, 0x3e007fff, 0x0405, NO_OPD, s7_do_empty}, + {"teq!", 0x0405, 0x7f0f, 0x00001054, NO16_OPD, s7_do_empty}, + {"tgtu", 0x00000854, 0x3e007fff, 0x0205, NO_OPD, s7_do_empty}, + {"tgt", 0x00001854, 0x3e007fff, 0x0605, NO_OPD, s7_do_empty}, + {"tge", 0x00002054, 0x3e007fff, 0x0805, NO_OPD, s7_do_empty}, + {"tgtu!", 0x0205, 0x7f0f, 0x00000854, NO16_OPD, s7_do_empty}, + {"tgt!", 0x0605, 0x7f0f, 0x00001854, NO16_OPD, s7_do_empty}, + {"tge!", 0x0805, 0x7f0f, 0x00002054, NO16_OPD, s7_do_empty}, + {"tleu", 0x00000c54, 0x3e007fff, 0x0305, NO_OPD, s7_do_empty}, + {"tle", 0x00001c54, 0x3e007fff, 0x0705, NO_OPD, s7_do_empty}, + {"tlt", 0x00002454, 0x3e007fff, 0x0905, NO_OPD, s7_do_empty}, + {"stlb", 0x0c000004, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty}, + {"mftlb", 0x0c000024, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty}, + {"mtptlb", 0x0c000044, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty}, + {"mtrtlb", 0x0c000064, 0x3e0003ff, 0x8000, NO_OPD, s7_do_empty}, + {"tleu!", 0x0305, 0x7f0f, 0x00000c54, NO16_OPD, s7_do_empty}, + {"tle!", 0x0705, 0x7f0f, 0x00001c54, NO16_OPD, s7_do_empty}, + {"tlt!", 0x0905, 0x7f0f, 0x00002454, NO16_OPD, s7_do_empty}, + {"tmi", 0x00002854, 0x3e007fff, 0x0a05, NO_OPD, s7_do_empty}, + {"tmi!", 0x0a05, 0x7f0f, 0x00002854, NO16_OPD, s7_do_empty}, + {"tne", 0x00001454, 0x3e007fff, 0x0505, NO_OPD, s7_do_empty}, + {"tne!", 0x0505, 0x7f0f, 0x00001454, NO16_OPD, s7_do_empty}, + {"tpl", 0x00002c54, 0x3e007fff, 0x0b05, NO_OPD, s7_do_empty}, + {"tpl!", 0x0b05, 0x7f0f, 0x00002c54, NO16_OPD, s7_do_empty}, + {"trapcs", 0x00000004, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x}, + {"trapcc", 0x00000404, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x}, + {"trapgtu", 0x00000804, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x}, + {"trapleu", 0x00000c04, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x}, + {"trapeq", 0x00001004, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x}, + {"trapne", 0x00001404, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x}, + {"trapgt", 0x00001804, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x}, + {"traple", 0x00001c04, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x}, + {"trapge", 0x00002004, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x}, + {"traplt", 0x00002404, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x}, + {"trapmi", 0x00002804, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x}, + {"trappl", 0x00002c04, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x}, + {"trapvs", 0x00003004, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x}, + {"trapvc", 0x00003404, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x}, + {"trap", 0x00003c04, 0x3e007fff, 0x8000, x_I5_x, s7_do_xi5x}, + {"tset", 0x00003c54, 0x3e007fff, 0x0f05, NO_OPD, s7_do_empty}, + {"tset!", 0x0f05, 0x00007f0f, 0x00003c54, NO16_OPD, s7_do_empty}, + {"tvs", 0x00003054, 0x3e007fff, 0x0c05, NO_OPD, s7_do_empty}, + {"tvc", 0x00003454, 0x3e007fff, 0x0d05, NO_OPD, s7_do_empty}, + {"tvs!", 0x0c05, 0x7f0f, 0x00003054, NO16_OPD, s7_do_empty}, + {"tvc!", 0x0d05, 0x7f0f, 0x00003454, NO16_OPD, s7_do_empty}, + {"xor", 0x00000026, 0x3e0003ff, 0x8000, Rd_Rs_Rs, s7_do_rdrsrs}, + {"xor.c", 0x00000027, 0x3e0003ff, 0x2007, Rd_Rs_Rs, s7_do_rdrsrs}, + {"xor!", 0x2007, 0x700f, 0x00000027, Rd_Rs, s7_do16_rdrs}, + /* Macro instruction. */ + {"li", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, s7_do_macro_li_rdi32}, + /* la reg, imm32 -->(1) ldi reg, simm16 + (2) ldis reg, %HI(imm32) + ori reg, %LO(imm32) + + la reg, symbol -->(1) lis reg, %HI(imm32) + ori reg, %LO(imm32) */ + {"la", 0x020c0000, 0x3e0e0000, 0x8000, Insn_Type_SYN, s7_do_macro_la_rdi32}, + {"div", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs}, + {"divu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs}, + {"rem", 0x00000044, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs}, + {"remu", 0x00000046, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs}, + {"mul", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs}, + {"mulu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs}, + {"maz", 0x00000040, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs}, + {"mazu", 0x00000042, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs}, + {"mul.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs}, + {"maz.f", 0x00000041, 0x3e0003ff, 0x8000, Insn_Type_SYN, s7_do_macro_mul_rdrsrs}, + {"lb", INSN_LB, 0x00000000, 0x8000, Insn_Type_SYN, s7_do_macro_ldst_label}, + {"lbu", INSN_LBU, 0x00000000, 0x200b, Insn_Type_SYN, s7_do_macro_ldst_label}, + {"lh", INSN_LH, 0x00000000, 0x2009, Insn_Type_SYN, s7_do_macro_ldst_label}, + {"lhu", INSN_LHU, 0x00000000, 0x8000, Insn_Type_SYN, s7_do_macro_ldst_label}, + {"lw", INSN_LW, 0x00000000, 0x2008, Insn_Type_SYN, s7_do_macro_ldst_label}, + {"sb", INSN_SB, 0x00000000, 0x200f, Insn_Type_SYN, s7_do_macro_ldst_label}, + {"sh", INSN_SH, 0x00000000, 0x200d, Insn_Type_SYN, s7_do_macro_ldst_label}, + {"sw", INSN_SW, 0x00000000, 0x200c, Insn_Type_SYN, s7_do_macro_ldst_label}, + /* Assembler use internal. */ + {"ld_i32hi", 0x0a0c0000, 0x3e0e0000, 0x8000, Insn_internal, s7_do_macro_rdi32hi}, + {"ld_i32lo", 0x020a0000, 0x3e0e0001, 0x8000, Insn_internal, s7_do_macro_rdi32lo}, + {"ldis_pic", 0x0a0c0000, 0x3e0e0000, 0x5000, Insn_internal, s7_do_rdi16_pic}, + {"addi_s_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal, s7_do_addi_s_pic}, + {"addi_u_pic",0x02000000, 0x3e0e0001, 0x8000, Insn_internal, s7_do_addi_u_pic}, + {"lw_pic", 0x20000000, 0x3e000000, 0x8000, Insn_internal, s7_do_lw_pic}, +}; + +#define s7_SCORE5_PIPELINE 5 +#define s7_SCORE7_PIPELINE 7 + +static int s7_university_version = 0; +static int s7_vector_size = s7_SCORE7_PIPELINE; +static struct s7_score_it s7_dependency_vector[s7_SCORE7_PIPELINE]; + +static int s7_score7d = 1; + + + +static int +s7_end_of_line (char *str) +{ + int retval = s7_SUCCESS; + + s7_skip_whitespace (str); + if (*str != '\0') + { + retval = (int) s7_FAIL; + + if (!s7_inst.error) + s7_inst.error = s7_BAD_GARBAGE; + } + + return retval; +} + +static int +s7_score_reg_parse (char **ccp, struct hash_control *htab) +{ + char *start = *ccp; + char c; + char *p; + struct s7_reg_entry *reg; + + p = start; + if (!ISALPHA (*p) || !is_name_beginner (*p)) + return (int) s7_FAIL; + + c = *p++; + + while (ISALPHA (c) || ISDIGIT (c) || c == '_') + c = *p++; + + *--p = 0; + reg = (struct s7_reg_entry *) hash_find (htab, start); + *p = c; + + if (reg) + { + *ccp = p; + return reg->number; + } + return (int) s7_FAIL; +} + +/* If shift <= 0, only return reg. */ +static int +s7_reg_required_here (char **str, int shift, enum s7_score_reg_type reg_type) +{ + static char buff[s7_MAX_LITERAL_POOL_SIZE]; + int reg = (int) s7_FAIL; + char *start = *str; + + if ((reg = s7_score_reg_parse (str, s7_all_reg_maps[reg_type].htab)) != (int) s7_FAIL) + { + if (reg_type == s7_REG_TYPE_SCORE) + { + if ((reg == 1) && (s7_nor1 == 1) && (s7_inst.bwarn == 0)) + { + as_warn (_("Using temp register(r1)")); + s7_inst.bwarn = 1; + } + } + if (shift >= 0) + { + if (reg_type == s7_REG_TYPE_SCORE_CR) + strcpy (s7_inst.reg, s7_score_crn_table[reg].name); + else if (reg_type == s7_REG_TYPE_SCORE_SR) + strcpy (s7_inst.reg, s7_score_srn_table[reg].name); + else + strcpy (s7_inst.reg, ""); + + s7_inst.instruction |= reg << shift; + } + } + else + { + *str = start; + sprintf (buff, _("register expected, not '%.100s'"), start); + s7_inst.error = buff; + } + + return reg; +} + +static int +s7_skip_past_comma (char **str) +{ + char *p = *str; + char c; + int comma = 0; + + while ((c = *p) == ' ' || c == ',') + { + p++; + if (c == ',' && comma++) + { + s7_inst.error = s7_BAD_SKIP_COMMA; + return (int) s7_FAIL; + } + } + + if ((c == '\0') || (comma == 0)) + { + s7_inst.error = s7_BAD_SKIP_COMMA; + return (int) s7_FAIL; + } + + *str = p; + return comma ? s7_SUCCESS : (int) s7_FAIL; +} + +static void +s7_do_rdrsrs (char *str) +{ + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL + || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL + || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE) == (int) s7_FAIL + || s7_end_of_line (str) == (int) s7_FAIL) + { + return; + } + else + { + if ((((s7_inst.instruction >> 15) & 0x10) == 0) + && (((s7_inst.instruction >> 10) & 0x10) == 0) + && (((s7_inst.instruction >> 20) & 0x10) == 0) + && (s7_inst.relax_inst != 0x8000) + && (((s7_inst.instruction >> 20) & 0xf) == ((s7_inst.instruction >> 15) & 0xf))) + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 4) + | (((s7_inst.instruction >> 15) & 0xf) << 8); + s7_inst.relax_size = 2; + } + else + { + s7_inst.relax_inst = 0x8000; + } + } +} + +static int +s7_walk_no_bignums (symbolS * sp) +{ + if (symbol_get_value_expression (sp)->X_op == O_big) + return 1; + + if (symbol_get_value_expression (sp)->X_add_symbol) + return (s7_walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol) + || (symbol_get_value_expression (sp)->X_op_symbol + && s7_walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol))); + + return 0; +} + +static int +s7_my_get_expression (expressionS * ep, char **str) +{ + char *save_in; + segT seg; + + save_in = input_line_pointer; + input_line_pointer = *str; + s7_in_my_get_expression = 1; + seg = expression (ep); + s7_in_my_get_expression = 0; + + if (ep->X_op == O_illegal) + { + *str = input_line_pointer; + input_line_pointer = save_in; + s7_inst.error = _("illegal expression"); + return (int) s7_FAIL; + } + /* Get rid of any bignums now, so that we don't generate an error for which + we can't establish a line number later on. Big numbers are never valid + in instructions, which is where this routine is always called. */ + if (ep->X_op == O_big + || (ep->X_add_symbol + && (s7_walk_no_bignums (ep->X_add_symbol) + || (ep->X_op_symbol && s7_walk_no_bignums (ep->X_op_symbol))))) + { + s7_inst.error = _("invalid constant"); + *str = input_line_pointer; + input_line_pointer = save_in; + return (int) s7_FAIL; + } + + if ((ep->X_add_symbol != NULL) + && (s7_inst.type != PC_DISP19div2) + && (s7_inst.type != PC_DISP8div2) + && (s7_inst.type != PC_DISP24div2) + && (s7_inst.type != PC_DISP11div2) + && (s7_inst.type != Insn_Type_SYN) + && (s7_inst.type != Rd_rvalueRs_SI15) + && (s7_inst.type != Rd_lvalueRs_SI15) + && (s7_inst.type != Insn_internal)) + { + s7_inst.error = s7_BAD_ARGS; + *str = input_line_pointer; + input_line_pointer = save_in; + return (int) s7_FAIL; + } + + *str = input_line_pointer; + input_line_pointer = save_in; + return s7_SUCCESS; +} + +/* Check if an immediate is valid. If so, convert it to the right format. */ + +static bfd_signed_vma +s7_validate_immediate (bfd_signed_vma val, unsigned int data_type, int hex_p) +{ + switch (data_type) + { + case _VALUE_HI16: + { + int val_hi = ((val & 0xffff0000) >> 16); + + if (s7_score_df_range[data_type].range[0] <= val_hi + && val_hi <= s7_score_df_range[data_type].range[1]) + return val_hi; + } + break; + + case _VALUE_LO16: + { + int val_lo = (val & 0xffff); + + if (s7_score_df_range[data_type].range[0] <= val_lo + && val_lo <= s7_score_df_range[data_type].range[1]) + return val_lo; + } + break; + + case _SIMM12: + if (hex_p == 1) + { + if (!(val >= -0x800 && val <= 0xfff)) + { + return (int) s7_FAIL; + } + } + else + { + if (!(val >= -2048 && val <= 2047)) + { + return (int) s7_FAIL; + } + } + + return val; + break; + + case _SIMM14: + if (hex_p == 1) + { + if (!(val >= -0x2000 && val <= 0x3fff)) + { + return (int) s7_FAIL; + } + } + else + { + if (!(val >= -8192 && val <= 8191)) + { + return (int) s7_FAIL; + } + } + + return val; + break; + + case _SIMM15: + if (hex_p == 1) + { + if (!(val >= -0x4000 && val <= 0x7fff)) + { + return (int) s7_FAIL; + } + } + else + { + if (!(val >= -16384 && val <= 16383)) + { + return (int) s7_FAIL; + } + } + + return val; + break; + + case _SIMM16: + if (hex_p == 1) + { + if (!(val >= -0x8000 && val <= 0xffff)) + { + return (int) s7_FAIL; + } + } + else + { + if (!(val >= -32768 && val <= 32767)) + { + return (int) s7_FAIL; + } + } + + return val; + break; + + case _SIMM16_NEG: + if (hex_p == 1) + { + if (!(val >= -0x7fff && val <= 0xffff && val != 0x8000)) + { + return (int) s7_FAIL; + } + } + else + { + if (!(val >= -32767 && val <= 32768)) + { + return (int) s7_FAIL; + } + } + + val = -val; + return val; + break; + + case _IMM32: + if (val >= 0 && val <= 0xffffffff) + { + return val; + } + else + { + return (int) s7_FAIL; + } + + default: + if (data_type == _SIMM14_NEG || data_type == _IMM16_NEG) + val = -val; + + if (s7_score_df_range[data_type].range[0] <= val + && val <= s7_score_df_range[data_type].range[1]) + return val; + + break; + } + + return (int) s7_FAIL; +} + +static int +s7_data_op2 (char **str, int shift, enum score_data_type data_type) +{ + int value; + char data_exp[s7_MAX_LITERAL_POOL_SIZE]; + char *dataptr; + int cnt = 0; + char *pp = NULL; + + s7_skip_whitespace (*str); + s7_inst.error = NULL; + dataptr = * str; + + /* Set hex_p to zero. */ + int hex_p = 0; + + while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= s7_MAX_LITERAL_POOL_SIZE)) /* 0x7c = ='|' */ + { + data_exp[cnt] = *dataptr; + dataptr++; + cnt++; + } + + data_exp[cnt] = '\0'; + pp = (char *)&data_exp; + + if (*dataptr == '|') /* process PCE */ + { + if (s7_my_get_expression (&s7_inst.reloc.exp, &pp) == (int) s7_FAIL) + return (int) s7_FAIL; + s7_end_of_line (pp); + if (s7_inst.error != 0) + return (int) s7_FAIL; /* to ouptut_inst to printf out the error */ + *str = dataptr; + } + else /* process 16 bit */ + { + if (s7_my_get_expression (&s7_inst.reloc.exp, str) == (int) s7_FAIL) + { + return (int) s7_FAIL; + } + + dataptr = (char *) data_exp; + for (; *dataptr != '\0'; dataptr++) + { + *dataptr = TOLOWER (*dataptr); + if (*dataptr == '!' || *dataptr == ' ') + break; + } + dataptr = (char *) data_exp; + + if ((dataptr != NULL) + && (((strstr (dataptr, "0x")) != NULL) + || ((strstr (dataptr, "0X")) != NULL))) + { + hex_p = 1; + if ((data_type != _SIMM16_LA) + && (data_type != _VALUE_HI16) + && (data_type != _VALUE_LO16) + && (data_type != _IMM16) + && (data_type != _IMM15) + && (data_type != _IMM14) + && (data_type != _IMM4) + && (data_type != _IMM5) + && (data_type != _IMM8) + && (data_type != _IMM5_RSHIFT_1) + && (data_type != _IMM5_RSHIFT_2) + && (data_type != _SIMM14) + && (data_type != _SIMM16) + && (data_type != _SIMM14_NEG) + && (data_type != _SIMM16_NEG) + && (data_type != _IMM10_RSHIFT_2) + && (data_type != _GP_IMM15)) + { + data_type += 24; + } + } + + if ((s7_inst.reloc.exp.X_add_number == 0) + /* for "addi r0,-((((((32*4)+4)+4)+4)+4)&0xf)". */ + && (s7_inst.type != Rd_SI16) + && (s7_inst.type != Insn_Type_SYN) + && (s7_inst.type != Rd_rvalueRs_SI15) + && (s7_inst.type != Rd_lvalueRs_SI15) + && (s7_inst.type != Insn_internal) + && (((*dataptr >= 'a') && (*dataptr <= 'z')) + || ((*dataptr == '0') && (*(dataptr + 1) == 'x') && (*(dataptr + 2) != '0')) + || ((*dataptr == '+') && (*(dataptr + 1) != '0')) + || ((*dataptr == '-') && (*(dataptr + 1) != '0')))) + { + s7_inst.error = s7_BAD_ARGS; + return (int) s7_FAIL; + } + } + + if ((s7_inst.reloc.exp.X_add_symbol) + && ((data_type == _SIMM16) + || (data_type == _SIMM16_NEG) + || (data_type == _IMM16_NEG) + || (data_type == _SIMM14) + || (data_type == _SIMM14_NEG) + || (data_type == _IMM5) + || (data_type == _IMM14) + || (data_type == _IMM20) + || (data_type == _IMM16) + || (data_type == _IMM15) + || (data_type == _IMM4))) + { + s7_inst.error = s7_BAD_ARGS; + return (int) s7_FAIL; + } + + if (s7_inst.reloc.exp.X_add_symbol) + { + switch (data_type) + { + case _SIMM16_LA: + return (int) s7_FAIL; + case _VALUE_HI16: + s7_inst.reloc.type = BFD_RELOC_HI16_S; + s7_inst.reloc.pc_rel = 0; + break; + case _VALUE_LO16: + s7_inst.reloc.type = BFD_RELOC_LO16; + s7_inst.reloc.pc_rel = 0; + break; + case _GP_IMM15: + s7_inst.reloc.type = BFD_RELOC_SCORE_GPREL15; + s7_inst.reloc.pc_rel = 0; + break; + case _SIMM16_pic: + case _IMM16_LO16_pic: + s7_inst.reloc.type = BFD_RELOC_SCORE_GOT_LO16; + s7_inst.reloc.pc_rel = 0; + break; + default: + s7_inst.reloc.type = BFD_RELOC_32; + s7_inst.reloc.pc_rel = 0; + break; + } + } + else + { + if (data_type == _IMM16_pic) + { + s7_inst.reloc.type = BFD_RELOC_SCORE_DUMMY_HI16; + s7_inst.reloc.pc_rel = 0; + } + + if (data_type == _SIMM16_LA && s7_inst.reloc.exp.X_unsigned == 1) + { + value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _SIMM16_LA_POS, hex_p); + if (value == (int) s7_FAIL) /* for advance to check if this is ldis */ + if ((s7_inst.reloc.exp.X_add_number & 0xffff) == 0) + { + s7_inst.instruction |= 0x8000000; + s7_inst.instruction |= ((s7_inst.reloc.exp.X_add_number >> 16) << 1) & 0x1fffe; + return s7_SUCCESS; + } + } + else + { + value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, data_type, hex_p); + } + + if (value == (int) s7_FAIL) + { + if ((data_type != _SIMM14_NEG) && (data_type != _SIMM16_NEG) && (data_type != _IMM16_NEG)) + { + sprintf (s7_err_msg, + _("invalid constant: %d bit expression not in range %d..%d"), + s7_score_df_range[data_type].bits, + s7_score_df_range[data_type].range[0], s7_score_df_range[data_type].range[1]); + } + else + { + sprintf (s7_err_msg, + _("invalid constant: %d bit expression not in range %d..%d"), + s7_score_df_range[data_type].bits, + -s7_score_df_range[data_type].range[1], -s7_score_df_range[data_type].range[0]); + } + + s7_inst.error = s7_err_msg; + return (int) s7_FAIL; + } + + if ((s7_score_df_range[data_type].range[0] != 0) || (data_type == _IMM5_RANGE_8_31)) + { + value &= (1 << s7_score_df_range[data_type].bits) - 1; + } + + s7_inst.instruction |= value << shift; + } + + if ((s7_inst.instruction & 0x3e000000) == 0x30000000) + { + if ((((s7_inst.instruction >> 20) & 0x1F) != 0) + && (((s7_inst.instruction >> 20) & 0x1F) != 1) + && (((s7_inst.instruction >> 20) & 0x1F) != 2) + && (((s7_inst.instruction >> 20) & 0x1F) != 3) + && (((s7_inst.instruction >> 20) & 0x1F) != 4) + && (((s7_inst.instruction >> 20) & 0x1F) != 8) + && (((s7_inst.instruction >> 20) & 0x1F) != 9) + && (((s7_inst.instruction >> 20) & 0x1F) != 0xa) + && (((s7_inst.instruction >> 20) & 0x1F) != 0xb) + && (((s7_inst.instruction >> 20) & 0x1F) != 0xc) + && (((s7_inst.instruction >> 20) & 0x1F) != 0xd) + && (((s7_inst.instruction >> 20) & 0x1F) != 0xe) + && (((s7_inst.instruction >> 20) & 0x1F) != 0x10) + && (((s7_inst.instruction >> 20) & 0x1F) != 0x11) + && (((s7_inst.instruction >> 20) & 0x1F) != 0x18) + && (((s7_inst.instruction >> 20) & 0x1F) != 0x1A) + && (((s7_inst.instruction >> 20) & 0x1F) != 0x1B) + && (((s7_inst.instruction >> 20) & 0x1F) != 0x1d) + && (((s7_inst.instruction >> 20) & 0x1F) != 0x1e) + && (((s7_inst.instruction >> 20) & 0x1F) != 0x1f)) + { + s7_inst.error = _("invalid constant: bit expression not defined"); + return (int) s7_FAIL; + } + } + + return s7_SUCCESS; +} + +/* Handle addi/addi.c/addis.c/cmpi.c/addis.c/ldi. */ + +static void +s7_do_rdsi16 (char *str) +{ + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL + || s7_data_op2 (&str, 1, _SIMM16) == (int) s7_FAIL + || s7_end_of_line (str) == (int) s7_FAIL) + return; + + /* ldi. */ + if ((s7_inst.instruction & 0x20c0000) == 0x20c0000) + { + if ((((s7_inst.instruction >> 20) & 0x10) == 0x10) || ((s7_inst.instruction & 0x1fe00) != 0)) + { + s7_inst.relax_inst = 0x8000; + } + else + { + s7_inst.relax_inst |= (s7_inst.instruction >> 1) & 0xff; + s7_inst.relax_inst |= (((s7_inst.instruction >> 20) & 0xf) << 8); + s7_inst.relax_size = 2; + } + } + else if (((s7_inst.instruction >> 20) & 0x10) == 0x10) + { + s7_inst.relax_inst = 0x8000; + } +} + +/* Handle subi/subi.c. */ + +static void +s7_do_sub_rdsi16 (char *str) +{ + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL + && s7_skip_past_comma (&str) != (int) s7_FAIL + && s7_data_op2 (&str, 1, _SIMM16_NEG) != (int) s7_FAIL) + s7_end_of_line (str); +} + + +/* Handle addri/addri.c. */ + +static void +s7_do_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */ +{ + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL + && s7_skip_past_comma (&str) != (int) s7_FAIL + && s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) != (int) s7_FAIL + && s7_skip_past_comma (&str) != (int) s7_FAIL) + s7_data_op2 (&str, 1, _SIMM14); +} + +/* Handle subri.c/subri. */ + +static void +s7_do_sub_rdrssi14 (char *str) /* -(2^13)~((2^13)-1) */ +{ + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL + && s7_skip_past_comma (&str) != (int) s7_FAIL + && s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) != (int) s7_FAIL + && s7_skip_past_comma (&str) != (int) s7_FAIL + && s7_data_op2 (&str, 1, _SIMM14_NEG) != (int) s7_FAIL) + s7_end_of_line (str); +} + +/* Handle bitclr.c/bitset.c/bittgl.c/slli.c/srai.c/srli.c/roli.c/rori.c/rolic.c. */ + +static void +s7_do_rdrsi5 (char *str) /* 0~((2^14)-1) */ +{ + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL + || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL + || s7_data_op2 (&str, 10, _IMM5) == (int) s7_FAIL + || s7_end_of_line (str) == (int) s7_FAIL) + return; + + if ((((s7_inst.instruction >> 20) & 0x1f) == ((s7_inst.instruction >> 15) & 0x1f)) + && (s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 15) & 0x10) == 0)) + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0x1f) << 3) | (((s7_inst.instruction >> 15) & 0xf) << 8); + s7_inst.relax_size = 2; + } + else + s7_inst.relax_inst = 0x8000; +} + +/* Handle andri/orri/andri.c/orri.c. */ + +static void +s7_do_rdrsi14 (char *str) /* 0 ~ ((2^14)-1) */ +{ + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL + && s7_skip_past_comma (&str) != (int) s7_FAIL + && s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) != (int) s7_FAIL + && s7_skip_past_comma (&str) != (int) s7_FAIL + && s7_data_op2 (&str, 1, _IMM14) != (int) s7_FAIL) + s7_end_of_line (str); +} + +/* Handle bittst.c. */ + +static void +s7_do_xrsi5 (char *str) +{ + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL + || s7_data_op2 (&str, 10, _IMM5) == (int) s7_FAIL + || s7_end_of_line (str) == (int) s7_FAIL) + return; + + if ((s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 15) & 0x10) == 0)) + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0x1f) << 3) | (((s7_inst.instruction >> 15) & 0xf) << 8); + s7_inst.relax_size = 2; + } + else + s7_inst.relax_inst = 0x8000; +} + +/* Handle addis/andi/ori/andis/oris/ldis. */ + +static void +s7_do_rdi16 (char *str) +{ + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL + || s7_data_op2 (&str, 1, _IMM16) == (int) s7_FAIL + || s7_end_of_line (str) == (int) s7_FAIL) + return; +} + +static void +s7_do_macro_rdi32hi (char *str) +{ + s7_skip_whitespace (str); + + /* Do not handle s7_end_of_line(). */ + if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL + && s7_skip_past_comma (&str) != (int) s7_FAIL) + s7_data_op2 (&str, 1, _VALUE_HI16); +} + +static void +s7_do_macro_rdi32lo (char *str) +{ + s7_skip_whitespace (str); + + /* Do not handle s7_end_of_line(). */ + if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL + && s7_skip_past_comma (&str) != (int) s7_FAIL) + s7_data_op2 (&str, 1, _VALUE_LO16); +} + +/* Handle ldis_pic. */ + +static void +s7_do_rdi16_pic (char *str) +{ + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL + && s7_skip_past_comma (&str) != (int) s7_FAIL + && s7_data_op2 (&str, 1, _IMM16_pic) != (int) s7_FAIL) + s7_end_of_line (str); +} + +/* Handle addi_s_pic to generate R_SCORE_GOT_LO16 . */ + +static void +s7_do_addi_s_pic (char *str) +{ + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL + && s7_skip_past_comma (&str) != (int) s7_FAIL + && s7_data_op2 (&str, 1, _SIMM16_pic) != (int) s7_FAIL) + s7_end_of_line (str); +} + +/* Handle addi_u_pic to generate R_SCORE_GOT_LO16 . */ + +static void +s7_do_addi_u_pic (char *str) +{ + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL + && s7_skip_past_comma (&str) != (int) s7_FAIL + && s7_data_op2 (&str, 1, _IMM16_LO16_pic) != (int) s7_FAIL) + s7_end_of_line (str); +} + +/* Handle mfceh/mfcel/mtceh/mtchl. */ + +static void +s7_do_rd (char *str) +{ + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL) + s7_end_of_line (str); +} + +static void +s7_do_rs (char *str) +{ + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL + || s7_end_of_line (str) == (int) s7_FAIL) + return; + + if ((s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 15) & 0x10) == 0)) + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 8) | (((s7_inst.instruction >> 15) & 0xf) << 4); + s7_inst.relax_size = 2; + } + else + s7_inst.relax_inst = 0x8000; +} + +static void +s7_do_i15 (char *str) +{ + s7_skip_whitespace (str); + + if (s7_data_op2 (&str, 10, _IMM15) != (int) s7_FAIL) + s7_end_of_line (str); +} + +static void +s7_do_xi5x (char *str) +{ + s7_skip_whitespace (str); + + if (s7_data_op2 (&str, 15, _IMM5) == (int) s7_FAIL || s7_end_of_line (str) == (int) s7_FAIL) + return; + + if (s7_inst.relax_inst != 0x8000) + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0x1f) << 3); + s7_inst.relax_size = 2; + } +} + +static void +s7_do_rdrs (char *str) +{ + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL + || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL + || s7_end_of_line (str) == (int) s7_FAIL) + return; + + if (s7_inst.relax_inst != 0x8000) + { + if (((s7_inst.instruction & 0x7f) == 0x56)) /* adjust mv -> mv! / mlfh! / mhfl! */ + { + /* mlfh */ + if ((((s7_inst.instruction >> 15) & 0x10) != 0x0) && (((s7_inst.instruction >> 20) & 0x10) == 0)) + { + s7_inst.relax_inst = 0x00000001 | (((s7_inst.instruction >> 15) & 0xf) << 4) + | (((s7_inst.instruction >> 20) & 0xf) << 8); + s7_inst.relax_size = 2; + } + /* mhfl */ + else if ((((s7_inst.instruction >> 15) & 0x10) == 0x0) && ((s7_inst.instruction >> 20) & 0x10) != 0) + { + s7_inst.relax_inst = 0x00000002 | (((s7_inst.instruction >> 15) & 0xf) << 4) + | (((s7_inst.instruction >> 20) & 0xf) << 8); + s7_inst.relax_size = 2; + } + else if ((((s7_inst.instruction >> 15) & 0x10) == 0x0) && (((s7_inst.instruction >> 20) & 0x10) == 0)) + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4) + | (((s7_inst.instruction >> 20) & 0xf) << 8); + s7_inst.relax_size = 2; + } + else + { + s7_inst.relax_inst = 0x8000; + } + } + else if ((((s7_inst.instruction >> 15) & 0x10) == 0x0) && (((s7_inst.instruction >> 20) & 0x10) == 0)) + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4) + | (((s7_inst.instruction >> 20) & 0xf) << 8); + s7_inst.relax_size = 2; + } + else + { + s7_inst.relax_inst = 0x8000; + } + } +} + +/* Handle mfcr/mtcr. */ +static void +s7_do_rdcrs (char *str) +{ + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL + && s7_skip_past_comma (&str) != (int) s7_FAIL + && s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE_CR) != (int) s7_FAIL) + s7_end_of_line (str); +} + +/* Handle mfsr/mtsr. */ + +static void +s7_do_rdsrs (char *str) +{ + s7_skip_whitespace (str); + + /* mfsr */ + if ((s7_inst.instruction & 0xff) == 0x50) + { + if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL + && s7_skip_past_comma (&str) != (int) s7_FAIL + && s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE_SR) != (int) s7_FAIL) + s7_end_of_line (str); + } + else + { + if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) != (int) s7_FAIL + && s7_skip_past_comma (&str) != (int) s7_FAIL) + s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE_SR); + } +} + +/* Handle neg. */ + +static void +s7_do_rdxrs (char *str) +{ + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL + || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE) == (int) s7_FAIL + || s7_end_of_line (str) == (int) s7_FAIL) + return; + + if ((s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 10) & 0x10) == 0) + && (((s7_inst.instruction >> 20) & 0x10) == 0)) + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 4) | (((s7_inst.instruction >> 20) & 0xf) << 8); + s7_inst.relax_size = 2; + } + else + s7_inst.relax_inst = 0x8000; +} + +/* Handle cmp.c/cmp. */ +static void +s7_do_rsrs (char *str) +{ + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL + || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE) == (int) s7_FAIL + || s7_end_of_line (str) == (int) s7_FAIL) + return; + + if ((s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 20) & 0x1f) == 3) + && (((s7_inst.instruction >> 10) & 0x10) == 0) && (((s7_inst.instruction >> 15) & 0x10) == 0)) + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 4) | (((s7_inst.instruction >> 15) & 0xf) << 8); + s7_inst.relax_size = 2; + } + else + s7_inst.relax_inst = 0x8000; +} + +static void +s7_do_ceinst (char *str) +{ + char *strbak; + + strbak = str; + s7_skip_whitespace (str); + + if (s7_data_op2 (&str, 20, _IMM5) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL + || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL + || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL + || s7_data_op2 (&str, 5, _IMM5) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL + || s7_data_op2 (&str, 0, _IMM5) == (int) s7_FAIL + || s7_end_of_line (str) == (int) s7_FAIL) + { + return; + } + else + { + str = strbak; + if (s7_data_op2 (&str, 0, _IMM25) == (int) s7_FAIL) + return; + } +} + +static int +s7_reglow_required_here (char **str, int shift) +{ + static char buff[s7_MAX_LITERAL_POOL_SIZE]; + int reg; + char *start = *str; + + if ((reg = s7_score_reg_parse (str, s7_all_reg_maps[s7_REG_TYPE_SCORE].htab)) != (int) s7_FAIL) + { + if ((reg == 1) && (s7_nor1 == 1) && (s7_inst.bwarn == 0)) + { + as_warn (_("Using temp register(r1)")); + s7_inst.bwarn = 1; + } + if (reg < 16) + { + if (shift >= 0) + s7_inst.instruction |= reg << shift; + + return reg; + } + } + + /* Restore the start point, we may have got a reg of the wrong class. */ + *str = start; + sprintf (buff, _("low register(r0-r15)expected, not '%.100s'"), start); + s7_inst.error = buff; + return (int) s7_FAIL; +} + +/* Handle addc!/add!/and!/cmp!/neg!/not!/or!/sll!/srl!/sra!/xor!/sub!. */ + +static void +s7_do16_rdrs (char *str) +{ + s7_skip_whitespace (str); + + if (s7_reglow_required_here (&str, 8) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL + || s7_reglow_required_here (&str, 4) == (int) s7_FAIL + || s7_end_of_line (str) == (int) s7_FAIL) + { + return; + } + else + { + if ((s7_inst.instruction & 0x700f) == 0x2003) /* cmp! */ + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 15) + | (((s7_inst.instruction >> 4) & 0xf) << 10); + } + else if ((s7_inst.instruction & 0x700f) == 0x2006) /* not! */ + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20) + | (((s7_inst.instruction >> 4) & 0xf) << 15); + } + else if ((s7_inst.instruction & 0x700f) == 0x1009) /* mazh.f! */ + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 15) + | (((s7_inst.instruction >> 4) & 0xf) << 10); + } + else + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20) + | (((s7_inst.instruction >> 8) & 0xf) << 15) | (((s7_inst.instruction >> 4) & 0xf) << 10); + } + s7_inst.relax_size = 4; + } +} + +static void +s7_do16_rs (char *str) +{ + int rd = 0; + + s7_skip_whitespace (str); + + if ((rd = s7_reglow_required_here (&str, 4)) == (int) s7_FAIL + || s7_end_of_line (str) == (int) s7_FAIL) + { + return; + } + else + { + s7_inst.relax_inst |= rd << 20; + s7_inst.relax_size = 4; + } +} + +/* Handle br!/brl!. */ + +static void +s7_do16_xrs (char *str) +{ + s7_skip_whitespace (str); + + if (s7_reglow_required_here (&str, 4) == (int) s7_FAIL || s7_end_of_line (str) == (int) s7_FAIL) + { + return; + } + else + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 10) + | (((s7_inst.instruction >> 4) & 0xf) << 15); + s7_inst.relax_size = 4; + } +} + +static int +s7_reghigh_required_here (char **str, int shift) +{ + static char buff[s7_MAX_LITERAL_POOL_SIZE]; + int reg; + char *start = *str; + + if ((reg = s7_score_reg_parse (str, s7_all_reg_maps[s7_REG_TYPE_SCORE].htab)) != (int) s7_FAIL) + { + if (15 < reg && reg < 32) + { + if (shift >= 0) + s7_inst.instruction |= (reg & 0xf) << shift; + + return reg; + } + } + + *str = start; + sprintf (buff, _("high register(r16-r31)expected, not '%.100s'"), start); + s7_inst.error = buff; + return (int) s7_FAIL; +} + +/* Handle mhfl!. */ + +static void +s7_do16_hrdrs (char *str) +{ + s7_skip_whitespace (str); + + if (s7_reghigh_required_here (&str, 8) != (int) s7_FAIL + && s7_skip_past_comma (&str) != (int) s7_FAIL + && s7_reglow_required_here (&str, 4) != (int) s7_FAIL + && s7_end_of_line (str) != (int) s7_FAIL) + { + s7_inst.relax_inst |= ((((s7_inst.instruction >> 8) & 0xf) | 0x10) << 20) + | (((s7_inst.instruction >> 4) & 0xf) << 15) | (0xf << 10); + s7_inst.relax_size = 4; + } +} + +/* Handle mlfh!. */ + +static void +s7_do16_rdhrs (char *str) +{ + s7_skip_whitespace (str); + + if (s7_reglow_required_here (&str, 8) != (int) s7_FAIL + && s7_skip_past_comma (&str) != (int) s7_FAIL + && s7_reghigh_required_here (&str, 4) != (int) s7_FAIL + && s7_end_of_line (str) != (int) s7_FAIL) + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20) + | ((((s7_inst.instruction >> 4) & 0xf) | 0x10) << 15) | (0xf << 10); + s7_inst.relax_size = 4; + } +} + +/* We need to be able to fix up arbitrary expressions in some statements. + This is so that we can handle symbols that are an arbitrary distance from + the pc. The most common cases are of the form ((+/-sym -/+ . - 8) & mask), + which returns part of an address in a form which will be valid for + a data instruction. We do this by pushing the expression into a symbol + in the expr_section, and creating a fix for that. */ + +static fixS * +s7_fix_new_score (fragS * frag, int where, short int size, expressionS * exp, int pc_rel, int reloc) +{ + fixS *new_fix; + + switch (exp->X_op) + { + case O_constant: + case O_symbol: + case O_add: + case O_subtract: + new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc); + break; + default: + new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0, pc_rel, reloc); + break; + } + return new_fix; +} + +static void +s7_init_dependency_vector (void) +{ + int i; + + for (i = 0; i < s7_vector_size; i++) + memset (&s7_dependency_vector[i], '\0', sizeof (s7_dependency_vector[i])); + + return; +} + +static enum s7_insn_type_for_dependency +s7_dependency_type_from_insn (char *insn_name) +{ + char name[s7_INSN_NAME_LEN]; + const struct s7_insn_to_dependency *tmp; + + strcpy (name, insn_name); + tmp = (const struct s7_insn_to_dependency *) hash_find (s7_dependency_insn_hsh, name); + + if (tmp) + return tmp->type; + + return s7_D_all_insn; +} + +static int +s7_check_dependency (char *pre_insn, char *pre_reg, + char *cur_insn, char *cur_reg, int *warn_or_error) +{ + int bubbles = 0; + unsigned int i; + enum s7_insn_type_for_dependency pre_insn_type; + enum s7_insn_type_for_dependency cur_insn_type; + + pre_insn_type = s7_dependency_type_from_insn (pre_insn); + cur_insn_type = s7_dependency_type_from_insn (cur_insn); + + for (i = 0; i < sizeof (s7_data_dependency_table) / sizeof (s7_data_dependency_table[0]); i++) + { + if ((pre_insn_type == s7_data_dependency_table[i].pre_insn_type) + && (s7_D_all_insn == s7_data_dependency_table[i].cur_insn_type + || cur_insn_type == s7_data_dependency_table[i].cur_insn_type) + && (strcmp (s7_data_dependency_table[i].pre_reg, "") == 0 + || strcmp (s7_data_dependency_table[i].pre_reg, pre_reg) == 0) + && (strcmp (s7_data_dependency_table[i].cur_reg, "") == 0 + || strcmp (s7_data_dependency_table[i].cur_reg, cur_reg) == 0)) + { + if (s7_vector_size == s7_SCORE5_PIPELINE) + bubbles = s7_data_dependency_table[i].bubblenum_5; + else + bubbles = s7_data_dependency_table[i].bubblenum_7; + *warn_or_error = s7_data_dependency_table[i].warn_or_error; + break; + } + } + + return bubbles; +} + +/* Turn an integer of n bytes (in val) into a stream of bytes appropriate + for use in the a.out file, and stores them in the array pointed to by buf. + This knows about the endian-ness of the target machine and does + THE RIGHT THING, whatever it is. Possible values for n are 1 (byte) + 2 (short) and 4 (long) Floating numbers are put out as a series of + LITTLENUMS (shorts, here at least). */ + +static void +s7_number_to_chars (char *buf, valueT val, int n) +{ + if (target_big_endian) + number_to_chars_bigendian (buf, val, n); + else + number_to_chars_littleendian (buf, val, n); +} + +static void +s7_build_one_frag (struct s7_score_it one_inst) +{ + char *p; + int relaxable_p = s7_g_opt; + int relax_size = 0; + + /* Start a new frag if frag_now is not empty. */ + if (frag_now_fix () != 0) + { + if (!frag_now->tc_frag_data.is_insn) + frag_wane (frag_now); + + frag_new (0); + } + frag_grow (20); + + p = frag_more (one_inst.size); + s7_number_to_chars (p, one_inst.instruction, one_inst.size); + +#ifdef OBJ_ELF + dwarf2_emit_insn (one_inst.size); +#endif + + relaxable_p &= (one_inst.relax_size != 0); + relax_size = relaxable_p ? one_inst.relax_size : 0; + + p = frag_var (rs_machine_dependent, relax_size + s7_RELAX_PAD_BYTE, 0, + s7_RELAX_ENCODE (one_inst.size, one_inst.relax_size, + one_inst.type, 0, 0, relaxable_p), + NULL, 0, NULL); + + if (relaxable_p) + s7_number_to_chars (p, one_inst.relax_inst, relax_size); +} + +static void +s7_handle_dependency (struct s7_score_it *theinst) +{ + int i; + int warn_or_error = 0; /* warn - 0; error - 1 */ + int bubbles = 0; + int remainder_bubbles = 0; + char cur_insn[s7_INSN_NAME_LEN]; + char pre_insn[s7_INSN_NAME_LEN]; + struct s7_score_it nop_inst; + struct s7_score_it pflush_inst; + + nop_inst.instruction = 0x0000; + nop_inst.size = 2; + nop_inst.relax_inst = 0x80008000; + nop_inst.relax_size = 4; + nop_inst.type = NO16_OPD; + + pflush_inst.instruction = 0x8000800a; + pflush_inst.size = 4; + pflush_inst.relax_inst = 0x8000; + pflush_inst.relax_size = 0; + pflush_inst.type = NO_OPD; + + /* pflush will clear all data dependency. */ + if (strcmp (theinst->name, "pflush") == 0) + { + s7_init_dependency_vector (); + return; + } + + /* Push current instruction to s7_dependency_vector[0]. */ + for (i = s7_vector_size - 1; i > 0; i--) + memcpy (&s7_dependency_vector[i], &s7_dependency_vector[i - 1], sizeof (s7_dependency_vector[i])); + + memcpy (&s7_dependency_vector[0], theinst, sizeof (s7_dependency_vector[i])); + + /* There is no dependency between nop and any instruction. */ + if (strcmp (s7_dependency_vector[0].name, "nop") == 0 + || strcmp (s7_dependency_vector[0].name, "nop!") == 0) + return; + + /* "pce" is defined in s7_insn_to_dependency_table. */ +#define PCE_NAME "pce" + + if (s7_dependency_vector[0].type == Insn_Type_PCE) + strcpy (cur_insn, PCE_NAME); + else + strcpy (cur_insn, s7_dependency_vector[0].name); + + for (i = 1; i < s7_vector_size; i++) + { + /* The element of s7_dependency_vector is NULL. */ + if (s7_dependency_vector[i].name[0] == '\0') + continue; + + if (s7_dependency_vector[i].type == Insn_Type_PCE) + strcpy (pre_insn, PCE_NAME); + else + strcpy (pre_insn, s7_dependency_vector[i].name); + + bubbles = s7_check_dependency (pre_insn, s7_dependency_vector[i].reg, + cur_insn, s7_dependency_vector[0].reg, &warn_or_error); + remainder_bubbles = bubbles - i + 1; + + if (remainder_bubbles > 0) + { + int j; + + if (s7_fix_data_dependency == 1) + { + if (remainder_bubbles <= 2) + { + if (s7_warn_fix_data_dependency) + as_warn (_("Fix data dependency: %s %s -- %s %s (insert %d nop!/%d)"), + s7_dependency_vector[i].name, s7_dependency_vector[i].reg, + s7_dependency_vector[0].name, s7_dependency_vector[0].reg, + remainder_bubbles, bubbles); + + for (j = (s7_vector_size - 1); (j - remainder_bubbles) > 0; j--) + memcpy (&s7_dependency_vector[j], &s7_dependency_vector[j - remainder_bubbles], + sizeof (s7_dependency_vector[j])); + + for (j = 1; j <= remainder_bubbles; j++) + { + memset (&s7_dependency_vector[j], '\0', sizeof (s7_dependency_vector[j])); + /* Insert nop!. */ + s7_build_one_frag (nop_inst); + } + } + else + { + if (s7_warn_fix_data_dependency) + as_warn (_("Fix data dependency: %s %s -- %s %s (insert 1 pflush/%d)"), + s7_dependency_vector[i].name, s7_dependency_vector[i].reg, + s7_dependency_vector[0].name, s7_dependency_vector[0].reg, + bubbles); + + for (j = 1; j < s7_vector_size; j++) + memset (&s7_dependency_vector[j], '\0', sizeof (s7_dependency_vector[j])); + + /* Insert pflush. */ + s7_build_one_frag (pflush_inst); + } + } + else + { + if (warn_or_error) + { + as_bad (_("data dependency: %s %s -- %s %s (%d/%d bubble)"), + s7_dependency_vector[i].name, s7_dependency_vector[i].reg, + s7_dependency_vector[0].name, s7_dependency_vector[0].reg, + remainder_bubbles, bubbles); + } + else + { + as_warn (_("data dependency: %s %s -- %s %s (%d/%d bubble)"), + s7_dependency_vector[i].name, s7_dependency_vector[i].reg, + s7_dependency_vector[0].name, s7_dependency_vector[0].reg, + remainder_bubbles, bubbles); + } + } + } + } +} + +static enum insn_class +s7_get_insn_class_from_type (enum score_insn_type type) +{ + enum insn_class retval = (int) s7_FAIL; + + switch (type) + { + case Rd_I4: + case Rd_I5: + case Rd_rvalueBP_I5: + case Rd_lvalueBP_I5: + case Rd_I8: + case PC_DISP8div2: + case PC_DISP11div2: + case Rd_Rs: + case Rd_HighRs: + case Rd_lvalueRs: + case Rd_rvalueRs: + case x_Rs: + case Rd_LowRs: + case NO16_OPD: + retval = INSN_CLASS_16; + break; + case Rd_Rs_I5: + case x_Rs_I5: + case x_I5_x: + case Rd_Rs_I14: + case I15: + case Rd_I16: + case Rd_SI16: + case Rd_rvalueRs_SI10: + case Rd_lvalueRs_SI10: + case Rd_rvalueRs_preSI12: + case Rd_rvalueRs_postSI12: + case Rd_lvalueRs_preSI12: + case Rd_lvalueRs_postSI12: + case Rd_Rs_SI14: + case Rd_rvalueRs_SI15: + case Rd_lvalueRs_SI15: + case PC_DISP19div2: + case PC_DISP24div2: + case Rd_Rs_Rs: + case x_Rs_x: + case x_Rs_Rs: + case Rd_Rs_x: + case Rd_x_Rs: + case Rd_x_x: + case OP5_rvalueRs_SI15: + case I5_Rs_Rs_I5_OP5: + case x_rvalueRs_post4: + case Rd_rvalueRs_post4: + case Rd_x_I5: + case Rd_lvalueRs_post4: + case x_lvalueRs_post4: + case Rd_Rs_Rs_imm: + case NO_OPD: + case Rd_lvalue32Rs: + case Rd_rvalue32Rs: + case Insn_GP: + case Insn_PIC: + case Insn_internal: + retval = INSN_CLASS_32; + break; + case Insn_Type_PCE: + retval = INSN_CLASS_PCE; + break; + case Insn_Type_SYN: + retval = INSN_CLASS_SYN; + break; + default: + abort (); + break; + } + return retval; +} + +static unsigned long +s7_adjust_paritybit (unsigned long m_code, enum insn_class class) +{ + unsigned long result = 0; + unsigned long m_code_high = 0; + unsigned long m_code_low = 0; + unsigned long pb_high = 0; + unsigned long pb_low = 0; + + if (class == INSN_CLASS_32) + { + pb_high = 0x80000000; + pb_low = 0x00008000; + } + else if (class == INSN_CLASS_16) + { + pb_high = 0; + pb_low = 0; + } + else if (class == INSN_CLASS_PCE) + { + pb_high = 0; + pb_low = 0x00008000; + } + else if (class == INSN_CLASS_SYN) + { + /* FIXME. at this time, INSN_CLASS_SYN must be 32 bit, but, instruction type should + be changed if macro instruction has been expanded. */ + pb_high = 0x80000000; + pb_low = 0x00008000; + } + else + { + abort (); + } + + m_code_high = m_code & 0x3fff8000; + m_code_low = m_code & 0x00007fff; + result = pb_high | (m_code_high << 1) | pb_low | m_code_low; + return result; + +} + +static void +s7_gen_insn_frag (struct s7_score_it *part_1, struct s7_score_it *part_2) +{ + char *p; + bfd_boolean pce_p = FALSE; + int relaxable_p = s7_g_opt; + int relax_size = 0; + struct s7_score_it *inst1 = part_1; + struct s7_score_it *inst2 = part_2; + struct s7_score_it backup_inst1; + + pce_p = (inst2) ? TRUE : FALSE; + memcpy (&backup_inst1, inst1, sizeof (struct s7_score_it)); + + /* Adjust instruction opcode and to be relaxed instruction opcode. */ + if (pce_p) + { + backup_inst1.instruction = ((backup_inst1.instruction & 0x7FFF) << 15) + | (inst2->instruction & 0x7FFF); + backup_inst1.instruction = s7_adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE); + if (!target_big_endian) + { + unsigned long tmp = backup_inst1.instruction; + backup_inst1.instruction = ((tmp & 0xffff) << 16) + | (tmp >> 16); + } + backup_inst1.relax_inst = 0x8000; + backup_inst1.size = s7_INSN_SIZE; + backup_inst1.relax_size = 0; + backup_inst1.type = Insn_Type_PCE; + } + else + { + backup_inst1.instruction = s7_adjust_paritybit (backup_inst1.instruction, + s7_GET_INSN_CLASS (backup_inst1.type)); + } + + if (backup_inst1.relax_size != 0) + { + enum insn_class tmp; + + tmp = (backup_inst1.size == s7_INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32; + backup_inst1.relax_inst = s7_adjust_paritybit (backup_inst1.relax_inst, tmp); + } + + /* Check data dependency. */ + s7_handle_dependency (&backup_inst1); + + /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains + data produced by .ascii etc. Doing this is to make one instruction per frag. */ + if (frag_now_fix () != 0) + { + if (!frag_now->tc_frag_data.is_insn) + frag_wane (frag_now); + + frag_new (0); + } + + /* Here, we must call frag_grow in order to keep the instruction frag type is + rs_machine_dependent. + For, frag_var may change frag_now->fr_type to rs_fill by calling frag_grow which + acturally will call frag_wane. + Calling frag_grow first will create a new frag_now which free size is 20 that is enough + for frag_var. */ + frag_grow (20); + + p = frag_more (backup_inst1.size); + s7_number_to_chars (p, backup_inst1.instruction, backup_inst1.size); + +#ifdef OBJ_ELF + dwarf2_emit_insn (backup_inst1.size); +#endif + + /* Generate fixup structure. */ + if (pce_p) + { + if (inst1->reloc.type != BFD_RELOC_NONE) + s7_fix_new_score (frag_now, p - frag_now->fr_literal, + inst1->size, &inst1->reloc.exp, + inst1->reloc.pc_rel, inst1->reloc.type); + + if (inst2->reloc.type != BFD_RELOC_NONE) + s7_fix_new_score (frag_now, p - frag_now->fr_literal + 2, + inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type); + } + else + { + if (backup_inst1.reloc.type != BFD_RELOC_NONE) + s7_fix_new_score (frag_now, p - frag_now->fr_literal, + backup_inst1.size, &backup_inst1.reloc.exp, + backup_inst1.reloc.pc_rel, backup_inst1.reloc.type); + } + + /* relax_size may be 2, 4, 12 or 0, 0 indicates no relaxation. */ + relaxable_p &= (backup_inst1.relax_size != 0); + relax_size = relaxable_p ? backup_inst1.relax_size : 0; + + p = frag_var (rs_machine_dependent, relax_size + s7_RELAX_PAD_BYTE, 0, + s7_RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size, + backup_inst1.type, 0, 0, relaxable_p), + backup_inst1.reloc.exp.X_add_symbol, 0, NULL); + + if (relaxable_p) + s7_number_to_chars (p, backup_inst1.relax_inst, relax_size); + + memcpy (inst1, &backup_inst1, sizeof (struct s7_score_it)); +} + +static void +s7_parse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p) +{ + char c; + char *p; + char *operator = insnstr; + const struct s7_asm_opcode *opcode; + + /* Parse operator and operands. */ + s7_skip_whitespace (operator); + + for (p = operator; *p != '\0'; p++) + if ((*p == ' ') || (*p == '!')) + break; + + if (*p == '!') + p++; + + c = *p; + *p = '\0'; + + opcode = (const struct s7_asm_opcode *) hash_find (s7_score_ops_hsh, operator); + *p = c; + + memset (&s7_inst, '\0', sizeof (s7_inst)); + sprintf (s7_inst.str, "%s", insnstr); + if (opcode) + { + s7_inst.instruction = opcode->value; + s7_inst.relax_inst = opcode->relax_value; + s7_inst.type = opcode->type; + s7_inst.size = s7_GET_INSN_SIZE (s7_inst.type); + s7_inst.relax_size = 0; + s7_inst.bwarn = 0; + sprintf (s7_inst.name, "%s", opcode->template); + strcpy (s7_inst.reg, ""); + s7_inst.error = NULL; + s7_inst.reloc.type = BFD_RELOC_NONE; + + (*opcode->parms) (p); + + /* It indicates current instruction is a macro instruction if s7_inst.bwarn equals -1. */ + if ((s7_inst.bwarn != -1) && (!s7_inst.error) && (gen_frag_p)) + s7_gen_insn_frag (&s7_inst, NULL); + } + else + s7_inst.error = _("unrecognized opcode"); +} + +static int +s7_append_insn (char *str, bfd_boolean gen_frag_p) +{ + int retval = s7_SUCCESS; + + s7_parse_16_32_inst (str, gen_frag_p); + + if (s7_inst.error) + { + retval = (int) s7_FAIL; + as_bad (_("%s -- `%s'"), s7_inst.error, s7_inst.str); + s7_inst.error = NULL; + } + + return retval; +} + +/* Handle mv! reg_high, reg_low; + mv! reg_low, reg_high; + mv! reg_low, reg_low; */ +static void +s7_do16_mv_rdrs (char *str) +{ + int reg_rd; + int reg_rs; + char *backupstr = NULL; + + backupstr = str; + s7_skip_whitespace (str); + + if ((reg_rd = s7_reg_required_here (&str, 8, s7_REG_TYPE_SCORE)) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL + || (reg_rs = s7_reg_required_here (&str, 4, s7_REG_TYPE_SCORE)) == (int) s7_FAIL + || s7_end_of_line (str) == (int) s7_FAIL) + { + return; + } + else + { + /* Case 1 : mv! or mlfh!. */ + if (reg_rd < 16) + { + if (reg_rs < 16) + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20) + | (((s7_inst.instruction >> 4) & 0xf) << 15) | (0xf << 10); + s7_inst.relax_size = 4; + } + else + { + char append_str[s7_MAX_LITERAL_POOL_SIZE]; + + sprintf (append_str, "mlfh! %s", backupstr); + if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL) + return; + /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ + s7_inst.bwarn = -1; + } + } + /* Case 2 : mhfl!. */ + else + { + if (reg_rs > 16) + { + s7_SET_INSN_ERROR (s7_BAD_ARGS); + return; + } + else + { + char append_str[s7_MAX_LITERAL_POOL_SIZE]; + + sprintf (append_str, "mhfl! %s", backupstr); + if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL) + return; + + /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ + s7_inst.bwarn = -1; + } + } + } +} + +static void +s7_do16_rdi4 (char *str) +{ + s7_skip_whitespace (str); + + if (s7_reglow_required_here (&str, 8) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL + || s7_data_op2 (&str, 3, _IMM4) == (int) s7_FAIL + || s7_end_of_line (str) == (int) s7_FAIL) + { + return; + } + else + { + if (((s7_inst.instruction >> 3) & 0x10) == 0) /* for judge is addei or subei : bit 5 =0 : addei */ + { + if (((s7_inst.instruction >> 3) & 0xf) != 0xf) + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20) + | ((1 << ((s7_inst.instruction >> 3) & 0xf)) << 1); + s7_inst.relax_size = 4; + } + else + { + s7_inst.relax_inst = 0x8000; + } + } + else + { + if (((s7_inst.instruction >> 3) & 0xf) != 0xf) + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20) + | (((-(1 << ((s7_inst.instruction >> 3) & 0xf))) & 0xffff) << 1); + s7_inst.relax_size = 4; + } + else + { + s7_inst.relax_inst = 0x8000; + } + } + } +} + +static void +s7_do16_rdi5 (char *str) +{ + s7_skip_whitespace (str); + + if (s7_reglow_required_here (&str, 8) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL + || s7_data_op2 (&str, 3, _IMM5) == (int) s7_FAIL + || s7_end_of_line (str) == (int) s7_FAIL) + return; + else + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20) + | (((s7_inst.instruction >> 8) & 0xf) << 15) | (((s7_inst.instruction >> 3) & 0x1f) << 10); + s7_inst.relax_size = 4; + } +} + +/* Handle sdbbp. */ + +static void +s7_do16_xi5 (char *str) +{ + s7_skip_whitespace (str); + + if (s7_data_op2 (&str, 3, _IMM5) == (int) s7_FAIL || s7_end_of_line (str) == (int) s7_FAIL) + return; + else + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 3) & 0x1f) << 15); + s7_inst.relax_size = 4; + } +} + +/* Check that an immediate is word alignment or half word alignment. + If so, convert it to the right format. */ + +static int +s7_validate_immediate_align (int val, unsigned int data_type) +{ + if (data_type == _IMM5_RSHIFT_1) + { + if (val % 2) + { + s7_inst.error = _("address offset must be half word alignment"); + return (int) s7_FAIL; + } + } + else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2)) + { + if (val % 4) + { + s7_inst.error = _("address offset must be word alignment"); + return (int) s7_FAIL; + } + } + + return s7_SUCCESS; +} + +static int +s7_exp_ldst_offset (char **str, int shift, unsigned int data_type) +{ + char *dataptr; + int hex_p = 0; + + dataptr = * str; + + if ((dataptr != NULL) + && (((strstr (dataptr, "0x")) != NULL) + || ((strstr (dataptr, "0X")) != NULL))) + { + hex_p = 1; + if ((data_type != _SIMM16_LA) + && (data_type != _VALUE_HI16) + && (data_type != _VALUE_LO16) + && (data_type != _IMM16) + && (data_type != _IMM15) + && (data_type != _IMM14) + && (data_type != _IMM4) + && (data_type != _IMM5) + && (data_type != _IMM8) + && (data_type != _IMM5_RSHIFT_1) + && (data_type != _IMM5_RSHIFT_2) + && (data_type != _SIMM12) + && (data_type != _SIMM15) + && (data_type != _SIMM14_NEG) + && (data_type != _IMM10_RSHIFT_2)) + { + data_type += 24; + } + } + + if (s7_my_get_expression (&s7_inst.reloc.exp, str) == (int) s7_FAIL) + return (int) s7_FAIL; + + if (s7_inst.reloc.exp.X_op == O_constant) + { + /* Need to check the immediate align. */ + int value = s7_validate_immediate_align (s7_inst.reloc.exp.X_add_number, data_type); + + if (value == (int) s7_FAIL) + return (int) s7_FAIL; + + value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, data_type, hex_p); + if (value == (int) s7_FAIL) + { + if (data_type < 30) + sprintf (s7_err_msg, + _("invalid constant: %d bit expression not in range %d..%d"), + s7_score_df_range[data_type].bits, + s7_score_df_range[data_type].range[0], s7_score_df_range[data_type].range[1]); + else + sprintf (s7_err_msg, + _("invalid constant: %d bit expression not in range %d..%d"), + s7_score_df_range[data_type - 24].bits, + s7_score_df_range[data_type - 24].range[0], s7_score_df_range[data_type - 24].range[1]); + s7_inst.error = s7_err_msg; + return (int) s7_FAIL; + } + + if (data_type == _IMM5_RSHIFT_1) + { + value >>= 1; + } + else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2)) + { + value >>= 2; + } + + if (s7_score_df_range[data_type].range[0] != 0) + { + value &= (1 << s7_score_df_range[data_type].bits) - 1; + } + + s7_inst.instruction |= value << shift; + } + else + { + s7_inst.reloc.pc_rel = 0; + } + + return s7_SUCCESS; +} + +static void +s7_do_ldst_insn (char *str) +{ + int pre_inc = 0; + int conflict_reg; + int value; + char * temp; + char *strbak; + char *dataptr; + int reg; + int ldst_idx = 0; + + int hex_p = 0; + + strbak = str; + s7_skip_whitespace (str); + + if (((conflict_reg = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL) + || (s7_skip_past_comma (&str) == (int) s7_FAIL)) + return; + + /* ld/sw rD, [rA, simm15] ld/sw rD, [rA]+, simm12 ld/sw rD, [rA, simm12]+. */ + if (*str == '[') + { + str++; + s7_skip_whitespace (str); + + if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL) + return; + + /* Conflicts can occur on stores as well as loads. */ + conflict_reg = (conflict_reg == reg); + s7_skip_whitespace (str); + temp = str + 1; /* The latter will process decimal/hex expression. */ + + /* ld/sw rD, [rA]+, simm12 ld/sw rD, [rA]+. */ + if (*str == ']') + { + str++; + if (*str == '+') + { + str++; + /* ld/sw rD, [rA]+, simm12. */ + if (s7_skip_past_comma (&str) == s7_SUCCESS) + { + if ((s7_exp_ldst_offset (&str, 3, _SIMM12) == (int) s7_FAIL) + || (s7_end_of_line (str) == (int) s7_FAIL)) + return; + + if (conflict_reg) + { + unsigned int ldst_func = s7_inst.instruction & OPC_PSEUDOLDST_MASK; + + if ((ldst_func == INSN_LH) + || (ldst_func == INSN_LHU) + || (ldst_func == INSN_LW) + || (ldst_func == INSN_LB) + || (ldst_func == INSN_LBU)) + { + s7_inst.error = _("register same as write-back base"); + return; + } + } + + ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK; + s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK; + s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + LDST_POST].value; + + /* lw rD, [rA]+, 4 convert to pop rD, [rA]. */ + if ((s7_inst.instruction & 0x3e000007) == 0x0e000000) + { + /* rs = r0-r7, offset = 4 */ + if ((((s7_inst.instruction >> 15) & 0x18) == 0) + && (((s7_inst.instruction >> 3) & 0xfff) == 4)) + { + /* Relax to pophi. */ + if ((((s7_inst.instruction >> 20) & 0x10) == 0x10)) + { + s7_inst.relax_inst = 0x0000200a | (((s7_inst.instruction >> 20) & 0xf) + << 8) | 1 << 7 | + (((s7_inst.instruction >> 15) & 0x7) << 4); + } + /* Relax to pop. */ + else + { + s7_inst.relax_inst = 0x0000200a | (((s7_inst.instruction >> 20) & 0xf) + << 8) | 0 << 7 | + (((s7_inst.instruction >> 15) & 0x7) << 4); + } + s7_inst.relax_size = 2; + } + } + return; + } + /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+. */ + else + { + s7_SET_INSN_ERROR (NULL); + if (s7_end_of_line (str) == (int) s7_FAIL) + { + return; + } + + pre_inc = 1; + value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _SIMM12, 0); + value &= (1 << s7_score_df_range[_SIMM12].bits) - 1; + ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK; + s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK; + s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + pre_inc].value; + s7_inst.instruction |= value << 3; + s7_inst.relax_inst = 0x8000; + return; + } + } + /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15]. */ + else + { + if (s7_end_of_line (str) == (int) s7_FAIL) + return; + + ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK; + s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK; + s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value; + + /* lbu rd, [rs] -> lbu! rd, [rs] */ + if (ldst_idx == INSN_LBU) + { + s7_inst.relax_inst = INSN16_LBU; + } + else if (ldst_idx == INSN_LH) + { + s7_inst.relax_inst = INSN16_LH; + } + else if (ldst_idx == INSN_LW) + { + s7_inst.relax_inst = INSN16_LW; + } + else if (ldst_idx == INSN_SB) + { + s7_inst.relax_inst = INSN16_SB; + } + else if (ldst_idx == INSN_SH) + { + s7_inst.relax_inst = INSN16_SH; + } + else if (ldst_idx == INSN_SW) + { + s7_inst.relax_inst = INSN16_SW; + } + else + { + s7_inst.relax_inst = 0x8000; + } + + /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction. */ + if ((ldst_idx == INSN_LBU) + || (ldst_idx == INSN_LH) + || (ldst_idx == INSN_LW) + || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW)) + { + if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0)) + { + s7_inst.relax_inst |= (2 << 12) | (((s7_inst.instruction >> 20) & 0xf) << 8) | + (((s7_inst.instruction >> 15) & 0xf) << 4); + s7_inst.relax_size = 2; + } + } + + return; + } + } + /* ld/sw rD, [rA, simm15] ld/sw rD, [rA, simm12]+. */ + else + { + if (s7_skip_past_comma (&str) == (int) s7_FAIL) + { + s7_inst.error = _("pre-indexed expression expected"); + return; + } + + if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL) + return; + + s7_skip_whitespace (str); + if (*str++ != ']') + { + s7_inst.error = _("missing ]"); + return; + } + + s7_skip_whitespace (str); + /* ld/sw rD, [rA, simm12]+. */ + if (*str == '+') + { + str++; + pre_inc = 1; + if (conflict_reg) + { + unsigned int ldst_func = s7_inst.instruction & OPC_PSEUDOLDST_MASK; + + if ((ldst_func == INSN_LH) + || (ldst_func == INSN_LHU) + || (ldst_func == INSN_LW) + || (ldst_func == INSN_LB) + || (ldst_func == INSN_LBU)) + { + s7_inst.error = _("register same as write-back base"); + return; + } + } + } + + if (s7_end_of_line (str) == (int) s7_FAIL) + return; + + if (s7_inst.reloc.exp.X_op == O_constant) + { + int value; + unsigned int data_type; + + if (pre_inc == 1) + data_type = _SIMM12; + else + data_type = _SIMM15; + dataptr = temp; + + if ((dataptr != NULL) + && (((strstr (dataptr, "0x")) != NULL) + || ((strstr (dataptr, "0X")) != NULL))) + { + hex_p = 1; + if ((data_type != _SIMM16_LA) + && (data_type != _VALUE_HI16) + && (data_type != _VALUE_LO16) + && (data_type != _IMM16) + && (data_type != _IMM15) + && (data_type != _IMM14) + && (data_type != _IMM4) + && (data_type != _IMM5) + && (data_type != _IMM8) + && (data_type != _SIMM12) + && (data_type != _SIMM15) + && (data_type != _IMM5_RSHIFT_1) + && (data_type != _IMM5_RSHIFT_2) + && (data_type != _SIMM14_NEG) + && (data_type != _IMM10_RSHIFT_2)) + { + data_type += 24; + } + } + + value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, data_type, hex_p); + if (value == (int) s7_FAIL) + { + if (data_type < 30) + sprintf (s7_err_msg, + _("invalid constant: %d bit expression not in range %d..%d"), + s7_score_df_range[data_type].bits, + s7_score_df_range[data_type].range[0], s7_score_df_range[data_type].range[1]); + else + sprintf (s7_err_msg, + _("invalid constant: %d bit expression not in range %d..%d"), + s7_score_df_range[data_type - 24].bits, + s7_score_df_range[data_type - 24].range[0], + s7_score_df_range[data_type - 24].range[1]); + s7_inst.error = s7_err_msg; + return; + } + + value &= (1 << s7_score_df_range[data_type].bits) - 1; + ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK; + s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK; + s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + pre_inc].value; + if (pre_inc == 1) + s7_inst.instruction |= value << 3; + else + s7_inst.instruction |= value; + + /* lw rD, [rA, simm15] */ + if ((s7_inst.instruction & 0x3e000000) == 0x20000000) + { + /* Both rD and rA are in [r0 - r15]. */ + if ((((s7_inst.instruction >> 15) & 0x10) == 0) + && (((s7_inst.instruction >> 20) & 0x10) == 0)) + { + /* simm15 = 0, lw -> lw!. */ + if ((s7_inst.instruction & 0x7fff) == 0) + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4) + | (((s7_inst.instruction >> 20) & 0xf) << 8); + s7_inst.relax_size = 2; + } + /* rA = r2, lw -> lwp!. */ + else if ((((s7_inst.instruction >> 15) & 0xf) == 2) + && ((s7_inst.instruction & 0x3) == 0) + && ((s7_inst.instruction & 0x7fff) < 128)) + { + s7_inst.relax_inst = 0x7000 | (((s7_inst.instruction >> 20) & 0xf) << 8) + | (((s7_inst.instruction & 0x7fff) >> 2) << 3); + s7_inst.relax_size = 2; + } + else + { + s7_inst.relax_inst = 0x8000; + } + } + else + { + s7_inst.relax_inst = 0x8000; + } + } + /* sw rD, [rA, simm15] */ + else if ((s7_inst.instruction & 0x3e000000) == 0x28000000) + { + /* Both rD and rA are in [r0 - r15]. */ + if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0)) + { + /* simm15 = 0, sw -> sw!. */ + if ((s7_inst.instruction & 0x7fff) == 0) + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4) + | (((s7_inst.instruction >> 20) & 0xf) << 8); + s7_inst.relax_size = 2; + } + /* rA = r2, sw -> swp!. */ + else if ((((s7_inst.instruction >> 15) & 0xf) == 2) + && ((s7_inst.instruction & 0x3) == 0) + && ((s7_inst.instruction & 0x7fff) < 128)) + { + s7_inst.relax_inst = 0x7004 | (((s7_inst.instruction >> 20) & 0xf) << 8) + | (((s7_inst.instruction & 0x7fff) >> 2) << 3); + s7_inst.relax_size = 2; + } + else + { + s7_inst.relax_inst = 0x8000; + } + } + else + { + s7_inst.relax_inst = 0x8000; + } + } + /* sw rD, [rA, simm15]+ sw pre. */ + else if ((s7_inst.instruction & 0x3e000007) == 0x06000004) + { + /* rA is in [r0 - r7], and simm15 = -4. */ + if ((((s7_inst.instruction >> 15) & 0x18) == 0) + && (((s7_inst.instruction >> 3) & 0xfff) == 0xffc)) + { + /* sw -> pushhi!. */ + if ((((s7_inst.instruction >> 20) & 0x10) == 0x10)) + { + s7_inst.relax_inst = 0x0000200e | (((s7_inst.instruction >> 20) & 0xf) << 8) + | 1 << 7 | (((s7_inst.instruction >> 15) & 0x7) << 4); + s7_inst.relax_size = 2; + } + /* sw -> push!. */ + else + { + s7_inst.relax_inst = 0x0000200e | (((s7_inst.instruction >> 20) & 0xf) << 8) + | 0 << 7 | (((s7_inst.instruction >> 15) & 0x7) << 4); + s7_inst.relax_size = 2; + } + } + else + { + s7_inst.relax_inst = 0x8000; + } + } + /* lh rD, [rA, simm15] */ + else if ((s7_inst.instruction & 0x3e000000) == 0x22000000) + { + /* Both rD and rA are in [r0 - r15]. */ + if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0)) + { + /* simm15 = 0, lh -> lh!. */ + if ((s7_inst.instruction & 0x7fff) == 0) + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4) + | (((s7_inst.instruction >> 20) & 0xf) << 8); + s7_inst.relax_size = 2; + } + /* rA = r2, lh -> lhp!. */ + else if ((((s7_inst.instruction >> 15) & 0xf) == 2) + && ((s7_inst.instruction & 0x1) == 0) + && ((s7_inst.instruction & 0x7fff) < 64)) + { + s7_inst.relax_inst = 0x7001 | (((s7_inst.instruction >> 20) & 0xf) << 8) + | (((s7_inst.instruction & 0x7fff) >> 1) << 3); + s7_inst.relax_size = 2; + } + else + { + s7_inst.relax_inst = 0x8000; + } + } + else + { + s7_inst.relax_inst = 0x8000; + } + } + /* sh rD, [rA, simm15] */ + else if ((s7_inst.instruction & 0x3e000000) == 0x2a000000) + { + /* Both rD and rA are in [r0 - r15]. */ + if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0)) + { + /* simm15 = 0, sh -> sh!. */ + if ((s7_inst.instruction & 0x7fff) == 0) + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4) + | (((s7_inst.instruction >> 20) & 0xf) << 8); + s7_inst.relax_size = 2; + } + /* rA = r2, sh -> shp!. */ + else if ((((s7_inst.instruction >> 15) & 0xf) == 2) + && ((s7_inst.instruction & 0x1) == 0) + && ((s7_inst.instruction & 0x7fff) < 64)) + { + s7_inst.relax_inst = 0x7005 | (((s7_inst.instruction >> 20) & 0xf) << 8) + | (((s7_inst.instruction & 0x7fff) >> 1) << 3); + s7_inst.relax_size = 2; + } + else + { + s7_inst.relax_inst = 0x8000; + } + } + else + { + s7_inst.relax_inst = 0x8000; + } + } + /* lbu rD, [rA, simm15] */ + else if ((s7_inst.instruction & 0x3e000000) == 0x2c000000) + { + /* Both rD and rA are in [r0 - r15]. */ + if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0)) + { + /* simm15 = 0, lbu -> lbu!. */ + if ((s7_inst.instruction & 0x7fff) == 0) + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4) + | (((s7_inst.instruction >> 20) & 0xf) << 8); + s7_inst.relax_size = 2; + } + /* rA = r2, lbu -> lbup!. */ + else if ((((s7_inst.instruction >> 15) & 0xf) == 2) + && ((s7_inst.instruction & 0x7fff) < 32)) + { + s7_inst.relax_inst = 0x7003 | (((s7_inst.instruction >> 20) & 0xf) << 8) + | ((s7_inst.instruction & 0x7fff) << 3); + s7_inst.relax_size = 2; + } + else + { + s7_inst.relax_inst = 0x8000; + } + } + else + { + s7_inst.relax_inst = 0x8000; + } + } + /* sb rD, [rA, simm15] */ + else if ((s7_inst.instruction & 0x3e000000) == 0x2e000000) + { + /* Both rD and rA are in [r0 - r15]. */ + if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0)) + { + /* simm15 = 0, sb -> sb!. */ + if ((s7_inst.instruction & 0x7fff) == 0) + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4) + | (((s7_inst.instruction >> 20) & 0xf) << 8); + s7_inst.relax_size = 2; + } + /* rA = r2, sb -> sb!. */ + else if ((((s7_inst.instruction >> 15) & 0xf) == 2) + && ((s7_inst.instruction & 0x7fff) < 32)) + { + s7_inst.relax_inst = 0x7007 | (((s7_inst.instruction >> 20) & 0xf) << 8) + | ((s7_inst.instruction & 0x7fff) << 3); + s7_inst.relax_size = 2; + } + else + { + s7_inst.relax_inst = 0x8000; + } + } + else + { + s7_inst.relax_inst = 0x8000; + } + } + else + { + s7_inst.relax_inst = 0x8000; + } + + return; + } + else + { + /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */ + s7_inst.reloc.pc_rel = 0; + } + } + } + else + { + s7_inst.error = s7_BAD_ARGS; + } +} + +/* Handle cache. */ +static void +s7_do_cache (char *str) +{ + s7_skip_whitespace (str); + + if ((s7_data_op2 (&str, 20, _IMM5) == (int) s7_FAIL) || (s7_skip_past_comma (&str) == (int) s7_FAIL)) + { + return; + } + else + { + int cache_op; + + cache_op = (s7_inst.instruction >> 20) & 0x1F; + sprintf (s7_inst.name, "cache %d", cache_op); + } + + if (*str == '[') + { + str++; + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL) + return; + + s7_skip_whitespace (str); + + /* cache op, [rA] */ + if (s7_skip_past_comma (&str) == (int) s7_FAIL) + { + s7_SET_INSN_ERROR (NULL); + if (*str != ']') + { + s7_inst.error = _("missing ]"); + return; + } + str++; + } + /* cache op, [rA, simm15] */ + else + { + if (s7_exp_ldst_offset (&str, 0, _SIMM15) == (int) s7_FAIL) + { + return; + } + + s7_skip_whitespace (str); + if (*str++ != ']') + { + s7_inst.error = _("missing ]"); + return; + } + } + + if (s7_end_of_line (str) == (int) s7_FAIL) + return; + } + else + { + s7_inst.error = s7_BAD_ARGS; + } +} + +static void +s7_do_crdcrscrsimm5 (char *str) +{ + char *strbak; + + strbak = str; + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL + || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL + || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL) + { + str = strbak; + /* cop1 cop_code20. */ + if (s7_data_op2 (&str, 5, _IMM20) == (int) s7_FAIL) + return; + } + else + { + if (s7_data_op2 (&str, 5, _IMM5) == (int) s7_FAIL) + return; + } + + s7_end_of_line (str); +} + +/* Handle ldc/stc. */ +static void +s7_do_ldst_cop (char *str) +{ + s7_skip_whitespace (str); + + if ((s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL) + || (s7_skip_past_comma (&str) == (int) s7_FAIL)) + return; + + if (*str == '[') + { + str++; + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL) + return; + + s7_skip_whitespace (str); + + if (*str++ != ']') + { + if (s7_exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) s7_FAIL) + return; + + s7_skip_whitespace (str); + if (*str++ != ']') + { + s7_inst.error = _("missing ]"); + return; + } + } + + s7_end_of_line (str); + } + else + s7_inst.error = s7_BAD_ARGS; +} + +static void +s7_do16_ldst_insn (char *str) +{ + s7_skip_whitespace (str); + + if ((s7_reglow_required_here (&str, 8) == (int) s7_FAIL) || (s7_skip_past_comma (&str) == (int) s7_FAIL)) + return; + + if (*str == '[') + { + int reg; + + str++; + s7_skip_whitespace (str); + + if ((reg = s7_reglow_required_here (&str, 4)) == (int) s7_FAIL) + return; + + s7_skip_whitespace (str); + if (*str++ == ']') + { + if (s7_end_of_line (str) == (int) s7_FAIL) + return; + else + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20) + | (((s7_inst.instruction >> 4) & 0xf) << 15); + s7_inst.relax_size = 4; + } + } + else + { + s7_inst.error = _("missing ]"); + } + } + else + { + s7_inst.error = s7_BAD_ARGS; + } +} + +/* Handle lbup!/lhp!/ldiu!/lwp!/sbp!/shp!/swp!. */ + +static void +s7_do16_ldst_imm_insn (char *str) +{ + char data_exp[s7_MAX_LITERAL_POOL_SIZE]; + int reg_rd; + char *dataptr = NULL, *pp = NULL; + int cnt = 0; + int assign_data = (int) s7_FAIL; + unsigned int ldst_func; + + s7_skip_whitespace (str); + + if (((reg_rd = s7_reglow_required_here (&str, 8)) == (int) s7_FAIL) + || (s7_skip_past_comma (&str) == (int) s7_FAIL)) + return; + + s7_skip_whitespace (str); + dataptr = str; + + while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= s7_MAX_LITERAL_POOL_SIZE)) + { + data_exp[cnt] = *dataptr; + dataptr++; + cnt++; + } + + data_exp[cnt] = '\0'; + pp = &data_exp[0]; + + str = dataptr; + + ldst_func = s7_inst.instruction & LDST16_RI_MASK; + if (ldst_func == N16_LIU) + assign_data = s7_exp_ldst_offset (&pp, 0, _IMM8); + else if (ldst_func == N16_LHP || ldst_func == N16_SHP) + assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_1); + else if (ldst_func == N16_LWP || ldst_func == N16_SWP) + assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_2); + else + assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5); + + if ((assign_data == (int) s7_FAIL) || (s7_end_of_line (pp) == (int) s7_FAIL)) + return; + else + { + if ((s7_inst.instruction & 0x7000) == N16_LIU) + { + s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 + | ((s7_inst.instruction & 0xff) << 1); + } + else if (((s7_inst.instruction & 0x7007) == N16_LHP) + || ((s7_inst.instruction & 0x7007) == N16_SHP)) + { + s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15 + | (((s7_inst.instruction >> 3) & 0x1f) << 1); + } + else if (((s7_inst.instruction & 0x7007) == N16_LWP) + || ((s7_inst.instruction & 0x7007) == N16_SWP)) + { + s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15 + | (((s7_inst.instruction >> 3) & 0x1f) << 2); + } + else if (((s7_inst.instruction & 0x7007) == N16_LBUP) + || ((s7_inst.instruction & 0x7007) == N16_SBP)) + { + s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15 + | (((s7_inst.instruction >> 3) & 0x1f)); + } + + s7_inst.relax_size = 4; + } +} + +static void +s7_do16_push_pop (char *str) +{ + int reg_rd; + int H_bit_mask = 0; + + s7_skip_whitespace (str); + if (((reg_rd = s7_reg_required_here (&str, 8, s7_REG_TYPE_SCORE)) == (int) s7_FAIL) + || (s7_skip_past_comma (&str) == (int) s7_FAIL)) + return; + + if (reg_rd >= 16) + H_bit_mask = 1; + + /* s7_reg_required_here will change bit 12 of opcode, so we must restore bit 12. */ + s7_inst.instruction &= ~(1 << 12); + + s7_inst.instruction |= H_bit_mask << 7; + + if (*str == '[') + { + int reg; + + str++; + s7_skip_whitespace (str); + if ((reg = s7_reg_required_here (&str, 4, s7_REG_TYPE_SCORE)) == (int) s7_FAIL) + return; + else if (reg > 7) + { + if (!s7_inst.error) + s7_inst.error = _("base register nums are over 3 bit"); + + return; + } + + s7_skip_whitespace (str); + if ((*str++ != ']') || (s7_end_of_line (str) == (int) s7_FAIL)) + { + if (!s7_inst.error) + s7_inst.error = _("missing ]"); + + return; + } + + /* pop! */ + if ((s7_inst.instruction & 0xf) == 0xa) + { + if (H_bit_mask) + { + s7_inst.relax_inst |= ((((s7_inst.instruction >> 8) & 0xf) | 0x10) << 20) + | (((s7_inst.instruction >> 4) & 0x7) << 15) | (4 << 3); + } + else + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20) + | (((s7_inst.instruction >> 4) & 0x7) << 15) | (4 << 3); + } + } + /* push! */ + else + { + if (H_bit_mask) + { + s7_inst.relax_inst |= ((((s7_inst.instruction >> 8) & 0xf) | 0x10) << 20) + | (((s7_inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3); + } + else + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20) + | (((s7_inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3); + } + } + s7_inst.relax_size = 4; + } + else + { + s7_inst.error = s7_BAD_ARGS; + } +} + +/* Handle lcb/lcw/lce/scb/scw/sce. */ +static void +s7_do_ldst_unalign (char *str) +{ + int conflict_reg; + + if (s7_university_version == 1) + { + s7_inst.error = s7_ERR_FOR_SCORE5U_ATOMIC; + return; + } + + s7_skip_whitespace (str); + + /* lcb/scb [rA]+. */ + if (*str == '[') + { + str++; + s7_skip_whitespace (str); + + if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL) + return; + + if (*str++ == ']') + { + if (*str++ != '+') + { + s7_inst.error = _("missing +"); + return; + } + } + else + { + s7_inst.error = _("missing ]"); + return; + } + + if (s7_end_of_line (str) == (int) s7_FAIL) + return; + } + /* lcw/lce/scb/sce rD, [rA]+. */ + else + { + if (((conflict_reg = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL) + || (s7_skip_past_comma (&str) == (int) s7_FAIL)) + { + return; + } + + s7_skip_whitespace (str); + if (*str++ == '[') + { + int reg; + + s7_skip_whitespace (str); + if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL) + { + return; + } + + /* Conflicts can occur on stores as well as loads. */ + conflict_reg = (conflict_reg == reg); + s7_skip_whitespace (str); + if (*str++ == ']') + { + unsigned int ldst_func = s7_inst.instruction & LDST_UNALIGN_MASK; + + if (*str++ == '+') + { + if (conflict_reg) + { + as_warn (_("%s register same as write-back base"), + ((ldst_func & UA_LCE) || (ldst_func & UA_LCW) + ? _("destination") : _("source"))); + } + } + else + { + s7_inst.error = _("missing +"); + return; + } + + if (s7_end_of_line (str) == (int) s7_FAIL) + return; + } + else + { + s7_inst.error = _("missing ]"); + return; + } + } + else + { + s7_inst.error = s7_BAD_ARGS; + return; + } + } +} + +/* Handle alw/asw. */ + +static void +s7_do_ldst_atomic (char *str) +{ + if (s7_university_version == 1) + { + s7_inst.error = s7_ERR_FOR_SCORE5U_ATOMIC; + return; + } + + s7_skip_whitespace (str); + + if ((s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL) + || (s7_skip_past_comma (&str) == (int) s7_FAIL)) + { + return; + } + else + { + + s7_skip_whitespace (str); + if (*str++ == '[') + { + int reg; + + s7_skip_whitespace (str); + if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL) + { + return; + } + + s7_skip_whitespace (str); + if (*str++ != ']') + { + s7_inst.error = _("missing ]"); + return; + } + + s7_end_of_line (str); + } + else + s7_inst.error = s7_BAD_ARGS; + } +} + +static void +s7_build_relax_frag (struct s7_score_it fix_insts[s7_RELAX_INST_NUM], + int fix_num ATTRIBUTE_UNUSED, + struct s7_score_it var_insts[s7_RELAX_INST_NUM], int var_num, + symbolS *add_symbol) +{ + int i; + char *p; + fixS *fixp = NULL; + fixS *cur_fixp = NULL; + long where; + struct s7_score_it inst_main; + + memcpy (&inst_main, &fix_insts[0], sizeof (struct s7_score_it)); + + /* Adjust instruction opcode and to be relaxed instruction opcode. */ + inst_main.instruction = s7_adjust_paritybit (inst_main.instruction, s7_GET_INSN_CLASS (inst_main.type)); + inst_main.type = Insn_PIC; + + for (i = 0; i < var_num; i++) + { + inst_main.relax_size += var_insts[i].size; + var_insts[i].instruction = s7_adjust_paritybit (var_insts[i].instruction, + s7_GET_INSN_CLASS (var_insts[i].type)); + } + + /* Check data dependency. */ + s7_handle_dependency (&inst_main); + + /* Start a new frag if frag_now is not empty. */ + if (frag_now_fix () != 0) + { + if (!frag_now->tc_frag_data.is_insn) + { + frag_wane (frag_now); + } + frag_new (0); + } + frag_grow (20); + + /* Write fr_fix part. */ + p = frag_more (inst_main.size); + s7_number_to_chars (p, inst_main.instruction, inst_main.size); + + if (inst_main.reloc.type != BFD_RELOC_NONE) + fixp = s7_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size, + &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type); + + frag_now->tc_frag_data.fixp = fixp; + cur_fixp = frag_now->tc_frag_data.fixp; + +#ifdef OBJ_ELF + dwarf2_emit_insn (inst_main.size); +#endif + + where = p - frag_now->fr_literal + inst_main.size; + for (i = 0; i < var_num; i++) + { + if (i > 0) + where += var_insts[i - 1].size; + + if (var_insts[i].reloc.type != BFD_RELOC_NONE) + { + fixp = s7_fix_new_score (frag_now, where, var_insts[i].size, + &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel, + var_insts[i].reloc.type); + if (fixp) + { + if (cur_fixp) + { + cur_fixp->fx_next = fixp; + cur_fixp = cur_fixp->fx_next; + } + else + { + frag_now->tc_frag_data.fixp = fixp; + cur_fixp = frag_now->tc_frag_data.fixp; + } + } + } + } + + p = frag_var (rs_machine_dependent, inst_main.relax_size + s7_RELAX_PAD_BYTE, 0, + s7_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, + 0, inst_main.size, 0), add_symbol, 0, NULL); + + /* Write fr_var part. + no calling s7_gen_insn_frag, no fixS will be generated. */ + for (i = 0; i < var_num; i++) + { + s7_number_to_chars (p, var_insts[i].instruction, var_insts[i].size); + p += var_insts[i].size; + } + /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ + s7_inst.bwarn = -1; +} + +/* Build a relax frag for la instruction when generating s7_PIC, + external symbol first and local symbol second. */ + +static void +s7_build_la_pic (int reg_rd, expressionS exp) +{ + symbolS *add_symbol = exp.X_add_symbol; + offsetT add_number = exp.X_add_number; + struct s7_score_it fix_insts[s7_RELAX_INST_NUM]; + struct s7_score_it var_insts[s7_RELAX_INST_NUM]; + int fix_num = 0; + int var_num = 0; + char tmp[s7_MAX_LITERAL_POOL_SIZE]; + int r1_bak; + + r1_bak = s7_nor1; + s7_nor1 = 0; + + if (add_number == 0) + { + fix_num = 1; + var_num = 2; + + /* For an external symbol, only one insn is generated; + For a local symbol, two insns are generated. */ + /* Fix part + For an external symbol: lw rD, ($gp) + (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15) */ + sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name); + if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL) + return; + + if (reg_rd == s7_PIC_CALL_REG) + s7_inst.reloc.type = BFD_RELOC_SCORE_CALL15; + memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it)); + + /* Var part + For a local symbol : + lw rD, ($gp) (BFD_RELOC_SCORE_GOT15) + addi rD, (BFD_RELOC_GOT_LO16) */ + s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15; + memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it)); + sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, add_symbol->bsym->name); + if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL) + return; + + memcpy (&var_insts[1], &s7_inst, sizeof (struct s7_score_it)); + s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); + } + else if (add_number >= -0x8000 && add_number <= 0x7fff) + { + /* Insn 1: lw rD, ($gp) (BFD_RELOC_SCORE_GOT15) */ + sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name); + if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL) + return; + + /* Insn 2 */ + fix_num = 1; + var_num = 1; + /* Fix part + For an external symbol: addi rD, */ + sprintf (tmp, "addi r%d, %d", reg_rd, (int) add_number); + if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL) + return; + + memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it)); + + /* Var part + For a local symbol: addi rD, + (BFD_RELOC_GOT_LO16) */ + sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd, add_symbol->bsym->name, (int) add_number); + if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL) + return; + + memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it)); + s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); + } + else + { + int hi = (add_number >> 16) & 0x0000FFFF; + int lo = add_number & 0x0000FFFF; + + /* Insn 1: lw rD, ($gp) (BFD_RELOC_SCORE_GOT15) */ + sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name); + if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL) + return; + + /* Insn 2 */ + fix_num = 1; + var_num = 1; + /* Fix part + For an external symbol: ldis r1, HI% */ + sprintf (tmp, "ldis r1, %d", hi); + if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL) + return; + + memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it)); + + /* Var part + For a local symbol: ldis r1, HI% + but, if lo is outof 16 bit, make hi plus 1 */ + if ((lo < -0x8000) || (lo > 0x7fff)) + { + hi += 1; + } + sprintf (tmp, "ldis_pic r1, %d", hi); + if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL) + return; + + memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it)); + s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); + + /* Insn 3 */ + fix_num = 1; + var_num = 1; + /* Fix part + For an external symbol: ori r1, LO% */ + sprintf (tmp, "ori r1, %d", lo); + if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL) + return; + + memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it)); + + /* Var part + For a local symbol: addi r1, +LO% (BFD_RELOC_GOT_LO16) */ + sprintf (tmp, "addi_u_pic r1, %s + %d", add_symbol->bsym->name, lo); + if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL) + return; + + memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it)); + s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); + + /* Insn 4: add rD, rD, r1 */ + sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd); + if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL) + return; + + /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ + s7_inst.bwarn = -1; + } + + s7_nor1 = r1_bak; +} + +/* Handle la. */ + +static void +s7_do_macro_la_rdi32 (char *str) +{ + int reg_rd; + + s7_skip_whitespace (str); + if ((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL) + { + return; + } + else + { + char append_str[s7_MAX_LITERAL_POOL_SIZE]; + char *keep_data = str; + + /* Check immediate value. */ + if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL) + { + s7_inst.error = _("expression error"); + return; + } + else if ((s7_inst.reloc.exp.X_add_symbol == NULL) + && (s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _IMM32, 0) == (int) s7_FAIL)) + { + s7_inst.error = _("value not in range [0, 0xffffffff]"); + return; + } + + /* Reset str. */ + str = keep_data; + + /* la rd, simm16. */ + if (s7_data_op2 (&str, 1, _SIMM16_LA) != (int) s7_FAIL) + { + s7_end_of_line (str); + return; + } + /* la rd, imm32 or la rd, label. */ + else + { + s7_SET_INSN_ERROR (NULL); + str = keep_data; + if ((s7_data_op2 (&str, 1, _VALUE_HI16) == (int) s7_FAIL) + || (s7_end_of_line (str) == (int) s7_FAIL)) + { + return; + } + else + { + if ((s7_score_pic == s7_NO_PIC) || (!s7_inst.reloc.exp.X_add_symbol)) + { + sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data); + if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL) + return; + + sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data); + if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL) + return; + } + else + { + assert (s7_inst.reloc.exp.X_add_symbol); + s7_build_la_pic (reg_rd, s7_inst.reloc.exp); + } + + /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ + s7_inst.bwarn = -1; + } + } + } +} + +/* Handle li. */ + +static void +s7_do_macro_li_rdi32 (char *str) +{ + int reg_rd; + + s7_skip_whitespace (str); + if ((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL + || s7_skip_past_comma (&str) == (int) s7_FAIL) + { + return; + } + else + { + char *keep_data = str; + + /* Check immediate value. */ + if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL) + { + s7_inst.error = _("expression error"); + return; + } + else if (!(s7_inst.reloc.exp.X_add_number >= -0xffffffffLL + && s7_inst.reloc.exp.X_add_number <= 0xffffffffLL)) + { + s7_inst.error = _("value not in range [-0xffffffff, 0xffffffff]"); + return; + } + + /* Reset str. */ + str = keep_data; + + /* li rd, simm16. */ + if (s7_data_op2 (&str, 1, _SIMM16_LA) != (int) s7_FAIL) + { + s7_end_of_line (str); + return; + } + /* li rd, imm32. */ + else + { + char append_str[s7_MAX_LITERAL_POOL_SIZE]; + + str = keep_data; + + if ((s7_data_op2 (&str, 1, _VALUE_HI16) == (int) s7_FAIL) + || (s7_end_of_line (str) == (int) s7_FAIL)) + { + return; + } + else if (s7_inst.reloc.exp.X_add_symbol) + { + s7_inst.error = _("li rd label isn't correct instruction form"); + return; + } + else + { + sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data); + + if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL) + return; + else + { + sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data); + if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL) + return; + + /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ + s7_inst.bwarn = -1; + } + } + } + } +} + +/* Handle mul/mulu/div/divu/rem/remu. */ + +static void +s7_do_macro_mul_rdrsrs (char *str) +{ + int reg_rd; + int reg_rs1; + int reg_rs2; + char *backupstr; + char append_str[s7_MAX_LITERAL_POOL_SIZE]; + + if (s7_university_version == 1) + as_warn ("%s", s7_ERR_FOR_SCORE5U_MUL_DIV); + + strcpy (append_str, str); + backupstr = append_str; + s7_skip_whitespace (backupstr); + if (((reg_rd = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL) + || (s7_skip_past_comma (&backupstr) == (int) s7_FAIL) + || ((reg_rs1 = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)) + { + s7_inst.error = s7_BAD_ARGS; + return; + } + + if (s7_skip_past_comma (&backupstr) == (int) s7_FAIL) + { + /* rem/remu rA, rB is error format. */ + if (strcmp (s7_inst.name, "rem") == 0 || strcmp (s7_inst.name, "remu") == 0) + { + s7_SET_INSN_ERROR (s7_BAD_ARGS); + } + else + { + s7_SET_INSN_ERROR (NULL); + s7_do_rsrs (str); + } + return; + } + else + { + s7_SET_INSN_ERROR (NULL); + if (((reg_rs2 = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL) + || (s7_end_of_line (backupstr) == (int) s7_FAIL)) + { + return; + } + else + { + char append_str1[s7_MAX_LITERAL_POOL_SIZE]; + + if (strcmp (s7_inst.name, "rem") == 0) + { + sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2); + sprintf (append_str1, "mfceh r%d", reg_rd); + } + else if (strcmp (s7_inst.name, "remu") == 0) + { + sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2); + sprintf (append_str1, "mfceh r%d", reg_rd); + } + else + { + sprintf (append_str, "%s r%d, r%d", s7_inst.name, reg_rs1, reg_rs2); + sprintf (append_str1, "mfcel r%d", reg_rd); + } + + /* Output mul/mulu or div/divu or rem/remu. */ + if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL) + return; + + /* Output mfcel or mfceh. */ + if (s7_append_insn (append_str1, TRUE) == (int) s7_FAIL) + return; + + /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ + s7_inst.bwarn = -1; + } + } +} + +static void +s7_exp_macro_ldst_abs (char *str) +{ + int reg_rd; + char *backupstr, *tmp; + char append_str[s7_MAX_LITERAL_POOL_SIZE]; + char verifystr[s7_MAX_LITERAL_POOL_SIZE]; + struct s7_score_it inst_backup; + int r1_bak = 0; + + r1_bak = s7_nor1; + s7_nor1 = 0; + memcpy (&inst_backup, &s7_inst, sizeof (struct s7_score_it)); + + strcpy (verifystr, str); + backupstr = verifystr; + s7_skip_whitespace (backupstr); + if ((reg_rd = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL) + return; + + tmp = backupstr; + if (s7_skip_past_comma (&backupstr) == (int) s7_FAIL) + return; + + backupstr = tmp; + sprintf (append_str, "li r1 %s", backupstr); + s7_append_insn (append_str, TRUE); + + memcpy (&s7_inst, &inst_backup, sizeof (struct s7_score_it)); + sprintf (append_str, " r%d, [r1,0]", reg_rd); + s7_do_ldst_insn (append_str); + + s7_nor1 = r1_bak; +} + +static int +s7_nopic_need_relax (symbolS * sym, int before_relaxing) +{ + if (sym == NULL) + return 0; + else if (s7_USE_GLOBAL_POINTER_OPT && s7_g_switch_value > 0) + { + const char *symname; + const char *segname; + + /* Find out whether this symbol can be referenced off the $gp + register. It can be if it is smaller than the -G size or if + it is in the .sdata or .sbss section. Certain symbols can + not be referenced off the $gp, although it appears as though + they can. */ + symname = S_GET_NAME (sym); + if (symname != NULL + && (strcmp (symname, "eprol") == 0 + || strcmp (symname, "etext") == 0 + || strcmp (symname, "_gp") == 0 + || strcmp (symname, "edata") == 0 + || strcmp (symname, "_fbss") == 0 + || strcmp (symname, "_fdata") == 0 + || strcmp (symname, "_ftext") == 0 + || strcmp (symname, "end") == 0 + || strcmp (symname, GP_DISP_LABEL) == 0)) + { + return 1; + } + else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0 + /* We must defer this decision until after the whole file has been read, + since there might be a .extern after the first use of this symbol. */ + || (before_relaxing + && S_GET_VALUE (sym) == 0) + || (S_GET_VALUE (sym) != 0 + && S_GET_VALUE (sym) <= s7_g_switch_value))) + { + return 0; + } + + segname = segment_name (S_GET_SEGMENT (sym)); + return (strcmp (segname, ".sdata") != 0 + && strcmp (segname, ".sbss") != 0 + && strncmp (segname, ".sdata.", 7) != 0 + && strncmp (segname, ".gnu.linkonce.s.", 16) != 0); + } + /* We are not optimizing for the $gp register. */ + else + return 1; +} + +/* Build a relax frag for lw/st instruction when generating s7_PIC, + external symbol first and local symbol second. */ + +static void +s7_build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name) +{ + symbolS *add_symbol = exp.X_add_symbol; + int add_number = exp.X_add_number; + struct s7_score_it fix_insts[s7_RELAX_INST_NUM]; + struct s7_score_it var_insts[s7_RELAX_INST_NUM]; + int fix_num = 0; + int var_num = 0; + char tmp[s7_MAX_LITERAL_POOL_SIZE]; + int r1_bak; + + r1_bak = s7_nor1; + s7_nor1 = 0; + + if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff)) + { + fix_num = 1; + var_num = 2; + + /* For an external symbol, two insns are generated; + For a local symbol, three insns are generated. */ + /* Fix part + For an external symbol: lw rD, ($gp) + (BFD_RELOC_SCORE_GOT15) */ + sprintf (tmp, "lw_pic r1, %s", add_symbol->bsym->name); + if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL) + return; + + memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it)); + + /* Var part + For a local symbol : + lw rD, ($gp) (BFD_RELOC_SCORE_GOT15) + addi rD, (BFD_RELOC_GOT_LO16) */ + s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15; + memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it)); + sprintf (tmp, "addi_s_pic r1, %s", add_symbol->bsym->name); + if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL) + return; + + memcpy (&var_insts[1], &s7_inst, sizeof (struct s7_score_it)); + s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol); + + /* Insn 2 or Insn 3: lw/st rD, [r1, constant] */ + sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number); + if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL) + return; + + /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ + s7_inst.bwarn = -1; + } + else + { + s7_inst.error = _("PIC code offset overflow (max 16 signed bits)"); + return; + } + + s7_nor1 = r1_bak; +} + +static void +s7_do_macro_ldst_label (char *str) +{ + int i; + int ldst_gp_p = 0; + int reg_rd; + int r1_bak; + char *backup_str; + char *label_str; + char *absolute_value; + char append_str[3][s7_MAX_LITERAL_POOL_SIZE]; + char verifystr[s7_MAX_LITERAL_POOL_SIZE]; + struct s7_score_it inst_backup; + struct s7_score_it inst_expand[3]; + struct s7_score_it inst_main; + + memcpy (&inst_backup, &s7_inst, sizeof (struct s7_score_it)); + strcpy (verifystr, str); + backup_str = verifystr; + + s7_skip_whitespace (backup_str); + if ((reg_rd = s7_reg_required_here (&backup_str, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL) + return; + + if (s7_skip_past_comma (&backup_str) == (int) s7_FAIL) + return; + + label_str = backup_str; + + /* Ld/st rD, [rA, imm] ld/st rD, [rA]+, imm ld/st rD, [rA, imm]+. */ + if (*backup_str == '[') + { + s7_inst.type = Rd_rvalueRs_preSI12; + s7_do_ldst_insn (str); + return; + } + + /* Ld/st rD, imm. */ + absolute_value = backup_str; + s7_inst.type = Rd_rvalueRs_SI15; + + if (s7_my_get_expression (&s7_inst.reloc.exp, &backup_str) == (int) s7_FAIL) + { + s7_inst.error = _("expression error"); + return; + } + else if ((s7_inst.reloc.exp.X_add_symbol == NULL) + && (s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _VALUE, 0) == (int) s7_FAIL)) + { + s7_inst.error = _("value not in range [0, 0x7fffffff]"); + return; + } + else if (s7_end_of_line (backup_str) == (int) s7_FAIL) + { + s7_inst.error = _("end on line error"); + return; + } + else + { + if (s7_inst.reloc.exp.X_add_symbol == 0) + { + memcpy (&s7_inst, &inst_backup, sizeof (struct s7_score_it)); + s7_exp_macro_ldst_abs (str); + return; + } + } + + /* Ld/st rD, label. */ + s7_inst.type = Rd_rvalueRs_SI15; + backup_str = absolute_value; + if ((s7_data_op2 (&backup_str, 1, _GP_IMM15) == (int) s7_FAIL) + || (s7_end_of_line (backup_str) == (int) s7_FAIL)) + { + return; + } + else + { + if (s7_inst.reloc.exp.X_add_symbol == 0) + { + if (!s7_inst.error) + s7_inst.error = s7_BAD_ARGS; + + return; + } + + if (s7_score_pic == s7_PIC) + { + int ldst_idx = 0; + ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK; + s7_build_lwst_pic (reg_rd, s7_inst.reloc.exp, s7_score_ldst_insns[ldst_idx * 3 + 0].template); + return; + } + else + { + if ((s7_inst.reloc.exp.X_add_number <= 0x3fff) + && (s7_inst.reloc.exp.X_add_number >= -0x4000) + && (!s7_nopic_need_relax (s7_inst.reloc.exp.X_add_symbol, 1))) + { + int ldst_idx = 0; + + /* Assign the real opcode. */ + ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK; + s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK; + s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + 0].value; + s7_inst.instruction |= reg_rd << 20; + s7_inst.instruction |= s7_GP << 15; + s7_inst.relax_inst = 0x8000; + s7_inst.relax_size = 0; + ldst_gp_p = 1; + } + } + } + + /* Backup s7_inst. */ + memcpy (&inst_main, &s7_inst, sizeof (struct s7_score_it)); + r1_bak = s7_nor1; + s7_nor1 = 0; + + /* Determine which instructions should be output. */ + sprintf (append_str[0], "ld_i32hi r1, %s", label_str); + sprintf (append_str[1], "ld_i32lo r1, %s", label_str); + sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd); + + /* Generate three instructions. + la r1, label + ld/st rd, [r1, 0] */ + for (i = 0; i < 3; i++) + { + if (s7_append_insn (append_str[i], FALSE) == (int) s7_FAIL) + return; + + memcpy (&inst_expand[i], &s7_inst, sizeof (struct s7_score_it)); + } + + if (ldst_gp_p) + { + char *p; + + /* Adjust instruction opcode and to be relaxed instruction opcode. */ + inst_main.instruction = s7_adjust_paritybit (inst_main.instruction, s7_GET_INSN_CLASS (inst_main.type)); + inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size; + inst_main.type = Insn_GP; + + for (i = 0; i < 3; i++) + inst_expand[i].instruction = s7_adjust_paritybit (inst_expand[i].instruction + , s7_GET_INSN_CLASS (inst_expand[i].type)); + + /* Check data dependency. */ + s7_handle_dependency (&inst_main); + + /* Start a new frag if frag_now is not empty. */ + if (frag_now_fix () != 0) + { + if (!frag_now->tc_frag_data.is_insn) + frag_wane (frag_now); + + frag_new (0); + } + frag_grow (20); + + /* Write fr_fix part. */ + p = frag_more (inst_main.size); + s7_number_to_chars (p, inst_main.instruction, inst_main.size); + + if (inst_main.reloc.type != BFD_RELOC_NONE) + { + s7_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size, + &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type); + } + +#ifdef OBJ_ELF + dwarf2_emit_insn (inst_main.size); +#endif + + /* s7_GP instruction can not do optimization, only can do relax between + 1 instruction and 3 instructions. */ + p = frag_var (rs_machine_dependent, inst_main.relax_size + s7_RELAX_PAD_BYTE, 0, + s7_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0), + inst_main.reloc.exp.X_add_symbol, 0, NULL); + + /* Write fr_var part. + no calling s7_gen_insn_frag, no fixS will be generated. */ + s7_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size); + p += inst_expand[0].size; + s7_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size); + p += inst_expand[1].size; + s7_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size); + } + else + { + s7_gen_insn_frag (&inst_expand[0], NULL); + s7_gen_insn_frag (&inst_expand[1], NULL); + s7_gen_insn_frag (&inst_expand[2], NULL); + } + s7_nor1 = r1_bak; + + /* Set bwarn as -1, so macro instruction itself will not be generated frag. */ + s7_inst.bwarn = -1; +} + +static void +s7_do_lw_pic (char *str) +{ + int reg_rd; + + s7_skip_whitespace (str); + if (((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL) + || (s7_skip_past_comma (&str) == (int) s7_FAIL) + || (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL) + || (s7_end_of_line (str) == (int) s7_FAIL)) + { + return; + } + else + { + if (s7_inst.reloc.exp.X_add_symbol == 0) + { + if (!s7_inst.error) + s7_inst.error = s7_BAD_ARGS; + + return; + } + + s7_inst.instruction |= s7_GP << 15; + s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15; + } +} + +static void +s7_do_empty (char *str) +{ + str = str; + if (s7_university_version == 1) + { + if (((s7_inst.instruction & 0x3e0003ff) == 0x0c000004) + || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000024) + || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000044) + || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000064)) + { + s7_inst.error = s7_ERR_FOR_SCORE5U_MMU; + return; + } + } + if (s7_end_of_line (str) == (int) s7_FAIL) + return; + + if (s7_inst.relax_inst != 0x8000) + { + if (s7_inst.type == NO_OPD) + { + s7_inst.relax_size = 2; + } + else + { + s7_inst.relax_size = 4; + } + } +} + +static void +s7_do_jump (char *str) +{ + char *save_in; + + s7_skip_whitespace (str); + if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL + || s7_end_of_line (str) == (int) s7_FAIL) + return; + + if (s7_inst.reloc.exp.X_add_symbol == 0) + { + s7_inst.error = _("lacking label "); + return; + } + + if (!(s7_inst.reloc.exp.X_add_number >= -16777216 + && s7_inst.reloc.exp.X_add_number <= 16777215)) + { + s7_inst.error = _("invalid constant: 25 bit expression not in range [-16777216, 16777215]"); + return; + } + + save_in = input_line_pointer; + input_line_pointer = str; + s7_inst.reloc.type = BFD_RELOC_SCORE_JMP; + s7_inst.reloc.pc_rel = 1; + input_line_pointer = save_in; +} + +static void +s7_do16_jump (char *str) +{ + s7_skip_whitespace (str); + if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL + || s7_end_of_line (str) == (int) s7_FAIL) + { + return; + } + else if (s7_inst.reloc.exp.X_add_symbol == 0) + { + s7_inst.error = _("lacking label "); + return; + } + else if (!(s7_inst.reloc.exp.X_add_number >= 0 + && s7_inst.reloc.exp.X_add_number <= 4095)) + { + s7_inst.error = _("invalid constant: 12 bit expression not in range [0, 4095]"); + return; + } + + s7_inst.reloc.type = BFD_RELOC_SCORE16_JMP; + s7_inst.reloc.pc_rel = 1; +} + +static void +s7_do_branch (char *str) +{ + unsigned long abs_value = 0; + + if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL + || s7_end_of_line (str) == (int) s7_FAIL) + { + return; + } + else if (s7_inst.reloc.exp.X_add_symbol == 0) + { + s7_inst.error = _("lacking label "); + return; + } + else if (!(s7_inst.reloc.exp.X_add_number >= -524288 + && s7_inst.reloc.exp.X_add_number <= 524287)) + { + s7_inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19"); + return; + } + + s7_inst.reloc.type = BFD_RELOC_SCORE_BRANCH; + s7_inst.reloc.pc_rel = 1; + + /* Branch 32 offset field : 20 bit, 16 bit branch offset field : 8 bit. */ + s7_inst.instruction |= (s7_inst.reloc.exp.X_add_number & 0x3fe) | ((s7_inst.reloc.exp.X_add_number & 0xffc00) << 5); + + /* Compute 16 bit branch instruction. */ + if ((s7_inst.relax_inst != 0x8000) && (abs_value & 0xfffffe00) == 0) + { + s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 8); + s7_inst.relax_inst |= ((s7_inst.reloc.exp.X_add_number >> 1) & 0xff); + s7_inst.relax_size = 2; + } + else + { + s7_inst.relax_inst = 0x8000; + } +} + +static void +s7_do16_branch (char *str) +{ + if ((s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL + || s7_end_of_line (str) == (int) s7_FAIL)) + { + ; + } + else if (s7_inst.reloc.exp.X_add_symbol == 0) + { + s7_inst.error = _("lacking label"); + } + else if (!(s7_inst.reloc.exp.X_add_number >= -512 + && s7_inst.reloc.exp.X_add_number <= 511)) + { + s7_inst.error = _("invalid constant: 10 bit expression not in range [-2^9, 2^9-1]"); + } + else + { + s7_inst.reloc.type = BFD_RELOC_SCORE16_BRANCH; + s7_inst.reloc.pc_rel = 1; + s7_inst.instruction |= ((s7_inst.reloc.exp.X_add_number >> 1) & 0xff); + } +} + +/* Iterate over the base tables to create the instruction patterns. */ + +static void +s7_build_score_ops_hsh (void) +{ + unsigned int i; + static struct obstack insn_obstack; + + obstack_begin (&insn_obstack, 4000); + for (i = 0; i < sizeof (s7_score_insns) / sizeof (struct s7_asm_opcode); i++) + { + const struct s7_asm_opcode *insn = s7_score_insns + i; + unsigned len = strlen (insn->template); + struct s7_asm_opcode *new; + char *template; + new = obstack_alloc (&insn_obstack, sizeof (struct s7_asm_opcode)); + template = obstack_alloc (&insn_obstack, len + 1); + + strcpy (template, insn->template); + new->template = template; + new->parms = insn->parms; + new->value = insn->value; + new->relax_value = insn->relax_value; + new->type = insn->type; + new->bitmask = insn->bitmask; + hash_insert (s7_score_ops_hsh, new->template, (void *) new); + } +} + +static void +s7_build_dependency_insn_hsh (void) +{ + unsigned int i; + static struct obstack dependency_obstack; + + obstack_begin (&dependency_obstack, 4000); + for (i = 0; i < ARRAY_SIZE (s7_insn_to_dependency_table); i++) + { + const struct s7_insn_to_dependency *tmp = s7_insn_to_dependency_table + i; + unsigned len = strlen (tmp->insn_name); + struct s7_insn_to_dependency *new; + + new = obstack_alloc (&dependency_obstack, sizeof (struct s7_insn_to_dependency)); + new->insn_name = obstack_alloc (&dependency_obstack, len + 1); + + strcpy (new->insn_name, tmp->insn_name); + new->type = tmp->type; + hash_insert (s7_dependency_insn_hsh, new->insn_name, (void *) new); + } +} + +static valueT +s7_md_chars_to_number (char *buf, int n) +{ + valueT result = 0; + unsigned char *where = (unsigned char *) buf; + + if (target_big_endian) + { + while (n--) + { + result <<= 8; + result |= (*where++ & 255); + } + } + else + { + while (n--) + { + result <<= 8; + result |= (where[n] & 255); + } + } + + return result; +} + +/* Return true if the given symbol should be considered local for s7_PIC. */ + +static bfd_boolean +s7_pic_need_relax (symbolS *sym, asection *segtype) +{ + asection *symsec; + bfd_boolean linkonce; + + /* Handle the case of a symbol equated to another symbol. */ + while (symbol_equated_reloc_p (sym)) + { + symbolS *n; + + /* It's possible to get a loop here in a badly written + program. */ + n = symbol_get_value_expression (sym)->X_add_symbol; + if (n == sym) + break; + sym = n; + } + + symsec = S_GET_SEGMENT (sym); + + /* Duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */ + linkonce = FALSE; + if (symsec != segtype && ! S_IS_LOCAL (sym)) + { + if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE) != 0) + linkonce = TRUE; + + /* The GNU toolchain uses an extension for ELF: a section + beginning with the magic string .gnu.linkonce is a linkonce + section. */ + if (strncmp (segment_name (symsec), ".gnu.linkonce", + sizeof ".gnu.linkonce" - 1) == 0) + linkonce = TRUE; + } + + /* This must duplicate the test in adjust_reloc_syms. */ + return (symsec != &bfd_und_section + && symsec != &bfd_abs_section + && ! bfd_is_com_section (symsec) + && !linkonce +#ifdef OBJ_ELF + /* A global or weak symbol is treated as external. */ + && (OUTPUT_FLAVOR != bfd_target_elf_flavour + || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym))) +#endif + ); +} + +static int +s7_judge_size_before_relax (fragS * fragp, asection *sec) +{ + int change = 0; + + if (s7_score_pic == s7_NO_PIC) + change = s7_nopic_need_relax (fragp->fr_symbol, 0); + else + change = s7_pic_need_relax (fragp->fr_symbol, sec); + + if (change == 1) + { + /* Only at the first time determining whether s7_GP instruction relax should be done, + return the difference between insntruction size and instruction relax size. */ + if (fragp->fr_opcode == NULL) + { + fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype); + fragp->fr_opcode = fragp->fr_literal + s7_RELAX_RELOC1 (fragp->fr_subtype); + return s7_RELAX_NEW (fragp->fr_subtype) - s7_RELAX_OLD (fragp->fr_subtype); + } + } + + return 0; +} + +static int +s7_b32_relax_to_b16 (fragS * fragp) +{ + int grows = 0; + int relaxable_p = 0; + int old; + int new; + int frag_addr = fragp->fr_address + fragp->insn_addr; + + addressT symbol_address = 0; + symbolS *s; + offsetT offset; + unsigned long value; + unsigned long abs_value; + + /* FIXME : here may be able to modify better . + I don't know how to get the fragp's section , + so in relax stage , it may be wrong to calculate the symbol's offset when the frag's section + is different from the symbol's. */ + + old = s7_RELAX_OLD (fragp->fr_subtype); + new = s7_RELAX_NEW (fragp->fr_subtype); + relaxable_p = s7_RELAX_OPT (fragp->fr_subtype); + + s = fragp->fr_symbol; + /* b/bl immediate */ + if (s == NULL) + frag_addr = 0; + else + { + if (s->bsym != 0) + symbol_address = (addressT) s->sy_frag->fr_address; + } + + value = s7_md_chars_to_number (fragp->fr_literal, s7_INSN_SIZE); + + /* b 32's offset : 20 bit, b 16's tolerate field : 0xff. */ + offset = ((value & 0x3ff0000) >> 6) | (value & 0x3fe); + if ((offset & 0x80000) == 0x80000) + offset |= 0xfff00000; + + abs_value = offset + symbol_address - frag_addr; + if ((abs_value & 0x80000000) == 0x80000000) + abs_value = 0xffffffff - abs_value + 1; + + /* Relax branch 32 to branch 16. */ + if (relaxable_p && (s->bsym != NULL) && ((abs_value & 0xffffff00) == 0) + && (S_IS_DEFINED (s) && !S_IS_COMMON (s) && !S_IS_EXTERNAL (s))) + { + /* do nothing. */ + } + else + { + /* Branch 32 can not be relaxed to b 16, so clear OPT bit. */ + fragp->fr_opcode = NULL; + fragp->fr_subtype = s7_RELAX_OPT_CLEAR (fragp->fr_subtype); + } + + return grows; +} + +static void +s7_parse_pce_inst (char *insnstr) +{ + char c; + char *p; + char *q; + char first[s7_MAX_LITERAL_POOL_SIZE]; + char second[s7_MAX_LITERAL_POOL_SIZE]; + struct s7_score_it pec_part_1; + + /* Get first part string of PCE. */ + p = strstr (insnstr, "||"); + c = *p; + *p = '\0'; + sprintf (first, "%s", insnstr); + + /* Get second part string of PCE. */ + *p = c; + p += 2; + sprintf (second, "%s", p); + + s7_parse_16_32_inst (first, FALSE); + if (s7_inst.error) + return; + + memcpy (&pec_part_1, &s7_inst, sizeof (s7_inst)); + + q = second; + while (q && *q) + { + *q = TOLOWER (*q); + q++; + } + + s7_parse_16_32_inst (second, FALSE); + if (s7_inst.error) + return; + + if ( ((pec_part_1.size == s7_INSN_SIZE) && (s7_inst.size == s7_INSN_SIZE)) + || ((pec_part_1.size == s7_INSN_SIZE) && (s7_inst.size == s7_INSN16_SIZE)) + || ((pec_part_1.size == s7_INSN16_SIZE) && (s7_inst.size == s7_INSN_SIZE))) + { + s7_inst.error = _("pce instruction error (16 bit || 16 bit)'"); + sprintf (s7_inst.str, insnstr); + return; + } + + if (!s7_inst.error) + s7_gen_insn_frag (&pec_part_1, &s7_inst); +} + + + +static void +s7_insert_reg (const struct s7_reg_entry *r, struct hash_control *htab) +{ + int i = 0; + int len = strlen (r->name) + 2; + char *buf = xmalloc (len); + char *buf2 = xmalloc (len); + + strcpy (buf + i, r->name); + for (i = 0; buf[i]; i++) + { + buf2[i] = TOUPPER (buf[i]); + } + buf2[i] = '\0'; + + hash_insert (htab, buf, (void *) r); + hash_insert (htab, buf2, (void *) r); +} + +static void +s7_build_reg_hsh (struct s7_reg_map *map) +{ + const struct s7_reg_entry *r; + + if ((map->htab = hash_new ()) == NULL) + { + as_fatal (_("virtual memory exhausted")); + } + for (r = map->names; r->name != NULL; r++) + { + s7_insert_reg (r, map->htab); + } +} + + + +/* If we change section we must dump the literal pool first. */ +static void +s7_s_score_bss (int ignore ATTRIBUTE_UNUSED) +{ + subseg_set (bss_section, (subsegT) get_absolute_expression ()); + demand_empty_rest_of_line (); +} + +static void +s7_s_score_text (int ignore) +{ + obj_elf_text (ignore); + record_alignment (now_seg, 2); +} + +static void +s7_s_section (int ignore) +{ + obj_elf_section (ignore); + if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0) + record_alignment (now_seg, 2); + +} + +static void +s7_s_change_sec (int sec) +{ + segT seg; + +#ifdef OBJ_ELF + /* The ELF backend needs to know that we are changing sections, so + that .previous works correctly. We could do something like check + for an obj_section_change_hook macro, but that might be confusing + as it would not be appropriate to use it in the section changing + functions in read.c, since obj-elf.c intercepts those. FIXME: + This should be cleaner, somehow. */ + obj_elf_section_change_hook (); +#endif + switch (sec) + { + case 'r': + seg = subseg_new (s7_RDATA_SECTION_NAME, (subsegT) get_absolute_expression ()); + bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA)); + if (strcmp (TARGET_OS, "elf") != 0) + record_alignment (seg, 4); + demand_empty_rest_of_line (); + break; + case 's': + seg = subseg_new (".sdata", (subsegT) get_absolute_expression ()); + bfd_set_section_flags (stdoutput, seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA); + if (strcmp (TARGET_OS, "elf") != 0) + record_alignment (seg, 4); + demand_empty_rest_of_line (); + break; + } +} + +static void +s7_s_score_mask (int reg_type ATTRIBUTE_UNUSED) +{ + long mask, off; + + if (s7_cur_proc_ptr == NULL) + { + as_warn (_(".mask outside of .ent")); + demand_empty_rest_of_line (); + return; + } + if (get_absolute_expression_and_terminator (&mask) != ',') + { + as_warn (_("Bad .mask directive")); + --input_line_pointer; + demand_empty_rest_of_line (); + return; + } + off = get_absolute_expression (); + s7_cur_proc_ptr->reg_mask = mask; + s7_cur_proc_ptr->reg_offset = off; + demand_empty_rest_of_line (); +} + +static symbolS * +s7_get_symbol (void) +{ + int c; + char *name; + symbolS *p; + + name = input_line_pointer; + c = get_symbol_end (); + p = (symbolS *) symbol_find_or_make (name); + *input_line_pointer = c; + return p; +} + +static long +s7_get_number (void) +{ + int negative = 0; + long val = 0; + + if (*input_line_pointer == '-') + { + ++input_line_pointer; + negative = 1; + } + if (!ISDIGIT (*input_line_pointer)) + as_bad (_("expected simple number")); + if (input_line_pointer[0] == '0') + { + if (input_line_pointer[1] == 'x') + { + input_line_pointer += 2; + while (ISXDIGIT (*input_line_pointer)) + { + val <<= 4; + val |= hex_value (*input_line_pointer++); + } + return negative ? -val : val; + } + else + { + ++input_line_pointer; + while (ISDIGIT (*input_line_pointer)) + { + val <<= 3; + val |= *input_line_pointer++ - '0'; + } + return negative ? -val : val; + } + } + if (!ISDIGIT (*input_line_pointer)) + { + printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer); + as_warn (_("invalid number")); + return -1; + } + while (ISDIGIT (*input_line_pointer)) + { + val *= 10; + val += *input_line_pointer++ - '0'; + } + return negative ? -val : val; +} + +/* The .aent and .ent directives. */ + +static void +s7_s_score_ent (int aent) +{ + symbolS *symbolP; + int maybe_text; + + symbolP = s7_get_symbol (); + if (*input_line_pointer == ',') + ++input_line_pointer; + SKIP_WHITESPACE (); + if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-') + s7_get_number (); + +#ifdef BFD_ASSEMBLER + if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0) + maybe_text = 1; + else + maybe_text = 0; +#else + if (now_seg != data_section && now_seg != bss_section) + maybe_text = 1; + else + maybe_text = 0; +#endif + if (!maybe_text) + as_warn (_(".ent or .aent not in text section.")); + if (!aent && s7_cur_proc_ptr) + as_warn (_("missing .end")); + if (!aent) + { + s7_cur_proc_ptr = &s7_cur_proc; + s7_cur_proc_ptr->reg_mask = 0xdeadbeaf; + s7_cur_proc_ptr->reg_offset = 0xdeadbeaf; + s7_cur_proc_ptr->fpreg_mask = 0xdeafbeaf; + s7_cur_proc_ptr->leaf = 0xdeafbeaf; + s7_cur_proc_ptr->frame_offset = 0xdeafbeaf; + s7_cur_proc_ptr->frame_reg = 0xdeafbeaf; + s7_cur_proc_ptr->pc_reg = 0xdeafbeaf; + s7_cur_proc_ptr->isym = symbolP; + symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION; + ++s7_numprocs; + if (debug_type == DEBUG_STABS) + stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP)); + } + demand_empty_rest_of_line (); +} + +static void +s7_s_score_frame (int ignore ATTRIBUTE_UNUSED) +{ + char *backupstr; + char str[30]; + long val; + int i = 0; + + backupstr = input_line_pointer; + +#ifdef OBJ_ELF + if (s7_cur_proc_ptr == NULL) + { + as_warn (_(".frame outside of .ent")); + demand_empty_rest_of_line (); + return; + } + s7_cur_proc_ptr->frame_reg = s7_reg_required_here ((&backupstr), 0, s7_REG_TYPE_SCORE); + SKIP_WHITESPACE (); + s7_skip_past_comma (&backupstr); + while (*backupstr != ',') + { + str[i] = *backupstr; + i++; + backupstr++; + } + str[i] = '\0'; + val = atoi (str); + + SKIP_WHITESPACE (); + s7_skip_past_comma (&backupstr); + s7_cur_proc_ptr->frame_offset = val; + s7_cur_proc_ptr->pc_reg = s7_reg_required_here ((&backupstr), 0, s7_REG_TYPE_SCORE); + + SKIP_WHITESPACE (); + s7_skip_past_comma (&backupstr); + i = 0; + while (*backupstr != '\n') + { + str[i] = *backupstr; + i++; + backupstr++; + } + str[i] = '\0'; + val = atoi (str); + s7_cur_proc_ptr->leaf = val; + SKIP_WHITESPACE (); + s7_skip_past_comma (&backupstr); + +#endif /* OBJ_ELF */ + while (input_line_pointer != backupstr) + input_line_pointer++; +} + +/* The .end directive. */ + +static void +s7_s_score_end (int x ATTRIBUTE_UNUSED) +{ + symbolS *p; + int maybe_text; + + /* Generate a .pdr section. */ + segT saved_seg = now_seg; + subsegT saved_subseg = now_subseg; + valueT dot; + expressionS exp; + char *fragp; + + if (!is_end_of_line[(unsigned char)*input_line_pointer]) + { + p = s7_get_symbol (); + demand_empty_rest_of_line (); + } + else + p = NULL; + +#ifdef BFD_ASSEMBLER + if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0) + maybe_text = 1; + else + maybe_text = 0; +#else + if (now_seg != data_section && now_seg != bss_section) + maybe_text = 1; + else + maybe_text = 0; +#endif + + if (!maybe_text) + as_warn (_(".end not in text section")); + if (!s7_cur_proc_ptr) + { + as_warn (_(".end directive without a preceding .ent directive.")); + demand_empty_rest_of_line (); + return; + } + if (p != NULL) + { + assert (S_GET_NAME (p)); + if (strcmp (S_GET_NAME (p), S_GET_NAME (s7_cur_proc_ptr->isym))) + as_warn (_(".end symbol does not match .ent symbol.")); + if (debug_type == DEBUG_STABS) + stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p)); + } + else + as_warn (_(".end directive missing or unknown symbol")); + + if ((s7_cur_proc_ptr->reg_mask == 0xdeadbeaf) || + (s7_cur_proc_ptr->reg_offset == 0xdeadbeaf) || + (s7_cur_proc_ptr->leaf == 0xdeafbeaf) || + (s7_cur_proc_ptr->frame_offset == 0xdeafbeaf) || + (s7_cur_proc_ptr->frame_reg == 0xdeafbeaf) || (s7_cur_proc_ptr->pc_reg == 0xdeafbeaf)); + + else + { + dot = frag_now_fix (); + assert (s7_pdr_seg); + subseg_set (s7_pdr_seg, 0); + /* Write the symbol. */ + exp.X_op = O_symbol; + exp.X_add_symbol = p; + exp.X_add_number = 0; + emit_expr (&exp, 4); + fragp = frag_more (7 * 4); + s7_number_to_chars (fragp, (valueT) s7_cur_proc_ptr->reg_mask, 4); + s7_number_to_chars (fragp + 4, (valueT) s7_cur_proc_ptr->reg_offset, 4); + s7_number_to_chars (fragp + 8, (valueT) s7_cur_proc_ptr->fpreg_mask, 4); + s7_number_to_chars (fragp + 12, (valueT) s7_cur_proc_ptr->leaf, 4); + s7_number_to_chars (fragp + 16, (valueT) s7_cur_proc_ptr->frame_offset, 4); + s7_number_to_chars (fragp + 20, (valueT) s7_cur_proc_ptr->frame_reg, 4); + s7_number_to_chars (fragp + 24, (valueT) s7_cur_proc_ptr->pc_reg, 4); + subseg_set (saved_seg, saved_subseg); + + } + s7_cur_proc_ptr = NULL; +} + +/* Handle the .set pseudo-op. */ + +static void +s7_s_score_set (int x ATTRIBUTE_UNUSED) +{ + int i = 0; + char name[s7_MAX_LITERAL_POOL_SIZE]; + char * orig_ilp = input_line_pointer; + + while (!is_end_of_line[(unsigned char)*input_line_pointer]) + { + name[i] = (char) * input_line_pointer; + i++; + ++input_line_pointer; + } + + name[i] = '\0'; + + if (strcmp (name, "nwarn") == 0) + { + s7_warn_fix_data_dependency = 0; + } + else if (strcmp (name, "fixdd") == 0) + { + s7_fix_data_dependency = 1; + } + else if (strcmp (name, "nofixdd") == 0) + { + s7_fix_data_dependency = 0; + } + else if (strcmp (name, "r1") == 0) + { + s7_nor1 = 0; + } + else if (strcmp (name, "nor1") == 0) + { + s7_nor1 = 1; + } + else if (strcmp (name, "optimize") == 0) + { + s7_g_opt = 1; + } + else if (strcmp (name, "volatile") == 0) + { + s7_g_opt = 0; + } + else if (strcmp (name, "pic") == 0) + { + s7_score_pic = s7_PIC; + } + else + { + input_line_pointer = orig_ilp; + s_set (0); + } +} + +/* Handle the .cpload pseudo-op. This is used when generating s7_PIC code. It sets the + $gp register for the function based on the function address, which is in the register + named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled + specially by the linker. The result is: + ldis gp, %hi(GP_DISP_LABEL) + ori gp, %low(GP_DISP_LABEL) + add gp, gp, .cpload argument + The .cpload argument is normally r29. */ + +static void +s7_s_score_cpload (int ignore ATTRIBUTE_UNUSED) +{ + int reg; + char insn_str[s7_MAX_LITERAL_POOL_SIZE]; + + /* If we are not generating s7_PIC code, .cpload is ignored. */ + if (s7_score_pic == s7_NO_PIC) + { + s_ignore (0); + return; + } + + if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL) + return; + + demand_empty_rest_of_line (); + + sprintf (insn_str, "ld_i32hi r%d, %s", s7_GP, GP_DISP_LABEL); + if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL) + return; + + sprintf (insn_str, "ld_i32lo r%d, %s", s7_GP, GP_DISP_LABEL); + if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL) + return; + + sprintf (insn_str, "add r%d, r%d, r%d", s7_GP, s7_GP, reg); + if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL) + return; +} + +/* Handle the .cprestore pseudo-op. This stores $gp into a given + offset from $sp. The offset is remembered, and after making a s7_PIC + call $gp is restored from that location. */ + +static void +s7_s_score_cprestore (int ignore ATTRIBUTE_UNUSED) +{ + int reg; + int cprestore_offset; + char insn_str[s7_MAX_LITERAL_POOL_SIZE]; + + /* If we are not generating s7_PIC code, .cprestore is ignored. */ + if (s7_score_pic == s7_NO_PIC) + { + s_ignore (0); + return; + } + + if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL + || s7_skip_past_comma (&input_line_pointer) == (int) s7_FAIL) + { + return; + } + + cprestore_offset = get_absolute_expression (); + + if (cprestore_offset <= 0x3fff) + { + sprintf (insn_str, "sw r%d, [r%d, %d]", s7_GP, reg, cprestore_offset); + if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL) + return; + } + else + { + int r1_bak; + + r1_bak = s7_nor1; + s7_nor1 = 0; + + sprintf (insn_str, "li r1, %d", cprestore_offset); + if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL) + return; + + sprintf (insn_str, "add r1, r1, r%d", reg); + if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL) + return; + + sprintf (insn_str, "sw r%d, [r1]", s7_GP); + if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL) + return; + + s7_nor1 = r1_bak; + } + + demand_empty_rest_of_line (); +} + +/* Handle the .gpword pseudo-op. This is used when generating s7_PIC + code. It generates a 32 bit s7_GP relative reloc. */ + +static void +s7_s_score_gpword (int ignore ATTRIBUTE_UNUSED) +{ + expressionS ex; + char *p; + + /* When not generating s7_PIC code, this is treated as .word. */ + if (s7_score_pic == s7_NO_PIC) + { + cons (4); + return; + } + expression (&ex); + if (ex.X_op != O_symbol || ex.X_add_number != 0) + { + as_bad (_("Unsupported use of .gpword")); + ignore_rest_of_line (); + } + p = frag_more (4); + s7_number_to_chars (p, (valueT) 0, 4); + fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32); + demand_empty_rest_of_line (); +} + +/* Handle the .cpadd pseudo-op. This is used when dealing with switch + tables in s7_PIC code. */ + +static void +s7_s_score_cpadd (int ignore ATTRIBUTE_UNUSED) +{ + int reg; + char insn_str[s7_MAX_LITERAL_POOL_SIZE]; + + /* If we are not generating s7_PIC code, .cpload is ignored. */ + if (s7_score_pic == s7_NO_PIC) + { + s_ignore (0); + return; + } + + if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL) + { + return; + } + demand_empty_rest_of_line (); + + /* Add $gp to the register named as an argument. */ + sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, s7_GP); + if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL) + return; +} + +#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT +#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR) \ + do \ + { \ + if ((SIZE) >= 8) \ + (P2VAR) = 3; \ + else if ((SIZE) >= 4) \ + (P2VAR) = 2; \ + else if ((SIZE) >= 2) \ + (P2VAR) = 1; \ + else \ + (P2VAR) = 0; \ + } \ + while (0) +#endif + +static void +s7_s_score_lcomm (int bytes_p) +{ + char *name; + char c; + char *p; + int temp; + symbolS *symbolP; + segT current_seg = now_seg; + subsegT current_subseg = now_subseg; + const int max_alignment = 15; + int align = 0; + segT bss_seg = bss_section; + int needs_align = 0; + + name = input_line_pointer; + c = get_symbol_end (); + p = input_line_pointer; + *p = c; + + if (name == p) + { + as_bad (_("expected symbol name")); + discard_rest_of_line (); + return; + } + + SKIP_WHITESPACE (); + + /* Accept an optional comma after the name. The comma used to be + required, but Irix 5 cc does not generate it. */ + if (*input_line_pointer == ',') + { + ++input_line_pointer; + SKIP_WHITESPACE (); + } + + if (is_end_of_line[(unsigned char)*input_line_pointer]) + { + as_bad (_("missing size expression")); + return; + } + + if ((temp = get_absolute_expression ()) < 0) + { + as_warn (_("BSS length (%d) < 0 ignored"), temp); + ignore_rest_of_line (); + return; + } + +#if defined (TC_SCORE) + if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour) + { + /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss. */ + if ((unsigned) temp <= bfd_get_gp_size (stdoutput)) + { + bss_seg = subseg_new (".sbss", 1); + seg_info (bss_seg)->bss = 1; +#ifdef BFD_ASSEMBLER + if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC)) + as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ())); +#endif + } + } +#endif + + SKIP_WHITESPACE (); + if (*input_line_pointer == ',') + { + ++input_line_pointer; + SKIP_WHITESPACE (); + + if (is_end_of_line[(unsigned char)*input_line_pointer]) + { + as_bad (_("missing alignment")); + return; + } + else + { + align = get_absolute_expression (); + needs_align = 1; + } + } + + if (!needs_align) + { + TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align); + + /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it. */ + if (align) + record_alignment (bss_seg, align); + } + + if (needs_align) + { + if (bytes_p) + { + /* Convert to a power of 2. */ + if (align != 0) + { + unsigned int i; + + for (i = 0; align != 0; align >>= 1, ++i) + ; + align = i - 1; + } + } + + if (align > max_alignment) + { + align = max_alignment; + as_warn (_("alignment too large; %d assumed"), align); + } + else if (align < 0) + { + align = 0; + as_warn (_("alignment negative; 0 assumed")); + } + + record_alignment (bss_seg, align); + } + else + { + /* Assume some objects may require alignment on some systems. */ +#if defined (TC_ALPHA) && ! defined (VMS) + if (temp > 1) + { + align = ffs (temp) - 1; + if (temp % (1 << align)) + abort (); + } +#endif + } + + *p = 0; + symbolP = symbol_find_or_make (name); + *p = c; + + if ( +#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \ + || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT)) +#ifdef BFD_ASSEMBLER + (OUTPUT_FLAVOR != bfd_target_aout_flavour + || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) && +#else + (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) && +#endif +#endif + (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0))) + { + char *pfrag; + + subseg_set (bss_seg, 1); + + if (align) + frag_align (align, 0, 0); + + /* Detach from old frag. */ + if (S_GET_SEGMENT (symbolP) == bss_seg) + symbol_get_frag (symbolP)->fr_symbol = NULL; + + symbol_set_frag (symbolP, frag_now); + pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL); + *pfrag = 0; + + + S_SET_SEGMENT (symbolP, bss_seg); + +#ifdef OBJ_COFF + /* The symbol may already have been created with a preceding + ".globl" directive -- be careful not to step on storage class + in that case. Otherwise, set it to static. */ + if (S_GET_STORAGE_CLASS (symbolP) != C_EXT) + { + S_SET_STORAGE_CLASS (symbolP, C_STAT); + } +#endif /* OBJ_COFF */ + +#ifdef S_SET_SIZE + S_SET_SIZE (symbolP, temp); +#endif + } + else + as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP)); + + subseg_set (current_seg, current_subseg); + + demand_empty_rest_of_line (); +} + + + +static void +s7_begin (void) +{ + unsigned int i; + segT seg; + subsegT subseg; + + if ((s7_score_ops_hsh = hash_new ()) == NULL) + as_fatal (_("virtual memory exhausted")); + + s7_build_score_ops_hsh (); + + if ((s7_dependency_insn_hsh = hash_new ()) == NULL) + as_fatal (_("virtual memory exhausted")); + + s7_build_dependency_insn_hsh (); + + for (i = (int) REG_TYPE_FIRST; i < (int) s7_REG_TYPE_MAX; i++) + s7_build_reg_hsh (s7_all_reg_maps + i); + + /* Initialize dependency vector. */ + s7_init_dependency_vector (); + + bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0); + seg = now_seg; + subseg = now_subseg; + s7_pdr_seg = subseg_new (".pdr", (subsegT) 0); + (void) bfd_set_section_flags (stdoutput, s7_pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING); + (void) bfd_set_section_alignment (stdoutput, s7_pdr_seg, 2); + subseg_set (seg, subseg); + + if (s7_USE_GLOBAL_POINTER_OPT) + bfd_set_gp_size (stdoutput, s7_g_switch_value); +} + +static void +s7_assemble (char *str) +{ + know (str); + know (strlen (str) < s7_MAX_LITERAL_POOL_SIZE); + + memset (&s7_inst, '\0', sizeof (s7_inst)); + if (s7_INSN_IS_PCE_P (str)) + s7_parse_pce_inst (str); + else + s7_parse_16_32_inst (str, TRUE); + + if (s7_inst.error) + as_bad (_("%s -- `%s'"), s7_inst.error, s7_inst.str); +} + +/* We handle all bad expressions here, so that we can report the faulty + instruction in the error message. */ + +static void +s7_operand (expressionS * expr) +{ + if (s7_in_my_get_expression) + { + expr->X_op = O_illegal; + if (s7_inst.error == NULL) + { + s7_inst.error = _("bad expression"); + } + } +} + +/* Turn a string in input_line_pointer into a floating point constant + of type TYPE, and store the appropriate bytes in *LITP. The number + of LITTLENUMS emitted is stored in *SIZEP. An error message is + returned, or NULL on OK. + + Note that fp constants aren't represent in the normal way on the ARM. + In big endian mode, things are as expected. However, in little endian + mode fp constants are big-endian word-wise, and little-endian byte-wise + within the words. For example, (double) 1.1 in big endian mode is + the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is + the byte sequence 99 99 f1 3f 9a 99 99 99. */ + +static char * +s7_atof (int type, char *litP, int *sizeP) +{ + int prec; + LITTLENUM_TYPE words[s7_MAX_LITTLENUMS]; + char *t; + int i; + + switch (type) + { + case 'f': + case 'F': + case 's': + case 'S': + prec = 2; + break; + case 'd': + case 'D': + case 'r': + case 'R': + prec = 4; + break; + case 'x': + case 'X': + case 'p': + case 'P': + prec = 6; + break; + default: + *sizeP = 0; + return _("bad call to MD_ATOF()"); + } + + t = atof_ieee (input_line_pointer, type, words); + if (t) + input_line_pointer = t; + *sizeP = prec * 2; + + if (target_big_endian) + { + for (i = 0; i < prec; i++) + { + s7_number_to_chars (litP, (valueT) words[i], 2); + litP += 2; + } + } + else + { + for (i = 0; i < prec; i += 2) + { + s7_number_to_chars (litP, (valueT) words[i + 1], 2); + s7_number_to_chars (litP + 2, (valueT) words[i], 2); + litP += 4; + } + } + + return 0; +} + +/* Implementation of md_frag_check. + Called after md_convert_frag(). */ + +static void +s7_frag_check (fragS * fragp) +{ + know (fragp->insn_addr <= s7_RELAX_PAD_BYTE); +} + +/* Implementation of TC_VALIDATE_FIX. + Called before md_apply_fix() and after md_convert_frag(). */ + +static void +s7_validate_fix (fixS *fixP) +{ + fixP->fx_where += fixP->fx_frag->insn_addr; +} + +static int +s7_force_relocation (struct fix *fixp) +{ + int retval = 0; + + if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT + || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY + || fixp->fx_r_type == BFD_RELOC_SCORE_JMP + || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH + || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP + || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH) + { + retval = 1; + } + + return retval; +} + +static bfd_boolean +s7_fix_adjustable (fixS * fixP) +{ + if (fixP->fx_addsy == NULL) + { + return 1; + } + else if (OUTPUT_FLAVOR == bfd_target_elf_flavour + && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy))) + { + return 0; + } + else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT + || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY + || fixP->fx_r_type == BFD_RELOC_SCORE_JMP + || fixP->fx_r_type == BFD_RELOC_SCORE16_JMP) + { + return 0; + } + + return 1; +} + +static void +s7_elf_final_processing (void) +{ + unsigned long val = E_SCORE_MACH_SCORE7; + + elf_elfheader (stdoutput)->e_machine = EM_SCORE; + elf_elfheader (stdoutput)->e_flags &= ~EF_SCORE_MACH; + elf_elfheader (stdoutput)->e_flags |= val; + + if (s7_fix_data_dependency == 1) + { + elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP; + } + if (s7_score_pic == s7_PIC) + { + elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC; + } +} + +/* In this function, we determine whether s7_GP instruction should do relaxation, + for the label being against was known now. + Doing this here but not in md_relax_frag() can induce iteration times + in stage of doing relax. */ + +static int +s7_estimate_size_before_relax (fragS * fragp, asection * sec) +{ + if ((s7_RELAX_TYPE (fragp->fr_subtype) == Insn_GP) + || (s7_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC)) + return s7_judge_size_before_relax (fragp, sec); + + return 0; +} + +static int +s7_relax_frag (asection * sec ATTRIBUTE_UNUSED, + fragS * fragp, + long stretch ATTRIBUTE_UNUSED) +{ + int grows = 0; + int insn_size; + int insn_relax_size; + int do_relax_p = 0; /* Indicate doing relaxation for this frag. */ + int relaxable_p = 0; + bfd_boolean word_align_p = FALSE; + fragS *next_fragp; + + /* If the instruction address is odd, make it half word align first. */ + if ((fragp->fr_address) % 2 != 0) + { + if ((fragp->fr_address + fragp->insn_addr) % 2 != 0) + { + fragp->insn_addr = 1; + grows += 1; + } + } + + word_align_p = ((fragp->fr_address + fragp->insn_addr) % 4 == 0) ? TRUE : FALSE; + + /* Get instruction size and relax size after the last relaxation. */ + if (fragp->fr_opcode) + { + insn_size = s7_RELAX_NEW (fragp->fr_subtype); + insn_relax_size = s7_RELAX_OLD (fragp->fr_subtype); + } + else + { + insn_size = s7_RELAX_OLD (fragp->fr_subtype); + insn_relax_size = s7_RELAX_NEW (fragp->fr_subtype); + } + + /* Handle specially for s7_GP instruction. for, s7_judge_size_before_relax() has already determine + whether the s7_GP instruction should do relax. */ + if ((s7_RELAX_TYPE (fragp->fr_subtype) == Insn_GP) + || (s7_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC)) + { + if (!word_align_p) + { + if (fragp->insn_addr < 2) + { + fragp->insn_addr += 2; + grows += 2; + } + else + { + fragp->insn_addr -= 2; + grows -= 2; + } + } + + if (fragp->fr_opcode) + fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype) + fragp->insn_addr; + else + fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype) + fragp->insn_addr; + } + else + { + if (s7_RELAX_TYPE (fragp->fr_subtype) == PC_DISP19div2) + s7_b32_relax_to_b16 (fragp); + + relaxable_p = s7_RELAX_OPT (fragp->fr_subtype); + next_fragp = fragp->fr_next; + while ((next_fragp) && (next_fragp->fr_type != rs_machine_dependent)) + { + next_fragp = next_fragp->fr_next; + } + + if (next_fragp) + { + int n_insn_size; + int n_relaxable_p = 0; + + if (next_fragp->fr_opcode) + { + n_insn_size = s7_RELAX_NEW (next_fragp->fr_subtype); + } + else + { + n_insn_size = s7_RELAX_OLD (next_fragp->fr_subtype); + } + + if (s7_RELAX_TYPE (next_fragp->fr_subtype) == PC_DISP19div2) + s7_b32_relax_to_b16 (next_fragp); + n_relaxable_p = s7_RELAX_OPT (next_fragp->fr_subtype); + + if (word_align_p) + { + if (insn_size == 4) + { + /* 32 -> 16. */ + if (relaxable_p && ((n_insn_size == 2) || n_relaxable_p)) + { + grows -= 2; + do_relax_p = 1; + } + } + else if (insn_size == 2) + { + /* 16 -> 32. */ + if (relaxable_p && (((n_insn_size == 4) && !n_relaxable_p) || (n_insn_size > 4))) + { + grows += 2; + do_relax_p = 1; + } + } + else + { + abort (); + } + } + else + { + if (insn_size == 4) + { + /* 32 -> 16. */ + if (relaxable_p) + { + grows -= 2; + do_relax_p = 1; + } + /* Make the 32 bit insturction word align. */ + else + { + fragp->insn_addr += 2; + grows += 2; + } + } + else if (insn_size == 2) + { + /* Do nothing. */ + } + else + { + abort (); + } + } + } + else + { + /* Here, try best to do relax regardless fragp->fr_next->fr_type. */ + if (word_align_p == FALSE) + { + if (insn_size % 4 == 0) + { + /* 32 -> 16. */ + if (relaxable_p) + { + grows -= 2; + do_relax_p = 1; + } + else + { + fragp->insn_addr += 2; + grows += 2; + } + } + } + else + { + /* Do nothing. */ + } + } + + /* fragp->fr_opcode indicates whether this frag should be relaxed. */ + if (do_relax_p) + { + if (fragp->fr_opcode) + { + fragp->fr_opcode = NULL; + /* Guarantee estimate stage is correct. */ + fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype); + fragp->fr_fix += fragp->insn_addr; + } + else + { + fragp->fr_opcode = fragp->fr_literal + s7_RELAX_RELOC1 (fragp->fr_subtype); + /* Guarantee estimate stage is correct. */ + fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype); + fragp->fr_fix += fragp->insn_addr; + } + } + else + { + if (fragp->fr_opcode) + { + /* Guarantee estimate stage is correct. */ + fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype); + fragp->fr_fix += fragp->insn_addr; + } + else + { + /* Guarantee estimate stage is correct. */ + fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype); + fragp->fr_fix += fragp->insn_addr; + } + } + } + + return grows; +} + +static void +s7_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, + segT sec ATTRIBUTE_UNUSED, + fragS * fragp) +{ + int old; + int new; + char backup[20]; + fixS *fixp; + + old = s7_RELAX_OLD (fragp->fr_subtype); + new = s7_RELAX_NEW (fragp->fr_subtype); + + /* fragp->fr_opcode indicates whether this frag should be relaxed. */ + if (fragp->fr_opcode == NULL) + { + memcpy (backup, fragp->fr_literal, old); + fragp->fr_fix = old; + } + else + { + memcpy (backup, fragp->fr_literal + old, new); + fragp->fr_fix = new; + } + + fixp = fragp->tc_frag_data.fixp; + while (fixp && fixp->fx_frag == fragp && fixp->fx_where < old) + { + if (fragp->fr_opcode) + fixp->fx_done = 1; + fixp = fixp->fx_next; + } + while (fixp && fixp->fx_frag == fragp) + { + if (fragp->fr_opcode) + fixp->fx_where -= old + fragp->insn_addr; + else + fixp->fx_done = 1; + fixp = fixp->fx_next; + } + + if (fragp->insn_addr) + { + s7_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr); + } + memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix); + fragp->fr_fix += fragp->insn_addr; +} + +static long +s7_pcrel_from (fixS * fixP) +{ + long retval = 0; + + if (fixP->fx_addsy + && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section) + && (fixP->fx_subsy == NULL)) + { + retval = 0; + } + else + { + retval = fixP->fx_where + fixP->fx_frag->fr_address; + } + + return retval; +} + +/* Round up a section size to the appropriate boundary. */ +static valueT +s7_section_align (segT segment, valueT size) +{ + int align = bfd_get_section_alignment (stdoutput, segment); + + return ((size + (1 << align) - 1) & (-1 << align)); +} + +static void +s7_apply_fix (fixS *fixP, valueT *valP, segT seg) +{ + offsetT value = *valP; + offsetT abs_value = 0; + offsetT newval; + offsetT content; + unsigned short HI, LO; + + char *buf = fixP->fx_frag->fr_literal + fixP->fx_where; + + assert (fixP->fx_r_type < BFD_RELOC_UNUSED); + if (fixP->fx_addsy == 0 && !fixP->fx_pcrel) + { + if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16) + fixP->fx_done = 1; + } + + /* If this symbol is in a different section then we need to leave it for + the linker to deal with. Unfortunately, md_pcrel_from can't tell, + so we have to undo it's effects here. */ + if (fixP->fx_pcrel) + { + if (fixP->fx_addsy != NULL + && S_IS_DEFINED (fixP->fx_addsy) + && S_GET_SEGMENT (fixP->fx_addsy) != seg) + value += md_pcrel_from (fixP); + } + + /* Remember value for emit_reloc. */ + fixP->fx_addnumber = value; + + switch (fixP->fx_r_type) + { + case BFD_RELOC_HI16_S: + if (fixP->fx_done) + { /* For la rd, imm32. */ + newval = s7_md_chars_to_number (buf, s7_INSN_SIZE); + HI = (value) >> 16; /* mul to 2, then take the hi 16 bit. */ + newval |= (HI & 0x3fff) << 1; + newval |= ((HI >> 14) & 0x3) << 16; + s7_number_to_chars (buf, newval, s7_INSN_SIZE); + } + break; + case BFD_RELOC_LO16: + if (fixP->fx_done) /* For la rd, imm32. */ + { + newval = s7_md_chars_to_number (buf, s7_INSN_SIZE); + LO = (value) & 0xffff; + newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi. */ + newval |= ((LO >> 14) & 0x3) << 16; + s7_number_to_chars (buf, newval, s7_INSN_SIZE); + } + break; + case BFD_RELOC_SCORE_JMP: + { + content = s7_md_chars_to_number (buf, s7_INSN_SIZE); + value = fixP->fx_offset; + if (!(value >= 0 && value <= 0x1ffffff)) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + _("j or jl truncate (0x%x) [0 ~ 2^25-1]"), (unsigned int) value); + return; + } + content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff); + s7_number_to_chars (buf, content, s7_INSN_SIZE); + } + break; + case BFD_RELOC_SCORE_BRANCH: + if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) + value = fixP->fx_offset; + else + fixP->fx_done = 1; + + content = s7_md_chars_to_number (buf, s7_INSN_SIZE); + if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) != 0x80008000)) + { + if ((value & 0x80000000) == 0x80000000) + abs_value = 0xffffffff - value + 1; + if ((abs_value & 0xffffff00) != 0) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int) value); + return; + } + content = s7_md_chars_to_number (buf, s7_INSN16_SIZE); + content &= 0xff00; + content = (content & 0xff00) | ((value >> 1) & 0xff); + s7_number_to_chars (buf, content, s7_INSN16_SIZE); + fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH; + fixP->fx_size = 2; + } + else + { + if ((value & 0x80000000) == 0x80000000) + abs_value = 0xffffffff - value + 1; + if ((abs_value & 0xfff80000) != 0) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), + (unsigned int) value); + return; + } + content = s7_md_chars_to_number (buf, s7_INSN_SIZE); + content &= 0xfc00fc01; + content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000); + s7_number_to_chars (buf, content, s7_INSN_SIZE); + } + break; + case BFD_RELOC_SCORE16_JMP: + content = s7_md_chars_to_number (buf, s7_INSN16_SIZE); + content &= 0xf001; + value = fixP->fx_offset; + if (!(value >= 0 && value <= 0xfff)) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + _("j! or jl! truncate (0x%x) [0 ~ 2^12-1]"), (unsigned int) value); + return; + } + value = fixP->fx_offset & 0xfff; + content = (content & 0xfc01) | (value & 0xffe); + s7_number_to_chars (buf, content, s7_INSN16_SIZE); + break; + case BFD_RELOC_SCORE16_BRANCH: + content = s7_md_chars_to_number (buf, s7_INSN_SIZE); + if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) == 0x80008000)) + { + if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || + (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) + value = fixP->fx_offset; + else + fixP->fx_done = 1; + + if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), + (unsigned int) value); + return; + } + content = s7_md_chars_to_number (buf, s7_INSN_SIZE); + content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000); + s7_number_to_chars (buf, content, s7_INSN_SIZE); + fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH; + fixP->fx_size = 4; + break; + } + else + { + /* In differnt section. */ + if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || + (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy))) + value = fixP->fx_offset; + else + fixP->fx_done = 1; + + if ((value & 0xffffff00) != 0 && (value & 0xffffff00) != 0xffffff00) + { + as_bad_where (fixP->fx_file, fixP->fx_line, + _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), + (unsigned int) value); + return; + } + content = s7_md_chars_to_number (buf, s7_INSN16_SIZE); + content = (content & 0xff00) | ((value >> 1) & 0xff); + s7_number_to_chars (buf, content, s7_INSN16_SIZE); + break; + } + case BFD_RELOC_8: + if (fixP->fx_done || fixP->fx_pcrel) + s7_number_to_chars (buf, value, 1); +#ifdef OBJ_ELF + else + { + value = fixP->fx_offset; + s7_number_to_chars (buf, value, 1); + } +#endif + break; + + case BFD_RELOC_16: + if (fixP->fx_done || fixP->fx_pcrel) + s7_number_to_chars (buf, value, 2); +#ifdef OBJ_ELF + else + { + value = fixP->fx_offset; + s7_number_to_chars (buf, value, 2); + } +#endif + break; + case BFD_RELOC_RVA: + case BFD_RELOC_32: + if (fixP->fx_done || fixP->fx_pcrel) + s7_number_to_chars (buf, value, 4); +#ifdef OBJ_ELF + else + { + value = fixP->fx_offset; + s7_number_to_chars (buf, value, 4); + } +#endif + break; + case BFD_RELOC_VTABLE_INHERIT: + fixP->fx_done = 0; + if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy)) + S_SET_WEAK (fixP->fx_addsy); + break; + case BFD_RELOC_VTABLE_ENTRY: + fixP->fx_done = 0; + break; + case BFD_RELOC_SCORE_GPREL15: + content = s7_md_chars_to_number (buf, s7_INSN_SIZE); + if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94188000)) + fixP->fx_r_type = BFD_RELOC_NONE; + fixP->fx_done = 0; + break; + case BFD_RELOC_SCORE_GOT15: + case BFD_RELOC_SCORE_DUMMY_HI16: + case BFD_RELOC_SCORE_GOT_LO16: + case BFD_RELOC_SCORE_CALL15: + case BFD_RELOC_GPREL32: + break; + case BFD_RELOC_NONE: + default: + as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type); + } +} + +/* Translate internal representation of relocation info to BFD target format. */ + +static arelent ** +s7_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp) +{ + static arelent *retval[MAX_RELOC_EXPANSION + 1]; /* MAX_RELOC_EXPANSION equals 2. */ + arelent *reloc; + bfd_reloc_code_real_type code; + char *type; + fragS *f; + symbolS *s; + expressionS e; + + reloc = retval[0] = xmalloc (sizeof (arelent)); + retval[1] = NULL; + + reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); + *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); + reloc->address = fixp->fx_frag->fr_address + fixp->fx_where; + reloc->addend = fixp->fx_offset; + + /* If this is a variant frag, we may need to adjust the existing + reloc and generate a new one. */ + if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15)) + { + /* Update instruction imm bit. */ + offsetT newval; + unsigned short off; + char *buf; + + buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr; + newval = s7_md_chars_to_number (buf, s7_INSN_SIZE); + off = fixp->fx_offset >> 16; + newval |= (off & 0x3fff) << 1; + newval |= ((off >> 14) & 0x3) << 16; + s7_number_to_chars (buf, newval, s7_INSN_SIZE); + + buf += s7_INSN_SIZE; + newval = s7_md_chars_to_number (buf, s7_INSN_SIZE); + off = fixp->fx_offset & 0xffff; + newval |= ((off & 0x3fff) << 1); + newval |= (((off >> 14) & 0x3) << 16); + s7_number_to_chars (buf, newval, s7_INSN_SIZE); + + retval[1] = xmalloc (sizeof (arelent)); + retval[2] = NULL; + retval[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); + *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy); + retval[1]->address = (reloc->address + s7_RELAX_RELOC2 (fixp->fx_frag->fr_subtype)); + + f = fixp->fx_frag; + s = f->fr_symbol; + e = s->sy_value; + + retval[1]->addend = 0; + retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16); + assert (retval[1]->howto != NULL); + + fixp->fx_r_type = BFD_RELOC_HI16_S; + } + + code = fixp->fx_r_type; + switch (fixp->fx_r_type) + { + case BFD_RELOC_32: + if (fixp->fx_pcrel) + { + code = BFD_RELOC_32_PCREL; + break; + } + case BFD_RELOC_HI16_S: + case BFD_RELOC_LO16: + case BFD_RELOC_SCORE_JMP: + case BFD_RELOC_SCORE_BRANCH: + case BFD_RELOC_SCORE16_JMP: + case BFD_RELOC_SCORE16_BRANCH: + case BFD_RELOC_VTABLE_ENTRY: + case BFD_RELOC_VTABLE_INHERIT: + case BFD_RELOC_SCORE_GPREL15: + case BFD_RELOC_SCORE_GOT15: + case BFD_RELOC_SCORE_DUMMY_HI16: + case BFD_RELOC_SCORE_GOT_LO16: + case BFD_RELOC_SCORE_CALL15: + case BFD_RELOC_GPREL32: + case BFD_RELOC_NONE: + code = fixp->fx_r_type; + break; + default: + type = _(""); + as_bad_where (fixp->fx_file, fixp->fx_line, + _("cannot represent %s relocation in this object file format"), type); + return NULL; + } + + reloc->howto = bfd_reloc_type_lookup (stdoutput, code); + if (reloc->howto == NULL) + { + as_bad_where (fixp->fx_file, fixp->fx_line, + _("cannot represent %s relocation in this object file format1"), + bfd_get_reloc_code_name (code)); + return NULL; + } + /* HACK: Since arm ELF uses Rel instead of Rela, encode the + vtable entry to be used in the relocation's section offset. */ + if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY) + reloc->address = fixp->fx_offset; + + return retval; +} diff --git a/gas/doc/Makefile.am b/gas/doc/Makefile.am index 793058d29a8..6a02ccf48f6 100644 --- a/gas/doc/Makefile.am +++ b/gas/doc/Makefile.am @@ -58,6 +58,7 @@ CPU_DOCS = \ c-pj.texi \ c-ppc.texi \ c-s390.texi \ + c-score.texi \ c-sh.texi \ c-sh64.texi \ c-sparc.texi \ @@ -75,7 +76,7 @@ install-data-local: install-info pdf__strip_dir = `echo $$p | sed -e 's|^.*/||'`; install-pdf: install-pdf-am - + install-pdf-am: $(PDFS) @$(NORMAL_INSTALL) test -z "$(pdfdir)" || $(mkinstalldirs) "$(DESTDIR)$(pdfdir)" diff --git a/gas/doc/Makefile.in b/gas/doc/Makefile.in index 7e8b03b70fa..847b352ab2c 100644 --- a/gas/doc/Makefile.in +++ b/gas/doc/Makefile.in @@ -279,6 +279,7 @@ CPU_DOCS = \ c-pj.texi \ c-ppc.texi \ c-s390.texi \ + c-score.texi \ c-sh.texi \ c-sh64.texi \ c-sparc.texi \ diff --git a/gas/doc/all.texi b/gas/doc/all.texi index 6ccc6f35df8..9a94e6be899 100644 --- a/gas/doc/all.texi +++ b/gas/doc/all.texi @@ -1,5 +1,5 @@ @c Copyright 1992, 1993, 1994, 1996, 1997, 1999, 2000, 2001, 2002, -@c 2003, 2005 +@c 2003, 2005, 2009 @c Free Software Foundation, Inc. @c This file is part of the documentation for the GAS manual @@ -58,6 +58,7 @@ @set PJ @set PPC @set S390 +@set SCORE @set SH @set SPARC @set TIC54X diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo index 18fd9622fbc..fd6c0a37444 100644 --- a/gas/doc/as.texinfo +++ b/gas/doc/as.texinfo @@ -1,6 +1,6 @@ \input texinfo @c -*-Texinfo-*- @c Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -@c 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 +@c 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 @c Free Software Foundation, Inc. @c UPDATE!! On future updates-- @c (1) check for new machine-dep cmdline options in @@ -101,7 +101,7 @@ This file documents the GNU Assembler "@value{AS}". @c man begin COPYRIGHT Copyright @copyright{} 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001, 2002, -2006, 2007, 2008 Free Software Foundation, Inc. +2006, 2007, 2008, 2009 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 @@ -151,7 +151,7 @@ done. @vskip 0pt plus 1filll Copyright @copyright{} 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000, 2001, 2002, -2006, 2007, 2008 Free Software Foundation, Inc. +2006, 2007, 2008, 2009 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 @@ -423,6 +423,14 @@ gcc(1), ld(1), and the Info entries for @file{binutils} and @file{ld}. [@b{-mregnames}|@b{-mno-regnames}] [@b{-mwarn-areg-zero}] @end ifset +@ifset SCORE + +@emph{Target SCORE options:} + [@b{-EB}][@b{-EL}][@b{-FIXDD}][@b{-NWARN}] + [@b{-SCORE5}][@b{-SCORE5U}][@b{-SCORE7}][@b{-SCORE3}] + [@b{-march=score7}][@b{-march=score3}] + [@b{-USE_R1}][@b{-KPIC}][@b{-O0}][@b{-G} @var{num}][@b{-V}] +@end ifset @ifset SPARC @emph{Target SPARC options:} @@ -2233,9 +2241,15 @@ is considered a comment and is ignored. The line comment character is @ifset PPC @samp{#} for Motorola PowerPC; @end ifset +<<<<<<< as.texinfo +@ifset SCORE +@samp{#} for the Sunplus SCORE; +@end ifset +======= @ifset S390 @samp{#} for IBM S/390; @end ifset +>>>>>>> 1.196 @ifset SH @samp{!} for the Renesas / SuperH SH; @end ifset @@ -6750,9 +6764,15 @@ subject, see the hardware manufacturer's manual. @ifset PPC * PPC-Dependent:: PowerPC Dependent Features @end ifset +<<<<<<< as.texinfo +@ifset SCORE +* SCORE-Dependent:: SCORE Dependent Features +@end ifset +======= @ifset S390 * S/390-Dependent:: IBM S/390 Dependent Features @end ifset +>>>>>>> 1.196 @ifset SPARC * Sparc-Dependent:: SPARC Dependent Features @end ifset @@ -6921,10 +6941,17 @@ family. @include c-ppc.texi @end ifset +<<<<<<< as.texinfo +@ifset SCORE +@include c-score.texi +@end ifset + +======= @ifset S390 @include c-s390.texi @end ifset +>>>>>>> 1.196 @ifset SH @include c-sh.texi @include c-sh64.texi diff --git a/gas/doc/c-score.texi b/gas/doc/c-score.texi new file mode 100644 index 00000000000..08201154aee --- /dev/null +++ b/gas/doc/c-score.texi @@ -0,0 +1,142 @@ +@c Copyright 2009 +@c Free Software Foundation, Inc. +@c This is part of the GAS manual. +@c For copying conditions, see the file as.texinfo. +@ifset GENERIC +@page +@node SCORE-Dependent +@chapter SCORE Dependent Features +@end ifset +@ifclear GENERIC +@node Machine Dependencies +@chapter SCORE Dependent Features +@end ifclear + +@cindex SCORE processor +@menu +* SCORE-Opts:: Assembler options +* SCORE-Pseudo:: SCORE Assembler Directives +@end menu + +@node SCORE-Opts +@section Options + +@cindex options for SCORE +@cindex SCORE options +@cindex architectures, SCORE +@cindex SCORE architectures + +The following table lists all available SCORE options. + +@table @code +@item -G @var{num} +This option sets the largest size of an object that can be referenced +implicitly with the @code{gp} register. The default value is 8. + +@item -EB +Assemble code for a big-endian cpu + +@itemx -EL +Assemble code for a little-endian cpu + +@item -FIXDD +Assemble code for fix data dependency + +@item -NWARN +Assemble code for no warning message for fix data dependency + +@item -SCORE5 +Assemble code for target is SCORE5 + +@itemx -SCORE5U +Assemble code for target is SCORE5U + +@itemx -SCORE7 +Assemble code for target is SCORE7, this is default setting + +@itemx -SCORE3 +Assemble code for target is SCORE3 + +@item -march=score7 +Assemble code for target is SCORE7, this is default setting + +@item -march=score3 +Assemble code for target is SCORE3 + +@item -USE_R1 +Assemble code for no warning message when using temp register r1 + +@item -KPIC +Generate code for PIC. This option tells the assembler to generate +score position-independent macro expansions. It also tells the +assembler to mark the output file as PIC. + +@item -O0 +Assembler will not perform any optimizations + +@item -V +Sunplus release version + +@end table + +@node SCORE-Pseudo +@section SCORE Assembler Directives + +@cindex directives for SCORE +@cindex SCORE directives +A number of assembler directives are available for SCORE. The +following table is far from complete. + +@table @code +@item .set nwarn +Let the assembler not to generate warnings if the source machine +language instructions happen data dependency. + +@item .set fixdd +Let the assembler to insert bubbles (32 bit nop instruction / +16 bit nop! Instruction) if the source machine language instructions +happen data dependency. + +@item .set nofixdd +Let the assembler to generate warnings if the source machine +language instructions happen data dependency. (Default) + +@item .set r1 +Let the assembler not to generate warnings if the source program +uses r1. allow user to use r1 + +@item set nor1 +Let the assembler to generate warnings if the source program uses +r1. (Default) + +@item .sdata +Tell the assembler to add subsequent data into the sdata section + +@item .rdata +Tell the assembler to add subsequent data into the rdata section + +@item .frame "frame-register", "offset", "return-pc-register" +Describe a stack frame. "frame-register" is the frame register, +"offset" is the distance from the frame register to the virtual +frame pointer, "return-pc-register" is the return program register. +You must use ".ent" before ".frame" and only one ".frame" can be +used per ".ent". + +@item .mask "bitmask", "frameoffset" +Indicate which of the integer registers are saved in the current +function's stack frame, this is for the debugger to explain the +frame chain. + +@item .ent "proc-name" +Set the beginning of the procedure "proc_name". Use this directive +when you want to generate information for the debugger. + +@item .end proc-name +Set the end of a procedure. Use this directive to generate information +for the debugger. + +@item .bss +Switch the destination of following statements into the bss section, +which is used for data that is uninitialized anywhere. + +@end table diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 69d31f497d8..0cc36523cbd 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,35 @@ +2009-03-02 Qinwei + + * gas/score/arith_32-lt.d: New file. + * gas/score/arith_32.d: New file. + * gas/score/arith_32.s: New file. + * gas/score/bit_32-lt.d: New file. + * gas/score/bit_32.d: New file. + * gas/score/bit_32.s: New file. + * gas/score/branch_32-lt.d: New file. + * gas/score/branch_32.d: New file. + * gas/score/branch_32.s: New file. + * gas/score/cmp_32-lt.d: New file. + * gas/score/cmp_32.d: New file. + * gas/score/cmp_32.s: New file. + * gas/score/load_store_32-lt.d: New file. + * gas/score/load_store_32.d: New file. + * gas/score/load_store_32.s: New file. + * gas/score/logical_32-lt.d: New file. + * gas/score/logical_32.d: New file. + * gas/score/logical_32.s: New file. + * gas/score/mv_32-lt.d: New file. + * gas/score/mv_32.d: New file. + * gas/score/mv_32.s: New file. + * gas/score/relax_32.exp: New file. + * gas/score/relaxation_macro.h: New file. + * gas/score/shift_32-lt.d: New file. + * gas/score/shift_32.d: New file. + * gas/score/shift_32.s: New file. + * gas/score/syscontrol_32-lt.d: New file. + * gas/score/syscontrol_32.d: New file. + * gas/score/syscontrol_32.s: New file. + 2009-03-01 Mark Mitchell * gas/arm/archv6m.s: Add dmb, dsb, and isb. diff --git a/gas/testsuite/gas/score/arith_32-lt.d b/gas/testsuite/gas/score/arith_32-lt.d new file mode 100644 index 00000000000..c6f8630a374 --- /dev/null +++ b/gas/testsuite/gas/score/arith_32-lt.d @@ -0,0 +1,16 @@ +#as: -march=score3 -I${srcdir}/${subdir} -EL +#objdump: -s +#source: arith_32.s + +.*: file format elf32-littlescore + +Contents of section .text: + 0000 0f480f48 0f480f48 0f480f48 0f480f48 .* + 0010 0f480080 113c0080 10401082 10001082 .* + 0020 10440180 10080f49 0f490f49 0f490f49 .* + 0030 0f490f49 0f490f49 0080153c 00801440 .* + 0040 10821400 10821444 01801408 205c1f5c .* + 0050 e05fdf5f 205c205c 205c205c 205c205c .* + 0060 205c205c 0384c17f 0384be7f 00844000 .* + 0070 0386c07f 00863e00 .* +#pass diff --git a/gas/testsuite/gas/score/arith_32.d b/gas/testsuite/gas/score/arith_32.d new file mode 100644 index 00000000000..cf63259ab23 --- /dev/null +++ b/gas/testsuite/gas/score/arith_32.d @@ -0,0 +1,55 @@ +#as: -march=score3 -I${srcdir}/${subdir} +#objdump: -d +#source: arith_32.s + +.*: file format .* + +Disassembly of section .text: + +00000000 <.text>: + 0: 480f add! r0, r15 + 2: 480f add! r0, r15 + 4: 480f add! r0, r15 + 6: 480f add! r0, r15 + 8: 480f add! r0, r15 + a: 480f add! r0, r15 + c: 480f add! r0, r15 + e: 480f add! r0, r15 + 10: 480f add! r0, r15 + 12: 8000 3c11 add.c r0, r0, r15 + 16: 8000 4010 add r0, r0, r16 + 1a: 8210 0010 add r16, r16, r0 + 1e: 8210 4410 add r16, r16, r17 + 22: 8001 0810 add r0, r1, r2 + 26: 490f sub! r0, r15 + 28: 490f sub! r0, r15 + 2a: 490f sub! r0, r15 + 2c: 490f sub! r0, r15 + 2e: 490f sub! r0, r15 + 30: 490f sub! r0, r15 + 32: 490f sub! r0, r15 + 34: 490f sub! r0, r15 + 36: 490f sub! r0, r15 + 38: 8000 3c15 sub.c r0, r0, r15 + 3c: 8000 4014 sub r0, r0, r16 + 40: 8210 0014 sub r16, r16, r0 + 44: 8210 4414 sub r16, r16, r17 + 48: 8001 0814 sub r0, r1, r2 + 4c: 5c20 addi! r0, -32 + 4e: 5c1f addi! r0, 31 + 50: 5fe0 addi! r15, -32 + 52: 5fdf addi! r15, 31 + 54: 5c20 addi! r0, -32 + 56: 5c20 addi! r0, -32 + 58: 5c20 addi! r0, -32 + 5a: 5c20 addi! r0, -32 + 5c: 5c20 addi! r0, -32 + 5e: 5c20 addi! r0, -32 + 60: 5c20 addi! r0, -32 + 62: 5c20 addi! r0, -32 + 64: 8403 7fc1 addi.c r0, -32 + 68: 8403 7fbe addi r0, -33 + 6c: 8400 0040 addi r0, 32 + 70: 8603 7fc0 addi r16, -32 + 74: 8600 003e addi r16, 31 +#pass diff --git a/gas/testsuite/gas/score/arith_32.s b/gas/testsuite/gas/score/arith_32.s new file mode 100644 index 00000000000..7e2f76b5afe --- /dev/null +++ b/gas/testsuite/gas/score/arith_32.s @@ -0,0 +1,43 @@ +/* + * tests for arithmetic instruction relaxation + * + * Author: libin + */ + +.include "relaxation_macro.h" + +.macro _arith_op_pattern insn insn1 + insn_32 "\insn r0, r0, r15" + + tran_16_32 "\insn! r0, r15", "\insn r0, r0, r15" + + /* shouldn't alter */ + .set r1 + insn_32 "\insn1 r0, r0, r15" + insn_32 "\insn r0, r0, r16" + insn_32 "\insn r16, r16, r0" + insn_32 "\insn r16, r16, r17" + insn_32 "\insn r0, r1, r2" +.endm + +.text +/* add rD,rA,rB -> add! rD,rA */ +_arith_op_pattern "add", "add.c" + +/* sub rD,rA,rB -> sub rD,rA */ +_arith_op_pattern "sub", "sub.c" + +/* addi rD,SImm16 -> addi! rD,SImm6 */ +insn_32 "addi r0, -32" +insn_32 "addi r0, 31" +insn_32 "addi r15, -32" +insn_32 "addi r15, 31" + +tran_16_32 "addi! r0,-32", "addi r0,-32" + +/* shouldn't alter */ +insn_32 "addi.c r0, -32" +insn_32 "addi r0, -33" +insn_32 "addi r0, 32" +insn_32 "addi r16, -32" +insn_32 "addi r16, 31" diff --git a/gas/testsuite/gas/score/bit_32-lt.d b/gas/testsuite/gas/score/bit_32-lt.d new file mode 100644 index 00000000000..018d8dcf356 --- /dev/null +++ b/gas/testsuite/gas/score/bit_32-lt.d @@ -0,0 +1,17 @@ +#as: -march=score3 -I${srcdir}/${subdir} -EL +#objdump: -s +#source: bit_32.s + +.*: file format elf32-littlescore + +Contents of section .text: + 0000 00501f50 e051ff51 00500050 00500050 .* + 0010 00500050 00500050 00802900 10822800 .* + 0020 1082287c 00521f52 e053ff53 00520052 .* + 0030 00520052 00520052 00520052 00802b00 .* + 0040 10822a00 10822a7c 00561f56 e057ff57 .* + 0050 00560056 00560056 00560056 00560056 .* + 0060 00802f00 10822e00 10822e7c 00541f54 .* + 0070 e055ff55 00540054 00540054 00540054 .* + 0080 00540054 10802d00 10802d7c .* +#pass diff --git a/gas/testsuite/gas/score/bit_32.d b/gas/testsuite/gas/score/bit_32.d new file mode 100644 index 00000000000..60a4cb27128 --- /dev/null +++ b/gas/testsuite/gas/score/bit_32.d @@ -0,0 +1,69 @@ +#as: -march=score3 -I${srcdir}/${subdir} +#objdump: -d +#source: bit_32.s + +.*: file format .* + +Disassembly of section .text: + +00000000 <.text>: + 0: 5000 bitclr! r0, 0x0 + 2: 501f bitclr! r0, 0x1f + 4: 51e0 bitclr! r15, 0x0 + 6: 51ff bitclr! r15, 0x1f + 8: 5000 bitclr! r0, 0x0 + a: 5000 bitclr! r0, 0x0 + c: 5000 bitclr! r0, 0x0 + e: 5000 bitclr! r0, 0x0 + 10: 5000 bitclr! r0, 0x0 + 12: 5000 bitclr! r0, 0x0 + 14: 5000 bitclr! r0, 0x0 + 16: 5000 bitclr! r0, 0x0 + 18: 8000 0029 bitclr.c r0, r0, 0x0 + 1c: 8210 0028 bitclr r16, r16, 0x0 + 20: 8210 7c28 bitclr r16, r16, 0x1f + 24: 5200 bitset! r0, 0x0 + 26: 521f bitset! r0, 0x1f + 28: 53e0 bitset! r15, 0x0 + 2a: 53ff bitset! r15, 0x1f + 2c: 5200 bitset! r0, 0x0 + 2e: 5200 bitset! r0, 0x0 + 30: 5200 bitset! r0, 0x0 + 32: 5200 bitset! r0, 0x0 + 34: 5200 bitset! r0, 0x0 + 36: 5200 bitset! r0, 0x0 + 38: 5200 bitset! r0, 0x0 + 3a: 5200 bitset! r0, 0x0 + 3c: 8000 002b bitset.c r0, r0, 0x0 + 40: 8210 002a bitset r16, r16, 0x0 + 44: 8210 7c2a bitset r16, r16, 0x1f + 48: 5600 bittgl! r0, 0x0 + 4a: 561f bittgl! r0, 0x1f + 4c: 57e0 bittgl! r15, 0x0 + 4e: 57ff bittgl! r15, 0x1f + 50: 5600 bittgl! r0, 0x0 + 52: 5600 bittgl! r0, 0x0 + 54: 5600 bittgl! r0, 0x0 + 56: 5600 bittgl! r0, 0x0 + 58: 5600 bittgl! r0, 0x0 + 5a: 5600 bittgl! r0, 0x0 + 5c: 5600 bittgl! r0, 0x0 + 5e: 5600 bittgl! r0, 0x0 + 60: 8000 002f bittgl.c r0, r0, 0x0 + 64: 8210 002e bittgl r16, r16, 0x0 + 68: 8210 7c2e bittgl r16, r16, 0x1f + 6c: 5400 bittst! r0, 0x0 + 6e: 541f bittst! r0, 0x1f + 70: 55e0 bittst! r15, 0x0 + 72: 55ff bittst! r15, 0x1f + 74: 5400 bittst! r0, 0x0 + 76: 5400 bittst! r0, 0x0 + 78: 5400 bittst! r0, 0x0 + 7a: 5400 bittst! r0, 0x0 + 7c: 5400 bittst! r0, 0x0 + 7e: 5400 bittst! r0, 0x0 + 80: 5400 bittst! r0, 0x0 + 82: 5400 bittst! r0, 0x0 + 84: 8010 002d bittst.c r16, 0x0 + 88: 8010 7c2d bittst.c r16, 0x1f +#pass diff --git a/gas/testsuite/gas/score/bit_32.s b/gas/testsuite/gas/score/bit_32.s new file mode 100644 index 00000000000..9490df4faf3 --- /dev/null +++ b/gas/testsuite/gas/score/bit_32.s @@ -0,0 +1,43 @@ +/* + * tests for bit operations' instruction relaxation + * + * Author: libin + */ + +.include "relaxation_macro.h" + +.macro _bit_op_pattern insn insn1 + insn_32 "\insn r0, r0, 0" + insn_32 "\insn r0, r0, 0x1f" + insn_32 "\insn r15, r15, 0" + insn_32 "\insn r15, r15, 0x1f" + + tran_16_32 "\insn! r0,0", "\insn r0,r0,0" + + /* shouldn't alter */ + insn_32 "\insn1 r0, r0, 0" + insn_32 "\insn r16, r16, 0" + insn_32 "\insn r16, r16, 0x1f" +.endm + +.text +/* + * bitclr rD,rA,BN5 -> bitclr! rD,BN5 + * bitset rD,rA,BN5 -> bitset! rD,BN5 + * bittgl rD,rA,BN5 -> bittgl! rD,BN5 + */ +_bit_op_pattern "bitclr", "bitclr.c" +_bit_op_pattern "bitset", "bitset.c" +_bit_op_pattern "bittgl", "bittgl.c" + +/* bittst.c rA,BN5 <-> bittst! rD,BN5" */ +insn_32 "bittst.c r0, 0" +insn_32 "bittst.c r0, 0x1f" +insn_32 "bittst.c r15, 0" +insn_32 "bittst.c r15, 0x1f" + +tran_16_32 "bittst! r0,0", "bittst.c r0,0" + +/* shouldn't alter */ +insn_32 "bittst.c r16, 0" +insn_32 "bittst.c r16, 0x1f" diff --git a/gas/testsuite/gas/score/branch_32-lt.d b/gas/testsuite/gas/score/branch_32-lt.d new file mode 100644 index 00000000000..5175c4f1282 --- /dev/null +++ b/gas/testsuite/gas/score/branch_32-lt.d @@ -0,0 +1,1652 @@ +#as: -march=score3 -I${srcdir}/${subdir} -EL +#objdump: -s +#source: branch_32.s + +.*: file format elf32-littlescore + +Contents of section .text: + 0000 0034ff35 fe35fd35 ff93f80b ff93f40b .* + 0010 f835ff93 ee0bff93 ea0bff93 e70b0000 .* + 0020 00000000 00000000 00000000 00000000 .* + 0030 00000000 00000000 00000000 00000000 .* + 0040 00000000 00000000 00000000 00000000 .* + 0050 00000000 00000000 00000000 00000000 .* + 0060 00000000 00000000 00000000 00000000 .* + 0070 00000000 00000000 00000000 00000000 .* + 0080 00000000 00000000 00000000 00000000 .* + 0090 00000000 00000000 00000000 00000000 .* + 00a0 00000000 00000000 00000000 00000000 .* + 00b0 00000000 00000000 00000000 00000000 .* + 00c0 00000000 00000000 00000000 00000000 .* + 00d0 00000000 00000000 00000000 00000000 .* + 00e0 00000000 00000000 00000000 00000000 .* + 00f0 00000000 00000000 00000000 00000000 .* + 0100 00000000 00000000 00000000 00000000 .* + 0110 00000000 00000000 00000000 00000000 .* + 0120 00000000 00000000 00000000 00000000 .* + 0130 00000000 00000000 00000000 00000000 .* + 0140 00000000 00000000 00000000 00000000 .* + 0150 00000000 00000000 00000000 00000000 .* + 0160 00000000 00000000 00000000 00000000 .* + 0170 00000000 00000000 00000000 00000000 .* + 0180 00000000 00000000 00000000 00000000 .* + 0190 00000000 00000000 00000000 00000000 .* + 01a0 00000000 00000000 00000000 00000000 .* + 01b0 00000000 00000000 00000000 00000000 .* + 01c0 00000000 00000000 00000000 00000000 .* + 01d0 00000000 00000000 00000000 00000000 .* + 01e0 00000000 00000000 00000000 00000000 .* + 01f0 00000000 00000000 00000000 00000000 .* + 0200 00000000 00000000 00000000 00000000 .* + 0210 00000000 00000000 00000000 0000ff93 .* + 0220 e209ff93 de09ff93 da09ff93 d609ff93 .* + 0230 d209ff93 ce09ff93 ca09ff93 c609ff93 .* + 0240 c209ff93 bf090090 460a0090 420a0090 .* + 0250 3e0a0090 3a0a0090 360a0090 320a0090 .* + 0260 2e0a0090 2a0a0090 260a0090 230a0000 .* + 0270 00000000 00000000 00000000 00000000 .* + 0280 00000000 00000000 00000000 00000000 .* + 0290 00000000 00000000 00000000 00000000 .* + 02a0 00000000 00000000 00000000 00000000 .* + 02b0 00000000 00000000 00000000 00000000 .* + 02c0 00000000 00000000 00000000 00000000 .* + 02d0 00000000 00000000 00000000 00000000 .* + 02e0 00000000 00000000 00000000 00000000 .* + 02f0 00000000 00000000 00000000 00000000 .* + 0300 00000000 00000000 00000000 00000000 .* + 0310 00000000 00000000 00000000 00000000 .* + 0320 00000000 00000000 00000000 00000000 .* + 0330 00000000 00000000 00000000 00000000 .* + 0340 00000000 00000000 00000000 00000000 .* + 0350 00000000 00000000 00000000 00000000 .* + 0360 00000000 00000000 00000000 00000000 .* + 0370 00000000 00000000 00000000 00000000 .* + 0380 00000000 00000000 00000000 00000000 .* + 0390 00000000 00000000 00000000 00000000 .* + 03a0 00000000 00000000 00000000 00000000 .* + 03b0 00000000 00000000 00000000 00000000 .* + 03c0 00000000 00000000 00000000 00000000 .* + 03d0 00000000 00000000 00000000 00000000 .* + 03e0 00000000 00000000 00000000 00000000 .* + 03f0 00000000 00000000 00000000 00000000 .* + 0400 00000000 00000000 00000000 00000000 .* + 0410 00000000 00000000 00000000 00000000 .* + 0420 00000000 00000000 00000000 00000000 .* + 0430 00000000 00000000 00000000 00000000 .* + 0440 00000000 00000000 00000000 00000000 .* + 0450 00000000 00000000 00000000 00000000 .* + 0460 00000000 00000000 00000000 00000f34 .* + 0470 0e340d34 0c340090 16080090 12080734 .* + 0480 00900c08 00900808 00900508 00000000 .* + 0490 00000000 00000000 00000000 00000000 .* + 04a0 00000000 00000000 00000000 00000000 .* + 04b0 00000000 00000000 00000000 00000000 .* + 04c0 00000000 00000000 00000000 00000000 .* + 04d0 00000000 00000000 00000000 00000000 .* + 04e0 00000000 00000000 00000000 00000000 .* + 04f0 00000000 00000000 00000000 00000000 .* + 0500 00000000 00000000 00000000 00000000 .* + 0510 00000000 00000000 00000000 00000000 .* + 0520 00000000 00000000 00000000 00000000 .* + 0530 00000000 00000000 00000000 00000000 .* + 0540 00000000 00000000 00000000 00000000 .* + 0550 00000000 00000000 00000000 00000000 .* + 0560 00000000 00000000 00000000 00000000 .* + 0570 00000000 00000000 00000000 00000000 .* + 0580 00000000 00000000 00000000 00000000 .* + 0590 00000000 00000000 00000000 00000000 .* + 05a0 00000000 00000000 00000000 00000000 .* + 05b0 00000000 00000000 00000000 00000000 .* + 05c0 00000000 00000000 00000000 00000000 .* + 05d0 00000000 00000000 00000000 00000000 .* + 05e0 00000000 00000000 00000000 00000000 .* + 05f0 00000000 00000000 00000000 00000000 .* + 0600 00000000 00000000 00000000 00000000 .* + 0610 00000000 00000000 00000000 00000000 .* + 0620 00000000 00000000 00000000 00000000 .* + 0630 00000000 00000000 00000000 00000000 .* + 0640 00000000 00000000 00000000 00000000 .* + 0650 00000000 00000000 00000000 00000000 .* + 0660 00000000 00000000 00000000 00000000 .* + 0670 00000000 00000000 00000000 00000000 .* + 0680 00000000 00000000 00000000 00000035 .* + 0690 ff93fe09 0090060a 0090020a 00000000 .* + 06a0 00000000 00000000 00000000 00000000 .* + 06b0 00000000 00000000 00000000 00000000 .* + 06c0 00000000 00000000 00000000 00000000 .* + 06d0 00000000 00000000 00000000 00000000 .* + 06e0 00000000 00000000 00000000 00000000 .* + 06f0 00000000 00000000 00000000 00000000 .* + 0700 00000000 00000000 00000000 00000000 .* + 0710 00000000 00000000 00000000 00000000 .* + 0720 00000000 00000000 00000000 00000000 .* + 0730 00000000 00000000 00000000 00000000 .* + 0740 00000000 00000000 00000000 00000000 .* + 0750 00000000 00000000 00000000 00000000 .* + 0760 00000000 00000000 00000000 00000000 .* + 0770 00000000 00000000 00000000 00000000 .* + 0780 00000000 00000000 00000000 00000000 .* + 0790 00000000 00000000 00000000 00000000 .* + 07a0 00000000 00000000 00000000 00000000 .* + 07b0 00000000 00000000 00000000 00000000 .* + 07c0 00000000 00000000 00000000 00000000 .* + 07d0 00000000 00000000 00000000 00000000 .* + 07e0 00000000 00000000 00000000 00000000 .* + 07f0 00000000 00000000 00000000 00000000 .* + 0800 00000000 00000000 00000000 00000000 .* + 0810 00000000 00000000 00000000 00000000 .* + 0820 00000000 00000000 00000000 00000000 .* + 0830 00000000 00000000 00000000 00000000 .* + 0840 00000000 00000000 00000000 00000000 .* + 0850 00000000 00000000 00000000 00000000 .* + 0860 00000000 00000000 00000000 00000000 .* + 0870 00000000 00000000 00000000 00000000 .* + 0880 00000000 00000000 00000000 00000000 .* + 0890 00000000 00000000 00000000 00000036 .* + 08a0 ff37fe37 fd37ff93 f80fff93 f40ff837 .* + 08b0 ff93ee0f ff93ea0f ff93e70f 00000000 .* + 08c0 00000000 00000000 00000000 00000000 .* + 08d0 00000000 00000000 00000000 00000000 .* + 08e0 00000000 00000000 00000000 00000000 .* + 08f0 00000000 00000000 00000000 00000000 .* + 0900 00000000 00000000 00000000 00000000 .* + 0910 00000000 00000000 00000000 00000000 .* + 0920 00000000 00000000 00000000 00000000 .* + 0930 00000000 00000000 00000000 00000000 .* + 0940 00000000 00000000 00000000 00000000 .* + 0950 00000000 00000000 00000000 00000000 .* + 0960 00000000 00000000 00000000 00000000 .* + 0970 00000000 00000000 00000000 00000000 .* + 0980 00000000 00000000 00000000 00000000 .* + 0990 00000000 00000000 00000000 00000000 .* + 09a0 00000000 00000000 00000000 00000000 .* + 09b0 00000000 00000000 00000000 00000000 .* + 09c0 00000000 00000000 00000000 00000000 .* + 09d0 00000000 00000000 00000000 00000000 .* + 09e0 00000000 00000000 00000000 00000000 .* + 09f0 00000000 00000000 00000000 00000000 .* + 0a00 00000000 00000000 00000000 00000000 .* + 0a10 00000000 00000000 00000000 00000000 .* + 0a20 00000000 00000000 00000000 00000000 .* + 0a30 00000000 00000000 00000000 00000000 .* + 0a40 00000000 00000000 00000000 00000000 .* + 0a50 00000000 00000000 00000000 00000000 .* + 0a60 00000000 00000000 00000000 00000000 .* + 0a70 00000000 00000000 00000000 00000000 .* + 0a80 00000000 00000000 00000000 00000000 .* + 0a90 00000000 00000000 00000000 00000000 .* + 0aa0 00000000 00000000 00000000 00000000 .* + 0ab0 00000000 00000000 00000000 ff93e20d .* + 0ac0 ff93de0d ff93da0d ff93d60d ff93d20d .* + 0ad0 ff93ce0d ff93ca0d ff93c60d ff93c20d .* + 0ae0 ff93bf0d 0090460e 0090420e 00903e0e .* + 0af0 00903a0e 0090360e 0090320e 00902e0e .* + 0b00 00902a0e 0090260e 0090230e 00000000 .* + 0b10 00000000 00000000 00000000 00000000 .* + 0b20 00000000 00000000 00000000 00000000 .* + 0b30 00000000 00000000 00000000 00000000 .* + 0b40 00000000 00000000 00000000 00000000 .* + 0b50 00000000 00000000 00000000 00000000 .* + 0b60 00000000 00000000 00000000 00000000 .* + 0b70 00000000 00000000 00000000 00000000 .* + 0b80 00000000 00000000 00000000 00000000 .* + 0b90 00000000 00000000 00000000 00000000 .* + 0ba0 00000000 00000000 00000000 00000000 .* + 0bb0 00000000 00000000 00000000 00000000 .* + 0bc0 00000000 00000000 00000000 00000000 .* + 0bd0 00000000 00000000 00000000 00000000 .* + 0be0 00000000 00000000 00000000 00000000 .* + 0bf0 00000000 00000000 00000000 00000000 .* + 0c00 00000000 00000000 00000000 00000000 .* + 0c10 00000000 00000000 00000000 00000000 .* + 0c20 00000000 00000000 00000000 00000000 .* + 0c30 00000000 00000000 00000000 00000000 .* + 0c40 00000000 00000000 00000000 00000000 .* + 0c50 00000000 00000000 00000000 00000000 .* + 0c60 00000000 00000000 00000000 00000000 .* + 0c70 00000000 00000000 00000000 00000000 .* + 0c80 00000000 00000000 00000000 00000000 .* + 0c90 00000000 00000000 00000000 00000000 .* + 0ca0 00000000 00000000 00000000 00000000 .* + 0cb0 00000000 00000000 00000000 00000000 .* + 0cc0 00000000 00000000 00000000 00000000 .* + 0cd0 00000000 00000000 00000000 00000000 .* + 0ce0 00000000 00000000 00000000 00000000 .* + 0cf0 00000000 00000000 00000000 00000000 .* + 0d00 00000000 00000000 00000000 0f360e36 .* + 0d10 0d360c36 0090160c 0090120c 07360090 .* + 0d20 0c0c0090 080c0090 050c0000 00000000 .* + 0d30 00000000 00000000 00000000 00000000 .* + 0d40 00000000 00000000 00000000 00000000 .* + 0d50 00000000 00000000 00000000 00000000 .* + 0d60 00000000 00000000 00000000 00000000 .* + 0d70 00000000 00000000 00000000 00000000 .* + 0d80 00000000 00000000 00000000 00000000 .* + 0d90 00000000 00000000 00000000 00000000 .* + 0da0 00000000 00000000 00000000 00000000 .* + 0db0 00000000 00000000 00000000 00000000 .* + 0dc0 00000000 00000000 00000000 00000000 .* + 0dd0 00000000 00000000 00000000 00000000 .* + 0de0 00000000 00000000 00000000 00000000 .* + 0df0 00000000 00000000 00000000 00000000 .* + 0e00 00000000 00000000 00000000 00000000 .* + 0e10 00000000 00000000 00000000 00000000 .* + 0e20 00000000 00000000 00000000 00000000 .* + 0e30 00000000 00000000 00000000 00000000 .* + 0e40 00000000 00000000 00000000 00000000 .* + 0e50 00000000 00000000 00000000 00000000 .* + 0e60 00000000 00000000 00000000 00000000 .* + 0e70 00000000 00000000 00000000 00000000 .* + 0e80 00000000 00000000 00000000 00000000 .* + 0e90 00000000 00000000 00000000 00000000 .* + 0ea0 00000000 00000000 00000000 00000000 .* + 0eb0 00000000 00000000 00000000 00000000 .* + 0ec0 00000000 00000000 00000000 00000000 .* + 0ed0 00000000 00000000 00000000 00000000 .* + 0ee0 00000000 00000000 00000000 00000000 .* + 0ef0 00000000 00000000 00000000 00000000 .* + 0f00 00000000 00000000 00000000 00000000 .* + 0f10 00000000 00000000 00000000 00000000 .* + 0f20 00000000 00000000 00000000 0037ff93 .* + 0f30 fe0d0090 060e0090 020e0000 00000000 .* + 0f40 00000000 00000000 00000000 00000000 .* + 0f50 00000000 00000000 00000000 00000000 .* + 0f60 00000000 00000000 00000000 00000000 .* + 0f70 00000000 00000000 00000000 00000000 .* + 0f80 00000000 00000000 00000000 00000000 .* + 0f90 00000000 00000000 00000000 00000000 .* + 0fa0 00000000 00000000 00000000 00000000 .* + 0fb0 00000000 00000000 00000000 00000000 .* + 0fc0 00000000 00000000 00000000 00000000 .* + 0fd0 00000000 00000000 00000000 00000000 .* + 0fe0 00000000 00000000 00000000 00000000 .* + 0ff0 00000000 00000000 00000000 00000000 .* + 1000 00000000 00000000 00000000 00000000 .* + 1010 00000000 00000000 00000000 00000000 .* + 1020 00000000 00000000 00000000 00000000 .* + 1030 00000000 00000000 00000000 00000000 .* + 1040 00000000 00000000 00000000 00000000 .* + 1050 00000000 00000000 00000000 00000000 .* + 1060 00000000 00000000 00000000 00000000 .* + 1070 00000000 00000000 00000000 00000000 .* + 1080 00000000 00000000 00000000 00000000 .* + 1090 00000000 00000000 00000000 00000000 .* + 10a0 00000000 00000000 00000000 00000000 .* + 10b0 00000000 00000000 00000000 00000000 .* + 10c0 00000000 00000000 00000000 00000000 .* + 10d0 00000000 00000000 00000000 00000000 .* + 10e0 00000000 00000000 00000000 00000000 .* + 10f0 00000000 00000000 00000000 00000000 .* + 1100 00000000 00000000 00000000 00000000 .* + 1110 00000000 00000000 00000000 00000000 .* + 1120 00000000 00000000 00000000 00000000 .* + 1130 00000000 00000000 00000000 0038ff39 .* + 1140 fe39fd39 ff93f813 ff93f413 f839ff93 .* + 1150 ee13ff93 ea13ff93 e7130000 00000000 .* + 1160 00000000 00000000 00000000 00000000 .* + 1170 00000000 00000000 00000000 00000000 .* + 1180 00000000 00000000 00000000 00000000 .* + 1190 00000000 00000000 00000000 00000000 .* + 11a0 00000000 00000000 00000000 00000000 .* + 11b0 00000000 00000000 00000000 00000000 .* + 11c0 00000000 00000000 00000000 00000000 .* + 11d0 00000000 00000000 00000000 00000000 .* + 11e0 00000000 00000000 00000000 00000000 .* + 11f0 00000000 00000000 00000000 00000000 .* + 1200 00000000 00000000 00000000 00000000 .* + 1210 00000000 00000000 00000000 00000000 .* + 1220 00000000 00000000 00000000 00000000 .* + 1230 00000000 00000000 00000000 00000000 .* + 1240 00000000 00000000 00000000 00000000 .* + 1250 00000000 00000000 00000000 00000000 .* + 1260 00000000 00000000 00000000 00000000 .* + 1270 00000000 00000000 00000000 00000000 .* + 1280 00000000 00000000 00000000 00000000 .* + 1290 00000000 00000000 00000000 00000000 .* + 12a0 00000000 00000000 00000000 00000000 .* + 12b0 00000000 00000000 00000000 00000000 .* + 12c0 00000000 00000000 00000000 00000000 .* + 12d0 00000000 00000000 00000000 00000000 .* + 12e0 00000000 00000000 00000000 00000000 .* + 12f0 00000000 00000000 00000000 00000000 .* + 1300 00000000 00000000 00000000 00000000 .* + 1310 00000000 00000000 00000000 00000000 .* + 1320 00000000 00000000 00000000 00000000 .* + 1330 00000000 00000000 00000000 00000000 .* + 1340 00000000 00000000 00000000 00000000 .* + 1350 00000000 00000000 0000ff93 e211ff93 .* + 1360 de11ff93 da11ff93 d611ff93 d211ff93 .* + 1370 ce11ff93 ca11ff93 c611ff93 c211ff93 .* + 1380 bf110090 46120090 42120090 3e120090 .* + 1390 3a120090 36120090 32120090 2e120090 .* + 13a0 2a120090 26120090 23120000 00000000 .* + 13b0 00000000 00000000 00000000 00000000 .* + 13c0 00000000 00000000 00000000 00000000 .* + 13d0 00000000 00000000 00000000 00000000 .* + 13e0 00000000 00000000 00000000 00000000 .* + 13f0 00000000 00000000 00000000 00000000 .* + 1400 00000000 00000000 00000000 00000000 .* + 1410 00000000 00000000 00000000 00000000 .* + 1420 00000000 00000000 00000000 00000000 .* + 1430 00000000 00000000 00000000 00000000 .* + 1440 00000000 00000000 00000000 00000000 .* + 1450 00000000 00000000 00000000 00000000 .* + 1460 00000000 00000000 00000000 00000000 .* + 1470 00000000 00000000 00000000 00000000 .* + 1480 00000000 00000000 00000000 00000000 .* + 1490 00000000 00000000 00000000 00000000 .* + 14a0 00000000 00000000 00000000 00000000 .* + 14b0 00000000 00000000 00000000 00000000 .* + 14c0 00000000 00000000 00000000 00000000 .* + 14d0 00000000 00000000 00000000 00000000 .* + 14e0 00000000 00000000 00000000 00000000 .* + 14f0 00000000 00000000 00000000 00000000 .* + 1500 00000000 00000000 00000000 00000000 .* + 1510 00000000 00000000 00000000 00000000 .* + 1520 00000000 00000000 00000000 00000000 .* + 1530 00000000 00000000 00000000 00000000 .* + 1540 00000000 00000000 00000000 00000000 .* + 1550 00000000 00000000 00000000 00000000 .* + 1560 00000000 00000000 00000000 00000000 .* + 1570 00000000 00000000 00000000 00000000 .* + 1580 00000000 00000000 00000000 00000000 .* + 1590 00000000 00000000 00000000 00000000 .* + 15a0 00000000 00000000 00000f38 0e380d38 .* + 15b0 0c380090 16100090 12100738 00900c10 .* + 15c0 00900810 00900510 00000000 00000000 .* + 15d0 00000000 00000000 00000000 00000000 .* + 15e0 00000000 00000000 00000000 00000000 .* + 15f0 00000000 00000000 00000000 00000000 .* + 1600 00000000 00000000 00000000 00000000 .* + 1610 00000000 00000000 00000000 00000000 .* + 1620 00000000 00000000 00000000 00000000 .* + 1630 00000000 00000000 00000000 00000000 .* + 1640 00000000 00000000 00000000 00000000 .* + 1650 00000000 00000000 00000000 00000000 .* + 1660 00000000 00000000 00000000 00000000 .* + 1670 00000000 00000000 00000000 00000000 .* + 1680 00000000 00000000 00000000 00000000 .* + 1690 00000000 00000000 00000000 00000000 .* + 16a0 00000000 00000000 00000000 00000000 .* + 16b0 00000000 00000000 00000000 00000000 .* + 16c0 00000000 00000000 00000000 00000000 .* + 16d0 00000000 00000000 00000000 00000000 .* + 16e0 00000000 00000000 00000000 00000000 .* + 16f0 00000000 00000000 00000000 00000000 .* + 1700 00000000 00000000 00000000 00000000 .* + 1710 00000000 00000000 00000000 00000000 .* + 1720 00000000 00000000 00000000 00000000 .* + 1730 00000000 00000000 00000000 00000000 .* + 1740 00000000 00000000 00000000 00000000 .* + 1750 00000000 00000000 00000000 00000000 .* + 1760 00000000 00000000 00000000 00000000 .* + 1770 00000000 00000000 00000000 00000000 .* + 1780 00000000 00000000 00000000 00000000 .* + 1790 00000000 00000000 00000000 00000000 .* + 17a0 00000000 00000000 00000000 00000000 .* + 17b0 00000000 00000000 00000000 00000000 .* + 17c0 00000000 00000000 00000039 ff93fe11 .* + 17d0 00900612 00900212 00000000 00000000 .* + 17e0 00000000 00000000 00000000 00000000 .* + 17f0 00000000 00000000 00000000 00000000 .* + 1800 00000000 00000000 00000000 00000000 .* + 1810 00000000 00000000 00000000 00000000 .* + 1820 00000000 00000000 00000000 00000000 .* + 1830 00000000 00000000 00000000 00000000 .* + 1840 00000000 00000000 00000000 00000000 .* + 1850 00000000 00000000 00000000 00000000 .* + 1860 00000000 00000000 00000000 00000000 .* + 1870 00000000 00000000 00000000 00000000 .* + 1880 00000000 00000000 00000000 00000000 .* + 1890 00000000 00000000 00000000 00000000 .* + 18a0 00000000 00000000 00000000 00000000 .* + 18b0 00000000 00000000 00000000 00000000 .* + 18c0 00000000 00000000 00000000 00000000 .* + 18d0 00000000 00000000 00000000 00000000 .* + 18e0 00000000 00000000 00000000 00000000 .* + 18f0 00000000 00000000 00000000 00000000 .* + 1900 00000000 00000000 00000000 00000000 .* + 1910 00000000 00000000 00000000 00000000 .* + 1920 00000000 00000000 00000000 00000000 .* + 1930 00000000 00000000 00000000 00000000 .* + 1940 00000000 00000000 00000000 00000000 .* + 1950 00000000 00000000 00000000 00000000 .* + 1960 00000000 00000000 00000000 00000000 .* + 1970 00000000 00000000 00000000 00000000 .* + 1980 00000000 00000000 00000000 00000000 .* + 1990 00000000 00000000 00000000 00000000 .* + 19a0 00000000 00000000 00000000 00000000 .* + 19b0 00000000 00000000 00000000 00000000 .* + 19c0 00000000 00000000 00000000 00000000 .* + 19d0 00000000 00000000 0000003a ff3bfe3b .* + 19e0 fd3bff93 f817ff93 f417f83b ff93ee17 .* + 19f0 ff93ea17 ff93e717 00000000 00000000 .* + 1a00 00000000 00000000 00000000 00000000 .* + 1a10 00000000 00000000 00000000 00000000 .* + 1a20 00000000 00000000 00000000 00000000 .* + 1a30 00000000 00000000 00000000 00000000 .* + 1a40 00000000 00000000 00000000 00000000 .* + 1a50 00000000 00000000 00000000 00000000 .* + 1a60 00000000 00000000 00000000 00000000 .* + 1a70 00000000 00000000 00000000 00000000 .* + 1a80 00000000 00000000 00000000 00000000 .* + 1a90 00000000 00000000 00000000 00000000 .* + 1aa0 00000000 00000000 00000000 00000000 .* + 1ab0 00000000 00000000 00000000 00000000 .* + 1ac0 00000000 00000000 00000000 00000000 .* + 1ad0 00000000 00000000 00000000 00000000 .* + 1ae0 00000000 00000000 00000000 00000000 .* + 1af0 00000000 00000000 00000000 00000000 .* + 1b00 00000000 00000000 00000000 00000000 .* + 1b10 00000000 00000000 00000000 00000000 .* + 1b20 00000000 00000000 00000000 00000000 .* + 1b30 00000000 00000000 00000000 00000000 .* + 1b40 00000000 00000000 00000000 00000000 .* + 1b50 00000000 00000000 00000000 00000000 .* + 1b60 00000000 00000000 00000000 00000000 .* + 1b70 00000000 00000000 00000000 00000000 .* + 1b80 00000000 00000000 00000000 00000000 .* + 1b90 00000000 00000000 00000000 00000000 .* + 1ba0 00000000 00000000 00000000 00000000 .* + 1bb0 00000000 00000000 00000000 00000000 .* + 1bc0 00000000 00000000 00000000 00000000 .* + 1bd0 00000000 00000000 00000000 00000000 .* + 1be0 00000000 00000000 00000000 00000000 .* + 1bf0 00000000 00000000 ff93e215 ff93de15 .* + 1c00 ff93da15 ff93d615 ff93d215 ff93ce15 .* + 1c10 ff93ca15 ff93c615 ff93c215 ff93bf15 .* + 1c20 00904616 00904216 00903e16 00903a16 .* + 1c30 00903616 00903216 00902e16 00902a16 .* + 1c40 00902616 00902316 00000000 00000000 .* + 1c50 00000000 00000000 00000000 00000000 .* + 1c60 00000000 00000000 00000000 00000000 .* + 1c70 00000000 00000000 00000000 00000000 .* + 1c80 00000000 00000000 00000000 00000000 .* + 1c90 00000000 00000000 00000000 00000000 .* + 1ca0 00000000 00000000 00000000 00000000 .* + 1cb0 00000000 00000000 00000000 00000000 .* + 1cc0 00000000 00000000 00000000 00000000 .* + 1cd0 00000000 00000000 00000000 00000000 .* + 1ce0 00000000 00000000 00000000 00000000 .* + 1cf0 00000000 00000000 00000000 00000000 .* + 1d00 00000000 00000000 00000000 00000000 .* + 1d10 00000000 00000000 00000000 00000000 .* + 1d20 00000000 00000000 00000000 00000000 .* + 1d30 00000000 00000000 00000000 00000000 .* + 1d40 00000000 00000000 00000000 00000000 .* + 1d50 00000000 00000000 00000000 00000000 .* + 1d60 00000000 00000000 00000000 00000000 .* + 1d70 00000000 00000000 00000000 00000000 .* + 1d80 00000000 00000000 00000000 00000000 .* + 1d90 00000000 00000000 00000000 00000000 .* + 1da0 00000000 00000000 00000000 00000000 .* + 1db0 00000000 00000000 00000000 00000000 .* + 1dc0 00000000 00000000 00000000 00000000 .* + 1dd0 00000000 00000000 00000000 00000000 .* + 1de0 00000000 00000000 00000000 00000000 .* + 1df0 00000000 00000000 00000000 00000000 .* + 1e00 00000000 00000000 00000000 00000000 .* + 1e10 00000000 00000000 00000000 00000000 .* + 1e20 00000000 00000000 00000000 00000000 .* + 1e30 00000000 00000000 00000000 00000000 .* + 1e40 00000000 00000000 0f3a0e3a 0d3a0c3a .* + 1e50 00901614 00901214 073a0090 0c140090 .* + 1e60 08140090 05140000 00000000 00000000 .* + 1e70 00000000 00000000 00000000 00000000 .* + 1e80 00000000 00000000 00000000 00000000 .* + 1e90 00000000 00000000 00000000 00000000 .* + 1ea0 00000000 00000000 00000000 00000000 .* + 1eb0 00000000 00000000 00000000 00000000 .* + 1ec0 00000000 00000000 00000000 00000000 .* + 1ed0 00000000 00000000 00000000 00000000 .* + 1ee0 00000000 00000000 00000000 00000000 .* + 1ef0 00000000 00000000 00000000 00000000 .* + 1f00 00000000 00000000 00000000 00000000 .* + 1f10 00000000 00000000 00000000 00000000 .* + 1f20 00000000 00000000 00000000 00000000 .* + 1f30 00000000 00000000 00000000 00000000 .* + 1f40 00000000 00000000 00000000 00000000 .* + 1f50 00000000 00000000 00000000 00000000 .* + 1f60 00000000 00000000 00000000 00000000 .* + 1f70 00000000 00000000 00000000 00000000 .* + 1f80 00000000 00000000 00000000 00000000 .* + 1f90 00000000 00000000 00000000 00000000 .* + 1fa0 00000000 00000000 00000000 00000000 .* + 1fb0 00000000 00000000 00000000 00000000 .* + 1fc0 00000000 00000000 00000000 00000000 .* + 1fd0 00000000 00000000 00000000 00000000 .* + 1fe0 00000000 00000000 00000000 00000000 .* + 1ff0 00000000 00000000 00000000 00000000 .* + 2000 00000000 00000000 00000000 00000000 .* + 2010 00000000 00000000 00000000 00000000 .* + 2020 00000000 00000000 00000000 00000000 .* + 2030 00000000 00000000 00000000 00000000 .* + 2040 00000000 00000000 00000000 00000000 .* + 2050 00000000 00000000 00000000 00000000 .* + 2060 00000000 00000000 003bff93 fe150090 .* + 2070 06160090 02160000 00000000 00000000 .* + 2080 00000000 00000000 00000000 00000000 .* + 2090 00000000 00000000 00000000 00000000 .* + 20a0 00000000 00000000 00000000 00000000 .* + 20b0 00000000 00000000 00000000 00000000 .* + 20c0 00000000 00000000 00000000 00000000 .* + 20d0 00000000 00000000 00000000 00000000 .* + 20e0 00000000 00000000 00000000 00000000 .* + 20f0 00000000 00000000 00000000 00000000 .* + 2100 00000000 00000000 00000000 00000000 .* + 2110 00000000 00000000 00000000 00000000 .* + 2120 00000000 00000000 00000000 00000000 .* + 2130 00000000 00000000 00000000 00000000 .* + 2140 00000000 00000000 00000000 00000000 .* + 2150 00000000 00000000 00000000 00000000 .* + 2160 00000000 00000000 00000000 00000000 .* + 2170 00000000 00000000 00000000 00000000 .* + 2180 00000000 00000000 00000000 00000000 .* + 2190 00000000 00000000 00000000 00000000 .* + 21a0 00000000 00000000 00000000 00000000 .* + 21b0 00000000 00000000 00000000 00000000 .* + 21c0 00000000 00000000 00000000 00000000 .* + 21d0 00000000 00000000 00000000 00000000 .* + 21e0 00000000 00000000 00000000 00000000 .* + 21f0 00000000 00000000 00000000 00000000 .* + 2200 00000000 00000000 00000000 00000000 .* + 2210 00000000 00000000 00000000 00000000 .* + 2220 00000000 00000000 00000000 00000000 .* + 2230 00000000 00000000 00000000 00000000 .* + 2240 00000000 00000000 00000000 00000000 .* + 2250 00000000 00000000 00000000 00000000 .* + 2260 00000000 00000000 00000000 00000000 .* + 2270 00000000 00000000 003cff3d fe3dfd3d .* + 2280 ff93f81b ff93f41b f83dff93 ee1bff93 .* + 2290 ea1bff93 e71b0000 00000000 00000000 .* + 22a0 00000000 00000000 00000000 00000000 .* + 22b0 00000000 00000000 00000000 00000000 .* + 22c0 00000000 00000000 00000000 00000000 .* + 22d0 00000000 00000000 00000000 00000000 .* + 22e0 00000000 00000000 00000000 00000000 .* + 22f0 00000000 00000000 00000000 00000000 .* + 2300 00000000 00000000 00000000 00000000 .* + 2310 00000000 00000000 00000000 00000000 .* + 2320 00000000 00000000 00000000 00000000 .* + 2330 00000000 00000000 00000000 00000000 .* + 2340 00000000 00000000 00000000 00000000 .* + 2350 00000000 00000000 00000000 00000000 .* + 2360 00000000 00000000 00000000 00000000 .* + 2370 00000000 00000000 00000000 00000000 .* + 2380 00000000 00000000 00000000 00000000 .* + 2390 00000000 00000000 00000000 00000000 .* + 23a0 00000000 00000000 00000000 00000000 .* + 23b0 00000000 00000000 00000000 00000000 .* + 23c0 00000000 00000000 00000000 00000000 .* + 23d0 00000000 00000000 00000000 00000000 .* + 23e0 00000000 00000000 00000000 00000000 .* + 23f0 00000000 00000000 00000000 00000000 .* + 2400 00000000 00000000 00000000 00000000 .* + 2410 00000000 00000000 00000000 00000000 .* + 2420 00000000 00000000 00000000 00000000 .* + 2430 00000000 00000000 00000000 00000000 .* + 2440 00000000 00000000 00000000 00000000 .* + 2450 00000000 00000000 00000000 00000000 .* + 2460 00000000 00000000 00000000 00000000 .* + 2470 00000000 00000000 00000000 00000000 .* + 2480 00000000 00000000 00000000 00000000 .* + 2490 00000000 0000ff93 e219ff93 de19ff93 .* + 24a0 da19ff93 d619ff93 d219ff93 ce19ff93 .* + 24b0 ca19ff93 c619ff93 c219ff93 bf190090 .* + 24c0 461a0090 421a0090 3e1a0090 3a1a0090 .* + 24d0 361a0090 321a0090 2e1a0090 2a1a0090 .* + 24e0 261a0090 231a0000 00000000 00000000 .* + 24f0 00000000 00000000 00000000 00000000 .* + 2500 00000000 00000000 00000000 00000000 .* + 2510 00000000 00000000 00000000 00000000 .* + 2520 00000000 00000000 00000000 00000000 .* + 2530 00000000 00000000 00000000 00000000 .* + 2540 00000000 00000000 00000000 00000000 .* + 2550 00000000 00000000 00000000 00000000 .* + 2560 00000000 00000000 00000000 00000000 .* + 2570 00000000 00000000 00000000 00000000 .* + 2580 00000000 00000000 00000000 00000000 .* + 2590 00000000 00000000 00000000 00000000 .* + 25a0 00000000 00000000 00000000 00000000 .* + 25b0 00000000 00000000 00000000 00000000 .* + 25c0 00000000 00000000 00000000 00000000 .* + 25d0 00000000 00000000 00000000 00000000 .* + 25e0 00000000 00000000 00000000 00000000 .* + 25f0 00000000 00000000 00000000 00000000 .* + 2600 00000000 00000000 00000000 00000000 .* + 2610 00000000 00000000 00000000 00000000 .* + 2620 00000000 00000000 00000000 00000000 .* + 2630 00000000 00000000 00000000 00000000 .* + 2640 00000000 00000000 00000000 00000000 .* + 2650 00000000 00000000 00000000 00000000 .* + 2660 00000000 00000000 00000000 00000000 .* + 2670 00000000 00000000 00000000 00000000 .* + 2680 00000000 00000000 00000000 00000000 .* + 2690 00000000 00000000 00000000 00000000 .* + 26a0 00000000 00000000 00000000 00000000 .* + 26b0 00000000 00000000 00000000 00000000 .* + 26c0 00000000 00000000 00000000 00000000 .* + 26d0 00000000 00000000 00000000 00000000 .* + 26e0 00000000 00000f3c 0e3c0d3c 0c3c0090 .* + 26f0 16180090 1218073c 00900c18 00900818 .* + 2700 00900518 00000000 00000000 00000000 .* + 2710 00000000 00000000 00000000 00000000 .* + 2720 00000000 00000000 00000000 00000000 .* + 2730 00000000 00000000 00000000 00000000 .* + 2740 00000000 00000000 00000000 00000000 .* + 2750 00000000 00000000 00000000 00000000 .* + 2760 00000000 00000000 00000000 00000000 .* + 2770 00000000 00000000 00000000 00000000 .* + 2780 00000000 00000000 00000000 00000000 .* + 2790 00000000 00000000 00000000 00000000 .* + 27a0 00000000 00000000 00000000 00000000 .* + 27b0 00000000 00000000 00000000 00000000 .* + 27c0 00000000 00000000 00000000 00000000 .* + 27d0 00000000 00000000 00000000 00000000 .* + 27e0 00000000 00000000 00000000 00000000 .* + 27f0 00000000 00000000 00000000 00000000 .* + 2800 00000000 00000000 00000000 00000000 .* + 2810 00000000 00000000 00000000 00000000 .* + 2820 00000000 00000000 00000000 00000000 .* + 2830 00000000 00000000 00000000 00000000 .* + 2840 00000000 00000000 00000000 00000000 .* + 2850 00000000 00000000 00000000 00000000 .* + 2860 00000000 00000000 00000000 00000000 .* + 2870 00000000 00000000 00000000 00000000 .* + 2880 00000000 00000000 00000000 00000000 .* + 2890 00000000 00000000 00000000 00000000 .* + 28a0 00000000 00000000 00000000 00000000 .* + 28b0 00000000 00000000 00000000 00000000 .* + 28c0 00000000 00000000 00000000 00000000 .* + 28d0 00000000 00000000 00000000 00000000 .* + 28e0 00000000 00000000 00000000 00000000 .* + 28f0 00000000 00000000 00000000 00000000 .* + 2900 00000000 0000003d ff93fe19 0090061a .* + 2910 0090021a 00000000 00000000 00000000 .* + 2920 00000000 00000000 00000000 00000000 .* + 2930 00000000 00000000 00000000 00000000 .* + 2940 00000000 00000000 00000000 00000000 .* + 2950 00000000 00000000 00000000 00000000 .* + 2960 00000000 00000000 00000000 00000000 .* + 2970 00000000 00000000 00000000 00000000 .* + 2980 00000000 00000000 00000000 00000000 .* + 2990 00000000 00000000 00000000 00000000 .* + 29a0 00000000 00000000 00000000 00000000 .* + 29b0 00000000 00000000 00000000 00000000 .* + 29c0 00000000 00000000 00000000 00000000 .* + 29d0 00000000 00000000 00000000 00000000 .* + 29e0 00000000 00000000 00000000 00000000 .* + 29f0 00000000 00000000 00000000 00000000 .* + 2a00 00000000 00000000 00000000 00000000 .* + 2a10 00000000 00000000 00000000 00000000 .* + 2a20 00000000 00000000 00000000 00000000 .* + 2a30 00000000 00000000 00000000 00000000 .* + 2a40 00000000 00000000 00000000 00000000 .* + 2a50 00000000 00000000 00000000 00000000 .* + 2a60 00000000 00000000 00000000 00000000 .* + 2a70 00000000 00000000 00000000 00000000 .* + 2a80 00000000 00000000 00000000 00000000 .* + 2a90 00000000 00000000 00000000 00000000 .* + 2aa0 00000000 00000000 00000000 00000000 .* + 2ab0 00000000 00000000 00000000 00000000 .* + 2ac0 00000000 00000000 00000000 00000000 .* + 2ad0 00000000 00000000 00000000 00000000 .* + 2ae0 00000000 00000000 00000000 00000000 .* + 2af0 00000000 00000000 00000000 00000000 .* + 2b00 00000000 00000000 00000000 00000000 .* + 2b10 00000000 0000003e ff3ffe3f fd3fff93 .* + 2b20 f81fff93 f41ff83f ff93ee1f ff93ea1f .* + 2b30 ff93e71f 00000000 00000000 00000000 .* + 2b40 00000000 00000000 00000000 00000000 .* + 2b50 00000000 00000000 00000000 00000000 .* + 2b60 00000000 00000000 00000000 00000000 .* + 2b70 00000000 00000000 00000000 00000000 .* + 2b80 00000000 00000000 00000000 00000000 .* + 2b90 00000000 00000000 00000000 00000000 .* + 2ba0 00000000 00000000 00000000 00000000 .* + 2bb0 00000000 00000000 00000000 00000000 .* + 2bc0 00000000 00000000 00000000 00000000 .* + 2bd0 00000000 00000000 00000000 00000000 .* + 2be0 00000000 00000000 00000000 00000000 .* + 2bf0 00000000 00000000 00000000 00000000 .* + 2c00 00000000 00000000 00000000 00000000 .* + 2c10 00000000 00000000 00000000 00000000 .* + 2c20 00000000 00000000 00000000 00000000 .* + 2c30 00000000 00000000 00000000 00000000 .* + 2c40 00000000 00000000 00000000 00000000 .* + 2c50 00000000 00000000 00000000 00000000 .* + 2c60 00000000 00000000 00000000 00000000 .* + 2c70 00000000 00000000 00000000 00000000 .* + 2c80 00000000 00000000 00000000 00000000 .* + 2c90 00000000 00000000 00000000 00000000 .* + 2ca0 00000000 00000000 00000000 00000000 .* + 2cb0 00000000 00000000 00000000 00000000 .* + 2cc0 00000000 00000000 00000000 00000000 .* + 2cd0 00000000 00000000 00000000 00000000 .* + 2ce0 00000000 00000000 00000000 00000000 .* + 2cf0 00000000 00000000 00000000 00000000 .* + 2d00 00000000 00000000 00000000 00000000 .* + 2d10 00000000 00000000 00000000 00000000 .* + 2d20 00000000 00000000 00000000 00000000 .* + 2d30 00000000 ff93e21d ff93de1d ff93da1d .* + 2d40 ff93d61d ff93d21d ff93ce1d ff93ca1d .* + 2d50 ff93c61d ff93c21d ff93bf1d 0090461e .* + 2d60 0090421e 00903e1e 00903a1e 0090361e .* + 2d70 0090321e 00902e1e 00902a1e 0090261e .* + 2d80 0090231e 00000000 00000000 00000000 .* + 2d90 00000000 00000000 00000000 00000000 .* + 2da0 00000000 00000000 00000000 00000000 .* + 2db0 00000000 00000000 00000000 00000000 .* + 2dc0 00000000 00000000 00000000 00000000 .* + 2dd0 00000000 00000000 00000000 00000000 .* + 2de0 00000000 00000000 00000000 00000000 .* + 2df0 00000000 00000000 00000000 00000000 .* + 2e00 00000000 00000000 00000000 00000000 .* + 2e10 00000000 00000000 00000000 00000000 .* + 2e20 00000000 00000000 00000000 00000000 .* + 2e30 00000000 00000000 00000000 00000000 .* + 2e40 00000000 00000000 00000000 00000000 .* + 2e50 00000000 00000000 00000000 00000000 .* + 2e60 00000000 00000000 00000000 00000000 .* + 2e70 00000000 00000000 00000000 00000000 .* + 2e80 00000000 00000000 00000000 00000000 .* + 2e90 00000000 00000000 00000000 00000000 .* + 2ea0 00000000 00000000 00000000 00000000 .* + 2eb0 00000000 00000000 00000000 00000000 .* + 2ec0 00000000 00000000 00000000 00000000 .* + 2ed0 00000000 00000000 00000000 00000000 .* + 2ee0 00000000 00000000 00000000 00000000 .* + 2ef0 00000000 00000000 00000000 00000000 .* + 2f00 00000000 00000000 00000000 00000000 .* + 2f10 00000000 00000000 00000000 00000000 .* + 2f20 00000000 00000000 00000000 00000000 .* + 2f30 00000000 00000000 00000000 00000000 .* + 2f40 00000000 00000000 00000000 00000000 .* + 2f50 00000000 00000000 00000000 00000000 .* + 2f60 00000000 00000000 00000000 00000000 .* + 2f70 00000000 00000000 00000000 00000000 .* + 2f80 00000000 0f3e0e3e 0d3e0c3e 0090161c .* + 2f90 0090121c 073e0090 0c1c0090 081c0090 .* + 2fa0 051c0000 00000000 00000000 00000000 .* + 2fb0 00000000 00000000 00000000 00000000 .* + 2fc0 00000000 00000000 00000000 00000000 .* + 2fd0 00000000 00000000 00000000 00000000 .* + 2fe0 00000000 00000000 00000000 00000000 .* + 2ff0 00000000 00000000 00000000 00000000 .* + 3000 00000000 00000000 00000000 00000000 .* + 3010 00000000 00000000 00000000 00000000 .* + 3020 00000000 00000000 00000000 00000000 .* + 3030 00000000 00000000 00000000 00000000 .* + 3040 00000000 00000000 00000000 00000000 .* + 3050 00000000 00000000 00000000 00000000 .* + 3060 00000000 00000000 00000000 00000000 .* + 3070 00000000 00000000 00000000 00000000 .* + 3080 00000000 00000000 00000000 00000000 .* + 3090 00000000 00000000 00000000 00000000 .* + 30a0 00000000 00000000 00000000 00000000 .* + 30b0 00000000 00000000 00000000 00000000 .* + 30c0 00000000 00000000 00000000 00000000 .* + 30d0 00000000 00000000 00000000 00000000 .* + 30e0 00000000 00000000 00000000 00000000 .* + 30f0 00000000 00000000 00000000 00000000 .* + 3100 00000000 00000000 00000000 00000000 .* + 3110 00000000 00000000 00000000 00000000 .* + 3120 00000000 00000000 00000000 00000000 .* + 3130 00000000 00000000 00000000 00000000 .* + 3140 00000000 00000000 00000000 00000000 .* + 3150 00000000 00000000 00000000 00000000 .* + 3160 00000000 00000000 00000000 00000000 .* + 3170 00000000 00000000 00000000 00000000 .* + 3180 00000000 00000000 00000000 00000000 .* + 3190 00000000 00000000 00000000 00000000 .* + 31a0 00000000 003fff93 fe1d0090 061e0090 .* + 31b0 021e0000 00000000 00000000 00000000 .* + 31c0 00000000 00000000 00000000 00000000 .* + 31d0 00000000 00000000 00000000 00000000 .* + 31e0 00000000 00000000 00000000 00000000 .* + 31f0 00000000 00000000 00000000 00000000 .* + 3200 00000000 00000000 00000000 00000000 .* + 3210 00000000 00000000 00000000 00000000 .* + 3220 00000000 00000000 00000000 00000000 .* + 3230 00000000 00000000 00000000 00000000 .* + 3240 00000000 00000000 00000000 00000000 .* + 3250 00000000 00000000 00000000 00000000 .* + 3260 00000000 00000000 00000000 00000000 .* + 3270 00000000 00000000 00000000 00000000 .* + 3280 00000000 00000000 00000000 00000000 .* + 3290 00000000 00000000 00000000 00000000 .* + 32a0 00000000 00000000 00000000 00000000 .* + 32b0 00000000 00000000 00000000 00000000 .* + 32c0 00000000 00000000 00000000 00000000 .* + 32d0 00000000 00000000 00000000 00000000 .* + 32e0 00000000 00000000 00000000 00000000 .* + 32f0 00000000 00000000 00000000 00000000 .* + 3300 00000000 00000000 00000000 00000000 .* + 3310 00000000 00000000 00000000 00000000 .* + 3320 00000000 00000000 00000000 00000000 .* + 3330 00000000 00000000 00000000 00000000 .* + 3340 00000000 00000000 00000000 00000000 .* + 3350 00000000 00000000 00000000 00000000 .* + 3360 00000000 00000000 00000000 00000000 .* + 3370 00000000 00000000 00000000 00000000 .* + 3380 00000000 00000000 00000000 00000000 .* + 3390 00000000 00000000 00000000 00000000 .* + 33a0 00000000 00000000 00000000 00000000 .* + 33b0 00000000 0032ff33 fe33fd33 ff93f83b .* + 33c0 ff93f43b f833ff93 ee3bff93 ea3bff93 .* + 33d0 e73b0000 00000000 00000000 00000000 .* + 33e0 00000000 00000000 00000000 00000000 .* + 33f0 00000000 00000000 00000000 00000000 .* + 3400 00000000 00000000 00000000 00000000 .* + 3410 00000000 00000000 00000000 00000000 .* + 3420 00000000 00000000 00000000 00000000 .* + 3430 00000000 00000000 00000000 00000000 .* + 3440 00000000 00000000 00000000 00000000 .* + 3450 00000000 00000000 00000000 00000000 .* + 3460 00000000 00000000 00000000 00000000 .* + 3470 00000000 00000000 00000000 00000000 .* + 3480 00000000 00000000 00000000 00000000 .* + 3490 00000000 00000000 00000000 00000000 .* + 34a0 00000000 00000000 00000000 00000000 .* + 34b0 00000000 00000000 00000000 00000000 .* + 34c0 00000000 00000000 00000000 00000000 .* + 34d0 00000000 00000000 00000000 00000000 .* + 34e0 00000000 00000000 00000000 00000000 .* + 34f0 00000000 00000000 00000000 00000000 .* + 3500 00000000 00000000 00000000 00000000 .* + 3510 00000000 00000000 00000000 00000000 .* + 3520 00000000 00000000 00000000 00000000 .* + 3530 00000000 00000000 00000000 00000000 .* + 3540 00000000 00000000 00000000 00000000 .* + 3550 00000000 00000000 00000000 00000000 .* + 3560 00000000 00000000 00000000 00000000 .* + 3570 00000000 00000000 00000000 00000000 .* + 3580 00000000 00000000 00000000 00000000 .* + 3590 00000000 00000000 00000000 00000000 .* + 35a0 00000000 00000000 00000000 00000000 .* + 35b0 00000000 00000000 00000000 00000000 .* + 35c0 00000000 00000000 00000000 00000000 .* + 35d0 0000ff93 e239ff93 de39ff93 da39ff93 .* + 35e0 d639ff93 d239ff93 ce39ff93 ca39ff93 .* + 35f0 c639ff93 c239ff93 bf390090 463a0090 .* + 3600 423a0090 3e3a0090 3a3a0090 363a0090 .* + 3610 323a0090 2e3a0090 2a3a0090 263a0090 .* + 3620 233a0000 00000000 00000000 00000000 .* + 3630 00000000 00000000 00000000 00000000 .* + 3640 00000000 00000000 00000000 00000000 .* + 3650 00000000 00000000 00000000 00000000 .* + 3660 00000000 00000000 00000000 00000000 .* + 3670 00000000 00000000 00000000 00000000 .* + 3680 00000000 00000000 00000000 00000000 .* + 3690 00000000 00000000 00000000 00000000 .* + 36a0 00000000 00000000 00000000 00000000 .* + 36b0 00000000 00000000 00000000 00000000 .* + 36c0 00000000 00000000 00000000 00000000 .* + 36d0 00000000 00000000 00000000 00000000 .* + 36e0 00000000 00000000 00000000 00000000 .* + 36f0 00000000 00000000 00000000 00000000 .* + 3700 00000000 00000000 00000000 00000000 .* + 3710 00000000 00000000 00000000 00000000 .* + 3720 00000000 00000000 00000000 00000000 .* + 3730 00000000 00000000 00000000 00000000 .* + 3740 00000000 00000000 00000000 00000000 .* + 3750 00000000 00000000 00000000 00000000 .* + 3760 00000000 00000000 00000000 00000000 .* + 3770 00000000 00000000 00000000 00000000 .* + 3780 00000000 00000000 00000000 00000000 .* + 3790 00000000 00000000 00000000 00000000 .* + 37a0 00000000 00000000 00000000 00000000 .* + 37b0 00000000 00000000 00000000 00000000 .* + 37c0 00000000 00000000 00000000 00000000 .* + 37d0 00000000 00000000 00000000 00000000 .* + 37e0 00000000 00000000 00000000 00000000 .* + 37f0 00000000 00000000 00000000 00000000 .* + 3800 00000000 00000000 00000000 00000000 .* + 3810 00000000 00000000 00000000 00000000 .* + 3820 00000f32 0e320d32 0c320090 16380090 .* + 3830 12380732 00900c38 00900838 00900538 .* + 3840 00000000 00000000 00000000 00000000 .* + 3850 00000000 00000000 00000000 00000000 .* + 3860 00000000 00000000 00000000 00000000 .* + 3870 00000000 00000000 00000000 00000000 .* + 3880 00000000 00000000 00000000 00000000 .* + 3890 00000000 00000000 00000000 00000000 .* + 38a0 00000000 00000000 00000000 00000000 .* + 38b0 00000000 00000000 00000000 00000000 .* + 38c0 00000000 00000000 00000000 00000000 .* + 38d0 00000000 00000000 00000000 00000000 .* + 38e0 00000000 00000000 00000000 00000000 .* + 38f0 00000000 00000000 00000000 00000000 .* + 3900 00000000 00000000 00000000 00000000 .* + 3910 00000000 00000000 00000000 00000000 .* + 3920 00000000 00000000 00000000 00000000 .* + 3930 00000000 00000000 00000000 00000000 .* + 3940 00000000 00000000 00000000 00000000 .* + 3950 00000000 00000000 00000000 00000000 .* + 3960 00000000 00000000 00000000 00000000 .* + 3970 00000000 00000000 00000000 00000000 .* + 3980 00000000 00000000 00000000 00000000 .* + 3990 00000000 00000000 00000000 00000000 .* + 39a0 00000000 00000000 00000000 00000000 .* + 39b0 00000000 00000000 00000000 00000000 .* + 39c0 00000000 00000000 00000000 00000000 .* + 39d0 00000000 00000000 00000000 00000000 .* + 39e0 00000000 00000000 00000000 00000000 .* + 39f0 00000000 00000000 00000000 00000000 .* + 3a00 00000000 00000000 00000000 00000000 .* + 3a10 00000000 00000000 00000000 00000000 .* + 3a20 00000000 00000000 00000000 00000000 .* + 3a30 00000000 00000000 00000000 00000000 .* + 3a40 00000033 ff93fe39 0090063a 0090023a .* + 3a50 00000000 00000000 00000000 00000000 .* + 3a60 00000000 00000000 00000000 00000000 .* + 3a70 00000000 00000000 00000000 00000000 .* + 3a80 00000000 00000000 00000000 00000000 .* + 3a90 00000000 00000000 00000000 00000000 .* + 3aa0 00000000 00000000 00000000 00000000 .* + 3ab0 00000000 00000000 00000000 00000000 .* + 3ac0 00000000 00000000 00000000 00000000 .* + 3ad0 00000000 00000000 00000000 00000000 .* + 3ae0 00000000 00000000 00000000 00000000 .* + 3af0 00000000 00000000 00000000 00000000 .* + 3b00 00000000 00000000 00000000 00000000 .* + 3b10 00000000 00000000 00000000 00000000 .* + 3b20 00000000 00000000 00000000 00000000 .* + 3b30 00000000 00000000 00000000 00000000 .* + 3b40 00000000 00000000 00000000 00000000 .* + 3b50 00000000 00000000 00000000 00000000 .* + 3b60 00000000 00000000 00000000 00000000 .* + 3b70 00000000 00000000 00000000 00000000 .* + 3b80 00000000 00000000 00000000 00000000 .* + 3b90 00000000 00000000 00000000 00000000 .* + 3ba0 00000000 00000000 00000000 00000000 .* + 3bb0 00000000 00000000 00000000 00000000 .* + 3bc0 00000000 00000000 00000000 00000000 .* + 3bd0 00000000 00000000 00000000 00000000 .* + 3be0 00000000 00000000 00000000 00000000 .* + 3bf0 00000000 00000000 00000000 00000000 .* + 3c00 00000000 00000000 00000000 00000000 .* + 3c10 00000000 00000000 00000000 00000000 .* + 3c20 00000000 00000000 00000000 00000000 .* + 3c30 00000000 00000000 00000000 00000000 .* + 3c40 00000000 00000000 00000000 00000000 .* + 3c50 00000030 ff31fe31 fd31ff93 f83fff93 .* + 3c60 f43ff831 ff93ee3f ff93ea3f ff93e73f .* + 3c70 00000000 00000000 00000000 00000000 .* + 3c80 00000000 00000000 00000000 00000000 .* + 3c90 00000000 00000000 00000000 00000000 .* + 3ca0 00000000 00000000 00000000 00000000 .* + 3cb0 00000000 00000000 00000000 00000000 .* + 3cc0 00000000 00000000 00000000 00000000 .* + 3cd0 00000000 00000000 00000000 00000000 .* + 3ce0 00000000 00000000 00000000 00000000 .* + 3cf0 00000000 00000000 00000000 00000000 .* + 3d00 00000000 00000000 00000000 00000000 .* + 3d10 00000000 00000000 00000000 00000000 .* + 3d20 00000000 00000000 00000000 00000000 .* + 3d30 00000000 00000000 00000000 00000000 .* + 3d40 00000000 00000000 00000000 00000000 .* + 3d50 00000000 00000000 00000000 00000000 .* + 3d60 00000000 00000000 00000000 00000000 .* + 3d70 00000000 00000000 00000000 00000000 .* + 3d80 00000000 00000000 00000000 00000000 .* + 3d90 00000000 00000000 00000000 00000000 .* + 3da0 00000000 00000000 00000000 00000000 .* + 3db0 00000000 00000000 00000000 00000000 .* + 3dc0 00000000 00000000 00000000 00000000 .* + 3dd0 00000000 00000000 00000000 00000000 .* + 3de0 00000000 00000000 00000000 00000000 .* + 3df0 00000000 00000000 00000000 00000000 .* + 3e00 00000000 00000000 00000000 00000000 .* + 3e10 00000000 00000000 00000000 00000000 .* + 3e20 00000000 00000000 00000000 00000000 .* + 3e30 00000000 00000000 00000000 00000000 .* + 3e40 00000000 00000000 00000000 00000000 .* + 3e50 00000000 00000000 00000000 00000000 .* + 3e60 00000000 00000000 00000000 00000000 .* + 3e70 ff93e23d ff93de3d ff93da3d ff93d63d .* + 3e80 ff93d23d ff93ce3d ff93ca3d ff93c63d .* + 3e90 ff93c23d ff93bf3d 0090463e 0090423e .* + 3ea0 00903e3e 00903a3e 0090363e 0090323e .* + 3eb0 00902e3e 00902a3e 0090263e 0090233e .* + 3ec0 00000000 00000000 00000000 00000000 .* + 3ed0 00000000 00000000 00000000 00000000 .* + 3ee0 00000000 00000000 00000000 00000000 .* + 3ef0 00000000 00000000 00000000 00000000 .* + 3f00 00000000 00000000 00000000 00000000 .* + 3f10 00000000 00000000 00000000 00000000 .* + 3f20 00000000 00000000 00000000 00000000 .* + 3f30 00000000 00000000 00000000 00000000 .* + 3f40 00000000 00000000 00000000 00000000 .* + 3f50 00000000 00000000 00000000 00000000 .* + 3f60 00000000 00000000 00000000 00000000 .* + 3f70 00000000 00000000 00000000 00000000 .* + 3f80 00000000 00000000 00000000 00000000 .* + 3f90 00000000 00000000 00000000 00000000 .* + 3fa0 00000000 00000000 00000000 00000000 .* + 3fb0 00000000 00000000 00000000 00000000 .* + 3fc0 00000000 00000000 00000000 00000000 .* + 3fd0 00000000 00000000 00000000 00000000 .* + 3fe0 00000000 00000000 00000000 00000000 .* + 3ff0 00000000 00000000 00000000 00000000 .* + 4000 00000000 00000000 00000000 00000000 .* + 4010 00000000 00000000 00000000 00000000 .* + 4020 00000000 00000000 00000000 00000000 .* + 4030 00000000 00000000 00000000 00000000 .* + 4040 00000000 00000000 00000000 00000000 .* + 4050 00000000 00000000 00000000 00000000 .* + 4060 00000000 00000000 00000000 00000000 .* + 4070 00000000 00000000 00000000 00000000 .* + 4080 00000000 00000000 00000000 00000000 .* + 4090 00000000 00000000 00000000 00000000 .* + 40a0 00000000 00000000 00000000 00000000 .* + 40b0 00000000 00000000 00000000 00000000 .* + 40c0 0f300e30 0d300c30 0090163c 0090123c .* + 40d0 07300090 0c3c0090 083c0090 053c0000 .* + 40e0 00000000 00000000 00000000 00000000 .* + 40f0 00000000 00000000 00000000 00000000 .* + 4100 00000000 00000000 00000000 00000000 .* + 4110 00000000 00000000 00000000 00000000 .* + 4120 00000000 00000000 00000000 00000000 .* + 4130 00000000 00000000 00000000 00000000 .* + 4140 00000000 00000000 00000000 00000000 .* + 4150 00000000 00000000 00000000 00000000 .* + 4160 00000000 00000000 00000000 00000000 .* + 4170 00000000 00000000 00000000 00000000 .* + 4180 00000000 00000000 00000000 00000000 .* + 4190 00000000 00000000 00000000 00000000 .* + 41a0 00000000 00000000 00000000 00000000 .* + 41b0 00000000 00000000 00000000 00000000 .* + 41c0 00000000 00000000 00000000 00000000 .* + 41d0 00000000 00000000 00000000 00000000 .* + 41e0 00000000 00000000 00000000 00000000 .* + 41f0 00000000 00000000 00000000 00000000 .* + 4200 00000000 00000000 00000000 00000000 .* + 4210 00000000 00000000 00000000 00000000 .* + 4220 00000000 00000000 00000000 00000000 .* + 4230 00000000 00000000 00000000 00000000 .* + 4240 00000000 00000000 00000000 00000000 .* + 4250 00000000 00000000 00000000 00000000 .* + 4260 00000000 00000000 00000000 00000000 .* + 4270 00000000 00000000 00000000 00000000 .* + 4280 00000000 00000000 00000000 00000000 .* + 4290 00000000 00000000 00000000 00000000 .* + 42a0 00000000 00000000 00000000 00000000 .* + 42b0 00000000 00000000 00000000 00000000 .* + 42c0 00000000 00000000 00000000 00000000 .* + 42d0 00000000 00000000 00000000 00000000 .* + 42e0 0031ff93 fe3d0090 063e0090 023e0000 .* + 42f0 00000000 00000000 00000000 00000000 .* + 4300 00000000 00000000 00000000 00000000 .* + 4310 00000000 00000000 00000000 00000000 .* + 4320 00000000 00000000 00000000 00000000 .* + 4330 00000000 00000000 00000000 00000000 .* + 4340 00000000 00000000 00000000 00000000 .* + 4350 00000000 00000000 00000000 00000000 .* + 4360 00000000 00000000 00000000 00000000 .* + 4370 00000000 00000000 00000000 00000000 .* + 4380 00000000 00000000 00000000 00000000 .* + 4390 00000000 00000000 00000000 00000000 .* + 43a0 00000000 00000000 00000000 00000000 .* + 43b0 00000000 00000000 00000000 00000000 .* + 43c0 00000000 00000000 00000000 00000000 .* + 43d0 00000000 00000000 00000000 00000000 .* + 43e0 00000000 00000000 00000000 00000000 .* + 43f0 00000000 00000000 00000000 00000000 .* + 4400 00000000 00000000 00000000 00000000 .* + 4410 00000000 00000000 00000000 00000000 .* + 4420 00000000 00000000 00000000 00000000 .* + 4430 00000000 00000000 00000000 00000000 .* + 4440 00000000 00000000 00000000 00000000 .* + 4450 00000000 00000000 00000000 00000000 .* + 4460 00000000 00000000 00000000 00000000 .* + 4470 00000000 00000000 00000000 00000000 .* + 4480 00000000 00000000 00000000 00000000 .* + 4490 00000000 00000000 00000000 00000000 .* + 44a0 00000000 00000000 00000000 00000000 .* + 44b0 00000000 00000000 00000000 00000000 .* + 44c0 00000000 00000000 00000000 00000000 .* + 44d0 00000000 00000000 00000000 00000000 .* + 44e0 00000000 00000000 00000000 00000000 .* + 44f0 80008f00 80008000 80008000 80008000 .* + 4500 80008000 90009f00 a000af00 a000a000 .* + 4510 a000a000 a000a000 a000a000 b000bf00 .* + 4520 00804c3c ef83cc43 ef834c7f f083cc7e .* + 4530 00000000 00000000 00000000 00000000 .* + 4540 00000000 00000000 00000000 00000000 .* + 4550 00000000 00000000 00000000 00000000 .* + 4560 00000000 00000000 00000000 00000000 .* + 4570 00000000 00000000 00000000 00000000 .* + 4580 00000000 00000000 00000000 00000000 .* + 4590 00000000 00000000 00000000 00000000 .* + 45a0 00000000 00000000 00000000 00000000 .* + 45b0 00000000 00000000 00000000 00000000 .* + 45c0 00000000 00000000 00000000 00000000 .* + 45d0 00000000 00000000 00000000 00000000 .* + 45e0 00000000 00000000 00000000 00000000 .* + 45f0 00000000 00000000 00000000 00000000 .* + 4600 00000000 00000000 00000000 00000000 .* + 4610 00000000 00000000 00000000 00000000 .* + 4620 00000000 00000000 00000000 00000000 .* + 4630 00000000 00000000 00000000 00000000 .* + 4640 00000000 00000000 00000000 00000000 .* + 4650 00000000 00000000 00000000 00000000 .* + 4660 00000000 00000000 00000000 00000000 .* + 4670 00000000 00000000 00000000 00000000 .* + 4680 00000000 00000000 00000000 00000000 .* + 4690 00000000 00000000 00000000 00000000 .* + 46a0 00000000 00000000 00000000 00000000 .* + 46b0 00000000 00000000 00000000 00000000 .* + 46c0 00000000 00000000 00000000 00000000 .* + 46d0 00000000 00000000 00000000 00000000 .* + 46e0 00000000 00000000 00000000 00000000 .* + 46f0 00000000 00000000 00000000 00000000 .* + 4700 00000000 00000000 00000000 00000000 .* + 4710 00000000 00000000 00000000 00000000 .* + 4720 00000000 00000000 00000000 00000000 .* + 4730 0f44ff93 ee11f045 ff93e811 ff45ff93 .* + 4740 e2111f46 ff93dc11 0f440090 2612f045 .* + 4750 00902012 ff450090 1a121f46 00901412 .* + 4760 00000000 00000000 00000000 00000000 .* + 4770 00000000 00000000 00000000 00000000 .* + 4780 00000000 00000000 00000000 00000000 .* + 4790 00000000 00000000 00000000 00000000 .* + 47a0 00000000 00000000 00000000 00000000 .* + 47b0 00000000 00000000 00000000 00000000 .* + 47c0 00000000 00000000 00000000 00000000 .* + 47d0 00000000 00000000 00000000 00000000 .* + 47e0 00000000 00000000 00000000 00000000 .* + 47f0 00000000 00000000 00000000 00000000 .* + 4800 00000000 00000000 00000000 00000000 .* + 4810 00000000 00000000 00000000 00000000 .* + 4820 00000000 00000000 00000000 00000000 .* + 4830 00000000 00000000 00000000 00000000 .* + 4840 00000000 00000000 00000000 00000000 .* + 4850 00000000 00000000 00000000 00000000 .* + 4860 00000000 00000000 00000000 00000000 .* + 4870 00000000 00000000 00000000 00000000 .* + 4880 00000000 00000000 00000000 00000000 .* + 4890 00000000 00000000 00000000 00000000 .* + 48a0 00000000 00000000 00000000 00000000 .* + 48b0 00000000 00000000 00000000 00000000 .* + 48c0 00000000 00000000 00000000 00000000 .* + 48d0 00000000 00000000 00000000 00000000 .* + 48e0 00000000 00000000 00000000 00000000 .* + 48f0 00000000 00000000 00000000 00000000 .* + 4900 00000000 00000000 00000000 00000000 .* + 4910 00000000 00000000 00000000 00000000 .* + 4920 00000000 00000000 00000000 00000000 .* + 4930 00000000 00000000 00000000 00000000 .* + 4940 00000000 00000000 00000000 00000000 .* + 4950 00000000 00000000 00000000 00000000 .* + 4960 00804c3e 0f80cc41 0f804c7d 1080cc7c .* + 4970 00000000 00000000 00000000 00000000 .* + 4980 00000000 00000000 00000000 00000000 .* + 4990 00000000 00000000 00000000 00000000 .* + 49a0 00000000 00000000 00000000 00000000 .* + 49b0 00000000 00000000 00000000 00000000 .* + 49c0 00000000 00000000 00000000 00000000 .* + 49d0 00000000 00000000 00000000 00000000 .* + 49e0 00000000 00000000 00000000 00000000 .* + 49f0 00000000 00000000 00000000 00000000 .* + 4a00 00000000 00000000 00000000 00000000 .* + 4a10 00000000 00000000 00000000 00000000 .* + 4a20 00000000 00000000 00000000 00000000 .* + 4a30 00000000 00000000 00000000 00000000 .* + 4a40 00000000 00000000 00000000 00000000 .* + 4a50 00000000 00000000 00000000 00000000 .* + 4a60 00000000 00000000 00000000 00000000 .* + 4a70 00000000 00000000 00000000 00000000 .* + 4a80 00000000 00000000 00000000 00000000 .* + 4a90 00000000 00000000 00000000 00000000 .* + 4aa0 00000000 00000000 00000000 00000000 .* + 4ab0 00000000 00000000 00000000 00000000 .* + 4ac0 00000000 00000000 00000000 00000000 .* + 4ad0 00000000 00000000 00000000 00000000 .* + 4ae0 00000000 00000000 00000000 00000000 .* + 4af0 00000000 00000000 00000000 00000000 .* + 4b00 00000000 00000000 00000000 00000000 .* + 4b10 00000000 00000000 00000000 00000000 .* + 4b20 00000000 00000000 00000000 00000000 .* + 4b30 00000000 00000000 00000000 00000000 .* + 4b40 00000000 00000000 00000000 00000000 .* + 4b50 00000000 00000000 00000000 00000000 .* + 4b60 00000000 00000000 00000000 00000000 .* + 4b70 00000082 4c3c0f46 ff93fa11 0f440090 .* + 4b80 08120f46 00900212 00000000 00000000 .* + 4b90 00000000 00000000 00000000 00000000 .* + 4ba0 00000000 00000000 00000000 00000000 .* + 4bb0 00000000 00000000 00000000 00000000 .* + 4bc0 00000000 00000000 00000000 00000000 .* + 4bd0 00000000 00000000 00000000 00000000 .* + 4be0 00000000 00000000 00000000 00000000 .* + 4bf0 00000000 00000000 00000000 00000000 .* + 4c00 00000000 00000000 00000000 00000000 .* + 4c10 00000000 00000000 00000000 00000000 .* + 4c20 00000000 00000000 00000000 00000000 .* + 4c30 00000000 00000000 00000000 00000000 .* + 4c40 00000000 00000000 00000000 00000000 .* + 4c50 00000000 00000000 00000000 00000000 .* + 4c60 00000000 00000000 00000000 00000000 .* + 4c70 00000000 00000000 00000000 00000000 .* + 4c80 00000000 00000000 00000000 00000000 .* + 4c90 00000000 00000000 00000000 00000000 .* + 4ca0 00000000 00000000 00000000 00000000 .* + 4cb0 00000000 00000000 00000000 00000000 .* + 4cc0 00000000 00000000 00000000 00000000 .* + 4cd0 00000000 00000000 00000000 00000000 .* + 4ce0 00000000 00000000 00000000 00000000 .* + 4cf0 00000000 00000000 00000000 00000000 .* + 4d00 00000000 00000000 00000000 00000000 .* + 4d10 00000000 00000000 00000000 00000000 .* + 4d20 00000000 00000000 00000000 00000000 .* + 4d30 00000000 00000000 00000000 00000000 .* + 4d40 00000000 00000000 00000000 00000000 .* + 4d50 00000000 00000000 00000000 00000000 .* + 4d60 00000000 00000000 00000000 00000000 .* + 4d70 00000000 00000000 00000000 00000000 .* + 4d80 00000000 00000000 00804e3c ef83ce43 .* + 4d90 ef834e7f f083ce7e 00000000 00000000 .* + 4da0 00000000 00000000 00000000 00000000 .* + 4db0 00000000 00000000 00000000 00000000 .* + 4dc0 00000000 00000000 00000000 00000000 .* + 4dd0 00000000 00000000 00000000 00000000 .* + 4de0 00000000 00000000 00000000 00000000 .* + 4df0 00000000 00000000 00000000 00000000 .* + 4e00 00000000 00000000 00000000 00000000 .* + 4e10 00000000 00000000 00000000 00000000 .* + 4e20 00000000 00000000 00000000 00000000 .* + 4e30 00000000 00000000 00000000 00000000 .* + 4e40 00000000 00000000 00000000 00000000 .* + 4e50 00000000 00000000 00000000 00000000 .* + 4e60 00000000 00000000 00000000 00000000 .* + 4e70 00000000 00000000 00000000 00000000 .* + 4e80 00000000 00000000 00000000 00000000 .* + 4e90 00000000 00000000 00000000 00000000 .* + 4ea0 00000000 00000000 00000000 00000000 .* + 4eb0 00000000 00000000 00000000 00000000 .* + 4ec0 00000000 00000000 00000000 00000000 .* + 4ed0 00000000 00000000 00000000 00000000 .* + 4ee0 00000000 00000000 00000000 00000000 .* + 4ef0 00000000 00000000 00000000 00000000 .* + 4f00 00000000 00000000 00000000 00000000 .* + 4f10 00000000 00000000 00000000 00000000 .* + 4f20 00000000 00000000 00000000 00000000 .* + 4f30 00000000 00000000 00000000 00000000 .* + 4f40 00000000 00000000 00000000 00000000 .* + 4f50 00000000 00000000 00000000 00000000 .* + 4f60 00000000 00000000 00000000 00000000 .* + 4f70 00000000 00000000 00000000 00000000 .* + 4f80 00000000 00000000 00000000 00000000 .* + 4f90 00000000 00000000 0f44ff93 ee15f045 .* + 4fa0 ff93e815 ff45ff93 e2151f46 ff93dc15 .* + 4fb0 0f440090 2616f045 00902016 ff450090 .* + 4fc0 1a161f46 00901416 00000000 00000000 .* + 4fd0 00000000 00000000 00000000 00000000 .* + 4fe0 00000000 00000000 00000000 00000000 .* + 4ff0 00000000 00000000 00000000 00000000 .* + 5000 00000000 00000000 00000000 00000000 .* + 5010 00000000 00000000 00000000 00000000 .* + 5020 00000000 00000000 00000000 00000000 .* + 5030 00000000 00000000 00000000 00000000 .* + 5040 00000000 00000000 00000000 00000000 .* + 5050 00000000 00000000 00000000 00000000 .* + 5060 00000000 00000000 00000000 00000000 .* + 5070 00000000 00000000 00000000 00000000 .* + 5080 00000000 00000000 00000000 00000000 .* + 5090 00000000 00000000 00000000 00000000 .* + 50a0 00000000 00000000 00000000 00000000 .* + 50b0 00000000 00000000 00000000 00000000 .* + 50c0 00000000 00000000 00000000 00000000 .* + 50d0 00000000 00000000 00000000 00000000 .* + 50e0 00000000 00000000 00000000 00000000 .* + 50f0 00000000 00000000 00000000 00000000 .* + 5100 00000000 00000000 00000000 00000000 .* + 5110 00000000 00000000 00000000 00000000 .* + 5120 00000000 00000000 00000000 00000000 .* + 5130 00000000 00000000 00000000 00000000 .* + 5140 00000000 00000000 00000000 00000000 .* + 5150 00000000 00000000 00000000 00000000 .* + 5160 00000000 00000000 00000000 00000000 .* + 5170 00000000 00000000 00000000 00000000 .* + 5180 00000000 00000000 00000000 00000000 .* + 5190 00000000 00000000 00000000 00000000 .* + 51a0 00000000 00000000 00000000 00000000 .* + 51b0 00000000 00000000 00000000 00000000 .* + 51c0 00000000 00000000 00804e3e 0f80ce41 .* + 51d0 0f804e7d 1080ce7c 00000000 00000000 .* + 51e0 00000000 00000000 00000000 00000000 .* + 51f0 00000000 00000000 00000000 00000000 .* + 5200 00000000 00000000 00000000 00000000 .* + 5210 00000000 00000000 00000000 00000000 .* + 5220 00000000 00000000 00000000 00000000 .* + 5230 00000000 00000000 00000000 00000000 .* + 5240 00000000 00000000 00000000 00000000 .* + 5250 00000000 00000000 00000000 00000000 .* + 5260 00000000 00000000 00000000 00000000 .* + 5270 00000000 00000000 00000000 00000000 .* + 5280 00000000 00000000 00000000 00000000 .* + 5290 00000000 00000000 00000000 00000000 .* + 52a0 00000000 00000000 00000000 00000000 .* + 52b0 00000000 00000000 00000000 00000000 .* + 52c0 00000000 00000000 00000000 00000000 .* + 52d0 00000000 00000000 00000000 00000000 .* + 52e0 00000000 00000000 00000000 00000000 .* + 52f0 00000000 00000000 00000000 00000000 .* + 5300 00000000 00000000 00000000 00000000 .* + 5310 00000000 00000000 00000000 00000000 .* + 5320 00000000 00000000 00000000 00000000 .* + 5330 00000000 00000000 00000000 00000000 .* + 5340 00000000 00000000 00000000 00000000 .* + 5350 00000000 00000000 00000000 00000000 .* + 5360 00000000 00000000 00000000 00000000 .* + 5370 00000000 00000000 00000000 00000000 .* + 5380 00000000 00000000 00000000 00000000 .* + 5390 00000000 00000000 00000000 00000000 .* + 53a0 00000000 00000000 00000000 00000000 .* + 53b0 00000000 00000000 00000000 00000000 .* + 53c0 00000000 00000000 00000000 00000000 .* + 53d0 00000000 00000000 00000082 4e3c0f46 .* + 53e0 ff93fa15 0f440090 08160f46 00900216 .* + 53f0 00000000 00000000 00000000 00000000 .* + 5400 00000000 00000000 00000000 00000000 .* + 5410 00000000 00000000 00000000 00000000 .* + 5420 00000000 00000000 00000000 00000000 .* + 5430 00000000 00000000 00000000 00000000 .* + 5440 00000000 00000000 00000000 00000000 .* + 5450 00000000 00000000 00000000 00000000 .* + 5460 00000000 00000000 00000000 00000000 .* + 5470 00000000 00000000 00000000 00000000 .* + 5480 00000000 00000000 00000000 00000000 .* + 5490 00000000 00000000 00000000 00000000 .* + 54a0 00000000 00000000 00000000 00000000 .* + 54b0 00000000 00000000 00000000 00000000 .* + 54c0 00000000 00000000 00000000 00000000 .* + 54d0 00000000 00000000 00000000 00000000 .* + 54e0 00000000 00000000 00000000 00000000 .* + 54f0 00000000 00000000 00000000 00000000 .* + 5500 00000000 00000000 00000000 00000000 .* + 5510 00000000 00000000 00000000 00000000 .* + 5520 00000000 00000000 00000000 00000000 .* + 5530 00000000 00000000 00000000 00000000 .* + 5540 00000000 00000000 00000000 00000000 .* + 5550 00000000 00000000 00000000 00000000 .* + 5560 00000000 00000000 00000000 00000000 .* + 5570 00000000 00000000 00000000 00000000 .* + 5580 00000000 00000000 00000000 00000000 .* + 5590 00000000 00000000 00000000 00000000 .* + 55a0 00000000 00000000 00000000 00000000 .* + 55b0 00000000 00000000 00000000 00000000 .* + 55c0 00000000 00000000 00000000 00000000 .* + 55d0 00000000 00000000 00000000 00000000 .* + 55e0 00000000 00000000 00000000 00000000 .* + 55f0 00804c00 ef83cc03 f0834c03 ff83cc02 .* + 5600 00000000 00000000 00000000 00000000 .* + 5610 00000000 00000000 00000000 00000000 .* + 5620 00000000 00000000 00000000 00000000 .* + 5630 00000000 00000000 00000000 00000000 .* + 5640 00000000 00000000 00000000 00000000 .* + 5650 00000000 00000000 00000000 00000000 .* + 5660 00000000 00000000 00000000 00000000 .* + 5670 00000000 00000000 00000000 00000000 .* + 5680 00000000 00000000 00000000 00000000 .* + 5690 00000000 00000000 00000000 00000000 .* + 56a0 00000000 00000000 00000000 00000000 .* + 56b0 00000000 00000000 00000000 00000000 .* + 56c0 00000000 00000000 00000000 00000000 .* + 56d0 00000000 00000000 00000000 00000000 .* + 56e0 00000000 00000000 00000000 00000000 .* + 56f0 00000000 00000000 00000000 00000000 .* + 5700 00000000 00000000 00000000 00000000 .* + 5710 00000000 00000000 00000000 00000000 .* + 5720 00000000 00000000 00000000 00000000 .* + 5730 00000000 00000000 00000000 00000000 .* + 5740 00000000 00000000 00000000 00000000 .* + 5750 00000000 00000000 00000000 00000000 .* + 5760 00000000 00000000 00000000 00000000 .* + 5770 00000000 00000000 00000000 00000000 .* + 5780 00000000 00000000 00000000 00000000 .* + 5790 00000000 00000000 00000000 00000000 .* + 57a0 00000000 00000000 00000000 00000000 .* + 57b0 00000000 00000000 00000000 00000000 .* + 57c0 00000000 00000000 00000000 00000000 .* + 57d0 00000000 00000000 00000000 00000000 .* + 57e0 00000000 00000000 00000000 00000000 .* + 57f0 00000000 00000000 00000000 00000000 .* + 5800 0060ff93 ee11e061 ff93e811 0062ff93 .* + 5810 e211e063 ff93dc11 00600090 2612e061 .* + 5820 00902012 00620090 1a12e063 00901412 .* + 5830 00000000 00000000 00000000 00000000 .* + 5840 00000000 00000000 00000000 00000000 .* + 5850 00000000 00000000 00000000 00000000 .* + 5860 00000000 00000000 00000000 00000000 .* + 5870 00000000 00000000 00000000 00000000 .* + 5880 00000000 00000000 00000000 00000000 .* + 5890 00000000 00000000 00000000 00000000 .* + 58a0 00000000 00000000 00000000 00000000 .* + 58b0 00000000 00000000 00000000 00000000 .* + 58c0 00000000 00000000 00000000 00000000 .* + 58d0 00000000 00000000 00000000 00000000 .* + 58e0 00000000 00000000 00000000 00000000 .* + 58f0 00000000 00000000 00000000 00000000 .* + 5900 00000000 00000000 00000000 00000000 .* + 5910 00000000 00000000 00000000 00000000 .* + 5920 00000000 00000000 00000000 00000000 .* + 5930 00000000 00000000 00000000 00000000 .* + 5940 00000000 00000000 00000000 00000000 .* + 5950 00000000 00000000 00000000 00000000 .* + 5960 00000000 00000000 00000000 00000000 .* + 5970 00000000 00000000 00000000 00000000 .* + 5980 00000000 00000000 00000000 00000000 .* + 5990 00000000 00000000 00000000 00000000 .* + 59a0 00000000 00000000 00000000 00000000 .* + 59b0 00000000 00000000 00000000 00000000 .* + 59c0 00000000 00000000 00000000 00000000 .* + 59d0 00000000 00000000 00000000 00000000 .* + 59e0 00000000 00000000 00000000 00000000 .* + 59f0 00000000 00000000 00000000 00000000 .* + 5a00 00000000 00000000 00000000 00000000 .* + 5a10 00000000 00000000 00000000 00000000 .* + 5a20 00000000 00000000 00000000 00000000 .* + 5a30 00804c02 0f80cc01 10804c01 1f80cc00 .* + 5a40 00000000 00000000 00000000 00000000 .* + 5a50 00000000 00000000 00000000 00000000 .* + 5a60 00000000 00000000 00000000 00000000 .* + 5a70 00000000 00000000 00000000 00000000 .* + 5a80 00000000 00000000 00000000 00000000 .* + 5a90 00000000 00000000 00000000 00000000 .* + 5aa0 00000000 00000000 00000000 00000000 .* + 5ab0 00000000 00000000 00000000 00000000 .* + 5ac0 00000000 00000000 00000000 00000000 .* + 5ad0 00000000 00000000 00000000 00000000 .* + 5ae0 00000000 00000000 00000000 00000000 .* + 5af0 00000000 00000000 00000000 00000000 .* + 5b00 00000000 00000000 00000000 00000000 .* + 5b10 00000000 00000000 00000000 00000000 .* + 5b20 00000000 00000000 00000000 00000000 .* + 5b30 00000000 00000000 00000000 00000000 .* + 5b40 00000000 00000000 00000000 00000000 .* + 5b50 00000000 00000000 00000000 00000000 .* + 5b60 00000000 00000000 00000000 00000000 .* + 5b70 00000000 00000000 00000000 00000000 .* + 5b80 00000000 00000000 00000000 00000000 .* + 5b90 00000000 00000000 00000000 00000000 .* + 5ba0 00000000 00000000 00000000 00000000 .* + 5bb0 00000000 00000000 00000000 00000000 .* + 5bc0 00000000 00000000 00000000 00000000 .* + 5bd0 00000000 00000000 00000000 00000000 .* + 5be0 00000000 00000000 00000000 00000000 .* + 5bf0 00000000 00000000 00000000 00000000 .* + 5c00 00000000 00000000 00000000 00000000 .* + 5c10 00000000 00000000 00000000 00000000 .* + 5c20 00000000 00000000 00000000 00000000 .* + 5c30 00000000 00000000 00000000 00000000 .* + 5c40 00000082 4c000062 ff93fa11 00600090 .* + 5c50 08120062 00900212 00000000 00000000 .* + 5c60 00000000 00000000 00000000 00000000 .* + 5c70 00000000 00000000 00000000 00000000 .* + 5c80 00000000 00000000 00000000 00000000 .* + 5c90 00000000 00000000 00000000 00000000 .* + 5ca0 00000000 00000000 00000000 00000000 .* + 5cb0 00000000 00000000 00000000 00000000 .* + 5cc0 00000000 00000000 00000000 00000000 .* + 5cd0 00000000 00000000 00000000 00000000 .* + 5ce0 00000000 00000000 00000000 00000000 .* + 5cf0 00000000 00000000 00000000 00000000 .* + 5d00 00000000 00000000 00000000 00000000 .* + 5d10 00000000 00000000 00000000 00000000 .* + 5d20 00000000 00000000 00000000 00000000 .* + 5d30 00000000 00000000 00000000 00000000 .* + 5d40 00000000 00000000 00000000 00000000 .* + 5d50 00000000 00000000 00000000 00000000 .* + 5d60 00000000 00000000 00000000 00000000 .* + 5d70 00000000 00000000 00000000 00000000 .* + 5d80 00000000 00000000 00000000 00000000 .* + 5d90 00000000 00000000 00000000 00000000 .* + 5da0 00000000 00000000 00000000 00000000 .* + 5db0 00000000 00000000 00000000 00000000 .* + 5dc0 00000000 00000000 00000000 00000000 .* + 5dd0 00000000 00000000 00000000 00000000 .* + 5de0 00000000 00000000 00000000 00000000 .* + 5df0 00000000 00000000 00000000 00000000 .* + 5e00 00000000 00000000 00000000 00000000 .* + 5e10 00000000 00000000 00000000 00000000 .* + 5e20 00000000 00000000 00000000 00000000 .* + 5e30 00000000 00000000 00000000 00000000 .* + 5e40 00000000 00000000 00000000 00000000 .* + 5e50 00000000 00000000 00804e00 ef83ce03 .* + 5e60 f0834e03 ff83ce02 00000000 00000000 .* + 5e70 00000000 00000000 00000000 00000000 .* + 5e80 00000000 00000000 00000000 00000000 .* + 5e90 00000000 00000000 00000000 00000000 .* + 5ea0 00000000 00000000 00000000 00000000 .* + 5eb0 00000000 00000000 00000000 00000000 .* + 5ec0 00000000 00000000 00000000 00000000 .* + 5ed0 00000000 00000000 00000000 00000000 .* + 5ee0 00000000 00000000 00000000 00000000 .* + 5ef0 00000000 00000000 00000000 00000000 .* + 5f00 00000000 00000000 00000000 00000000 .* + 5f10 00000000 00000000 00000000 00000000 .* + 5f20 00000000 00000000 00000000 00000000 .* + 5f30 00000000 00000000 00000000 00000000 .* + 5f40 00000000 00000000 00000000 00000000 .* + 5f50 00000000 00000000 00000000 00000000 .* + 5f60 00000000 00000000 00000000 00000000 .* + 5f70 00000000 00000000 00000000 00000000 .* + 5f80 00000000 00000000 00000000 00000000 .* + 5f90 00000000 00000000 00000000 00000000 .* + 5fa0 00000000 00000000 00000000 00000000 .* + 5fb0 00000000 00000000 00000000 00000000 .* + 5fc0 00000000 00000000 00000000 00000000 .* + 5fd0 00000000 00000000 00000000 00000000 .* + 5fe0 00000000 00000000 00000000 00000000 .* + 5ff0 00000000 00000000 00000000 00000000 .* + 6000 00000000 00000000 00000000 00000000 .* + 6010 00000000 00000000 00000000 00000000 .* + 6020 00000000 00000000 00000000 00000000 .* + 6030 00000000 00000000 00000000 00000000 .* + 6040 00000000 00000000 00000000 00000000 .* + 6050 00000000 00000000 00000000 00000000 .* + 6060 00000000 00000000 0060ff93 ee15e061 .* + 6070 ff93e815 0062ff93 e215e063 ff93dc15 .* + 6080 00600090 2616e061 00902016 00620090 .* + 6090 1a16e063 00901416 00000000 00000000 .* + 60a0 00000000 00000000 00000000 00000000 .* + 60b0 00000000 00000000 00000000 00000000 .* + 60c0 00000000 00000000 00000000 00000000 .* + 60d0 00000000 00000000 00000000 00000000 .* + 60e0 00000000 00000000 00000000 00000000 .* + 60f0 00000000 00000000 00000000 00000000 .* + 6100 00000000 00000000 00000000 00000000 .* + 6110 00000000 00000000 00000000 00000000 .* + 6120 00000000 00000000 00000000 00000000 .* + 6130 00000000 00000000 00000000 00000000 .* + 6140 00000000 00000000 00000000 00000000 .* + 6150 00000000 00000000 00000000 00000000 .* + 6160 00000000 00000000 00000000 00000000 .* + 6170 00000000 00000000 00000000 00000000 .* + 6180 00000000 00000000 00000000 00000000 .* + 6190 00000000 00000000 00000000 00000000 .* + 61a0 00000000 00000000 00000000 00000000 .* + 61b0 00000000 00000000 00000000 00000000 .* + 61c0 00000000 00000000 00000000 00000000 .* + 61d0 00000000 00000000 00000000 00000000 .* + 61e0 00000000 00000000 00000000 00000000 .* + 61f0 00000000 00000000 00000000 00000000 .* + 6200 00000000 00000000 00000000 00000000 .* + 6210 00000000 00000000 00000000 00000000 .* + 6220 00000000 00000000 00000000 00000000 .* + 6230 00000000 00000000 00000000 00000000 .* + 6240 00000000 00000000 00000000 00000000 .* + 6250 00000000 00000000 00000000 00000000 .* + 6260 00000000 00000000 00000000 00000000 .* + 6270 00000000 00000000 00000000 00000000 .* + 6280 00000000 00000000 00000000 00000000 .* + 6290 00000000 00000000 00804e02 0f80ce01 .* + 62a0 10804e01 1f80ce00 00000000 00000000 .* + 62b0 00000000 00000000 00000000 00000000 .* + 62c0 00000000 00000000 00000000 00000000 .* + 62d0 00000000 00000000 00000000 00000000 .* + 62e0 00000000 00000000 00000000 00000000 .* + 62f0 00000000 00000000 00000000 00000000 .* + 6300 00000000 00000000 00000000 00000000 .* + 6310 00000000 00000000 00000000 00000000 .* + 6320 00000000 00000000 00000000 00000000 .* + 6330 00000000 00000000 00000000 00000000 .* + 6340 00000000 00000000 00000000 00000000 .* + 6350 00000000 00000000 00000000 00000000 .* + 6360 00000000 00000000 00000000 00000000 .* + 6370 00000000 00000000 00000000 00000000 .* + 6380 00000000 00000000 00000000 00000000 .* + 6390 00000000 00000000 00000000 00000000 .* + 63a0 00000000 00000000 00000000 00000000 .* + 63b0 00000000 00000000 00000000 00000000 .* + 63c0 00000000 00000000 00000000 00000000 .* + 63d0 00000000 00000000 00000000 00000000 .* + 63e0 00000000 00000000 00000000 00000000 .* + 63f0 00000000 00000000 00000000 00000000 .* + 6400 00000000 00000000 00000000 00000000 .* + 6410 00000000 00000000 00000000 00000000 .* + 6420 00000000 00000000 00000000 00000000 .* + 6430 00000000 00000000 00000000 00000000 .* + 6440 00000000 00000000 00000000 00000000 .* + 6450 00000000 00000000 00000000 00000000 .* + 6460 00000000 00000000 00000000 00000000 .* + 6470 00000000 00000000 00000000 00000000 .* + 6480 00000000 00000000 00000000 00000000 .* + 6490 00000000 00000000 00000000 00000000 .* + 64a0 00000000 00000000 00000082 4e000062 .* + 64b0 ff93fa15 00600090 08160062 00900216 .* + 64c0 00000000 00000000 00000000 00000000 .* + 64d0 00000000 00000000 00000000 00000000 .* + 64e0 00000000 00000000 00000000 00000000 .* + 64f0 00000000 00000000 00000000 00000000 .* + 6500 00000000 00000000 00000000 00000000 .* + 6510 00000000 00000000 00000000 00000000 .* + 6520 00000000 00000000 00000000 00000000 .* + 6530 00000000 00000000 00000000 00000000 .* + 6540 00000000 00000000 00000000 00000000 .* + 6550 00000000 00000000 00000000 00000000 .* + 6560 00000000 00000000 00000000 00000000 .* + 6570 00000000 00000000 00000000 00000000 .* + 6580 00000000 00000000 00000000 00000000 .* + 6590 00000000 00000000 00000000 00000000 .* + 65a0 00000000 00000000 00000000 00000000 .* + 65b0 00000000 00000000 00000000 00000000 .* + 65c0 00000000 00000000 00000000 00000000 .* + 65d0 00000000 00000000 00000000 00000000 .* + 65e0 00000000 00000000 00000000 00000000 .* + 65f0 00000000 00000000 00000000 00000000 .* + 6600 00000000 00000000 00000000 00000000 .* + 6610 00000000 00000000 00000000 00000000 .* + 6620 00000000 00000000 00000000 00000000 .* + 6630 00000000 00000000 00000000 00000000 .* + 6640 00000000 00000000 00000000 00000000 .* + 6650 00000000 00000000 00000000 00000000 .* + 6660 00000000 00000000 00000000 00000000 .* + 6670 00000000 00000000 00000000 00000000 .* + 6680 00000000 00000000 00000000 00000000 .* + 6690 00000000 00000000 00000000 00000000 .* + 66a0 00000000 00000000 00000000 00000000 .* + 66b0 00000000 00000000 00000000 00000000 .* +#pass diff --git a/gas/testsuite/gas/score/branch_32.d b/gas/testsuite/gas/score/branch_32.d new file mode 100644 index 00000000000..36c28519841 --- /dev/null +++ b/gas/testsuite/gas/score/branch_32.d @@ -0,0 +1,578 @@ +#as: -march=score3 -I${srcdir}/${subdir} +#objdump: -d +#source: branch_32.s + +.*: file format .* + +Disassembly of section .text: + +00000000 <.text>: + 0: 3400 bgtu! 0x0 + 2: 35ff bgtu! 0x0 + 4: 35fe bgtu! 0x0 + 6: 35fd bgtu! 0x0 + 8: 93ff 0bf8 bgtu 0x0 + c: 93ff 0bf4 bgtu 0x0 + 10: 35f8 bgtu! 0x0 + 12: 93ff 0bee bgtu 0x0 + 16: 93ff 0bea bgtu 0x0 + 1a: 93ff 0be7 bgtul 0x0 + ... + 21e: 93ff 09e2 bgtu 0x0 + 222: 93ff 09de bgtu 0x0 + 226: 93ff 09da bgtu 0x0 + 22a: 93ff 09d6 bgtu 0x0 + 22e: 93ff 09d2 bgtu 0x0 + 232: 93ff 09ce bgtu 0x0 + 236: 93ff 09ca bgtu 0x0 + 23a: 93ff 09c6 bgtu 0x0 + 23e: 93ff 09c2 bgtu 0x0 + 242: 93ff 09bf bgtul 0x0 + 246: 9000 0a46 bgtu 0x48c + 24a: 9000 0a42 bgtu 0x48c + 24e: 9000 0a3e bgtu 0x48c + 252: 9000 0a3a bgtu 0x48c + 256: 9000 0a36 bgtu 0x48c + 25a: 9000 0a32 bgtu 0x48c + 25e: 9000 0a2e bgtu 0x48c + 262: 9000 0a2a bgtu 0x48c + 266: 9000 0a26 bgtu 0x48c + 26a: 9000 0a23 bgtul 0x48c + ... + 46e: 340f bgtu! 0x48c + 470: 340e bgtu! 0x48c + 472: 340d bgtu! 0x48c + 474: 340c bgtu! 0x48c + 476: 9000 0816 bgtu 0x48c + 47a: 9000 0812 bgtu 0x48c + 47e: 3407 bgtu! 0x48c + 480: 9000 080c bgtu 0x48c + 484: 9000 0808 bgtu 0x48c + 488: 9000 0805 bgtul 0x48c + ... + 68c: 0000 nop! + 68e: 3500 bgtu! 0x48e + 690: 93ff 09fe bgtu 0x48e + 694: 9000 0a06 bgtu 0x89a + 698: 9000 0a02 bgtu 0x89a + ... + 89c: 0000 nop! + 89e: 3600 bleu! 0x89e + 8a0: 37ff bleu! 0x89e + 8a2: 37fe bleu! 0x89e + 8a4: 37fd bleu! 0x89e + 8a6: 93ff 0ff8 bleu 0x89e + 8aa: 93ff 0ff4 bleu 0x89e + 8ae: 37f8 bleu! 0x89e + 8b0: 93ff 0fee bleu 0x89e + 8b4: 93ff 0fea bleu 0x89e + 8b8: 93ff 0fe7 bleul 0x89e + ... + abc: 93ff 0de2 bleu 0x89e + ac0: 93ff 0dde bleu 0x89e + ac4: 93ff 0dda bleu 0x89e + ac8: 93ff 0dd6 bleu 0x89e + acc: 93ff 0dd2 bleu 0x89e + ad0: 93ff 0dce bleu 0x89e + ad4: 93ff 0dca bleu 0x89e + ad8: 93ff 0dc6 bleu 0x89e + adc: 93ff 0dc2 bleu 0x89e + ae0: 93ff 0dbf bleul 0x89e + ae4: 9000 0e46 bleu 0xd2a + ae8: 9000 0e42 bleu 0xd2a + aec: 9000 0e3e bleu 0xd2a + af0: 9000 0e3a bleu 0xd2a + af4: 9000 0e36 bleu 0xd2a + af8: 9000 0e32 bleu 0xd2a + afc: 9000 0e2e bleu 0xd2a + b00: 9000 0e2a bleu 0xd2a + b04: 9000 0e26 bleu 0xd2a + b08: 9000 0e23 bleul 0xd2a + ... + d0c: 360f bleu! 0xd2a + d0e: 360e bleu! 0xd2a + d10: 360d bleu! 0xd2a + d12: 360c bleu! 0xd2a + d14: 9000 0c16 bleu 0xd2a + d18: 9000 0c12 bleu 0xd2a + d1c: 3607 bleu! 0xd2a + d1e: 9000 0c0c bleu 0xd2a + d22: 9000 0c08 bleu 0xd2a + d26: 9000 0c05 bleul 0xd2a + ... + f2a: 0000 nop! + f2c: 3700 bleu! 0xd2c + f2e: 93ff 0dfe bleu 0xd2c + f32: 9000 0e06 bleu 0x1138 + f36: 9000 0e02 bleu 0x1138 + ... + 113a: 0000 nop! + 113c: 3800 beq! 0x113c + 113e: 39ff beq! 0x113c + 1140: 39fe beq! 0x113c + 1142: 39fd beq! 0x113c + 1144: 93ff 13f8 beq 0x113c + 1148: 93ff 13f4 beq 0x113c + 114c: 39f8 beq! 0x113c + 114e: 93ff 13ee beq 0x113c + 1152: 93ff 13ea beq 0x113c + 1156: 93ff 13e7 beql 0x113c + ... + 135a: 93ff 11e2 beq 0x113c + 135e: 93ff 11de beq 0x113c + 1362: 93ff 11da beq 0x113c + 1366: 93ff 11d6 beq 0x113c + 136a: 93ff 11d2 beq 0x113c + 136e: 93ff 11ce beq 0x113c + 1372: 93ff 11ca beq 0x113c + 1376: 93ff 11c6 beq 0x113c + 137a: 93ff 11c2 beq 0x113c + 137e: 93ff 11bf beql 0x113c + 1382: 9000 1246 beq 0x15c8 + 1386: 9000 1242 beq 0x15c8 + 138a: 9000 123e beq 0x15c8 + 138e: 9000 123a beq 0x15c8 + 1392: 9000 1236 beq 0x15c8 + 1396: 9000 1232 beq 0x15c8 + 139a: 9000 122e beq 0x15c8 + 139e: 9000 122a beq 0x15c8 + 13a2: 9000 1226 beq 0x15c8 + 13a6: 9000 1223 beql 0x15c8 + ... + 15aa: 380f beq! 0x15c8 + 15ac: 380e beq! 0x15c8 + 15ae: 380d beq! 0x15c8 + 15b0: 380c beq! 0x15c8 + 15b2: 9000 1016 beq 0x15c8 + 15b6: 9000 1012 beq 0x15c8 + 15ba: 3807 beq! 0x15c8 + 15bc: 9000 100c beq 0x15c8 + 15c0: 9000 1008 beq 0x15c8 + 15c4: 9000 1005 beql 0x15c8 + ... + 17c8: 0000 nop! + 17ca: 3900 beq! 0x15ca + 17cc: 93ff 11fe beq 0x15ca + 17d0: 9000 1206 beq 0x19d6 + 17d4: 9000 1202 beq 0x19d6 + ... + 19d8: 0000 nop! + 19da: 3a00 bne! 0x19da + 19dc: 3bff bne! 0x19da + 19de: 3bfe bne! 0x19da + 19e0: 3bfd bne! 0x19da + 19e2: 93ff 17f8 bne 0x19da + 19e6: 93ff 17f4 bne 0x19da + 19ea: 3bf8 bne! 0x19da + 19ec: 93ff 17ee bne 0x19da + 19f0: 93ff 17ea bne 0x19da + 19f4: 93ff 17e7 bnel 0x19da + ... + 1bf8: 93ff 15e2 bne 0x19da + 1bfc: 93ff 15de bne 0x19da + 1c00: 93ff 15da bne 0x19da + 1c04: 93ff 15d6 bne 0x19da + 1c08: 93ff 15d2 bne 0x19da + 1c0c: 93ff 15ce bne 0x19da + 1c10: 93ff 15ca bne 0x19da + 1c14: 93ff 15c6 bne 0x19da + 1c18: 93ff 15c2 bne 0x19da + 1c1c: 93ff 15bf bnel 0x19da + 1c20: 9000 1646 bne 0x1e66 + 1c24: 9000 1642 bne 0x1e66 + 1c28: 9000 163e bne 0x1e66 + 1c2c: 9000 163a bne 0x1e66 + 1c30: 9000 1636 bne 0x1e66 + 1c34: 9000 1632 bne 0x1e66 + 1c38: 9000 162e bne 0x1e66 + 1c3c: 9000 162a bne 0x1e66 + 1c40: 9000 1626 bne 0x1e66 + 1c44: 9000 1623 bnel 0x1e66 + ... + 1e48: 3a0f bne! 0x1e66 + 1e4a: 3a0e bne! 0x1e66 + 1e4c: 3a0d bne! 0x1e66 + 1e4e: 3a0c bne! 0x1e66 + 1e50: 9000 1416 bne 0x1e66 + 1e54: 9000 1412 bne 0x1e66 + 1e58: 3a07 bne! 0x1e66 + 1e5a: 9000 140c bne 0x1e66 + 1e5e: 9000 1408 bne 0x1e66 + 1e62: 9000 1405 bnel 0x1e66 + ... + 2066: 0000 nop! + 2068: 3b00 bne! 0x1e68 + 206a: 93ff 15fe bne 0x1e68 + 206e: 9000 1606 bne 0x2274 + 2072: 9000 1602 bne 0x2274 + ... + 2276: 0000 nop! + 2278: 3c00 bgt! 0x2278 + 227a: 3dff bgt! 0x2278 + 227c: 3dfe bgt! 0x2278 + 227e: 3dfd bgt! 0x2278 + 2280: 93ff 1bf8 bgt 0x2278 + 2284: 93ff 1bf4 bgt 0x2278 + 2288: 3df8 bgt! 0x2278 + 228a: 93ff 1bee bgt 0x2278 + 228e: 93ff 1bea bgt 0x2278 + 2292: 93ff 1be7 bgtl 0x2278 + ... + 2496: 93ff 19e2 bgt 0x2278 + 249a: 93ff 19de bgt 0x2278 + 249e: 93ff 19da bgt 0x2278 + 24a2: 93ff 19d6 bgt 0x2278 + 24a6: 93ff 19d2 bgt 0x2278 + 24aa: 93ff 19ce bgt 0x2278 + 24ae: 93ff 19ca bgt 0x2278 + 24b2: 93ff 19c6 bgt 0x2278 + 24b6: 93ff 19c2 bgt 0x2278 + 24ba: 93ff 19bf bgtl 0x2278 + 24be: 9000 1a46 bgt 0x2704 + 24c2: 9000 1a42 bgt 0x2704 + 24c6: 9000 1a3e bgt 0x2704 + 24ca: 9000 1a3a bgt 0x2704 + 24ce: 9000 1a36 bgt 0x2704 + 24d2: 9000 1a32 bgt 0x2704 + 24d6: 9000 1a2e bgt 0x2704 + 24da: 9000 1a2a bgt 0x2704 + 24de: 9000 1a26 bgt 0x2704 + 24e2: 9000 1a23 bgtl 0x2704 + ... + 26e6: 3c0f bgt! 0x2704 + 26e8: 3c0e bgt! 0x2704 + 26ea: 3c0d bgt! 0x2704 + 26ec: 3c0c bgt! 0x2704 + 26ee: 9000 1816 bgt 0x2704 + 26f2: 9000 1812 bgt 0x2704 + 26f6: 3c07 bgt! 0x2704 + 26f8: 9000 180c bgt 0x2704 + 26fc: 9000 1808 bgt 0x2704 + 2700: 9000 1805 bgtl 0x2704 + ... + 2904: 0000 nop! + 2906: 3d00 bgt! 0x2706 + 2908: 93ff 19fe bgt 0x2706 + 290c: 9000 1a06 bgt 0x2b12 + 2910: 9000 1a02 bgt 0x2b12 + ... + 2b14: 0000 nop! + 2b16: 3e00 ble! 0x2b16 + 2b18: 3fff ble! 0x2b16 + 2b1a: 3ffe ble! 0x2b16 + 2b1c: 3ffd ble! 0x2b16 + 2b1e: 93ff 1ff8 ble 0x2b16 + 2b22: 93ff 1ff4 ble 0x2b16 + 2b26: 3ff8 ble! 0x2b16 + 2b28: 93ff 1fee ble 0x2b16 + 2b2c: 93ff 1fea ble 0x2b16 + 2b30: 93ff 1fe7 blel 0x2b16 + ... + 2d34: 93ff 1de2 ble 0x2b16 + 2d38: 93ff 1dde ble 0x2b16 + 2d3c: 93ff 1dda ble 0x2b16 + 2d40: 93ff 1dd6 ble 0x2b16 + 2d44: 93ff 1dd2 ble 0x2b16 + 2d48: 93ff 1dce ble 0x2b16 + 2d4c: 93ff 1dca ble 0x2b16 + 2d50: 93ff 1dc6 ble 0x2b16 + 2d54: 93ff 1dc2 ble 0x2b16 + 2d58: 93ff 1dbf blel 0x2b16 + 2d5c: 9000 1e46 ble 0x2fa2 + 2d60: 9000 1e42 ble 0x2fa2 + 2d64: 9000 1e3e ble 0x2fa2 + 2d68: 9000 1e3a ble 0x2fa2 + 2d6c: 9000 1e36 ble 0x2fa2 + 2d70: 9000 1e32 ble 0x2fa2 + 2d74: 9000 1e2e ble 0x2fa2 + 2d78: 9000 1e2a ble 0x2fa2 + 2d7c: 9000 1e26 ble 0x2fa2 + 2d80: 9000 1e23 blel 0x2fa2 + ... + 2f84: 3e0f ble! 0x2fa2 + 2f86: 3e0e ble! 0x2fa2 + 2f88: 3e0d ble! 0x2fa2 + 2f8a: 3e0c ble! 0x2fa2 + 2f8c: 9000 1c16 ble 0x2fa2 + 2f90: 9000 1c12 ble 0x2fa2 + 2f94: 3e07 ble! 0x2fa2 + 2f96: 9000 1c0c ble 0x2fa2 + 2f9a: 9000 1c08 ble 0x2fa2 + 2f9e: 9000 1c05 blel 0x2fa2 + ... + 31a2: 0000 nop! + 31a4: 3f00 ble! 0x2fa4 + 31a6: 93ff 1dfe ble 0x2fa4 + 31aa: 9000 1e06 ble 0x33b0 + 31ae: 9000 1e02 ble 0x33b0 + ... + 33b2: 0000 nop! + 33b4: 3200 bcnz! 0x33b4 + 33b6: 33ff bcnz! 0x33b4 + 33b8: 33fe bcnz! 0x33b4 + 33ba: 33fd bcnz! 0x33b4 + 33bc: 93ff 3bf8 bcnz 0x33b4 + 33c0: 93ff 3bf4 bcnz 0x33b4 + 33c4: 33f8 bcnz! 0x33b4 + 33c6: 93ff 3bee bcnz 0x33b4 + 33ca: 93ff 3bea bcnz 0x33b4 + 33ce: 93ff 3be7 bcnzl 0x33b4 + ... + 35d2: 93ff 39e2 bcnz 0x33b4 + 35d6: 93ff 39de bcnz 0x33b4 + 35da: 93ff 39da bcnz 0x33b4 + 35de: 93ff 39d6 bcnz 0x33b4 + 35e2: 93ff 39d2 bcnz 0x33b4 + 35e6: 93ff 39ce bcnz 0x33b4 + 35ea: 93ff 39ca bcnz 0x33b4 + 35ee: 93ff 39c6 bcnz 0x33b4 + 35f2: 93ff 39c2 bcnz 0x33b4 + 35f6: 93ff 39bf bcnzl 0x33b4 + 35fa: 9000 3a46 bcnz 0x3840 + 35fe: 9000 3a42 bcnz 0x3840 + 3602: 9000 3a3e bcnz 0x3840 + 3606: 9000 3a3a bcnz 0x3840 + 360a: 9000 3a36 bcnz 0x3840 + 360e: 9000 3a32 bcnz 0x3840 + 3612: 9000 3a2e bcnz 0x3840 + 3616: 9000 3a2a bcnz 0x3840 + 361a: 9000 3a26 bcnz 0x3840 + 361e: 9000 3a23 bcnzl 0x3840 + ... + 3822: 320f bcnz! 0x3840 + 3824: 320e bcnz! 0x3840 + 3826: 320d bcnz! 0x3840 + 3828: 320c bcnz! 0x3840 + 382a: 9000 3816 bcnz 0x3840 + 382e: 9000 3812 bcnz 0x3840 + 3832: 3207 bcnz! 0x3840 + 3834: 9000 380c bcnz 0x3840 + 3838: 9000 3808 bcnz 0x3840 + 383c: 9000 3805 bcnzl 0x3840 + ... + 3a40: 0000 nop! + 3a42: 3300 bcnz! 0x3842 + 3a44: 93ff 39fe bcnz 0x3842 + 3a48: 9000 3a06 bcnz 0x3c4e + 3a4c: 9000 3a02 bcnz 0x3c4e + ... + 3c50: 0000 nop! + 3c52: 3000 b! 0x3c52 + 3c54: 31ff b! 0x3c52 + 3c56: 31fe b! 0x3c52 + 3c58: 31fd b! 0x3c52 + 3c5a: 93ff 3ff8 b 0x3c52 + 3c5e: 93ff 3ff4 b 0x3c52 + 3c62: 31f8 b! 0x3c52 + 3c64: 93ff 3fee b 0x3c52 + 3c68: 93ff 3fea b 0x3c52 + 3c6c: 93ff 3fe7 bl 0x3c52 + ... + 3e70: 93ff 3de2 b 0x3c52 + 3e74: 93ff 3dde b 0x3c52 + 3e78: 93ff 3dda b 0x3c52 + 3e7c: 93ff 3dd6 b 0x3c52 + 3e80: 93ff 3dd2 b 0x3c52 + 3e84: 93ff 3dce b 0x3c52 + 3e88: 93ff 3dca b 0x3c52 + 3e8c: 93ff 3dc6 b 0x3c52 + 3e90: 93ff 3dc2 b 0x3c52 + 3e94: 93ff 3dbf bl 0x3c52 + 3e98: 9000 3e46 b 0x40de + 3e9c: 9000 3e42 b 0x40de + 3ea0: 9000 3e3e b 0x40de + 3ea4: 9000 3e3a b 0x40de + 3ea8: 9000 3e36 b 0x40de + 3eac: 9000 3e32 b 0x40de + 3eb0: 9000 3e2e b 0x40de + 3eb4: 9000 3e2a b 0x40de + 3eb8: 9000 3e26 b 0x40de + 3ebc: 9000 3e23 bl 0x40de + ... + 40c0: 300f b! 0x40de + 40c2: 300e b! 0x40de + 40c4: 300d b! 0x40de + 40c6: 300c b! 0x40de + 40c8: 9000 3c16 b 0x40de + 40cc: 9000 3c12 b 0x40de + 40d0: 3007 b! 0x40de + 40d2: 9000 3c0c b 0x40de + 40d6: 9000 3c08 b 0x40de + 40da: 9000 3c05 bl 0x40de + ... + 42de: 0000 nop! + 42e0: 3100 b! 0x40e0 + 42e2: 93ff 3dfe b 0x40e0 + 42e6: 9000 3e06 b 0x44ec + 42ea: 9000 3e02 b 0x44ec + ... + 44ee: 0000 nop! + 44f0: 0080 br! r0 + 44f2: 008f br! r15 + 44f4: 0080 br! r0 + 44f6: 0080 br! r0 + 44f8: 0080 br! r0 + 44fa: 0080 br! r0 + 44fc: 0080 br! r0 + 44fe: 0080 br! r0 + 4500: 0080 br! r0 + 4502: 0080 br! r0 + 4504: 0090 br! r16 + 4506: 009f br! r31 + 4508: 00a0 brl! r0 + 450a: 00af brl! r15 + 450c: 00a0 brl! r0 + 450e: 00a0 brl! r0 + 4510: 00a0 brl! r0 + 4512: 00a0 brl! r0 + 4514: 00a0 brl! r0 + 4516: 00a0 brl! r0 + 4518: 00a0 brl! r0 + 451a: 00a0 brl! r0 + 451c: 00b0 brl! r16 + 451e: 00bf brl! r31 + 4520: 8000 3c4c bcmpeq r0, r15 ,0x4520 + 4524: 83ef 43cc bcmpeq r15, r16 ,0x4520 + 4528: 83ef 7f4c bcmpeq r15, r31 ,0x4520 + 452c: 83f0 7ecc bcmpeq r16, r31 ,0x4520 + ... + 4730: 440f cmp! r0, r15 + 4732: 93ff 11ee beq 0x4520 + 4736: 45f0 cmp! r15, r16 + 4738: 93ff 11e8 beq 0x4520 + 473c: 45ff cmp! r15, r31 + 473e: 93ff 11e2 beq 0x4520 + 4742: 461f cmp! r16, r31 + 4744: 93ff 11dc beq 0x4520 + 4748: 440f cmp! r0, r15 + 474a: 9000 1226 beq 0x4970 + 474e: 45f0 cmp! r15, r16 + 4750: 9000 1220 beq 0x4970 + 4754: 45ff cmp! r15, r31 + 4756: 9000 121a beq 0x4970 + 475a: 461f cmp! r16, r31 + 475c: 9000 1214 beq 0x4970 + ... + 4960: 8000 3e4c bcmpeq r0, r15 ,0x4970 + 4964: 800f 41cc bcmpeq r15, r16 ,0x4970 + 4968: 800f 7d4c bcmpeq r15, r31 ,0x4970 + 496c: 8010 7ccc bcmpeq r16, r31 ,0x4970 + ... + 4b70: 0000 nop! + 4b72: 8200 3c4c bcmpeq r0, r15 ,0x4972 + 4b76: 460f cmp! r16, r15 + 4b78: 93ff 11fa beq 0x4972 + 4b7c: 440f cmp! r0, r15 + 4b7e: 9000 1208 beq 0x4d86 + 4b82: 460f cmp! r16, r15 + 4b84: 9000 1202 beq 0x4d86 + ... + 4d88: 8000 3c4e bcmpne r0, r15 ,0x4d88 + 4d8c: 83ef 43ce bcmpne r15, r16 ,0x4d88 + 4d90: 83ef 7f4e bcmpne r15, r31 ,0x4d88 + 4d94: 83f0 7ece bcmpne r16, r31 ,0x4d88 + ... + 4f98: 440f cmp! r0, r15 + 4f9a: 93ff 15ee bne 0x4d88 + 4f9e: 45f0 cmp! r15, r16 + 4fa0: 93ff 15e8 bne 0x4d88 + 4fa4: 45ff cmp! r15, r31 + 4fa6: 93ff 15e2 bne 0x4d88 + 4faa: 461f cmp! r16, r31 + 4fac: 93ff 15dc bne 0x4d88 + 4fb0: 440f cmp! r0, r15 + 4fb2: 9000 1626 bne 0x51d8 + 4fb6: 45f0 cmp! r15, r16 + 4fb8: 9000 1620 bne 0x51d8 + 4fbc: 45ff cmp! r15, r31 + 4fbe: 9000 161a bne 0x51d8 + 4fc2: 461f cmp! r16, r31 + 4fc4: 9000 1614 bne 0x51d8 + ... + 51c8: 8000 3e4e bcmpne r0, r15 ,0x51d8 + 51cc: 800f 41ce bcmpne r15, r16 ,0x51d8 + 51d0: 800f 7d4e bcmpne r15, r31 ,0x51d8 + 51d4: 8010 7cce bcmpne r16, r31 ,0x51d8 + ... + 53d8: 0000 nop! + 53da: 8200 3c4e bcmpne r0, r15 ,0x51da + 53de: 460f cmp! r16, r15 + 53e0: 93ff 15fa bne 0x51da + 53e4: 440f cmp! r0, r15 + 53e6: 9000 1608 bne 0x55ee + 53ea: 460f cmp! r16, r15 + 53ec: 9000 1602 bne 0x55ee + ... + 55f0: 8000 004c bcmpeqz r0, 0x55f0 + 55f4: 83ef 03cc bcmpeqz r15, 0x55f0 + 55f8: 83f0 034c bcmpeqz r16, 0x55f0 + 55fc: 83ff 02cc bcmpeqz r31, 0x55f0 + ... + 5800: 6000 cmpi! r0, 0 + 5802: 93ff 11ee beq 0x55f0 + 5806: 61e0 cmpi! r15, 0 + 5808: 93ff 11e8 beq 0x55f0 + 580c: 6200 cmpi! r16, 0 + 580e: 93ff 11e2 beq 0x55f0 + 5812: 63e0 cmpi! r31, 0 + 5814: 93ff 11dc beq 0x55f0 + 5818: 6000 cmpi! r0, 0 + 581a: 9000 1226 beq 0x5a40 + 581e: 61e0 cmpi! r15, 0 + 5820: 9000 1220 beq 0x5a40 + 5824: 6200 cmpi! r16, 0 + 5826: 9000 121a beq 0x5a40 + 582a: 63e0 cmpi! r31, 0 + 582c: 9000 1214 beq 0x5a40 + ... + 5a30: 8000 024c bcmpeqz r0, 0x5a40 + 5a34: 800f 01cc bcmpeqz r15, 0x5a40 + 5a38: 8010 014c bcmpeqz r16, 0x5a40 + 5a3c: 801f 00cc bcmpeqz r31, 0x5a40 + ... + 5c40: 0000 nop! + 5c42: 8200 004c bcmpeqz r0, 0x5a42 + 5c46: 6200 cmpi! r16, 0 + 5c48: 93ff 11fa beq 0x5a42 + 5c4c: 6000 cmpi! r0, 0 + 5c4e: 9000 1208 beq 0x5e56 + 5c52: 6200 cmpi! r16, 0 + 5c54: 9000 1202 beq 0x5e56 + ... + 5e58: 8000 004e bcmpnez r0, 0x5e58 + 5e5c: 83ef 03ce bcmpnez r15, 0x5e58 + 5e60: 83f0 034e bcmpnez r16, 0x5e58 + 5e64: 83ff 02ce bcmpnez r31, 0x5e58 + ... + 6068: 6000 cmpi! r0, 0 + 606a: 93ff 15ee bne 0x5e58 + 606e: 61e0 cmpi! r15, 0 + 6070: 93ff 15e8 bne 0x5e58 + 6074: 6200 cmpi! r16, 0 + 6076: 93ff 15e2 bne 0x5e58 + 607a: 63e0 cmpi! r31, 0 + 607c: 93ff 15dc bne 0x5e58 + 6080: 6000 cmpi! r0, 0 + 6082: 9000 1626 bne 0x62a8 + 6086: 61e0 cmpi! r15, 0 + 6088: 9000 1620 bne 0x62a8 + 608c: 6200 cmpi! r16, 0 + 608e: 9000 161a bne 0x62a8 + 6092: 63e0 cmpi! r31, 0 + 6094: 9000 1614 bne 0x62a8 + ... + 6298: 8000 024e bcmpnez r0, 0x62a8 + 629c: 800f 01ce bcmpnez r15, 0x62a8 + 62a0: 8010 014e bcmpnez r16, 0x62a8 + 62a4: 801f 00ce bcmpnez r31, 0x62a8 + ... + 64a8: 0000 nop! + 64aa: 8200 004e bcmpnez r0, 0x62aa + 64ae: 6200 cmpi! r16, 0 + 64b0: 93ff 15fa bne 0x62aa + 64b4: 6000 cmpi! r0, 0 + 64b6: 9000 1608 bne 0x66be + 64ba: 6200 cmpi! r16, 0 + 64bc: 9000 1602 bne 0x66be + ... +#pass diff --git a/gas/testsuite/gas/score/branch_32.s b/gas/testsuite/gas/score/branch_32.s new file mode 100644 index 00000000000..aba4dcd8649 --- /dev/null +++ b/gas/testsuite/gas/score/branch_32.s @@ -0,0 +1,181 @@ +/* + * tests for branch instruction relaxation + * + * Author: libin + */ + +.include "relaxation_macro.h" + +.macro _b_op_pattern insn insn1 +.balign 2 + +/* + * for local label 1, assembler should NOT alter instructions before .skip; + * but it SHOULD alter instructions afte it. + */ +1: + insn_16 "\insn! 1b" + tran_16_32 "\insn! 1b", "\insn 1b" + insn_16 "\insn1 1b" +.skip 512 + insn_16 "\insn! 1b" + tran_16_32 "\insn! 1b", "\insn 1b" + insn_16 "\insn1 1b" + +/* + * for local label 2, assembler SHOULD alter instructions before .skip; + * but it should NOT alter instructions after it. + */ + insn_16 "\insn! 2f" + tran_16_32 "\insn! 2f", "\insn 2f" + insn_16 "\insn1 2f" +.skip 511 + insn_16 "\insn! 2f" + tran_16_32 "\insn! 2f", "\insn 2f" + insn_16 "\insn1 2f" +2: + nop! + +/* tests for boundary */ +3: +.skip 512 + insn_16 "\insn! 3b" + insn_16 "\insn! 3b" + + insn_16 "\insn! 4f" + insn_16 "\insn! 4f" +.skip 511 +4: + nop! +.endm + +.macro _br_op_pattern insn +.balign 2 + insn_32 "\insn r0" + insn_32 "\insn r15" + + tran_16_32 "\insn! r0", "\insn r0" + + /* shouldn't alter */ + insn_32 "\insn r16" + insn_32 "\insn r31" +.endm + +.macro _bcmp_op_pattern1 insn +.balign 2 + +/* as will give "Using temp register(r1)" warning if you using r1 */ + +/* + * for local label 1, assembler should NOT alter instructions before .skip; + * but it SHOULD alter instructions afte it. + */ +1: + insn_32 "\insn r0, r15, 1b" + insn_32 "\insn r15, r16, 1b" + insn_32 "\insn r15, r31, 1b" + insn_32 "\insn r16, r31, 1b" +.skip 512 + insn_32 "\insn r0, r15, 1b" + insn_32 "\insn r15, r16, 1b" + insn_32 "\insn r15, r31, 1b" + insn_32 "\insn r16, r31, 1b" + +/* + * for local label 2, assembler SHOULD alter instructions before .skip; + * but it should NOT alter instructions after it. + */ + insn_32 "\insn r0, r15, 2f" + insn_32 "\insn r15, r16, 2f" + insn_32 "\insn r15, r31, 2f" + insn_32 "\insn r16, r31, 2f" +.skip 511 + insn_32 "\insn r0, r15, 2f" + insn_32 "\insn r15, r16, 2f" + insn_32 "\insn r15, r31, 2f" + insn_32 "\insn r16, r31, 2f" +2: + nop! + +/* tests for boundary */ +3: +.skip 512 + insn_32 "\insn r0, r15, 3b" + insn_32 "\insn r16, r15, 3b" + + insn_32 "\insn r0, r15, 4f" + insn_32 "\insn r16, r15, 4f" +.skip 511 +4: +.endm + +.macro _bcmp_op_pattern2 insn +.balign 2 + +/* as will give "Using temp register(r1)" warning if you using r1 */ + +/* + * for local label 1, assembler should NOT alter instructions before .skip; + * but it SHOULD alter instructions afte it. + */ +1: + insn_32 "\insn r0, 1b" + insn_32 "\insn r15, 1b" + insn_32 "\insn r16, 1b" + insn_32 "\insn r31, 1b" +.skip 512 + insn_32 "\insn r0, 1b" + insn_32 "\insn r15, 1b" + insn_32 "\insn r16, 1b" + insn_32 "\insn r31, 1b" + +/* + * for local label 2, assembler SHOULD alter instructions before .skip; + * but it should NOT alter instructions after it. + */ + insn_32 "\insn r0, 2f" + insn_32 "\insn r15, 2f" + insn_32 "\insn r16, 2f" + insn_32 "\insn r31, 2f" +.skip 511 + insn_32 "\insn r0, 2f" + insn_32 "\insn r15, 2f" + insn_32 "\insn r16, 2f" + insn_32 "\insn r31, 2f" +2: + nop! + +/* tests for boundary */ +3: +.skip 512 + insn_32 "\insn r0, 3b" + insn_32 "\insn r16, 3b" + + insn_32 "\insn r0, 4f" + insn_32 "\insn r16, 4f" +.skip 511 +4: +.endm + +.text +/* b Disp19 <-> b! Disp9 */ +_b_op_pattern "bgtu", "bgtul" +_b_op_pattern "bleu", "bleul" +_b_op_pattern "beq", "beql" +_b_op_pattern "bne", "bnel" +_b_op_pattern "bgt", "bgtl" +_b_op_pattern "ble", "blel" +_b_op_pattern "bcnz", "bcnzl" +_b_op_pattern "b", "bl" + +/* br rD <-> br! rD */ +_br_op_pattern "br" +_br_op_pattern "brl" + +/* bcmpeq/bcmpne rA,rB,Disp9 -> cmp/cmp! rA, rB; beq/bne Disp19 */ +_bcmp_op_pattern1 "bcmpeq" +_bcmp_op_pattern1 "bcmpne" + +/* bcmpeqz/bcmpnez rA,Disp9 -> cmpi! rA, 0; beq/bne Disp19 */ +_bcmp_op_pattern2 "bcmpeqz" +_bcmp_op_pattern2 "bcmpnez" diff --git a/gas/testsuite/gas/score/cmp_32-lt.d b/gas/testsuite/gas/score/cmp_32-lt.d new file mode 100644 index 00000000000..3f87201186f --- /dev/null +++ b/gas/testsuite/gas/score/cmp_32-lt.d @@ -0,0 +1,12 @@ +#as: -march=score3 -I${srcdir}/${subdir} -EL +#objdump: -s +#source: cmp_32.s + +.*: file format elf32-littlescore + +Contents of section .text: + 0000 0f440f44 0f440f44 0f440f44 0f440f44 .* + 0010 0f441044 00461f46 10600f60 f061ef61 .* + 0020 10601060 10601060 10601060 10601060 .* + 0030 1062ef63 0b84df7f e8852100 08862100 .* +#pass diff --git a/gas/testsuite/gas/score/cmp_32.d b/gas/testsuite/gas/score/cmp_32.d new file mode 100644 index 00000000000..7c019632241 --- /dev/null +++ b/gas/testsuite/gas/score/cmp_32.d @@ -0,0 +1,39 @@ +#as: -march=score3 -I${srcdir}/${subdir} +#objdump: -d +#source: cmp_32.s + +.*: file format .* + +Disassembly of section .text: + +00000000 <.text>: + 0: 440f cmp! r0, r15 + 2: 440f cmp! r0, r15 + 4: 440f cmp! r0, r15 + 6: 440f cmp! r0, r15 + 8: 440f cmp! r0, r15 + a: 440f cmp! r0, r15 + c: 440f cmp! r0, r15 + e: 440f cmp! r0, r15 + 10: 440f cmp! r0, r15 + 12: 4410 cmp! r0, r16 + 14: 4600 cmp! r16, r0 + 16: 461f cmp! r16, r31 + 18: 6010 cmpi! r0, -16 + 1a: 600f cmpi! r0, 15 + 1c: 61f0 cmpi! r15, -16 + 1e: 61ef cmpi! r15, 15 + 20: 6010 cmpi! r0, -16 + 22: 6010 cmpi! r0, -16 + 24: 6010 cmpi! r0, -16 + 26: 6010 cmpi! r0, -16 + 28: 6010 cmpi! r0, -16 + 2a: 6010 cmpi! r0, -16 + 2c: 6010 cmpi! r0, -16 + 2e: 6010 cmpi! r0, -16 + 30: 6210 cmpi! r16, -16 + 32: 63ef cmpi! r31, 15 + 34: 840b 7fdf cmpi.c r0, -17 + 38: 85e8 0021 cmpi.c r15, 16 + 3c: 8608 0021 cmpi.c r16, 16 +#pass diff --git a/gas/testsuite/gas/score/cmp_32.s b/gas/testsuite/gas/score/cmp_32.s new file mode 100644 index 00000000000..162663eb2ac --- /dev/null +++ b/gas/testsuite/gas/score/cmp_32.s @@ -0,0 +1,33 @@ +/* + * tests for compare instruction relaxation + * + * Author: libin + */ + +.include "relaxation_macro.h" + +.text +/* cmp.c rA,rB -> cmp! rA,rB */ +insn_32 "cmp.c r0, r15" + +tran_16_32 "cmp! r0, r15", "cmp.c r0, r15" + +/* shouln't alter */ +insn_32 "cmp.c r0, r16" +insn_32 "cmp.c r16, r0" +insn_32 "cmp.c r16, r31" + +/* cmpi.c rD,SImm16 -> cmpi! rD,SImm5 */ +insn_32 "cmpi.c r0, -16" +insn_32 "cmpi.c r0, 15" +insn_32 "cmpi.c r15, -16" +insn_32 "cmpi.c r15, 15" + +tran_16_32 "cmpi! r0, -16", "cmpi.c r0, -16" + +/* shouldn't alter */ +insn_32 "cmpi.c r16, -16" +insn_32 "cmpi.c r31, 15" +insn_32 "cmpi.c r0, -17" +insn_32 "cmpi.c r15, 16" +insn_32 "cmpi.c r16, 16" diff --git a/gas/testsuite/gas/score/load_store_32-lt.d b/gas/testsuite/gas/score/load_store_32-lt.d new file mode 100644 index 00000000000..b78f380160d --- /dev/null +++ b/gas/testsuite/gas/score/load_store_32-lt.d @@ -0,0 +1,19 @@ +#as: -march=score3 -I${srcdir}/${subdir} -EL +#objdump: -s +#source: load_store_32.s + +.*: file format elf32-littlescore + +Contents of section .text: + 0000 0010001f e010e01f 1f101f1f ff10ff1f .* + 0010 1f101f10 1f101f10 1f101f10 1f101f10 .* + 0020 00c20000 08c07c00 08c27c00 07c0ff7f .* + 0030 07c08000 0020002f e020e02f 1f201f2f .* + 0040 ff20ff2f 1f201f20 1f201f20 1f201f20 .* + 0050 1f201f20 00d20000 08d07c00 08d27c00 .* + 0060 07d0ff7f 07d08000 0064e065 1f64ff65 .* + 0070 00640064 00640064 00640064 00640064 .* + 0080 00661b84 fe7f1884 40001886 40004200 .* + 0090 4f005000 829c2000 809ce07f 62006f00 .* + 00a0 7000828c e47f808c 24000000 .* +#pass diff --git a/gas/testsuite/gas/score/load_store_32.d b/gas/testsuite/gas/score/load_store_32.d new file mode 100644 index 00000000000..5c361497937 --- /dev/null +++ b/gas/testsuite/gas/score/load_store_32.d @@ -0,0 +1,79 @@ +#as: -march=score3 -I${srcdir}/${subdir} +#objdump: -d +#source: load_store_32.s + +.*: file format .* + +Disassembly of section .text: + +00000000 <.text>: + 0: 1000 lw! r0, \[r0,0\] + 2: 1f00 lw! r15, \[r0,0\] + 4: 10e0 lw! r0, \[r7,0\] + 6: 1fe0 lw! r15, \[r7,0\] + 8: 101f lw! r0, \[r0,124\] + a: 1f1f lw! r15, \[r0,124\] + c: 10ff lw! r0, \[r7,124\] + e: 1fff lw! r15, \[r7,124\] + 10: 101f lw! r0, \[r0,124\] + 12: 101f lw! r0, \[r0,124\] + 14: 101f lw! r0, \[r0,124\] + 16: 101f lw! r0, \[r0,124\] + 18: 101f lw! r0, \[r0,124\] + 1a: 101f lw! r0, \[r0,124\] + 1c: 101f lw! r0, \[r0,124\] + 1e: 101f lw! r0, \[r0,124\] + 20: c200 0000 lw r16, \[r0, 0\] + 24: c008 007c lw r0, \[r8, 124\] + 28: c208 007c lw r16, \[r8, 124\] + 2c: c007 7fff lw r0, \[r7, -1\] + 30: c007 0080 lw r0, \[r7, 128\] + 34: 2000 sw! r0, \[r0,0\] + 36: 2f00 sw! r15, \[r0,0\] + 38: 20e0 sw! r0, \[r7,0\] + 3a: 2fe0 sw! r15, \[r7,0\] + 3c: 201f sw! r0, \[r0,124\] + 3e: 2f1f sw! r15, \[r0,124\] + 40: 20ff sw! r0, \[r7,124\] + 42: 2fff sw! r15, \[r7,124\] + 44: 201f sw! r0, \[r0,124\] + 46: 201f sw! r0, \[r0,124\] + 48: 201f sw! r0, \[r0,124\] + 4a: 201f sw! r0, \[r0,124\] + 4c: 201f sw! r0, \[r0,124\] + 4e: 201f sw! r0, \[r0,124\] + 50: 201f sw! r0, \[r0,124\] + 52: 201f sw! r0, \[r0,124\] + 54: d200 0000 sw r16, \[r0, 0\] + 58: d008 007c sw r0, \[r8, 124\] + 5c: d208 007c sw r16, \[r8, 124\] + 60: d007 7fff sw r0, \[r7, -1\] + 64: d007 0080 sw r0, \[r7, 128\] + 68: 6400 ldiu! r0, 0 + 6a: 65e0 ldiu! r15, 0 + 6c: 641f ldiu! r0, 31 + 6e: 65ff ldiu! r15, 31 + 70: 6400 ldiu! r0, 0 + 72: 6400 ldiu! r0, 0 + 74: 6400 ldiu! r0, 0 + 76: 6400 ldiu! r0, 0 + 78: 6400 ldiu! r0, 0 + 7a: 6400 ldiu! r0, 0 + 7c: 6400 ldiu! r0, 0 + 7e: 6400 ldiu! r0, 0 + 80: 6600 ldiu! r16, 0 + 82: 841b 7ffe ldi r0, 0xffff\(-1\) + 86: 8418 0040 ldi r0, 0x20\(32\) + 8a: 8618 0040 ldi r16, 0x20\(32\) + 8e: 0042 pop! r2 + 90: 004f pop! r15 + 92: 0050 pop! r16 + 94: 9c82 0020 lw r4, \[r2\]\+, 4 + 98: 9c80 7fe0 lw r4, \[r0\]\+, -4 + 9c: 0062 push! r2 + 9e: 006f push! r15 + a0: 0070 push! r16 + a2: 8c82 7fe4 sw r4, \[r2, -4\]\+ + a6: 8c80 0024 sw r4, \[r0, 4\]\+ + ... +#pass diff --git a/gas/testsuite/gas/score/load_store_32.s b/gas/testsuite/gas/score/load_store_32.s new file mode 100644 index 00000000000..046553f2788 --- /dev/null +++ b/gas/testsuite/gas/score/load_store_32.s @@ -0,0 +1,71 @@ +/* + * tests for load/store instruction relaxation + * + * Author: libin + */ + +.include "relaxation_macro.h" + +.macro _ls_op_pattern insn +.balign 2 + insn_32 "\insn r0, [r0,0]" + insn_32 "\insn r15, [r0,0]" + insn_32 "\insn r0, [r7,0]" + insn_32 "\insn r15, [r7,0]" +/* NOTE: offset MUST be word aligned */ + insn_32 "\insn r0, [r0,124]" + insn_32 "\insn r15, [r0,124]" + insn_32 "\insn r0, [r7,124]" + insn_32 "\insn r15, [r7,124]" + + tran_16_32 "\insn! r0,[r0,124]", "\insn r0,[r0,124]" + + /* shouldn't alter */ + insn_32 "\insn r16, [r0, 0]" + insn_32 "\insn r0, [r8, 124]" + insn_32 "\insn r16, [r8, 124]" + insn_32 "\insn r0, [r7, -1]" + insn_32 "\insn r0, [r7, 128]" +.endm + +.text +/* lw/sw rD,[rA,SImm15] -> lw!/sw! rD,[rA,Imm5] */ +_ls_op_pattern "lw" +_ls_op_pattern "sw" + +/* ldi rD,SImm16 -> ldiu! rD,Imm6 */ +.balign 2 +insn_32 "ldi r0, 0" +insn_32 "ldi r15, 0" +insn_32 "ldi r0, 31" +insn_32 "ldi r15, 31" + +tran_16_32 "ldiu! r0, 0", "ldi r0, 0" + +/* shouldn't alter */ +insn_32 "ldi r16, 0" +insn_32 "ldi r0, -1" +insn_32 "ldi r0, 32" +insn_32 "ldi r16, 32" + +/* + * lw rD,[rA]+,SImm12 -> pop! rD + * + * r0: stack pointer(sp) + */ +insn_32 "lw r2, [r0]+, 4" +insn_32 "lw r15, [r0]+, 4" + +/* shouldn't alter */ +insn_32 "lw r16, [r0]+, 4" +insn_32 "lw r4, [r2]+, 4" +insn_32 "lw r4, [r0]+, -4" + +/* sw rD,[rA,SImm12]+ -> push! rD */ +insn_32 "sw r2, [r0, -4]+" +insn_32 "sw r15, [r0, -4]+" + +/* shouldn't alter */ +insn_32 "sw r16, [r0, -4]+" +insn_32 "sw r4, [r2, -4]+" +insn_32 "sw r4, [r0, 4]+" diff --git a/gas/testsuite/gas/score/logical_32-lt.d b/gas/testsuite/gas/score/logical_32-lt.d new file mode 100644 index 00000000000..c961fead8b2 --- /dev/null +++ b/gas/testsuite/gas/score/logical_32-lt.d @@ -0,0 +1,13 @@ +#as: -march=score3 -I${srcdir}/${subdir} -EL +#objdump: -s +#source: logical_32.s + +.*: file format elf32-littlescore + +Contents of section .text: + 0000 0f4b0f4b 0f4b0f4b 0f4b0f4b 0f4b0f4b .* + 0010 0f4b0080 213c0080 20401082 20001082 .* + 0020 20440180 20080f4a 0f4a0f4a 0f4a0f4a .* + 0030 0f4a0f4a 0f4a0f4a 0080233c 00802240 .* + 0040 10822200 10822244 01802208 .* +#pass diff --git a/gas/testsuite/gas/score/logical_32.d b/gas/testsuite/gas/score/logical_32.d new file mode 100644 index 00000000000..170a55a8985 --- /dev/null +++ b/gas/testsuite/gas/score/logical_32.d @@ -0,0 +1,38 @@ +#as: -march=score3 -I${srcdir}/${subdir} +#objdump: -d +#source: logical_32.s + +.*: file format .* + +Disassembly of section .text: + +00000000 <.text>: + 0: 4b0f and! r0, r15 + 2: 4b0f and! r0, r15 + 4: 4b0f and! r0, r15 + 6: 4b0f and! r0, r15 + 8: 4b0f and! r0, r15 + a: 4b0f and! r0, r15 + c: 4b0f and! r0, r15 + e: 4b0f and! r0, r15 + 10: 4b0f and! r0, r15 + 12: 8000 3c21 and.c r0, r0, r15 + 16: 8000 4020 and r0, r0, r16 + 1a: 8210 0020 and r16, r16, r0 + 1e: 8210 4420 and r16, r16, r17 + 22: 8001 0820 and r0, r1, r2 + 26: 4a0f or! r0, r15 + 28: 4a0f or! r0, r15 + 2a: 4a0f or! r0, r15 + 2c: 4a0f or! r0, r15 + 2e: 4a0f or! r0, r15 + 30: 4a0f or! r0, r15 + 32: 4a0f or! r0, r15 + 34: 4a0f or! r0, r15 + 36: 4a0f or! r0, r15 + 38: 8000 3c23 or.c r0, r0, r15 + 3c: 8000 4022 or r0, r0, r16 + 40: 8210 0022 or r16, r16, r0 + 44: 8210 4422 or r16, r16, r17 + 48: 8001 0822 or r0, r1, r2 +#pass diff --git a/gas/testsuite/gas/score/logical_32.s b/gas/testsuite/gas/score/logical_32.s new file mode 100644 index 00000000000..af71c55f35f --- /dev/null +++ b/gas/testsuite/gas/score/logical_32.s @@ -0,0 +1,26 @@ +/* + * tests for logical instruction relaxation + * + * Author: libin + */ + +.include "relaxation_macro.h" + +.macro _logical_op_pattern insn insn1 + insn_32 "\insn r0, r0, r15" + + tran_16_32 "\insn! r0, r15", "\insn r0, r0, r15" + + /* shouldn't alter */ + .set r1 + insn_32 "\insn1 r0, r0, r15" + insn_32 "\insn r0, r0, r16" + insn_32 "\insn r16, r16, r0" + insn_32 "\insn r16, r16, r17" + insn_32 "\insn r0, r1, r2" +.endm + +.text +/* and/or rD,rA,rB -> and!/or! rD,rA */ +_logical_op_pattern "and", "and.c" +_logical_op_pattern "or", "or.c" diff --git a/gas/testsuite/gas/score/mv_32-lt.d b/gas/testsuite/gas/score/mv_32-lt.d new file mode 100644 index 00000000000..67e8f9641cd --- /dev/null +++ b/gas/testsuite/gas/score/mv_32-lt.d @@ -0,0 +1,10 @@ +#as: -march=score3 -I${srcdir}/${subdir} -EL +#objdump: -s +#source: mv_32.s + +.*: file format elf32-littlescore + +Contents of section .text: + 0000 0f400f40 0f400f40 0f400f40 0f400f40 .* + 0010 0f400f42 10401042 .* +#pass diff --git a/gas/testsuite/gas/score/mv_32.d b/gas/testsuite/gas/score/mv_32.d new file mode 100644 index 00000000000..57fbe3c2039 --- /dev/null +++ b/gas/testsuite/gas/score/mv_32.d @@ -0,0 +1,22 @@ +#as: -march=score3 -I${srcdir}/${subdir} +#objdump: -d +#source: mv_32.s + +.*: file format .* + +Disassembly of section .text: + +00000000 <.text>: + 0: 400f mv! r0, r15 + 2: 400f mv! r0, r15 + 4: 400f mv! r0, r15 + 6: 400f mv! r0, r15 + 8: 400f mv! r0, r15 + a: 400f mv! r0, r15 + c: 400f mv! r0, r15 + e: 400f mv! r0, r15 + 10: 400f mv! r0, r15 + 12: 420f mv! r16, r15 + 14: 4010 mv! r0, r16 + 16: 4210 mv! r16, r16 +#pass diff --git a/gas/testsuite/gas/score/mv_32.s b/gas/testsuite/gas/score/mv_32.s new file mode 100644 index 00000000000..885f80ad27f --- /dev/null +++ b/gas/testsuite/gas/score/mv_32.s @@ -0,0 +1,18 @@ +/* + * tests for mv instruction relaxation + * + * Author: libin + */ + +.include "relaxation_macro.h" + +.text +/* mv rD,rA -> mv! rD,rA */ +insn_32 "mv r0, r15" + +tran_16_32 "mv! r0, r15", "mv r0, r15" + +/* shouldn't alter */ +insn_32 "mv r16, r15" +insn_32 "mv r0, r16" +insn_32 "mv r16, r16" diff --git a/gas/testsuite/gas/score/relax_32.exp b/gas/testsuite/gas/score/relax_32.exp new file mode 100644 index 00000000000..9e260548a7b --- /dev/null +++ b/gas/testsuite/gas/score/relax_32.exp @@ -0,0 +1,24 @@ +# tests for instruction relaxation + +if [istarget score-*-*] then { + run_dump_test "arith_32" + run_dump_test "bit_32" + run_dump_test "branch_32" + run_dump_test "cmp_32" + run_dump_test "load_store_32" + run_dump_test "logical_32" + run_dump_test "mv_32" + run_dump_test "shift_32" + run_dump_test "syscontrol_32" + + # tests for little endian + run_dump_test "arith_32-lt" + run_dump_test "bit_32-lt" + run_dump_test "branch_32-lt" + run_dump_test "cmp_32-lt" + run_dump_test "load_store_32-lt" + run_dump_test "logical_32-lt" + run_dump_test "mv_32-lt" + run_dump_test "shift_32-lt" + run_dump_test "syscontrol_32-lt" +} diff --git a/gas/testsuite/gas/score/relaxation_macro.h b/gas/testsuite/gas/score/relaxation_macro.h new file mode 100644 index 00000000000..88c666c0d93 --- /dev/null +++ b/gas/testsuite/gas/score/relaxation_macro.h @@ -0,0 +1,32 @@ +/* + * macros for S+core 3 instruction relaxation + * + * partial copyed from testpatterns for S+core 7 + * + * Author: libin + */ + +.macro _tran insn1 insn2 +.balign 2 + .irp i1,"\insn1", "\insn2" + .irp i2,"\insn1", "\insn2" + \i1 + \i2 + .endr + .endr +.endm + +/* insn32/insn16 may include special characters, for example, blank character */ +.macro tran_16_32 insn16 insn32 + _tran "\insn16", "\insn32" +.endm + +.macro insn_16 insn16 +.balign 2 + \insn16 +.endm + +.macro insn_32 insn32 +.balign 2 + \insn32 +.endm diff --git a/gas/testsuite/gas/score/shift_32-lt.d b/gas/testsuite/gas/score/shift_32-lt.d new file mode 100644 index 00000000000..a6f034b0627 --- /dev/null +++ b/gas/testsuite/gas/score/shift_32-lt.d @@ -0,0 +1,13 @@ +#as: -march=score3 -I${srcdir}/${subdir} -EL +#objdump: -s +#source: shift_32.s + +.*: file format elf32-littlescore + +Contents of section .text: + 0000 00581f58 e059ff59 00580058 00580058 .* + 0010 00580058 00580058 00807100 02807000 .* + 0020 10827000 005a1f5a e05bff5b 005a005a .* + 0030 005a005a 005a005a 005a005a 00807500 .* + 0040 02807400 10827400 .* +#pass diff --git a/gas/testsuite/gas/score/shift_32.d b/gas/testsuite/gas/score/shift_32.d new file mode 100644 index 00000000000..464970c0459 --- /dev/null +++ b/gas/testsuite/gas/score/shift_32.d @@ -0,0 +1,40 @@ +#as: -march=score3 -I${srcdir}/${subdir} +#objdump: -d +#source: shift_32.s + +.*: file format .* + +Disassembly of section .text: + +00000000 <.text>: + 0: 5800 slli! r0, 0 + 2: 581f slli! r0, 31 + 4: 59e0 slli! r15, 0 + 6: 59ff slli! r15, 31 + 8: 5800 slli! r0, 0 + a: 5800 slli! r0, 0 + c: 5800 slli! r0, 0 + e: 5800 slli! r0, 0 + 10: 5800 slli! r0, 0 + 12: 5800 slli! r0, 0 + 14: 5800 slli! r0, 0 + 16: 5800 slli! r0, 0 + 18: 8000 0071 slli.c r0, r0, 0 + 1c: 8002 0070 slli r0, r2, 0 + 20: 8210 0070 slli r16, r16, 0 + 24: 5a00 srli! r0, 0 + 26: 5a1f srli! r0, 31 + 28: 5be0 srli! r15, 0 + 2a: 5bff srli! r15, 31 + 2c: 5a00 srli! r0, 0 + 2e: 5a00 srli! r0, 0 + 30: 5a00 srli! r0, 0 + 32: 5a00 srli! r0, 0 + 34: 5a00 srli! r0, 0 + 36: 5a00 srli! r0, 0 + 38: 5a00 srli! r0, 0 + 3a: 5a00 srli! r0, 0 + 3c: 8000 0075 srli.c r0, r0, 0 + 40: 8002 0074 srli r0, r2, 0 + 44: 8210 0074 srli r16, r16, 0 +#pass diff --git a/gas/testsuite/gas/score/shift_32.s b/gas/testsuite/gas/score/shift_32.s new file mode 100644 index 00000000000..63450286ed2 --- /dev/null +++ b/gas/testsuite/gas/score/shift_32.s @@ -0,0 +1,26 @@ +/* + * tests for shift instruction relaxation + * + * Author: libin + */ + +.include "relaxation_macro.h" + +.macro _shift_op_pattern insn insn1 + insn_32 "\insn r0, r0, 0" + insn_32 "\insn r0, r0, 31" + insn_32 "\insn r15, r15, 0" + insn_32 "\insn r15, r15, 31" + + tran_16_32 "\insn! r0, 0", "\insn r0, r0, 0" + + /* shouldn't alter */ + insn_32 "\insn1 r0, r0, 0" + insn_32 "\insn r0, r2, 0" + insn_32 "\insn r16, r16, 0" +.endm + +.text +/* slli/srli rD,rA,Imm5 -> slli!/srli! rD,Imm5 */ +_shift_op_pattern "slli", "slli.c" +_shift_op_pattern "srli", "srli.c" diff --git a/gas/testsuite/gas/score/syscontrol_32-lt.d b/gas/testsuite/gas/score/syscontrol_32-lt.d new file mode 100644 index 00000000000..a7b9ecac137 --- /dev/null +++ b/gas/testsuite/gas/score/syscontrol_32-lt.d @@ -0,0 +1,11 @@ +#as: -march=score3 -I${srcdir}/${subdir} -EL +#objdump: -s +#source: syscontrol_32.s + +.*: file format elf32-littlescore + +Contents of section .text: + 0000 20003f00 20002000 20002000 20002000 .* + 0010 20002000 00000000 00000000 00000000 .* + 0020 00000000 00000000 .* +#pass diff --git a/gas/testsuite/gas/score/syscontrol_32.d b/gas/testsuite/gas/score/syscontrol_32.d new file mode 100644 index 00000000000..0b4ad31f5c7 --- /dev/null +++ b/gas/testsuite/gas/score/syscontrol_32.d @@ -0,0 +1,21 @@ +#as: -march=score3 -I${srcdir}/${subdir} +#objdump: -d +#source: syscontrol_32.s + +.*: file format .* + +Disassembly of section .text: + +00000000 <.text>: + 0: 0020 sdbbp! 0 + 2: 003f sdbbp! 31 + 4: 0020 sdbbp! 0 + 6: 0020 sdbbp! 0 + 8: 0020 sdbbp! 0 + a: 0020 sdbbp! 0 + c: 0020 sdbbp! 0 + e: 0020 sdbbp! 0 + 10: 0020 sdbbp! 0 + 12: 0020 sdbbp! 0 + ... +#pass diff --git a/gas/testsuite/gas/score/syscontrol_32.s b/gas/testsuite/gas/score/syscontrol_32.s new file mode 100644 index 00000000000..7997cb10be9 --- /dev/null +++ b/gas/testsuite/gas/score/syscontrol_32.s @@ -0,0 +1,19 @@ +/* + * tests for system control instruction relaxation + * + * Author: libin + */ + +.include "relaxation_macro.h" + +.text +/* sdbbp Imm5 -> sdbbp! Imm5 */ +insn_32 "sdbbp 0" +insn_32 "sdbbp 31" + +tran_16_32 "sdbbp! 0", "sdbbp 0" + +/* nop -> nop! */ +insn_32 "nop" + +tran_16_32 "nop!", "nop" diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog index e882628b269..606a170f61f 100644 --- a/include/elf/ChangeLog +++ b/include/elf/ChangeLog @@ -1,3 +1,8 @@ +2009-03-02 Qinwei + + * score.h (RELOC_NUMBER): Add R_SCORE_IMM32. + * common.h (EM_SCORE_OLD): Define. + 2009-02-23 H.J. Lu * common.h (STB_LOPROC): Replace Application-specific with diff --git a/include/elf/common.h b/include/elf/common.h index 557c650ad3c..3ba44d9462c 100644 --- a/include/elf/common.h +++ b/include/elf/common.h @@ -334,6 +334,9 @@ #define EM_CYGNUS_MEP 0xF00D /* Toshiba MeP */ +/* Old Sunplus S+core7 backend magic number. Written in the absence of an ABI. */ +#define EM_SCORE_OLD 95 + /* See the above comment before you add a new EM_* value here. */ /* Values for e_version. */ diff --git a/include/elf/score.h b/include/elf/score.h index 72ada054868..8d9c026bb04 100644 --- a/include/elf/score.h +++ b/include/elf/score.h @@ -1,6 +1,7 @@ /* Score ELF support for BFD. - Copyright 2006, 2008 Free Software Foundation, Inc. + Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by + Brain.lin (brain.lin@sunplusct.com) Mei Ligang (ligang@sunnorth.com.cn) Pei-Lin Tsai (pltsai@sunplus.com) @@ -8,7 +9,7 @@ This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -35,6 +36,10 @@ #define GP_DISP_LABEL "_gp_disp" /* Processor specific flags for the ELF header e_flags field: */ +#define EF_SCORE_MACH 0xffff0000 +#define EF_OMIT_PIC_FIXDD 0x0fff0000 +#define E_SCORE_MACH_SCORE3 0x00030000 +#define E_SCORE_MACH_SCORE7 0x00070000 /* File contains position independent code. */ #define EF_SCORE_PIC 0x80000000 @@ -101,7 +106,7 @@ START_RELOC_NUMBERS (elf_score_reloc_type) RELOC_NUMBER (R_SCORE_NONE, 0) RELOC_NUMBER (R_SCORE_HI16, 1) RELOC_NUMBER (R_SCORE_LO16, 2) - RELOC_NUMBER (R_SCORE_DUMMY1, 3) + RELOC_NUMBER (R_SCORE_BCMP, 3) RELOC_NUMBER (R_SCORE_24, 4) RELOC_NUMBER (R_SCORE_PC19, 5) RELOC_NUMBER (R_SCORE16_11, 6) @@ -118,6 +123,8 @@ START_RELOC_NUMBERS (elf_score_reloc_type) RELOC_NUMBER (R_SCORE_GPREL32, 17) RELOC_NUMBER (R_SCORE_REL32, 18) RELOC_NUMBER (R_SCORE_DUMMY_HI16, 19) + RELOC_NUMBER (R_SCORE_IMM30, 20) + RELOC_NUMBER (R_SCORE_IMM32, 21) END_RELOC_NUMBERS (R_SCORE_max) #endif /* _ELF_SCORE_H */ diff --git a/include/opcode/ChangeLog b/include/opcode/ChangeLog index f7018b845db..2a03208a94f 100644 --- a/include/opcode/ChangeLog +++ b/include/opcode/ChangeLog @@ -1,3 +1,9 @@ +2009-03-02 Qinwei + + * score-inst.h (score_insn_type, score_data_type): Add Ra_I9_I5 + and _IMM11 for mbitclr and mbitset. + * score-datadep.h: Update dependency information. + 2009-02-26 Peter Bergner * ppc.h (PPC_OPCODE_POWER7): New. diff --git a/include/opcode/score-datadep.h b/include/opcode/score-datadep.h index 8ef35adc807..33c05c060fc 100644 --- a/include/opcode/score-datadep.h +++ b/include/opcode/score-datadep.h @@ -1,6 +1,7 @@ /* score-datadep.h -- Score Instructions data dependency table - Copyright 2006 Free Software Foundation, Inc. + Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by: + Brain.lin (brain.lin@sunplusct.com) Mei Ligang (ligang@sunnorth.com.cn) Pei-Lin Tsai (pltsai@sunplus.com) @@ -8,7 +9,7 @@ GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) + the Free Software Foundation; either version 3, or (at your option) any later version. GAS is distributed in the hope that it will be useful, @@ -28,20 +29,7 @@ enum insn_type_for_dependency { - D_pce, - D_cond_br, - D_cond_mv, - D_cached, - D_cachei, - D_ldst, - D_ldcombine, D_mtcr, - D_mfcr, - D_mfsr, - D_mftlb, - D_mtptlb, - D_mtrtlb, - D_stlb, D_all_insn }; @@ -58,225 +46,20 @@ struct data_dependency enum insn_type_for_dependency cur_insn_type; char cur_reg[6]; int bubblenum_7; - int bubblenum_5; + int bubblenum_3; int warn_or_error; /* warning - 0; error - 1 */ }; static const struct insn_to_dependency insn_to_dependency_table[] = { - /* pce instruction. */ - {"pce", D_pce}, - /* conditional branch instruction. */ - {"bcs", D_cond_br}, - {"bcc", D_cond_br}, - {"bgtu", D_cond_br}, - {"bleu", D_cond_br}, - {"beq", D_cond_br}, - {"bne", D_cond_br}, - {"bgt", D_cond_br}, - {"ble", D_cond_br}, - {"bge", D_cond_br}, - {"blt", D_cond_br}, - {"bmi", D_cond_br}, - {"bpl", D_cond_br}, - {"bvs", D_cond_br}, - {"bvc", D_cond_br}, - {"bcsl", D_cond_br}, - {"bccl", D_cond_br}, - {"bgtul", D_cond_br}, - {"bleul", D_cond_br}, - {"beql", D_cond_br}, - {"bnel", D_cond_br}, - {"bgtl", D_cond_br}, - {"blel", D_cond_br}, - {"bgel", D_cond_br}, - {"bltl", D_cond_br}, - {"bmil", D_cond_br}, - {"bpll", D_cond_br}, - {"bvsl", D_cond_br}, - {"bvcl", D_cond_br}, - {"bcs!", D_cond_br}, - {"bcc!", D_cond_br}, - {"bgtu!", D_cond_br}, - {"bleu!", D_cond_br}, - {"beq!", D_cond_br}, - {"bne!", D_cond_br}, - {"bgt!", D_cond_br}, - {"ble!", D_cond_br}, - {"bge!", D_cond_br}, - {"blt!", D_cond_br}, - {"bmi!", D_cond_br}, - {"bpl!", D_cond_br}, - {"bvs!", D_cond_br}, - {"bvc!", D_cond_br}, - {"brcs", D_cond_br}, - {"brcc", D_cond_br}, - {"brgtu", D_cond_br}, - {"brleu", D_cond_br}, - {"breq", D_cond_br}, - {"brne", D_cond_br}, - {"brgt", D_cond_br}, - {"brle", D_cond_br}, - {"brge", D_cond_br}, - {"brlt", D_cond_br}, - {"brmi", D_cond_br}, - {"brpl", D_cond_br}, - {"brvs", D_cond_br}, - {"brvc", D_cond_br}, - {"brcsl", D_cond_br}, - {"brccl", D_cond_br}, - {"brgtul", D_cond_br}, - {"brleul", D_cond_br}, - {"breql", D_cond_br}, - {"brnel", D_cond_br}, - {"brgtl", D_cond_br}, - {"brlel", D_cond_br}, - {"brgel", D_cond_br}, - {"brltl", D_cond_br}, - {"brmil", D_cond_br}, - {"brpll", D_cond_br}, - {"brvsl", D_cond_br}, - {"brvcl", D_cond_br}, - {"brcs!", D_cond_br}, - {"brcc!", D_cond_br}, - {"brgtu!", D_cond_br}, - {"brleu!", D_cond_br}, - {"breq!", D_cond_br}, - {"brne!", D_cond_br}, - {"brgt!", D_cond_br}, - {"brle!", D_cond_br}, - {"brge!", D_cond_br}, - {"brlt!", D_cond_br}, - {"brmi!", D_cond_br}, - {"brpl!", D_cond_br}, - {"brvs!", D_cond_br}, - {"brvc!", D_cond_br}, - {"brcsl!", D_cond_br}, - {"brccl!", D_cond_br}, - {"brgtul!", D_cond_br}, - {"brleul!", D_cond_br}, - {"breql!", D_cond_br}, - {"brnel!", D_cond_br}, - {"brgtl!", D_cond_br}, - {"brlel!", D_cond_br}, - {"brgel!", D_cond_br}, - {"brltl!", D_cond_br}, - {"brmil!", D_cond_br}, - {"brpll!", D_cond_br}, - {"brvsl!", D_cond_br}, - {"brvcl!", D_cond_br}, - /* conditional move instruction. */ - {"mvcs", D_cond_mv}, - {"mvcc", D_cond_mv}, - {"mvgtu", D_cond_mv}, - {"mvleu", D_cond_mv}, - {"mveq", D_cond_mv}, - {"mvne", D_cond_mv}, - {"mvgt", D_cond_mv}, - {"mvle", D_cond_mv}, - {"mvge", D_cond_mv}, - {"mvlt", D_cond_mv}, - {"mvmi", D_cond_mv}, - {"mvpl", D_cond_mv}, - {"mvvs", D_cond_mv}, - {"mvvc", D_cond_mv}, /* move spectial instruction. */ {"mtcr", D_mtcr}, - {"mftlb", D_mftlb}, - {"mtptlb", D_mtptlb}, - {"mtrtlb", D_mtrtlb}, - {"stlb", D_stlb}, - {"mfcr", D_mfcr}, - {"mfsr", D_mfsr}, - /* cache instruction. */ - {"cache 8", D_cached}, - {"cache 9", D_cached}, - {"cache 10", D_cached}, - {"cache 11", D_cached}, - {"cache 12", D_cached}, - {"cache 13", D_cached}, - {"cache 14", D_cached}, - {"cache 24", D_cached}, - {"cache 26", D_cached}, - {"cache 27", D_cached}, - {"cache 29", D_cached}, - {"cache 30", D_cached}, - {"cache 31", D_cached}, - {"cache 0", D_cachei}, - {"cache 1", D_cachei}, - {"cache 2", D_cachei}, - {"cache 3", D_cachei}, - {"cache 4", D_cachei}, - {"cache 16", D_cachei}, - {"cache 17", D_cachei}, - /* load/store instruction. */ - {"lb", D_ldst}, - {"lbu", D_ldst}, - {"lbu!", D_ldst}, - {"lbup!", D_ldst}, - {"lh", D_ldst}, - {"lhu", D_ldst}, - {"lh!", D_ldst}, - {"lhp!", D_ldst}, - {"lw", D_ldst}, - {"lw!", D_ldst}, - {"lwp!", D_ldst}, - {"sb", D_ldst}, - {"sb!", D_ldst}, - {"sbp!", D_ldst}, - {"sh", D_ldst}, - {"sh!", D_ldst}, - {"shp!", D_ldst}, - {"sw", D_ldst}, - {"sw!", D_ldst}, - {"swp!", D_ldst}, - {"alw", D_ldst}, - {"asw", D_ldst}, - {"push!", D_ldst}, - {"pushhi!", D_ldst}, - {"pop!", D_ldst}, - {"pophi!", D_ldst}, - {"ldc1", D_ldst}, - {"ldc2", D_ldst}, - {"ldc3", D_ldst}, - {"stc1", D_ldst}, - {"stc2", D_ldst}, - {"stc3", D_ldst}, - {"scb", D_ldst}, - {"scw", D_ldst}, - {"sce", D_ldst}, - /* load combine instruction. */ - {"lcb", D_ldcombine}, - {"lcw", D_ldcombine}, - {"lce", D_ldcombine}, }; static const struct data_dependency data_dependency_table[] = { - /* Condition register. */ - {D_mtcr, "cr1", D_pce, "", 2, 1, 1}, - {D_mtcr, "cr1", D_cond_br, "", 1, 0, 1}, - {D_mtcr, "cr1", D_cond_mv, "", 1, 0, 1}, /* Status regiser. */ - {D_mtcr, "cr0", D_all_insn, "", 5, 4, 0}, - /* CCR regiser. */ - {D_mtcr, "cr4", D_all_insn, "", 6, 5, 0}, - /* EntryHi/EntryLo register. */ - {D_mftlb, "", D_mtptlb, "", 1, 1, 1}, - {D_mftlb, "", D_mtrtlb, "", 1, 1, 1}, - {D_mftlb, "", D_stlb, "", 1, 1,1}, - {D_mftlb, "", D_mfcr, "cr11", 1, 1, 1}, - {D_mftlb, "", D_mfcr, "cr12", 1, 1, 1}, - /* Index register. */ - {D_stlb, "", D_mtptlb, "", 1, 1, 1}, - {D_stlb, "", D_mftlb, "", 1, 1, 1}, - {D_stlb, "", D_mfcr, "cr8", 2, 2, 1}, - /* Cache. */ - {D_cached, "", D_ldst, "", 1, 1, 0}, - {D_cached, "", D_ldcombine, "", 1, 1, 0}, - {D_cachei, "", D_all_insn, "", 5, 4, 0}, - /* Load combine. */ - {D_ldcombine, "", D_mfsr, "sr1", 3, 3, 1}, + {D_mtcr, "cr0", D_all_insn, "", 5, 1, 0}, }; #endif diff --git a/include/opcode/score-inst.h b/include/opcode/score-inst.h index e87794f7744..0eac3824caa 100644 --- a/include/opcode/score-inst.h +++ b/include/opcode/score-inst.h @@ -1,6 +1,7 @@ /* score-inst.h -- Score Instructions Table - Copyright 2006 Free Software Foundation, Inc. + Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by: + Brain.lin (brain.lin@sunplusct.com) Mei Ligang (ligang@sunnorth.com.cn) Pei-Lin Tsai (pltsai@sunplus.com) @@ -8,7 +9,7 @@ GAS is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) + the Free Software Foundation; either version 3, or (at your option) any later version. GAS is distributed in the hope that it will be useful, @@ -96,6 +97,8 @@ enum score_insn_type Rd_Rs_I14, I15, Rd_I16, + Rd_I30, + Rd_I32, Rd_rvalueRs_SI10, Rd_lvalueRs_SI10, Rd_rvalueRs_preSI12, @@ -105,6 +108,8 @@ enum score_insn_type Rd_Rs_SI14, Rd_rvalueRs_SI15, Rd_lvalueRs_SI15, + Rd_SI5, + Rd_SI6, Rd_SI16, PC_DISP8div2, PC_DISP11div2, @@ -139,6 +144,8 @@ enum score_insn_type Insn_GP, Insn_PIC, Insn_internal, + Insn_BCMP, + Ra_I9_I5, }; enum score_data_type @@ -178,6 +185,13 @@ enum score_data_type _SIMM16_pic = 42, /* Index in score_df_range. */ _IMM16_LO16_pic = 43, _IMM16_pic = 44, + + _SIMM5 = 45, + _SIMM6 = 46, + _IMM32 = 47, + _SIMM32 = 48, + _IMM11 = 49, + _IMM5_MULTI_LOAD = 50, }; #define REG_TMP 1 @@ -206,302 +220,17 @@ enum score_data_type #define OP16_SH_DISP8 (OP_IMM_TYPE | 0) #define OP16_SH_DISP11 (OP_IMM_TYPE | 1) -struct datafield_range -{ - int data_type; - int bits; - int range[2]; -}; - -struct datafield_range score_df_range[] = -{ - {_IMM4, 4, {0, (1 << 4) - 1}}, /* ( 0 ~ 15 ) */ - {_IMM5, 5, {0, (1 << 5) - 1}}, /* ( 0 ~ 31 ) */ - {_IMM8, 8, {0, (1 << 8) - 1}}, /* ( 0 ~ 255 ) */ - {_IMM14, 14, {0, (1 << 14) - 1}}, /* ( 0 ~ 16383) */ - {_IMM15, 15, {0, (1 << 15) - 1}}, /* ( 0 ~ 32767) */ - {_IMM16, 16, {0, (1 << 16) - 1}}, /* ( 0 ~ 65535) */ - {_SIMM10, 10, {-(1 << 9), (1 << 9) - 1}}, /* ( -512 ~ 511 ) */ - {_SIMM12, 12, {-(1 << 11), (1 << 11) - 1}}, /* ( -2048 ~ 2047 ) */ - {_SIMM14, 14, {-(1 << 13), (1 << 13) - 1}}, /* ( -8192 ~ 8191 ) */ - {_SIMM15, 15, {-(1 << 14), (1 << 14) - 1}}, /* (-16384 ~ 16383) */ - {_SIMM16, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */ - {_SIMM14_NEG, 14, {-(1 << 13), (1 << 13) - 1}}, /* ( -8191 ~ 8192 ) */ - {_IMM16_NEG, 16, {0, (1 << 16) - 1}}, /* (-65535 ~ 0 ) */ - {_SIMM16_NEG, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */ - {_IMM20, 20, {0, (1 << 20) - 1}}, - {_IMM25, 25, {0, (1 << 25) - 1}}, - {_DISP8div2, 8, {-(1 << 8), (1 << 8) - 1}}, /* ( -256 ~ 255 ) */ - {_DISP11div2, 11, {0, 0}}, - {_DISP19div2, 19, {-(1 << 19), (1 << 19) - 1}}, /* (-524288 ~ 524287) */ - {_DISP24div2, 24, {0, 0}}, - {_VALUE, 32, {0, ((unsigned int)1 << 31) - 1}}, - {_VALUE_HI16, 16, {0, (1 << 16) - 1}}, - {_VALUE_LO16, 16, {0, (1 << 16) - 1}}, - {_VALUE_LDST_LO16, 16, {0, (1 << 16) - 1}}, - {_SIMM16_LA, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */ - {_IMM5_RSHIFT_1, 5, {0, (1 << 6) - 1}}, /* ( 0 ~ 63 ) */ - {_IMM5_RSHIFT_2, 5, {0, (1 << 7) - 1}}, /* ( 0 ~ 127 ) */ - {_SIMM16_LA_POS, 16, {0, (1 << 15) - 1}}, /* ( 0 ~ 32767) */ - {_IMM5_RANGE_8_31, 5, {8, 31}}, /* But for cop0 the valid data : (8 ~ 31). */ - {_IMM10_RSHIFT_2, 10, {-(1 << 11), (1 << 11) - 1}}, /* For ldc#, stc#. */ - {_SIMM10, 10, {0, (1 << 10) - 1}}, /* ( -1024 ~ 1023 ) */ - {_SIMM12, 12, {0, (1 << 12) - 1}}, /* ( -2048 ~ 2047 ) */ - {_SIMM14, 14, {0, (1 << 14) - 1}}, /* ( -8192 ~ 8191 ) */ - {_SIMM15, 15, {0, (1 << 15) - 1}}, /* (-16384 ~ 16383) */ - {_SIMM16, 16, {0, (1 << 16) - 1}}, /* (-65536 ~ 65536) */ - {_SIMM14_NEG, 14, {0, (1 << 16) - 1}}, /* ( -8191 ~ 8192 ) */ - {_IMM16_NEG, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */ - {_SIMM16_NEG, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */ - {_IMM20, 20, {0, (1 << 20) - 1}}, /* (-32768 ~ 32767) */ - {_IMM25, 25, {0, (1 << 25) - 1}}, /* (-32768 ~ 32767) */ - {_GP_IMM15, 15, {0, (1 << 15) - 1}}, /* ( 0 ~ 65535) */ - {_GP_IMM14, 14, {0, (1 << 14) - 1}}, /* ( 0 ~ 65535) */ - {_SIMM16_pic, 16, {-(1 << 15), (1 << 15) - 1}}, /* (-32768 ~ 32767) */ - {_IMM16_LO16_pic, 16, {0, (1 << 16) - 1}}, /* ( 65535 ~ 0 ) */ - {_IMM16_pic, 16, {0, (1 << 16) - 1}}, /* ( 0 ~ 65535) */ -}; - -struct shift_bitmask -{ - int opd_type; - int opd_num; - struct datafield_range *df_range; - int sh[4]; - long fieldbits[4]; -}; - -struct shift_bitmask score_sh_bits_map[] = -{ - { - Rd_I4, 2, &score_df_range[_IMM4], - {OP16_SH_REGD, OP16_SH_I45, 0, 0}, - {0xf, 0xf, 0, 0}, - }, - { - Rd_I5, 2, &score_df_range[_IMM5], - {OP16_SH_REGD, OP16_SH_I45, 0, 0}, - {0xf, 0x1f, 0, 0}, - }, - { - Rd_rvalueBP_I5, 2, &score_df_range[_IMM5], - {OP16_SH_REGD, OP16_SH_I45, 0, 0}, - {0xf, 0x1f, 0, 0}, - }, - { - Rd_lvalueBP_I5, 2, &score_df_range[_IMM5], - {OP16_SH_REGD, OP16_SH_I45, 0, 0}, - {0xf, 0x1f, 0, 0}, - }, - { - Rd_Rs_I5, 3, &score_df_range[_IMM5], - {OP_SH_REGD, OP_SH_REGS1, OP_SH_I5, 0}, - {0x1f, 0x1f, 0x1f, 0}, - }, - { - x_Rs_I5, 2, &score_df_range[_IMM5], - {OP_SH_REGS1, OP_SH_I5, 0, 0}, - {0x1f, 0x1f, 0, 0}, - }, - { - x_I5_x, 1, &score_df_range[_IMM5], - {OP_SH_TRAPI5, 0, 0, 0}, - {0x1f, 0, 0, 0}, - }, - { - Rd_I8, 2, &score_df_range[_IMM8], - {OP16_SH_REGD, OP16_SH_I8, 0, 0}, - {0xf, 0xff, 0, 0}, - }, - { - Rd_Rs_I14, 3, &score_df_range[_IMM14], - {OP_SH_REGD, OP_SH_REGS1, OP_SH_I, 0}, - {0x1f, 0x1f, 0x3fff, 0}, - }, - { - I15, 1, &score_df_range[_IMM15], - {OP_SH_I15, 0, 0, 0}, - {0x7fff, 0, 0, 0}, - }, - { - Rd_I16, 2, &score_df_range[_IMM16], - {OP_SH_REGD, OP_SH_I, 0, 0}, - {0x1f, 0xffff, 0, 0}, - }, - { - Rd_rvalueRs_SI10, 3, &score_df_range[_SIMM10], - {OP_SH_REGD, OP_SH_REGS1, OP_SH_I10, 0}, - {0x1f, 0x1f, 0x3ff, 0}, - }, - { - Rd_lvalueRs_SI10, 3, &score_df_range[_SIMM10], - {OP_SH_REGD, OP_SH_REGS1, OP_SH_I10, 0}, - {0x1f, 0x1f, 0x3ff, 0}, - }, - { - Rd_rvalueRs_preSI12, 3, &score_df_range[_SIMM12], - {OP_SH_REGD, OP_SH_REGS1, OP_SH_I12, 0}, - {0xf, 0xf, 0xfff, 0}, - }, - { - Rd_rvalueRs_postSI12, 3, &score_df_range[_SIMM12], - {OP_SH_REGD, OP_SH_REGS1, OP_SH_I12, 0}, - {0xf, 0xf, 0xfff, 0}, - }, - { - Rd_lvalueRs_preSI12, 3, &score_df_range[_SIMM12], - {OP_SH_REGD, OP_SH_REGS1, OP_SH_I12, 0}, - {0xf, 0xf, 0xfff, 0}, - }, - { - Rd_lvalueRs_postSI12, 3, &score_df_range[_SIMM12], - {OP_SH_REGD, OP_SH_REGS1, OP_SH_I12, 0}, - {0xf, 0xf, 0xfff, 0}, - }, - { - Rd_Rs_SI14, 3, &score_df_range[_SIMM14], - {OP_SH_REGD, OP_SH_REGS1, OP_SH_I, 0}, - {0x1f, 0x1f, 0x3fff, 0}, - }, - { - Rd_rvalueRs_SI15, 3, &score_df_range[_SIMM15], - {OP_SH_REGD, OP_SH_REGS1, OP_SH_RI15, 0}, - {0x1f, 0x1f, 0x7fff, 0}, - }, - { - Rd_lvalueRs_SI15, 3, &score_df_range[_SIMM15], - {OP_SH_REGD, OP_SH_REGS1, OP_SH_RI15, 0}, - {0x1f, 0x1f, 0x7fff, 0}, - }, - { - Rd_SI16, 2, &score_df_range[_SIMM16], - {OP_SH_REGD, OP_SH_I, 0, 0}, - {0x1f, 0xffff, 0, 0}, - }, - { - PC_DISP8div2, 1, &score_df_range[_DISP8div2], - {OP16_SH_DISP8, 0, 0, 0}, - {0xff, 0, 0, 0}, - }, - { - PC_DISP11div2, 1, &score_df_range[_DISP11div2], - {OP16_SH_DISP11, 0, 0, 0}, - {0x7ff, 0, 0, 0}, - }, - { - PC_DISP19div2, 2, &score_df_range[_DISP19div2], - {OP_SH_DISP19_p1, OP_SH_DISP19_p2, 0, 0}, - {0x3ff, 0x1ff, 0, 0}, - }, - { - PC_DISP24div2, 1, &score_df_range[_DISP24div2], - {OP_SH_DISP24, 0, 0, 0}, - {0xffffff, 0, 0, 0}, - }, - { - Rd_Rs_Rs, 3, NULL, - {OP_SH_REGD, OP_SH_REGS1, OP_SH_REGS2, 0}, - {0x1f, 0x1f, 0x1f, 0} - }, - { - Rd_Rs_x, 2, NULL, - {OP_SH_REGD, OP_SH_REGS1, 0, 0}, - {0x1f, 0x1f, 0, 0}, - }, - { - Rd_x_Rs, 2, NULL, - {OP_SH_REGD, OP_SH_REGS2, 0, 0}, - {0x1f, 0x1f, 0, 0}, - }, - { - Rd_x_x, 1, NULL, - {OP_SH_REGD, 0, 0, 0}, - {0x1f, 0, 0, 0}, - }, - { - x_Rs_Rs, 2, NULL, - {OP_SH_REGS1, OP_SH_REGS2, 0, 0}, - {0x1f, 0x1f, 0, 0}, - }, - { - x_Rs_x, 1, NULL, - {OP_SH_REGS1, 0, 0, 0}, - {0x1f, 0, 0, 0}, - }, - { - Rd_Rs, 2, NULL, - {OP16_SH_REGD, OP16_SH_REGS1, 0, 0}, - {0xf, 0xf, 0, 0}, - }, - { - Rd_HighRs, 2, NULL, - {OP16_SH_REGD, OP16_SH_REGS1, 0, 0}, - {0xf, 0xf, 0x1f, 0}, - }, - { - Rd_rvalueRs, 2, NULL, - {OP16_SH_REGD, OP16_SH_REGS1, 0, 0}, - {0xf, 0xf, 0, 0}, - }, - { - Rd_lvalueRs, 2, NULL, - {OP16_SH_REGD, OP16_SH_REGS1, 0, 0}, - {0xf, 0xf, 0, 0} - }, - { - Rd_lvalue32Rs, 2, NULL, - {OP_SH_REGD, OP_SH_REGS1, 0, 0}, - {0x1f, 0x1f, 0, 0}, - }, - { - Rd_rvalue32Rs, 2, NULL, - {OP_SH_REGD, OP_SH_REGS1, 0, 0}, - {0x1f, 0x1f, 0, 0}, - }, - { - x_Rs, 1, NULL, - {OP16_SH_REGS1, 0, 0, 0}, - {0xf, 0, 0, 0}, - }, - { - NO_OPD, 0, NULL, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - }, - { - NO16_OPD, 0, NULL, - {0, 0, 0, 0}, - {0, 0, 0, 0}, - }, -}; - -struct asm_opcode -{ - /* Instruction name. */ - const char *template; - - /* Instruction Opcode. */ - unsigned long value; - - /* Instruction bit mask. */ - unsigned long bitmask; - - /* Relax instruction opcode. 0x8000 imply no relaxation. */ - unsigned long relax_value; - - /* Instruction type. */ - enum score_insn_type type; - - /* Function to call to parse args. */ - void (*parms) (char *); -}; - enum insn_class { INSN_CLASS_16, INSN_CLASS_32, + INSN_CLASS_48, INSN_CLASS_PCE, INSN_CLASS_SYN }; +/* s3_s7: Globals for both tc-score.c and elf32-score.c. */ +extern int score3; +extern int score7; + #endif diff --git a/ld/ChangeLog b/ld/ChangeLog index 5f11b8d6795..de067e4ed16 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,13 @@ +2009-03-02 Qinwei + + * Makefile.am: Replace score elf emulation with score3 and score7 + emulations. + * Makefile.in: Regenerate, + * NEWS: Mention support for Score7 architecture. + * configure.tgt: Add score7 emulation to score-elf target. + * emulparams/scoreelf.sh: Add score7 support. + * emultempl/scoreelf.em: Likewise. + 2009-03-01 John David Anglin * configure.tgt: Only use elf64hppa target emulation for hpux. diff --git a/ld/Makefile.am b/ld/Makefile.am index 806168e3fe0..0dbc734e66c 100644 --- a/ld/Makefile.am +++ b/ld/Makefile.am @@ -356,7 +356,8 @@ ALL_EMULATIONS = \ eppcpe.o \ eppclynx.o \ eriscix.o \ - escoreelf.o \ + escore3_elf.o \ + escore7_elf.o \ esh.o \ eshelf32.o \ eshlelf32.o \ @@ -1556,10 +1557,14 @@ eppclynx.c: $(srcdir)/emulparams/ppclynx.sh \ eriscix.c: $(srcdir)/emulparams/riscix.sh \ $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS} ${GENSCRIPTS} riscix "$(tdir_riscix)" -escoreelf.c: $(srcdir)/emulparams/scoreelf.sh \ - $(srcdir)/emultempl/elf32.em $(srcdir)/emultempl/scoreelf.em \ - $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} - ${GENSCRIPTS} scoreelf "$(tdir_scoreelf)" +escore3_elf.c: $(srcdir)/emulparams/scoreelf.sh \ + $(ELF_DEPS) $(srcdir)/emultempl/scoreelf.em \ + $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} score3_elf "$(tdir_score3_elf)" scoreelf +escore7_elf.c: $(srcdir)/emulparams/scoreelf.sh \ + $(ELF_DEPS) $(srcdir)/emultempl/scoreelf.em \ + $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} score7_elf "$(tdir_score7_elf)" scoreelf esh.c: $(srcdir)/emulparams/sh.sh \ $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/sh.sc ${GEN_DEPENDS} ${GENSCRIPTS} sh "$(tdir_sh)" diff --git a/ld/Makefile.in b/ld/Makefile.in index 1c38d91c7da..e8b7476de14 100644 --- a/ld/Makefile.in +++ b/ld/Makefile.in @@ -620,7 +620,8 @@ ALL_EMULATIONS = \ eppcpe.o \ eppclynx.o \ eriscix.o \ - escoreelf.o \ + escore3_elf.o \ + escore7_elf.o \ esh.o \ eshelf32.o \ eshlelf32.o \ @@ -2402,10 +2403,14 @@ eppclynx.c: $(srcdir)/emulparams/ppclynx.sh \ eriscix.c: $(srcdir)/emulparams/riscix.sh \ $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS} ${GENSCRIPTS} riscix "$(tdir_riscix)" -escoreelf.c: $(srcdir)/emulparams/scoreelf.sh \ - $(srcdir)/emultempl/elf32.em $(srcdir)/emultempl/scoreelf.em \ - $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} - ${GENSCRIPTS} scoreelf "$(tdir_scoreelf)" +escore3_elf.c: $(srcdir)/emulparams/scoreelf.sh \ + $(ELF_DEPS) $(srcdir)/emultempl/scoreelf.em \ + $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} score3_elf "$(tdir_score3_elf)" scoreelf +escore7_elf.c: $(srcdir)/emulparams/scoreelf.sh \ + $(ELF_DEPS) $(srcdir)/emultempl/scoreelf.em \ + $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} score7_elf "$(tdir_score7_elf)" scoreelf esh.c: $(srcdir)/emulparams/sh.sh \ $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/sh.sc ${GEN_DEPENDS} ${GENSCRIPTS} sh "$(tdir_sh)" diff --git a/ld/NEWS b/ld/NEWS index 9a7908221f5..1789c8b49d5 100644 --- a/ld/NEWS +++ b/ld/NEWS @@ -13,6 +13,8 @@ * Add a new command line option, -Ttext-segment ADDR, for ELF targets to set the address of the first byte of the text segment. +* Add support for Sunplus score architecture. + * Add new option --use-nul-prefixed-import-tables to ld for PE targets to allow fallback to old import table generation with null element prefix. diff --git a/ld/configure.tgt b/ld/configure.tgt index 674468a21f7..72cef1778ef 100644 --- a/ld/configure.tgt +++ b/ld/configure.tgt @@ -506,7 +506,8 @@ s390-*-linux*) targ_emul=elf_s390 targ64_extra_libpath=elf64_s390 tdir_elf64_s390=`echo ${targ_alias} | sed -e 's/s390/s390x/'` ;; -score-*-elf) targ_emul=scoreelf ;; +score-*-elf) targ_emul=score7_elf + targ_extra_emuls=score3_elf ;; sh-*-linux*) targ_emul=shlelf_linux targ_extra_emuls=shelf_linux targ_extra_libpath=shelf_linux ;; diff --git a/ld/emulparams/scoreelf.sh b/ld/emulparams/scoreelf.sh index dfb5aca83f2..3a7ed3158a9 100644 --- a/ld/emulparams/scoreelf.sh +++ b/ld/emulparams/scoreelf.sh @@ -1,6 +1,7 @@ MACHINE= SCRIPT_NAME=elf TEMPLATE_NAME=elf32 +EXTRA_EM_FILE=scoreelf OUTPUT_FORMAT="elf32-bigscore" BIG_OUTPUT_FORMAT="elf32-bigscore" LITTLE_OUTPUT_FORMAT="elf32-littlescore" @@ -8,10 +9,8 @@ NO_RELA_RELOCS=yes GROUP="-lm -lc -lglsim -lgcc -lstdc++" TEXT_START_ADDR=0x00000000 -case ${LD_FLAG} in - n|N) TEXT_START_ADDR=0x0400000 ;; -esac MAXPAGESIZE=256 +NONPAGED_TEXT_START_ADDR=0x0400000 SHLIB_TEXT_START_ADDR=0x5ffe0000 OTHER_GOT_SYMBOLS=' _gp = ALIGN(16) + 0x3ff0; @@ -27,7 +26,15 @@ OTHER_BSS_SYMBOLS=' # This sets the stack to the top of the simulator memory (2^19 bytes). STACK_ADDR=0x8000000 -ARCH=score +SCORE_NAME=${EMULATION_NAME} +if [ "${SCORE_NAME}" = "score3_elf" ] ; then +ARCH=score3 +fi + +if [ "${SCORE_NAME}" = "score7_elf" ] ; then +ARCH=score7 +fi + MACHINE= ENTRY=_start EMBEDDED=yes diff --git a/ld/emultempl/scoreelf.em b/ld/emultempl/scoreelf.em index f6cb5100cae..897147e9d78 100644 --- a/ld/emultempl/scoreelf.em +++ b/ld/emultempl/scoreelf.em @@ -1,6 +1,7 @@ # This shell script emits a C file. -*- C -*- -# Copyright 2006, 2007, 2008 Free Software Foundation, Inc. +# Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. # Contributed by: +# Brain.lin (brain.lin@sunplusct.com) # Mei Ligang (ligang@sunnorth.com.cn) # Pei-Lin Tsai (pltsai@sunplus.com) @@ -27,14 +28,16 @@ # fragment < + + * score7-dis.c: New file. + * Makefile.am: Add dependencies for score7-dis.c. + * Makefile.in: Regenerate. + * configure.in: Add score7-dis to score files. + * configure: Regenerate. + * score-dis.c: Add support for score7 architecture. + * score-opc.h: Likewise. + 2009-03-01 Ralf Wildenhues * configure: Regenerate. diff --git a/opcodes/Makefile.am b/opcodes/Makefile.am index 390dba32994..6264e0750f7 100644 --- a/opcodes/Makefile.am +++ b/opcodes/Makefile.am @@ -189,6 +189,7 @@ CFILES = \ s390-opc.c \ s390-dis.c \ score-dis.c \ + score7-dis.c \ sh-dis.c \ sh64-dis.c \ sh64-opc.c \ @@ -337,6 +338,7 @@ ALL_MACHINES = \ s390-dis.lo \ s390-opc.lo \ score-dis.lo \ + score7-dis.lo \ sh-dis.lo \ sh64-dis.lo \ sh64-opc.lo \ @@ -1125,6 +1127,11 @@ score-dis.lo: score-dis.c sysdep.h config.h $(INCDIR)/ansidecl.h \ opintl.h $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h \ $(INCDIR)/elf/external.h $(INCDIR)/elf/internal.h $(INCDIR)/bfdlink.h \ $(INCDIR)/elf/score.h $(INCDIR)/elf/reloc-macros.h +score7-dis.lo: score7-dis.c sysdep.h config.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/dis-asm.h $(BFD_H) $(INCDIR)/symcat.h score-opc.h \ + opintl.h $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h \ + $(INCDIR)/elf/external.h $(INCDIR)/elf/internal.h $(INCDIR)/bfdlink.h \ + $(INCDIR)/elf/score.h $(INCDIR)/elf/reloc-macros.h sh-dis.lo: sh-dis.c sysdep.h config.h $(INCDIR)/ansidecl.h \ sh-opc.h $(BFD_H) $(INCDIR)/symcat.h $(INCDIR)/dis-asm.h sh64-dis.lo: sh64-dis.c $(INCDIR)/dis-asm.h $(BFD_H) \ diff --git a/opcodes/Makefile.in b/opcodes/Makefile.in index 9e12b0800d1..2429d82d61c 100644 --- a/opcodes/Makefile.in +++ b/opcodes/Makefile.in @@ -427,6 +427,7 @@ CFILES = \ s390-opc.c \ s390-dis.c \ score-dis.c \ + score7-dis.c \ sh-dis.c \ sh64-dis.c \ sh64-opc.c \ @@ -575,6 +576,7 @@ ALL_MACHINES = \ s390-dis.lo \ s390-opc.lo \ score-dis.lo \ + score7-dis.lo \ sh-dis.lo \ sh64-dis.lo \ sh64-opc.lo \ @@ -1689,6 +1691,11 @@ score-dis.lo: score-dis.c sysdep.h config.h $(INCDIR)/ansidecl.h \ opintl.h $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h \ $(INCDIR)/elf/external.h $(INCDIR)/elf/internal.h $(INCDIR)/bfdlink.h \ $(INCDIR)/elf/score.h $(INCDIR)/elf/reloc-macros.h +score7-dis.lo: score7-dis.c sysdep.h config.h $(INCDIR)/ansidecl.h \ + $(INCDIR)/dis-asm.h $(BFD_H) $(INCDIR)/symcat.h score-opc.h \ + opintl.h $(BFDDIR)/elf-bfd.h $(INCDIR)/elf/common.h \ + $(INCDIR)/elf/external.h $(INCDIR)/elf/internal.h $(INCDIR)/bfdlink.h \ + $(INCDIR)/elf/score.h $(INCDIR)/elf/reloc-macros.h sh-dis.lo: sh-dis.c sysdep.h config.h $(INCDIR)/ansidecl.h \ sh-opc.h $(BFD_H) $(INCDIR)/symcat.h $(INCDIR)/dis-asm.h sh64-dis.lo: sh64-dis.c $(INCDIR)/dis-asm.h $(BFD_H) \ diff --git a/opcodes/configure b/opcodes/configure index 3c6d3c82faa..998baf46b18 100755 --- a/opcodes/configure +++ b/opcodes/configure @@ -12558,7 +12558,7 @@ if test x${all_targets} = xfalse ; then bfd_romp_arch) ;; bfd_rs6000_arch) ta="$ta ppc-dis.lo ppc-opc.lo" ;; bfd_s390_arch) ta="$ta s390-dis.lo s390-opc.lo" ;; - bfd_score_arch) ta="$ta score-dis.lo" ;; + bfd_score_arch) ta="$ta score-dis.lo score7-dis.lo" ;; bfd_sh_arch) # We can't decide what we want just from the CPU family. # We want SH5 support unless a specific version of sh is diff --git a/opcodes/configure.in b/opcodes/configure.in index 60149adc10e..8bebe7e3235 100644 --- a/opcodes/configure.in +++ b/opcodes/configure.in @@ -231,7 +231,7 @@ if test x${all_targets} = xfalse ; then bfd_romp_arch) ;; bfd_rs6000_arch) ta="$ta ppc-dis.lo ppc-opc.lo" ;; bfd_s390_arch) ta="$ta s390-dis.lo s390-opc.lo" ;; - bfd_score_arch) ta="$ta score-dis.lo" ;; + bfd_score_arch) ta="$ta score-dis.lo score7-dis.lo" ;; bfd_sh_arch) # We can't decide what we want just from the CPU family. # We want SH5 support unless a specific version of sh is diff --git a/opcodes/score-dis.c b/opcodes/score-dis.c index 1210115b3d2..732ddfb612a 100644 --- a/opcodes/score-dis.c +++ b/opcodes/score-dis.c @@ -1,6 +1,7 @@ /* Instruction printing code for Score - Copyright 2006, 2007 Free Software Foundation, Inc. + Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by: + Brain.lin (brain.lin@sunplusct.com) Mei Ligang (ligang@sunnorth.com.cn) Pei-Lin Tsai (pltsai@sunplus.com) @@ -24,7 +25,7 @@ #include "sysdep.h" #include "dis-asm.h" #define DEFINE_TABLE -#include "score-opc.h" +/*****************************************************************************/ #include "opintl.h" #include "bfd.h" @@ -33,12 +34,455 @@ #include "elf/internal.h" #include "elf/score.h" +/*****************************************************************************/ +/* s3_s7: opcodes and export prototypes. */ +extern int +s7_print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little); + +struct score_opcode +{ + bfd_vma value; + bfd_vma mask; /* Recognise instruction if (op & mask) == value. */ + char *assembler; /* Disassembly string. */ +}; + +/* Note: There is a partial ordering in this table - it must be searched from + the top to obtain a correct match. */ + +static struct score_opcode score_opcodes[] = +{ + /* Score Instructions. */ + {0x3800000a, 0x3e007fff, "abs\t\t%20-24r, %15-19r"}, + {0x3800004b, 0x3e007fff, "abs.s\t\t%20-24r, %15-19r"}, + {0x00000010, 0x3e0003ff, "add\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000011, 0x3e0003ff, "add.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x38000048, 0x3e0003ff, "add.s\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000012, 0x3e0003ff, "addc\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000013, 0x3e0003ff, "addc.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x02000000, 0x3e0e0001, "addi\t\t%20-24r, %1-16i"}, + {0x02000001, 0x3e0e0001, "addi.c\t\t%20-24r, %1-16i"}, + {0x0a000000, 0x3e0e0001, "addis\t\t%20-24r, %1-16d(0x%1-16x)"}, + {0x0a000001, 0x3e0e0001, "addis.c\t\t%20-24r, %1-16d(0x%1-16x)"}, + {0x10000000, 0x3e000001, "addri\t\t%20-24r, %15-19r, %1-14i"}, + {0x10000001, 0x3e000001, "addri.c\t\t%20-24r, %15-19r, %1-14i"}, + {0x00004800, 0x00007f00, "add!\t\t%4-7r, %0-3r"}, + {0x00005c00, 0x00007c00, "addi!\t\t%6-9r, %0-5i"}, + {0x00000020, 0x3e0003ff, "and\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000021, 0x3e0003ff, "and.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x040000000000LL, 0x1c0000000003LL, "andri48\t\t%38-41r,%34-37r, 0x%2-33x"}, + {0x040000000001LL, 0x1c0000000003LL, "andri48.c\t\t%38-41r,%34-37r, 0x%2-33x"}, + {0x02080000, 0x3e0e0001, "andi\t\t%20-24r, 0x%1-16x"}, + {0x02080001, 0x3e0e0001, "andi.c\t\t%20-24r, 0x%1-16x"}, + {0x0a080000, 0x3e0e0001, "andis\t\t%20-24r, 0x%1-16x"}, + {0x0a080001, 0x3e0e0001, "andis.c\t\t%20-24r, 0x%1-16x"}, + {0x18000000, 0x3e000001, "andri\t\t%20-24r, %15-19r, 0x%1-14x"}, + {0x18000001, 0x3e000001, "andri.c\t\t%20-24r, %15-19r,0x%1-14x"}, + {0x00004b00, 0x00007f00, "and!\t\t%4-7r, %0-3r"}, + {0x08000000, 0x3e007c01, "bcs\t\t%b"}, + {0x08000400, 0x3e007c01, "bcc\t\t%b"}, + {0x08003800, 0x3e007c01, "bcnz\t\t%b"}, + {0x08000001, 0x3e007c01, "bcsl\t\t%b"}, + {0x08000401, 0x3e007c01, "bccl\t\t%b"}, + {0x08003801, 0x3e007c01, "bcnzl\t\t%b"}, + {0x0000004c, 0x3e00007e, "bcmpeqz\t\t%15-19r, %z"}, + {0x0000004c, 0x3e00007e, "bcmpeq\t\t%15-19r, %z"}, + {0x0000004e, 0x3e00007e, "bcmpnez\t\t%15-19r, %z"}, + {0x0000004e, 0x3e00007e, "bcmpne\t\t%15-19r, %z"}, + {0x00003200, 0x00007e00, "bcnz!\t\t%b"}, + {0x08001000, 0x3e007c01, "beq\t\t%b"}, + {0x08001001, 0x3e007c01, "beql\t\t%b"}, + {0x00003800, 0x00007e00, "beq!\t\t%b"}, + {0x08000800, 0x3e007c01, "bgtu\t\t%b"}, + {0x08001800, 0x3e007c01, "bgt\t\t%b"}, + {0x08002000, 0x3e007c01, "bge\t\t%b"}, + {0x08000801, 0x3e007c01, "bgtul\t\t%b"}, + {0x08001801, 0x3e007c01, "bgtl\t\t%b"}, + {0x08002001, 0x3e007c01, "bgel\t\t%b"}, + {0x00003400, 0x00007e00, "bgtu!\t\t%b"}, + {0x00003c00, 0x00007e00, "bgt!\t\t%b"}, + {0x00000029, 0x3e0003ff, "bitclr.c\t%20-24r, %15-19r, 0x%10-14x"}, + {0x00000028, 0x3e0003ff, "bitclr\t%20-24r, %15-19r, 0x%10-14x"}, + {0x0000002b, 0x3e0003ff, "bitset.c\t%20-24r, %15-19r, 0x%10-14x"}, + {0x0000002a, 0x3e0003ff, "bitset\t%20-24r, %15-19r, 0x%10-14x"}, + {0x0000002d, 0x3e0003ff, "bittst.c\t%15-19r, 0x%10-14x"}, + {0x0000002f, 0x3e0003ff, "bittgl.c\t%20-24r, %15-19r, 0x%10-14x"}, + {0x0000002e, 0x3e0003ff, "bittgl\t%20-24r, %15-19r, 0x%10-14x"}, + {0x00005000, 0x00007e00, "bitclr!\t\t%5-8r, 0x%0-4x"}, + {0x3800000c, 0x3e0003ff, "bitrev\t\t%20-24r, %15-19r,%10-14r"}, + {0x00005200, 0x00007e00, "bitset!\t\t%5-8r, 0x%0-4x"}, + {0x00005400, 0x00007e00, "bittst!\t\t%5-8r, 0x%0-4x"}, + {0x00005600, 0x00007e00, "bittgl!\t\t%5-8r, 0x%0-4x"}, + {0x08000c00, 0x3e007c01, "bleu\t\t%b"}, + {0x08001c00, 0x3e007c01, "ble\t\t%b"}, + {0x08002400, 0x3e007c01, "blt\t\t%b"}, + {0x08000c01, 0x3e007c01, "bleul\t\t%b"}, + {0x08001c01, 0x3e007c01, "blel\t\t%b"}, + {0x08002401, 0x3e007c01, "bltl\t\t%b"}, + {0x08003c01, 0x3e007c01, "bl\t\t%b"}, + {0x00003600, 0x00007e00, "bleu!\t\t%b"}, + {0x00003e00, 0x00007e00, "ble!\t\t%b"}, + {0x08002800, 0x3e007c01, "bmi\t\t%b"}, + {0x08002801, 0x3e007c01, "bmil\t\t%b"}, + {0x08001400, 0x3e007c01, "bne\t\t%b"}, + {0x08001401, 0x3e007c01, "bnel\t\t%b"}, + {0x00003a00, 0x00007e00, "bne!\t\t%b"}, + {0x08002c00, 0x3e007c01, "bpl\t\t%b"}, + {0x08002c01, 0x3e007c01, "bpll\t\t%b"}, + {0x00000008, 0x3e007fff, "brcs\t\t%15-19r"}, + {0x00000408, 0x3e007fff, "brcc\t\t%15-19r"}, + {0x00000808, 0x3e007fff, "brgtu\t\t%15-19r"}, + {0x00000c08, 0x3e007fff, "brleu\t\t%15-19r"}, + {0x00001008, 0x3e007fff, "breq\t\t%15-19r"}, + {0x00001408, 0x3e007fff, "brne\t\t%15-19r"}, + {0x00001808, 0x3e007fff, "brgt\t\t%15-19r"}, + {0x00001c08, 0x3e007fff, "brle\t\t%15-19r"}, + {0x00002008, 0x3e007fff, "brge\t\t%15-19r"}, + {0x00002408, 0x3e007fff, "brlt\t\t%15-19r"}, + {0x00002808, 0x3e007fff, "brmi\t\t%15-19r"}, + {0x00002c08, 0x3e007fff, "brpl\t\t%15-19r"}, + {0x00003008, 0x3e007fff, "brvs\t\t%15-19r"}, + {0x00003408, 0x3e007fff, "brvc\t\t%15-19r"}, + {0x00003808, 0x3e007fff, "brcnz\t\t%15-19r"}, + {0x00003c08, 0x3e007fff, "br\t\t%15-19r"}, + {0x00000009, 0x3e007fff, "brcsl\t\t%15-19r"}, + {0x00000409, 0x3e007fff, "brccl\t\t%15-19r"}, + {0x00000809, 0x3e007fff, "brgtul\t\t%15-19r"}, + {0x00000c09, 0x3e007fff, "brleul\t\t%15-19r"}, + {0x00001009, 0x3e007fff, "breql\t\t%15-19r"}, + {0x00001409, 0x3e007fff, "brnel\t\t%15-19r"}, + {0x00001809, 0x3e007fff, "brgtl\t\t%15-19r"}, + {0x00001c09, 0x3e007fff, "brlel\t\t%15-19r"}, + {0x00002009, 0x3e007fff, "brgel\t\t%15-19r"}, + {0x00002409, 0x3e007fff, "brltl\t\t%15-19r"}, + {0x00002809, 0x3e007fff, "brmil\t\t%15-19r"}, + {0x00002c09, 0x3e007fff, "brpll\t\t%15-19r"}, + {0x00003009, 0x3e007fff, "brvsl\t\t%15-19r"}, + {0x00003409, 0x3e007fff, "brvcl\t\t%15-19r"}, + {0x00003809, 0x3e007fff, "brcnzl\t\t%15-19r"}, + {0x00003c09, 0x3e007fff, "brl\t\t%15-19r"}, + {0x00000080, 0x00007fe0, "br!\t\t%0-4r"}, + {0x000000a0, 0x00007fe0, "brl!\t\t%0-4r"}, + {0x000000c0, 0x00007fe0, "brr!\t\t%0-4r"}, + {0x08003000, 0x3e007c01, "bvs\t\t%b"}, + {0x08003400, 0x3e007c01, "bvc\t\t%b"}, + {0x08003001, 0x3e007c01, "bvsl\t\t%b"}, + {0x08003401, 0x3e007c01, "bvcl\t\t%b"}, + {0x00003000, 0x00007e00, "b!\t\t%b"}, + {0x08003c00, 0x3e007c01, "b\t\t%b"}, + {0x30000000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30100000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30200000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30300000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30400000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30800000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30900000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30a00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30b00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30c00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30d00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30e00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x31000000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x31100000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x31800000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x31a00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x31b00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x31c00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x31d00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x31e00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x31f00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x38000000, 0x3ff003ff, "mad\t\t%15-19r, %10-14r"}, + {0x38000020, 0x3ff003ff, "madu\t\t%15-19r, %10-14r"}, + {0x38000080, 0x3ff003ff, "mad.f\t\t%15-19r, %10-14r"}, + {0x38000001, 0x3ff003ff, "msb\t\t%15-19r, %10-14r"}, + {0x38000021, 0x3ff003ff, "msbu\t\t%15-19r, %10-14r"}, + {0x38000081, 0x3ff003ff, "msb.f\t\t%15-19r, %10-14r"}, + {0x38000102, 0x3ff003ff, "mazl\t\t%15-19r, %10-14r"}, + {0x38000182, 0x3ff003ff, "mazl.f\t\t%15-19r, %10-14r"}, + {0x38000002, 0x3ff003ff, "madl\t\t%15-19r, %10-14r"}, + {0x380000c2, 0x3ff003ff, "madl.fs\t\t%15-19r, %10-14r"}, + {0x38000303, 0x3ff003ff, "mazh\t\t%15-19r, %10-14r"}, + {0x38000383, 0x3ff003ff, "mazh.f\t\t%15-19r, %10-14r"}, + {0x38000203, 0x3ff003ff, "madh\t\t%15-19r, %10-14r"}, + {0x380002c3, 0x3ff003ff, "madh.fs\t\t%15-19r, %10-14r"}, + {0x38000007, 0x3e0003ff, "max\t\t%20-24r, %15-19r, %10-14r"}, + + {0x00000064, 0x3e00007e, "mbitclr\t\t[%15-19r, %m], %10-14d"}, + {0x0000006c, 0x3e00007e, "mbitset\t\t[%15-19r, %m], %10-14d"}, + + {0x38000006, 0x3e0003ff, "min\t\t%20-24r, %15-19r, %10-14r"}, + {0x38000104, 0x3ff003ff, "mszl\t\t%15-19r, %10-14r"}, + {0x38000184, 0x3ff003ff, "mszl.f\t\t%15-19r, %10-14r"}, + {0x38000004, 0x3ff003ff, "msbl\t\t%15-19r, %10-14r"}, + {0x380000c4, 0x3ff003ff, "msbl.fs\t\t%15-19r, %10-14r"}, + {0x38000305, 0x3ff003ff, "mszh\t\t%15-19r, %10-14r"}, + {0x38000385, 0x3ff003ff, "mszh.f\t\t%15-19r, %10-14r"}, + {0x38000205, 0x3ff003ff, "msbh\t\t%15-19r, %10-14r"}, + {0x380002c5, 0x3ff003ff, "msbh.fs\t\t%15-19r, %10-14r"}, + {0x3800004e, 0x3e0003ff, "sll.s\t\t%20-24r, %15-19r, %10-14r"}, + {0x38000049, 0x3e0003ff, "sub.s\t\t%20-24r, %15-19r, %10-14r"}, + {0x0000001c, 0x3e007fff, "clz\t\t%20-24r, %15-19r"}, + {0x38000000, 0x3e000000, "ceinst\t\t%20-24d, %15-19r, %10-14r, %5-9d, %0-4d"}, + {0x00000019, 0x3ff003ff, "cmpteq.c\t\t%15-19r, %10-14r"}, + {0x00100019, 0x3ff003ff, "cmptmi.c\t\t%15-19r, %10-14r"}, + {0x00300019, 0x3ff003ff, "cmp.c\t\t%15-19r, %10-14r"}, + {0x0000001b, 0x3ff07fff, "cmpzteq.c\t%15-19r"}, + {0x0010001b, 0x3ff07fff, "cmpztmi.c\t%15-19r"}, + {0x0030001b, 0x3ff07fff, "cmpz.c\t\t%15-19r"}, + {0x02040001, 0x3e0e0001, "cmpi.c\t\t%20-24r, %1-16i"}, + {0x00004400, 0x00007c00, "cmp!\t\t%5-9r, %0-4r"}, + {0x00006000, 0x00007c00, "cmpi!\t\t%5-9r, %0-4i"}, + {0x0c00000c, 0x3e00001f, "cop1\t\tc%20-24r, c%15-19r, c%10-14r, %5-9d"}, + {0x0c000014, 0x3e00001f, "cop2\t\tc%20-24r, c%15-19r, c%10-14r, %5-9d"}, + {0x0c00001c, 0x3e00001f, "cop3\t\tc%20-24r, c%15-19r, c%10-14r, %5-9d"}, + {0x00000044, 0x3e0003ff, "div\t\t%15-19r, %10-14r"}, + {0x00000144, 0x3e0003ff, "divr.q\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000244, 0x3e0003ff, "divr.r\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000344, 0x3e0003ff, "divr\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000046, 0x3e0003ff, "divu\t\t%15-19r, %10-14r"}, + {0x00000146, 0x3e0003ff, "divur.q\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000246, 0x3e0003ff, "divur.r\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000346, 0x3e0003ff, "divur\t\t%20-24r,%15-19r, %10-14r"}, + {0x0c0000a4, 0x3e0003ff, "drte"}, + {0x00e0, 0xffe1, "disint!"}, + {0x00e1, 0xffe1, "enint!"}, + {0x00000058, 0x3e0003ff, "extsb\t\t%20-24r, %15-19r"}, + {0x00000059, 0x3e0003ff, "extsb.c\t\t%20-24r, %15-19r"}, + {0x0000005a, 0x3e0003ff, "extsh\t\t%20-24r, %15-19r"}, + {0x0000005b, 0x3e0003ff, "extsh.c\t\t%20-24r, %15-19r"}, + {0x0000005c, 0x3e0003ff, "extzb\t\t%20-24r, %15-19r"}, + {0x0000005d, 0x3e0003ff, "extzb.c\t\t%20-24r, %15-19r"}, + {0x0000005e, 0x3e0003ff, "extzh\t\t%20-24r, %15-19r"}, + {0x0000005f, 0x3e0003ff, "extzh.c\t\t%20-24r, %15-19r"}, + {0x04000001, 0x3e000001, "jl\t\t%j"}, + {0x04000000, 0x3e000001, "j\t\t%j"}, + {0x26000000, 0x3e000000, "lb\t\t%20-24r, [%15-19r, %0-14i]"}, + {0x2c000000, 0x3e000000, "lbu\t\t%20-24r, [%15-19r, %0-14i]"}, + {0x06000003, 0x3e000007, "lb\t\t%20-24r, [%15-19r, %3-14i]+"}, + {0x06000006, 0x3e000007, "lbu\t\t%20-24r, [%15-19r, %3-14i]+"}, + {0x0e000003, 0x3e000007, "lb\t\t%20-24r, [%15-19r]+, %3-14i"}, + {0x0e000006, 0x3e000007, "lbu\t\t%20-24r, [%15-19r]+, %3-14i"}, + {0x00000060, 0x3e0003ff, "lcb\t\t[%15-19r]+"}, + {0x00000062, 0x3e0003ff, "lcw\t\t%20-24r, [%15-19r]+"}, + {0x00000066, 0x3e0003ff, "lce\t\t%20-24r, [%15-19r]+"}, + {0x0c00000a, 0x3e00001f, "ldc1\t\tc%15-19r, [%20-24r, %5-14i]"}, + {0x0c000012, 0x3e00001f, "ldc2\t\tc%15-19r, [%20-24r, %5-14i]"}, + {0x0c00001a, 0x3e00001f, "ldc3\t\tc%15-19r, [%20-24r, %5-14i]"}, + {0x000000000001LL, 0x1c000000001fLL, "ldi48\t\t%37-41r, %5-36i"}, + {0x22000000, 0x3e000000, "lh\t\t%20-24r, [%15-19r, %0-14i]"}, + {0x24000000, 0x3e000000, "lhu\t\t%20-24r, [%15-19r, %0-14i]"}, + {0x06000001, 0x3e000007, "lh\t\t%20-24r, [%15-19r, %3-14i]+"}, + {0x06000002, 0x3e000007, "lhu\t\t%20-24r, [%15-19r, %3-14i]+"}, + {0x0e000001, 0x3e000007, "lh\t\t%20-24r, [%15-19r]+, %3-14i"}, + {0x0e000002, 0x3e000007, "lhu\t\t%20-24r, [%15-19r]+, %3-14i"}, + {0x020c0000, 0x3e0e0000, "ldi\t\t%20-24r, 0x%1-16x(%1-16i)"}, + {0x0a0c0000, 0x3e0e0000, "ldis\t\t%20-24r, 0x%1-16x(%1-16i)"}, + {0x00006400, 0x00007c00, "ldiu!\t\t%5-9r, %0-4d"}, + {0x00000032, 0x3e0003ff, "ltbw\t\t%20-24r, [%15-19r, %10-14r]"}, + {0x00000132, 0x3e0003ff, "ltbh\t\t%20-24r, [%15-19r, %10-14r]"}, + {0x00000332, 0x3e0003ff, "ltbb\t\t%20-24r, [%15-19r, %10-14r]"}, + {0x0000000c, 0x3e0003ff, "alw\t\t%20-24r, [%15-19r]"}, + {0x20000000, 0x3e000000, "lw\t\t%20-24r, [%15-19r, %0-14i]"}, + {0x06000000, 0x3e000007, "lw\t\t%20-24r, [%15-19r, %3-14i]+"}, + {0x0e000000, 0x3e000007, "lw\t\t%20-24r, [%15-19r]+, %3-14i"}, + {0x00001000, 0x00007000, "lw!\t\t%8-11r, [%5-7r,%0-4d2]"}, + {0x000000000002LL, 0x1c000000001fLL, "lw48\t\t%37-41r,[0x%7-36w]"}, + {0x00007a00, 0x00007f00, "madl.fs!\t\t%4-7r, %0-3r"}, + {0x00007500, 0x00007f00, "madu!\t\t%4-7r, %0-3r"}, + {0x00007400, 0x00007f00, "mad.f!\t\t%4-7r, %0-3r"}, + {0x00007900, 0x00007f00, "mazh.f!\t\t%4-7r, %0-3r"}, + {0x00007800, 0x00007f00, "mazl.f!\t\t%4-7r, %0-3r"}, + {0x00000448, 0x3e007fff, "mfcel\t\t%20-24r"}, + {0x00007100, 0x00007ff0, "mfcel!\t\t%0-3r"}, + {0x00000848, 0x3e007fff, "mfceh\t\t%20-24r"}, + {0x00007110, 0x00007ff0, "mfceh!\t\t%0-3r"}, + {0x00000c48, 0x3e007fff, "mfcehl\t\t%20-24r, %15-19r"}, + {0x00000048, 0x3e0003ff, "mfce\t\t%20-24r, er%10-14d"}, + {0x00000050, 0x3e0003ff, "mfsr\t\t%20-24r, sr%10-14d"}, + {0x0c000001, 0x3e00001f, "mfcr\t\t%20-24r, c%15-19r"}, + {0x0c000009, 0x3e00001f, "mfc1\t\t%20-24r, c%15-19r"}, + {0x0c000011, 0x3e00001f, "mfc2\t\t%20-24r, c%15-19r"}, + {0x0c000019, 0x3e00001f, "mfc3\t\t%20-24r, c%15-19r"}, + {0x0c00000f, 0x3e00001f, "mfcc1\t\t%20-24r, c%15-19r"}, + {0x0c000017, 0x3e00001f, "mfcc2\t\t%20-24r, c%15-19r"}, + {0x0c00001f, 0x3e00001f, "mfcc3\t\t%20-24r, c%15-19r"}, + /* confilct: push! mhfl!. */ + {0x00000040, 0x00007fe0, "pop!\t\t%0-4r"}, + {0x00000060, 0x00007fe0, "push!\t\t%0-4r"}, + {0x00006800, 0x00007c00, "rpop!\t\t%5-9r, %0-4d"}, + {0x00006c00, 0x00007c00, "rpush!\t\t%5-9r, %0-4d"}, + {0x00007600, 0x00007f00, "msb.f!\t\t%4-7r, %0-3r"}, + {0x00007f00, 0x00007f00, "msbh.fs!\t\t%4-7r, %0-3r"}, + {0x00007e00, 0x00007f00, "msbl.fs!\t\t%4-7r, %0-3r"}, + {0x00007700, 0x00007f00, "msbu!\t\t%4-7r, %0-3r"}, + {0x00007d00, 0x00007f00, "mszh.f!\t\t%4-7r, %0-3r"}, + {0x00007c00, 0x00007f00, "mszl.f!\t\t%4-7r, %0-3r"}, + {0x0000044a, 0x3e007fff, "mtcel\t\t%20-24r"}, + {0x00007000, 0x00007ff0, "mtcel!\t\t%0-3r"}, + {0x0000084a, 0x3e007fff, "mtceh\t\t%20-24r"}, + {0x00007010, 0x00007ff0, "mtceh!\t\t%0-3r"}, + {0x00000c4a, 0x3e007fff, "mtcehl\t\t%20-24r, %15-19r"}, + {0x0000004a, 0x3e0003ff, "mtce\t\t%20-24r, er%10-14d"}, + {0x00000052, 0x3e0003ff, "mtsr\t\t%15-19r, sr%10-14d"}, + {0x0c000000, 0x3e00001f, "mtcr\t\t%20-24r, c%15-19r"}, + {0x0c000008, 0x3e00001f, "mtc1\t\t%20-24r, c%15-19r"}, + {0x0c000010, 0x3e00001f, "mtc2\t\t%20-24r, c%15-19r"}, + {0x0c000018, 0x3e00001f, "mtc3\t\t%20-24r, c%15-19r"}, + {0x0c00000e, 0x3e00001f, "mtcc1\t\t%20-24r, c%15-19r"}, + {0x0c000016, 0x3e00001f, "mtcc2\t\t%20-24r, c%15-19r"}, + {0x0c00001e, 0x3e00001f, "mtcc3\t\t%20-24r, c%15-19r"}, + {0x00000040, 0x3e0003ff, "mul\t\t%15-19r, %10-14r"}, + {0x00000140, 0x3e0003ff, "mulr.l\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000240, 0x3e0003ff, "mulr.h\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000340, 0x3e0003ff, "mulr\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000141, 0x3e0003ff, "mulr.lf\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000241, 0x3e0003ff, "mulr.hf\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000341, 0x3e0003ff, "mulr.f\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000040, 0x3e0003ff, "maz\t\t%15-19r, %10-14r"}, + {0x00000041, 0x3e0003ff, "mul.f\t\t%15-19r, %10-14r"}, + {0x00000041, 0x3e0003ff, "maz.f\t\t%15-19r, %10-14r"}, + {0x00007200, 0x00007f00, "mul.f!\t\t%4-7r, %0-3r"}, + {0x00000042, 0x3e0003ff, "mulu\t\t%15-19r, %10-14r"}, + {0x00000142, 0x3e0003ff, "mulur.l\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000242, 0x3e0003ff, "mulur.h\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000342, 0x3e0003ff, "mulur\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000042, 0x3e0003ff, "mazu\t\t%15-19r, %10-14r"}, + {0x00007300, 0x00007f00, "mulu!\t\t%4-7r, %0-3r"}, + {0x00000056, 0x3e007fff, "mvcs\t\t%20-24r, %15-19r"}, + {0x00000456, 0x3e007fff, "mvcc\t\t%20-24r, %15-19r"}, + {0x00000856, 0x3e007fff, "mvgtu\t\t%20-24r, %15-19r"}, + {0x00000c56, 0x3e007fff, "mvleu\t\t%20-24r, %15-19r"}, + {0x00001056, 0x3e007fff, "mveq\t\t%20-24r, %15-19r"}, + {0x00001456, 0x3e007fff, "mvne\t\t%20-24r, %15-19r"}, + {0x00001856, 0x3e007fff, "mvgt\t\t%20-24r, %15-19r"}, + {0x00001c56, 0x3e007fff, "mvle\t\t%20-24r, %15-19r"}, + {0x00002056, 0x3e007fff, "mvge\t\t%20-24r, %15-19r"}, + {0x00002456, 0x3e007fff, "mvlt\t\t%20-24r, %15-19r"}, + {0x00002856, 0x3e007fff, "mvmi\t\t%20-24r, %15-19r"}, + {0x00002c56, 0x3e007fff, "mvpl\t\t%20-24r, %15-19r"}, + {0x00003056, 0x3e007fff, "mvvs\t\t%20-24r, %15-19r"}, + {0x00003456, 0x3e007fff, "mvvc\t\t%20-24r, %15-19r"}, + {0x00003c56, 0x3e007fff, "mv\t\t%20-24r, %15-19r"}, + {0x00004000, 0x00007c00, "mv!\t\t%5-9r, %0-4r"}, + {0x0000001e, 0x3e0003ff, "neg\t\t%20-24r, %10-14r"}, + {0x0000001f, 0x3e0003ff, "neg.c\t\t%20-24r, %10-14r"}, + {0x00000000, 0x3e0003ff, "nop"}, + {0x00000024, 0x3e0003ff, "not\t\t%20-24r, %15-19r"}, + {0x00000025, 0x3e0003ff, "not.c\t\t%20-24r, %15-19r"}, + {0x00000000, 0x00007fff, "nop!"}, + {0x00000022, 0x3e0003ff, "or\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000023, 0x3e0003ff, "or.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x020a0000, 0x3e0e0001, "ori\t\t%20-24r, 0x%1-16x"}, + {0x020a0001, 0x3e0e0001, "ori.c\t\t%20-24r, 0x%1-16x"}, + {0x0a0a0000, 0x3e0e0001, "oris\t\t%20-24r, 0x%1-16x"}, + {0x0a0a0001, 0x3e0e0001, "oris.c\t\t%20-24r, 0x%1-16x"}, + {0x1a000000, 0x3e000001, "orri\t\t%20-24r, %15-19r, 0x%1-14x"}, + {0x1a000001, 0x3e000001, "orri.c\t\t%20-24r, %15-19r, 0x%1-14x"}, + {0x00004a00, 0x00007f00, "or!\t\t%4-7r, %0-3r"}, + {0x040000000002LL, 0x1c0000000003LL, "orri48\t\t%38-41r,%34-37r, 0x%2-33x"}, + {0x040000000003LL, 0x1c0000000003LL, "orri48.c\t\t%38-41r,%34-37r, 0x%2-33x"}, + {0x0000000a, 0x3e0003ff, "pflush"}, + {0x00000038, 0x3e0003ff, "ror\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000039, 0x3e0003ff, "ror.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x0000003b, 0x3e0003ff, "rorc.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x0000003c, 0x3e0003ff, "rol\t\t%20-24r, %15-19r, %10-14r"}, + {0x0000003d, 0x3e0003ff, "rol.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x0000003f, 0x3e0003ff, "rolc.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000078, 0x3e0003ff, "rori\t\t%20-24r, %15-19r, %10-14d"}, + {0x00000079, 0x3e0003ff, "rori.c\t\t%20-24r, %15-19r, %10-14d"}, + {0x0000007b, 0x3e0003ff, "roric.c\t\t%20-24r, %15-19r, %10-14d"}, + {0x0000007c, 0x3e0003ff, "roli\t\t%20-24r, %15-19r, %10-14d"}, + {0x0000007d, 0x3e0003ff, "roli.c\t\t%20-24r, %15-19r, %10-14d"}, + {0x0000007f, 0x3e0003ff, "rolic.c\t\t%20-24r, %15-19r, %10-14d"}, + {0x0c000084, 0x3e0003ff, "rte"}, + {0x2e000000, 0x3e000000, "sb\t\t%20-24r, [%15-19r, %0-14i]"}, + {0x06000007, 0x3e000007, "sb\t\t%20-24r, [%15-19r, %3-14i]+"}, + {0x0e000007, 0x3e000007, "sb\t\t%20-24r, [%15-19r]+, %3-14i"}, + {0x0000000e, 0x3e0003ff, "asw\t\t%20-24r, [%15-19r]"}, + {0x00000068, 0x3e0003ff, "scb\t\t%20-24r, [%15-19r]+"}, + {0x0000006a, 0x3e0003ff, "scw\t\t%20-24r, [%15-19r]+"}, + {0x0000006e, 0x3e0003ff, "sce\t\t[%15-19r]+"}, + {0x00000006, 0x3e0003ff, "sdbbp\t\t%15-19d"}, + {0x00000020, 0x00007fe0, "sdbbp!\t\t%0-4d"}, + {0x000000000000LL, 0x1c000000001fLL, "sdbbp48\t\t%5-9d"}, + {0x2a000000, 0x3e000000, "sh\t\t%20-24r, [%15-19r, %0-14i]"}, + {0x06000005, 0x3e000007, "sh\t\t%20-24r, [%15-19r, %3-14i]+"}, + {0x0e000005, 0x3e000007, "sh\t\t%20-24r, [%15-19r]+, %3-14i"}, + {0x0c0000c4, 0x3e0003ff, "sleep"}, + {0x0c0000e4, 0x3e0003ff, "rti"}, + {0x00000030, 0x3e0003ff, "sll\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000031, 0x3e0003ff, "sll.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000070, 0x3e0003ff, "slli\t\t%20-24r, %15-19r, %10-14d"}, + {0x00000071, 0x3e0003ff, "slli.c\t\t%20-24r, %15-19r, %10-14d"}, + {0x00005800, 0x00007e00, "slli!\t\t%5-8r, %0-4d"}, + {0x00000034, 0x3e0003ff, "srl\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000035, 0x3e0003ff, "srl.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000036, 0x3e0003ff, "sra\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000037, 0x3e0003ff, "sra.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000074, 0x3e0003ff, "srli\t\t%20-24r, %15-19r, %10-14d"}, + {0x00000075, 0x3e0003ff, "srli.c\t\t%20-24r, %15-19r, %10-14d"}, + {0x00000076, 0x3e0003ff, "srai\t\t%20-24r, %15-19r, %10-14d"}, + {0x00000077, 0x3e0003ff, "srai.c\t\t%20-24r, %15-19r, %10-14d"}, + {0x00005a00, 0x00007e00, "srli!\t\t%5-8r, %0-4d"}, + {0x0c00000b, 0x3e00001f, "stc1\t\tc%15-19r, [%20-24r, %5-14i]"}, + {0x0c000013, 0x3e00001f, "stc2\t\tc%15-19r, [%20-24r, %5-14i]"}, + {0x0c00001b, 0x3e00001f, "stc3\t\tc%15-19r, [%20-24r, %5-14i]"}, + {0x00000014, 0x3e0003ff, "sub\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000015, 0x3e0003ff, "sub.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000016, 0x3e0003ff, "subc\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000017, 0x3e0003ff, "subc.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x00004900, 0x00007f00, "sub!\t\t%4-7r, %0-3r"}, + {0x28000000, 0x3e000000, "sw\t\t%20-24r, [%15-19r, %0-14i]"}, + {0x06000004, 0x3e000007, "sw\t\t%20-24r, [%15-19r, %3-14i]+"}, + {0x0e000004, 0x3e000007, "sw\t\t%20-24r, [%15-19r]+, %3-14i"}, + {0x00002000, 0x00007000, "sw!\t\t%8-11r, [%5-7r,%0-4d2]"}, + {0x000000000003LL, 0x1c000000001fLL, "sw48\t\t%37-41r, [0x%7-36w]"}, + {0x00000002, 0x3e0003ff, "syscall\t\t%10-24d"}, + {0x00000054, 0x3e007fff, "tcs"}, + {0x00000454, 0x3e007fff, "tcc"}, + {0x00003854, 0x3e007fff, "tcnz"}, + {0x00001054, 0x3e007fff, "teq"}, + {0x00000854, 0x3e007fff, "tgtu"}, + {0x00001854, 0x3e007fff, "tgt"}, + {0x00002054, 0x3e007fff, "tge"}, + {0x00000c54, 0x3e007fff, "tleu"}, + {0x00001c54, 0x3e007fff, "tle"}, + {0x00002454, 0x3e007fff, "tlt"}, + {0x0c000004, 0x3e0003ff, "stlb"}, + {0x0c000024, 0x3e0003ff, "mftlb"}, + {0x0c000044, 0x3e0003ff, "mtptlb"}, + {0x0c000064, 0x3e0003ff, "mtrtlb"}, + {0x00002854, 0x3e007fff, "tmi"}, + {0x00001454, 0x3e007fff, "tne"}, + {0x00002c54, 0x3e007fff, "tpl"}, + {0x00000004, 0x3e007fff, "trapcs\t\t%15-19d"}, + {0x00000404, 0x3e007fff, "trapcc\t\t%15-19d"}, + {0x00000804, 0x3e007fff, "trapgtu\t\t%15-19d"}, + {0x00000c04, 0x3e007fff, "trapleu\t\t%15-19d"}, + {0x00001004, 0x3e007fff, "trapeq\t\t%15-19d"}, + {0x00001404, 0x3e007fff, "trapne\t\t%15-19d"}, + {0x00001804, 0x3e007fff, "trapgt\t\t%15-19d"}, + {0x00001c04, 0x3e007fff, "traple\t\t%15-19d"}, + {0x00002004, 0x3e007fff, "trapge\t\t%15-19d"}, + {0x00002404, 0x3e007fff, "traplt\t\t%15-19d"}, + {0x00002804, 0x3e007fff, "trapmi\t\t%15-19d"}, + {0x00002c04, 0x3e007fff, "trappl\t\t%15-19d"}, + {0x00003004, 0x3e007fff, "trapvs\t\t%15-19d"}, + {0x00003404, 0x3e007fff, "trapvc\t\t%15-19d"}, + {0x00003c04, 0x3e007fff, "trap\t\t%15-19d"}, + {0x00003c54, 0x3e007fff, "tset"}, + {0x00003054, 0x3e007fff, "tvs"}, + {0x00003454, 0x3e007fff, "tvc"}, + {0x00000026, 0x3e0003ff, "xor\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000027, 0x3e0003ff, "xor.c\t\t%20-24r, %15-19r, %10-14r"}, +}; +/*****************************************************************************/ + #ifndef streq -#define streq(a,b) (strcmp ((a), (b)) == 0) +#define streq(a,b) (strcmp ((a), (b)) == 0) #endif #ifndef strneq -#define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0) +#define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0) #endif #ifndef NUM_ELEM @@ -65,6 +509,165 @@ static unsigned int regname_selected = 0; #define NUM_SCORE_REGNAMES NUM_ELEM (regnames) #define score_regnames regnames[regname_selected].reg_names +/* Print one instruction from PC on INFO->STREAM. + Return the size of the instruction. */ +static int +print_insn_score48 (struct disassemble_info *info, bfd_vma given) +{ + struct score_opcode *insn; + void *stream = info->stream; + fprintf_ftype func = info->fprintf_func; + + for (insn = score_opcodes; insn->assembler; insn++) + { + /* using insn->mask &0xff00000000 to distinguish 48/32 bit */ + if (((insn->mask & 0xff0000000000LL)!=0) && (given & insn->mask) == insn->value) + { + info->bytes_per_chunk = 2; + info->bytes_per_line =6; + + char *c; + + for (c = insn->assembler; *c; c++) + { + if (*c == '%') + { + switch (*++c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + int bitstart = *c++ - '0'; + int bitend = 0; + + while (*c >= '0' && *c <= '9') + bitstart = (bitstart * 10) + *c++ - '0'; + + switch (*c) + { + case '-': + c++; + while (*c >= '0' && *c <= '9') + bitend = (bitend * 10) + *c++ - '0'; + + if (!bitend) + abort (); + + switch (*c) + { + case 'r': + { + long reg; + + reg = given >> bitstart; + reg &= (2 << (bitend - bitstart)) - 1; + + func (stream, "%s", score_regnames[reg]); + } + break; + case 'd': + { + long reg; + + reg = given >> bitstart; + reg &= (2 << (bitend - bitstart)) - 1; + + func (stream, "%ld", reg); + } + break; + case 'i': + { + long reg; + reg = given >> bitstart; + reg &= (2 << (bitend - bitstart)) - 1; + reg = ((reg ^ (1 << (bitend - bitstart))) - + (1 << (bitend - bitstart))); + /* Fix bug: s3_testsuite 64-bit. + Remove high 32 bits. */ + reg = (int) reg; + + if (((given & insn->mask) == 0x0c00000a) /* ldc1 */ + || ((given & insn->mask) == 0x0c000012) /* ldc2 */ + || ((given & insn->mask) == 0x0c00001c) /* ldc3 */ + || ((given & insn->mask) == 0x0c00000b) /* stc1 */ + || ((given & insn->mask) == 0x0c000013) /* stc2 */ + || ((given & insn->mask) == 0x0c00001b)) /* stc3 */ + reg <<= 2; + + func (stream, "%ld", reg); + } + break; + case 'x': + { + long reg; + + reg = given >> bitstart; + reg &= (2 << (bitend - bitstart)) - 1; + /* Fix bug: s3_testsuite 64-bit. + Remove high 32 bits. */ + reg = (int) reg; + + func (stream, "%lx", reg); + } + break; + case 'w': + { + long reg; + reg = given >> bitstart; + reg &= (2 << (bitend - bitstart)) - 1; + reg <<=2; + func (stream, "%lx", reg); + } + break; + + default: + abort (); + } + break; + + case '`': + c++; + if ((given & (1 << bitstart)) == 0) + func (stream, "%c", *c); + break; + case '\'': + c++; + if ((given & (1 << bitstart)) != 0) + func (stream, "%c", *c); + break; + default: + abort (); + } + break; + + default: + abort (); + } + } + } + else + func (stream, "%c", *c); + } + return 6; + } + } + +#if (SCORE_SIMULATOR_ACTIVE) + func (stream, _("")); + return 6; +#endif + + abort (); +} + /* Print one instruction from PC on INFO->STREAM. Return the size of the instruction. */ static int @@ -72,12 +675,25 @@ print_insn_score32 (bfd_vma pc, struct disassemble_info *info, long given) { struct score_opcode *insn; void *stream = info->stream; + int rb_equal_zero=1; fprintf_ftype func = info->fprintf_func; for (insn = score_opcodes; insn->assembler; insn++) { - if ((insn->mask & 0xffff0000) && (given & insn->mask) == insn->value) + if (((insn->mask & 0xff0000000000LL)==0)&&(insn->mask & 0xffff0000) && (given & insn->mask) == insn->value) { + /* check for bcmpeq / bcmpeqz / bcmpne / bcmpnez */ + /* given &0x7c00 is for to test if rb is zero , + rb_equal_zero =1 : index to bcmpeqz + rb_equal_zero =0 , index to bcmpeq + this checking rule only for branch compare ( insn->mask ==0x3e00007e*/ + if (((given & 0x7c00) !=0)&&(rb_equal_zero ==1)&&(insn->mask == 0x3e00007e) + && (insn->value == 0x0000004c || insn->value == 0x0000004e)) + { + rb_equal_zero =0; + continue; + } + char *c; for (c = insn->assembler; *c; c++) @@ -106,6 +722,41 @@ print_insn_score32 (bfd_vma pc, struct disassemble_info *info, long given) (*info->print_address_func) (target, info); } break; + case 'z': + { +#define SEXT10(x) ((((x) & 0x3ff) ^ (~ 0x1ff)) + 0x200) + if ((given & 0x7c00 ) == 0) + { + /* Sign-extend a 20-bit number. */ + /* disp : [24 -20] , [9-7 ] , [0] */ + int disp = (given&1)<<1 |((given>>7)&7)<<2 |((given>>20)&0x1f)<<5; + int target = (pc + SEXT10 (disp)); + (*info->print_address_func) (target, info); + } + else + { + long reg; + int bitstart = 10; + int bitend = 14; + reg = given >> bitstart; + reg &= (2 << (bitend - bitstart)) - 1; + /* Sign-extend a 20-bit number. */ + int disp = (given&1)<<1 |((given>>7)&7)<<2 |((given>>20)&0x1f)<<5; + int target = (pc + SEXT10 (disp)); + func (stream, "%s ,", score_regnames[reg] ); + (*info->print_address_func) (target, info); + + } + + } + break; + case 'm': + { + /* disp : [24 -20] , [9-7 ] , [0] */ + int disp = (given&1)<<2 |((given>>7)&7)<<3 |((given>>20)&0x1f)<<6; + (*info->print_address_func) (disp, info); + } + break; case '0': case '1': case '2': @@ -189,6 +840,7 @@ print_insn_score32 (bfd_vma pc, struct disassemble_info *info, long given) abort (); } break; + case '`': c++; if ((given & (1 << bitstart)) == 0) @@ -224,18 +876,6 @@ print_insn_score32 (bfd_vma pc, struct disassemble_info *info, long given) abort (); } -static void -print_insn_parallel_sym (struct disassemble_info *info) -{ - void *stream = info->stream; - fprintf_ftype func = info->fprintf_func; - - /* 10: 0000 nop! - 4 space + 1 colon + 1 space + 1 tab + 8 opcode + 2 space + 1 tab. - FIXME: the space number is not accurate. */ - func (stream, "%s", " ||\n \t \t"); -} - /* Print one instruction from PC on INFO->STREAM. Return the size of the instruction. */ static int @@ -248,7 +888,7 @@ print_insn_score16 (bfd_vma pc, struct disassemble_info *info, long given) given &= 0xffff; for (insn = score_opcodes; insn->assembler; insn++) { - if (!(insn->mask & 0xffff0000) && (given & insn->mask) == insn->value) + if (((insn->mask & 0xff0000000000LL)==0) &&!(insn->mask & 0xffff0000) && (given & insn->mask) == insn->value) { char *c = insn->assembler; @@ -277,9 +917,9 @@ print_insn_score16 (bfd_vma pc, struct disassemble_info *info, long given) case 'b': { /* Sign-extend a 9-bit number. */ -#define SEXT9(x) ((((x) & 0x1ff) ^ (~ 0xff)) + 0x100) - int disp = (given & 0xff) << 1; - int target = (pc + SEXT9 (disp)); +#define SEXT10(x) ((((x) & 0x3ff) ^ (~ 0x1ff)) + 0x200) + int disp = (given & 0x1ff) << 1; + int target = (pc + SEXT10 (disp)); (*info->print_address_func) (target, info); } @@ -315,6 +955,16 @@ print_insn_score16 (bfd_vma pc, struct disassemble_info *info, long given) abort (); reg = given >> bitstart; reg &= (2 << (bitend - bitstart)) - 1; + + /* Check rpush rd, 0 and rpop! rd, 0. + If reg = 0, then set to 32. */ + if (((given & 0x00007c00) == 0x00006c00 + || (given & 0x00007c00) == 0x00006800) + && reg == 0) + { + reg = 32; + } + switch (*c) { case 'R': @@ -349,8 +999,8 @@ print_insn_score16 (bfd_vma pc, struct disassemble_info *info, long given) } break; case 'i': - reg = ((reg ^ (1 << bitend)) - (1 << bitend)); - func (stream, "%ld", reg); + reg = ((reg ^ (1 << bitend)) - (1 << bitend)); + func (stream, "%ld", reg); break; default: abort (); @@ -390,37 +1040,72 @@ print_insn_score16 (bfd_vma pc, struct disassemble_info *info, long given) /* NOTE: There are no checks in these routines that the relevant number of data bytes exist. */ static int -print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little) +s3_print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little) { - unsigned char b[4]; - long given; - long ridparity; - int status; - bfd_boolean insn_pce_p = FALSE; - bfd_boolean insn_16_p = FALSE; + unsigned char b[6]; + bfd_vma given,given_h , given_l, given_16, given_32, given_48; + bfd_vma ridparity; + int status; + void *stream = info->stream; + fprintf_ftype func = info->fprintf_func; info->display_endian = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG; - - if (pc & 0x2) + info->bytes_per_chunk = 2; + status = info->read_memory_func (pc, (bfd_byte *) & b[0], 4, info); + if (status != 0) { info->bytes_per_chunk = 2; status = info->read_memory_func (pc, (bfd_byte *) b, 2, info); b[3] = b[2] = 0; - insn_16_p = TRUE; + if (status != 0) + { + info->memory_error_func (status, pc, info); + return -1; + } + } + if (little) + { + given = b[0] | (b[1] << 8); } else { - info->bytes_per_chunk = 4; - status = info->read_memory_func (pc, (bfd_byte *) & b[0], 4, info); - if (status != 0) - { - info->bytes_per_chunk = 2; - status = info->read_memory_func (pc, (bfd_byte *) b, 2, info); - b[3] = b[2] = 0; - insn_16_p = TRUE; - } + given = (b[0] << 8) | b[1]; } + /* Set given_16. */ + given_16 = given; + + /* judge if now is insn_16_p */ + if ((given & 0x8000)==0) + return print_insn_score16 (pc, info, given); + + else + { + if (little) + { + given = ((bfd_vma)b[2]) | ((bfd_vma)b[3] << 8) | ((bfd_vma)b[0] << 16) | ((bfd_vma)b[1] << 24); + } + else + { + given = ((bfd_vma)b[0] << 24) | ((bfd_vma)b[1] << 16) | ((bfd_vma)b[2] << 8) | ((bfd_vma)b[3]); + } + + /* Set given_32. */ + given_32 = given; + + /* judge if now is insn_32 */ + if ((given &0x80008000)==0x80000000) + { + /* Get rid of parity. */ + ridparity = (given & 0x7FFF); + ridparity |= (given & 0x7FFF0000) >> 1; + given = ridparity; + return print_insn_score32 (pc, info, given); + } + } + + /* the insn is 48 bit */ + status = info->read_memory_func (pc, (bfd_byte *) & b[0], 6, info); if (status != 0) { info->memory_error_func (status, pc, info); @@ -429,76 +1114,83 @@ print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little) if (little) { - given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24); + given = ((bfd_vma)b[4]) | ((bfd_vma)b[5] << 8) | ((bfd_vma)b[2] << 16) | ((bfd_vma)b[3] << 24) + | ((bfd_vma)b[0] << 32) | ((bfd_vma)b[1] << 40); } else { - given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]); + given_l = ((bfd_vma)b[5]) | ((bfd_vma)b[4] << 8) | ((bfd_vma)b[3] << 16) | ((bfd_vma)b[2] << 24) ; + given_h = ((bfd_vma)b[1] )|((bfd_vma)b[0] <<8); + given = ((bfd_vma)given_h<<32) | (bfd_vma)given_l ; + } - if ((given & 0x80008000) == 0x80008000) - { - insn_pce_p = FALSE; - insn_16_p = FALSE; - } - else if ((given & 0x8000) == 0x8000) - { - insn_pce_p = TRUE; - } - else - { - insn_16_p = TRUE; - } + /* Set given_48. */ + given_48 = given; - /* 16 bit instruction. */ - if (insn_16_p) - { - if (little) - { - given = b[0] | (b[1] << 8); - } - else - { - given = (b[0] << 8) | b[1]; - } + if ((given & 0x800080008000LL) == 0x800080000000LL) + { + /* Get rid of parity. */ + ridparity = (given & 0x7FFF); + ridparity |= (given & 0x7FFF0000) >> 1; + ridparity |= (given & 0x7FFF00000000LL) >> 2; + given = ridparity; + status = print_insn_score48 (info, given); + return status; + } - status = print_insn_score16 (pc, info, given); - } - /* pce instruction. */ - else if (insn_pce_p) - { - long other; + /* Check 0x800080008000, 0x80008000, 0x8000. */ - other = given & 0xFFFF; - given = (given & 0xFFFF0000) >> 16; + if ((given_48 & 0x800080008000LL) != 0x800080000000LL) + { +#if (SCORE_SIMULATOR_ACTIVE) + func (stream, _("")); + return 6; +#endif + } + if (((given_32 & 0xffff00000000LL) == 0) && ((given_32 & 0x80008000) != 0x80000000)) + { +#if (SCORE_SIMULATOR_ACTIVE) + func (stream, _("")); + return 4; +#endif + } + if (((given_16 & 0xffffffff0000LL) == 0) && ((given_16 & 0x8000) != 0)) + { +#if (SCORE_SIMULATOR_ACTIVE) + func (stream, _("")); + return 2; +#endif + } + else + { + return 0; + } +} - status = print_insn_score16 (pc, info, given); - print_insn_parallel_sym (info); - status += print_insn_score16 (pc, info, other); - /* disassemble_bytes() will output 4 byte per chunk for pce instructio. */ - info->bytes_per_chunk = 4; - } - /* 32 bit instruction. */ +static unsigned long +score_get_arch (disassemble_info *info) +{ + if (info->arch == bfd_arch_score) + return info->mach; else - { - /* Get rid of parity. */ - ridparity = (given & 0x7FFF); - ridparity |= (given & 0x7FFF0000) >> 1; - given = ridparity; - status = print_insn_score32 (pc, info, given); - } - - return status; + return 0; } int print_insn_big_score (bfd_vma pc, struct disassemble_info *info) { - return print_insn (pc, info, FALSE); + if (score_get_arch (info) == bfd_mach_score3) + return s3_print_insn (pc, info, FALSE); + else + return s7_print_insn (pc, info, FALSE); } int print_insn_little_score (bfd_vma pc, struct disassemble_info *info) { - return print_insn (pc, info, TRUE); + if (score_get_arch (info) == bfd_mach_score3) + return s3_print_insn (pc, info, TRUE); + else + return s7_print_insn (pc, info, TRUE); } diff --git a/opcodes/score-opc.h b/opcodes/score-opc.h index 8c4e6c00b39..6cfc20f82af 100644 --- a/opcodes/score-opc.h +++ b/opcodes/score-opc.h @@ -19,9 +19,9 @@ struct score_opcode { - unsigned long value; - unsigned long mask; /* Recognise instruction if (op & mask) == value. */ - char *assembler; /* Disassembly string. */ + bfd_vma value; + bfd_vma mask; /* Recognise instruction if (op & mask) == value. */ + char *assembler; /* Disassembly string. */ }; /* Note: There is a partial ordering in this table - it must be searched from @@ -31,7 +31,7 @@ static struct score_opcode score_opcodes[] = { /* Score Instructions. */ {0x3800000a, 0x3e007fff, "abs\t\t%20-24r, %15-19r"}, - {0x3800004b, 0x3e007fff, "abs.s\t\t%20-24r, %15-19r"}, + {0x3800004b, 0x3e007fff, "abs.s\t\t%20-24r, %15-19r"}, {0x00000010, 0x3e0003ff, "add\t\t%20-24r, %15-19r, %10-14r"}, {0x00000011, 0x3e0003ff, "add.c\t\t%20-24r, %15-19r, %10-14r"}, {0x38000048, 0x3e0003ff, "add.s\t\t%20-24r, %15-19r, %10-14r"}, @@ -43,139 +43,110 @@ static struct score_opcode score_opcodes[] = {0x0a000001, 0x3e0e0001, "addis.c\t\t%20-24r, %1-16d(0x%1-16x)"}, {0x10000000, 0x3e000001, "addri\t\t%20-24r, %15-19r, %1-14i"}, {0x10000001, 0x3e000001, "addri.c\t\t%20-24r, %15-19r, %1-14i"}, - {0x00000009, 0x0000700f, "addc!\t\t%8-11r, %4-7r"}, - {0x00002000, 0x0000700f, "add!\t\t%8-11r, %4-7r"}, - {0x00006000, 0x00007087, "addei!\t\t%8-11r, %3-6d"}, + {0x00004800, 0x00007f00, "add!\t\t%4-7r, %0-3r"}, + {0x00005c00, 0x00007c00, "addi!\t\t%6-9r, %0-5i"}, {0x00000020, 0x3e0003ff, "and\t\t%20-24r, %15-19r, %10-14r"}, {0x00000021, 0x3e0003ff, "and.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x040000000000LL, 0x1c0000000003LL, "andri48\t\t%38-41r,%34-37r, 0x%2-33x"}, + {0x040000000001LL, 0x1c0000000003LL, "andri48.c\t\t%38-41r,%34-37r, 0x%2-33x"}, {0x02080000, 0x3e0e0001, "andi\t\t%20-24r, 0x%1-16x"}, {0x02080001, 0x3e0e0001, "andi.c\t\t%20-24r, 0x%1-16x"}, {0x0a080000, 0x3e0e0001, "andis\t\t%20-24r, 0x%1-16x"}, {0x0a080001, 0x3e0e0001, "andis.c\t\t%20-24r, 0x%1-16x"}, {0x18000000, 0x3e000001, "andri\t\t%20-24r, %15-19r, 0x%1-14x"}, {0x18000001, 0x3e000001, "andri.c\t\t%20-24r, %15-19r,0x%1-14x"}, - {0x00002004, 0x0000700f, "and!\t\t%8-11r, %4-7r"}, - {0x08000000, 0x3e007c01, "bcs\t\t%b" }, - {0x08000400, 0x3e007c01, "bcc\t\t%b" }, - {0x08003800, 0x3e007c01, "bcnz\t\t%b" }, - {0x08000001, 0x3e007c01, "bcsl\t\t%b" }, - {0x08000401, 0x3e007c01, "bccl\t\t%b" }, - {0x08003801, 0x3e007c01, "bcnzl\t\t%b" }, - {0x00004000, 0x00007f00, "bcs!\t\t%b" }, - {0x00004100, 0x00007f00, "bcc!\t\t%b" }, - {0x00004e00, 0x00007f00, "bcnz!\t\t%b" }, - {0x08001000, 0x3e007c01, "beq\t\t%b" }, - {0x08001001, 0x3e007c01, "beql\t\t%b" }, - {0x00004400, 0x00007f00, "beq!\t\t%b" }, - {0x08000800, 0x3e007c01, "bgtu\t\t%b" }, - {0x08001800, 0x3e007c01, "bgt\t\t%b" }, - {0x08002000, 0x3e007c01, "bge\t\t%b" }, - {0x08000801, 0x3e007c01, "bgtul\t\t%b" }, - {0x08001801, 0x3e007c01, "bgtl\t\t%b" }, - {0x08002001, 0x3e007c01, "bgel\t\t%b" }, - {0x00004200, 0x00007f00, "bgtu!\t\t%b" }, - {0x00004600, 0x00007f00, "bgt!\t\t%b" }, - {0x00004800, 0x00007f00, "bge!\t\t%b" }, + {0x00004b00, 0x00007f00, "and!\t\t%4-7r, %0-3r"}, + {0x08000000, 0x3e007c01, "bcs\t\t%b"}, + {0x08000400, 0x3e007c01, "bcc\t\t%b"}, + {0x08003800, 0x3e007c01, "bcnz\t\t%b"}, + {0x08000001, 0x3e007c01, "bcsl\t\t%b"}, + {0x08000401, 0x3e007c01, "bccl\t\t%b"}, + {0x08003801, 0x3e007c01, "bcnzl\t\t%b"}, + {0x0000004c, 0x3e00007e, "bcmpeqz\t\t%15-19r, %z"}, + {0x0000004c, 0x3e00007e, "bcmpeq\t\t%15-19r, %z"}, + {0x0000004e, 0x3e00007e, "bcmpnez\t\t%15-19r, %z"}, + {0x0000004e, 0x3e00007e, "bcmpne\t\t%15-19r, %z"}, + {0x00003200, 0x00007e00, "bcnz!\t\t%b"}, + {0x08001000, 0x3e007c01, "beq\t\t%b"}, + {0x08001001, 0x3e007c01, "beql\t\t%b"}, + {0x00003800, 0x00007e00, "beq!\t\t%b"}, + {0x08000800, 0x3e007c01, "bgtu\t\t%b"}, + {0x08001800, 0x3e007c01, "bgt\t\t%b"}, + {0x08002000, 0x3e007c01, "bge\t\t%b"}, + {0x08000801, 0x3e007c01, "bgtul\t\t%b"}, + {0x08001801, 0x3e007c01, "bgtl\t\t%b"}, + {0x08002001, 0x3e007c01, "bgel\t\t%b"}, + {0x00003400, 0x00007e00, "bgtu!\t\t%b"}, + {0x00003c00, 0x00007e00, "bgt!\t\t%b"}, {0x00000029, 0x3e0003ff, "bitclr.c\t%20-24r, %15-19r, 0x%10-14x"}, + {0x00000028, 0x3e0003ff, "bitclr\t%20-24r, %15-19r, 0x%10-14x"}, {0x0000002b, 0x3e0003ff, "bitset.c\t%20-24r, %15-19r, 0x%10-14x"}, + {0x0000002a, 0x3e0003ff, "bitset\t%20-24r, %15-19r, 0x%10-14x"}, {0x0000002d, 0x3e0003ff, "bittst.c\t%15-19r, 0x%10-14x"}, {0x0000002f, 0x3e0003ff, "bittgl.c\t%20-24r, %15-19r, 0x%10-14x"}, - {0x00006004, 0x00007007, "bitclr!\t\t%8-11r, 0x%3-7x"}, + {0x0000002e, 0x3e0003ff, "bittgl\t%20-24r, %15-19r, 0x%10-14x"}, + {0x00005000, 0x00007e00, "bitclr!\t\t%5-8r, 0x%0-4x"}, {0x3800000c, 0x3e0003ff, "bitrev\t\t%20-24r, %15-19r,%10-14r"}, - {0x00006005, 0x00007007, "bitset!\t\t%8-11r, 0x%3-7x"}, - {0x00006006, 0x00007007, "bittst!\t\t%8-11r, 0x%3-7x"}, - {0x00006007, 0x00007007, "bittgl!\t\t%8-11r, 0x%3-7x"}, - {0x08000c00, 0x3e007c01, "bleu\t\t%b" }, - {0x08001c00, 0x3e007c01, "ble\t\t%b" }, - {0x08002400, 0x3e007c01, "blt\t\t%b" }, - {0x08000c01, 0x3e007c01, "bleul\t\t%b" }, - {0x08001c01, 0x3e007c01, "blel\t\t%b" }, - {0x08002401, 0x3e007c01, "bltl\t\t%b" }, - {0x08003c01, 0x3e007c01, "bl\t\t%b" }, - {0x00004300, 0x00007f00, "bleu!\t\t%b" }, - {0x00004700, 0x00007f00, "ble!\t\t%b" }, - {0x00004900, 0x00007f00, "blt!\t\t%b" }, - {0x08002800, 0x3e007c01, "bmi\t\t%b" }, - {0x08002801, 0x3e007c01, "bmil\t\t%b" }, - {0x00004a00, 0x00007f00, "bmi!\t\t%b" }, - {0x08001400, 0x3e007c01, "bne\t\t%b" }, - {0x08001401, 0x3e007c01, "bnel\t\t%b" }, - {0x00004500, 0x00007f00, "bne!\t\t%b" }, - {0x08002c00, 0x3e007c01, "bpl\t\t%b" }, - {0x08002c01, 0x3e007c01, "bpll\t\t%b" }, - {0x00004b00, 0x00007f00, "bpl!\t\t%b" }, - {0x00000008, 0x3e007fff, "brcs\t\t%15-19r" }, - {0x00000408, 0x3e007fff, "brcc\t\t%15-19r" }, - {0x00000808, 0x3e007fff, "brgtu\t\t%15-19r" }, - {0x00000c08, 0x3e007fff, "brleu\t\t%15-19r" }, - {0x00001008, 0x3e007fff, "breq\t\t%15-19r" }, - {0x00001408, 0x3e007fff, "brne\t\t%15-19r" }, - {0x00001808, 0x3e007fff, "brgt\t\t%15-19r" }, - {0x00001c08, 0x3e007fff, "brle\t\t%15-19r" }, - {0x00002008, 0x3e007fff, "brge\t\t%15-19r" }, - {0x00002408, 0x3e007fff, "brlt\t\t%15-19r" }, - {0x00002808, 0x3e007fff, "brmi\t\t%15-19r" }, - {0x00002c08, 0x3e007fff, "brpl\t\t%15-19r" }, - {0x00003008, 0x3e007fff, "brvs\t\t%15-19r" }, - {0x00003408, 0x3e007fff, "brvc\t\t%15-19r" }, - {0x00003808, 0x3e007fff, "brcnz\t\t%15-19r" }, - {0x00003c08, 0x3e007fff, "br\t\t%15-19r" }, - {0x00000009, 0x3e007fff, "brcsl\t\t%15-19r" }, - {0x00000409, 0x3e007fff, "brccl\t\t%15-19r" }, - {0x00000809, 0x3e007fff, "brgtul\t\t%15-19r" }, - {0x00000c09, 0x3e007fff, "brleul\t\t%15-19r" }, - {0x00001009, 0x3e007fff, "breql\t\t%15-19r" }, - {0x00001409, 0x3e007fff, "brnel\t\t%15-19r" }, - {0x00001809, 0x3e007fff, "brgtl\t\t%15-19r" }, - {0x00001c09, 0x3e007fff, "brlel\t\t%15-19r" }, - {0x00002009, 0x3e007fff, "brgel\t\t%15-19r" }, - {0x00002409, 0x3e007fff, "brltl\t\t%15-19r" }, - {0x00002809, 0x3e007fff, "brmil\t\t%15-19r" }, - {0x00002c09, 0x3e007fff, "brpll\t\t%15-19r" }, - {0x00003009, 0x3e007fff, "brvsl\t\t%15-19r" }, - {0x00003409, 0x3e007fff, "brvcl\t\t%15-19r" }, - {0x00003809, 0x3e007fff, "brcnzl\t\t%15-19r" }, - {0x00003c09, 0x3e007fff, "brl\t\t%15-19r" }, - {0x00000004, 0x00007f0f, "brcs!\t\t%4-7r" }, - {0x00000104, 0x00007f0f, "brcc!\t\t%4-7r" }, - {0x00000204, 0x00007f0f, "brgtu!\t\t%4-7r" }, - {0x00000304, 0x00007f0f, "brleu!\t\t%4-7r" }, - {0x00000404, 0x00007f0f, "breq!\t\t%4-7r" }, - {0x00000504, 0x00007f0f, "brne!\t\t%4-7r" }, - {0x00000604, 0x00007f0f, "brgt!\t\t%4-7r" }, - {0x00000704, 0x00007f0f, "brle!\t\t%4-7r" }, - {0x00000804, 0x00007f0f, "brge!\t\t%4-7r" }, - {0x00000904, 0x00007f0f, "brlt!\t\t%4-7r" }, - {0x00000a04, 0x00007f0f, "brmi!\t\t%4-7r" }, - {0x00000b04, 0x00007f0f, "brpl!\t\t%4-7r" }, - {0x00000c04, 0x00007f0f, "brvs!\t\t%4-7r" }, - {0x00000d04, 0x00007f0f, "brvc!\t\t%4-7r" }, - {0x00000e04, 0x00007f0f, "brcnz!\t\t%4-7r" }, - {0x00000f04, 0x00007f0f, "br!\t\t%4-7r" }, - {0x0000000c, 0x00007f0f, "brcsl!\t\t%4-7r" }, - {0x0000010c, 0x00007f0f, "brccl!\t\t%4-7r" }, - {0x0000020c, 0x00007f0f, "brgtul!\t\t%4-7r" }, - {0x0000030c, 0x00007f0f, "brleul!\t\t%4-7r" }, - {0x0000040c, 0x00007f0f, "breql!\t\t%4-7r" }, - {0x0000050c, 0x00007f0f, "brnel!\t\t%4-7r" }, - {0x0000060c, 0x00007f0f, "brgtl!\t\t%4-7r" }, - {0x0000070c, 0x00007f0f, "brlel!\t\t%4-7r" }, - {0x0000080c, 0x00007f0f, "brgel!\t\t%4-7r" }, - {0x0000090c, 0x00007f0f, "brltl!\t\t%4-7r" }, - {0x00000a0c, 0x00007f0f, "brmil!\t\t%4-7r" }, - {0x00000b0c, 0x00007f0f, "brpll!\t\t%4-7r" }, - {0x00000c0c, 0x00007f0f, "brvsl!\t\t%4-7r" }, - {0x00000d0c, 0x00007f0f, "brvcl!\t\t%4-7r" }, - {0x00000e0c, 0x00007f0f, "brcnzl!\t\t%4-7r" }, - {0x00000f0c, 0x00007f0f, "brl!\t\t%4-7r" }, - {0x08003000, 0x3e007c01, "bvs\t\t%b" }, - {0x08003400, 0x3e007c01, "bvc\t\t%b" }, - {0x08003001, 0x3e007c01, "bvsl\t\t%b" }, - {0x08003401, 0x3e007c01, "bvcl\t\t%b" }, - {0x00004c00, 0x00007f00, "bvs!\t\t%b" }, - {0x00004d00, 0x00007f00, "bvc!\t\t%b" }, - {0x00004f00, 0x00007f00, "b!\t\t%b" }, - {0x08003c00, 0x3e007c01, "b\t\t%b" }, + {0x00005200, 0x00007e00, "bitset!\t\t%5-8r, 0x%0-4x"}, + {0x00005400, 0x00007e00, "bittst!\t\t%5-8r, 0x%0-4x"}, + {0x00005600, 0x00007e00, "bittgl!\t\t%5-8r, 0x%0-4x"}, + {0x08000c00, 0x3e007c01, "bleu\t\t%b"}, + {0x08001c00, 0x3e007c01, "ble\t\t%b"}, + {0x08002400, 0x3e007c01, "blt\t\t%b"}, + {0x08000c01, 0x3e007c01, "bleul\t\t%b"}, + {0x08001c01, 0x3e007c01, "blel\t\t%b"}, + {0x08002401, 0x3e007c01, "bltl\t\t%b"}, + {0x08003c01, 0x3e007c01, "bl\t\t%b"}, + {0x00003600, 0x00007e00, "bleu!\t\t%b"}, + {0x00003e00, 0x00007e00, "ble!\t\t%b"}, + {0x08002800, 0x3e007c01, "bmi\t\t%b"}, + {0x08002801, 0x3e007c01, "bmil\t\t%b"}, + {0x08001400, 0x3e007c01, "bne\t\t%b"}, + {0x08001401, 0x3e007c01, "bnel\t\t%b"}, + {0x00003a00, 0x00007e00, "bne!\t\t%b"}, + {0x08002c00, 0x3e007c01, "bpl\t\t%b"}, + {0x08002c01, 0x3e007c01, "bpll\t\t%b"}, + {0x00000008, 0x3e007fff, "brcs\t\t%15-19r"}, + {0x00000408, 0x3e007fff, "brcc\t\t%15-19r"}, + {0x00000808, 0x3e007fff, "brgtu\t\t%15-19r"}, + {0x00000c08, 0x3e007fff, "brleu\t\t%15-19r"}, + {0x00001008, 0x3e007fff, "breq\t\t%15-19r"}, + {0x00001408, 0x3e007fff, "brne\t\t%15-19r"}, + {0x00001808, 0x3e007fff, "brgt\t\t%15-19r"}, + {0x00001c08, 0x3e007fff, "brle\t\t%15-19r"}, + {0x00002008, 0x3e007fff, "brge\t\t%15-19r"}, + {0x00002408, 0x3e007fff, "brlt\t\t%15-19r"}, + {0x00002808, 0x3e007fff, "brmi\t\t%15-19r"}, + {0x00002c08, 0x3e007fff, "brpl\t\t%15-19r"}, + {0x00003008, 0x3e007fff, "brvs\t\t%15-19r"}, + {0x00003408, 0x3e007fff, "brvc\t\t%15-19r"}, + {0x00003808, 0x3e007fff, "brcnz\t\t%15-19r"}, + {0x00003c08, 0x3e007fff, "br\t\t%15-19r"}, + {0x00000009, 0x3e007fff, "brcsl\t\t%15-19r"}, + {0x00000409, 0x3e007fff, "brccl\t\t%15-19r"}, + {0x00000809, 0x3e007fff, "brgtul\t\t%15-19r"}, + {0x00000c09, 0x3e007fff, "brleul\t\t%15-19r"}, + {0x00001009, 0x3e007fff, "breql\t\t%15-19r"}, + {0x00001409, 0x3e007fff, "brnel\t\t%15-19r"}, + {0x00001809, 0x3e007fff, "brgtl\t\t%15-19r"}, + {0x00001c09, 0x3e007fff, "brlel\t\t%15-19r"}, + {0x00002009, 0x3e007fff, "brgel\t\t%15-19r"}, + {0x00002409, 0x3e007fff, "brltl\t\t%15-19r"}, + {0x00002809, 0x3e007fff, "brmil\t\t%15-19r"}, + {0x00002c09, 0x3e007fff, "brpll\t\t%15-19r"}, + {0x00003009, 0x3e007fff, "brvsl\t\t%15-19r"}, + {0x00003409, 0x3e007fff, "brvcl\t\t%15-19r"}, + {0x00003809, 0x3e007fff, "brcnzl\t\t%15-19r"}, + {0x00003c09, 0x3e007fff, "brl\t\t%15-19r"}, + {0x00000080, 0x00007fe0, "br!\t\t%0-4r"}, + {0x000000a0, 0x00007fe0, "brl!\t\t%0-4r"}, + {0x000000c0, 0x00007fe0, "brr!\t\t%0-4r"}, + {0x08003000, 0x3e007c01, "bvs\t\t%b"}, + {0x08003400, 0x3e007c01, "bvc\t\t%b"}, + {0x08003001, 0x3e007c01, "bvsl\t\t%b"}, + {0x08003401, 0x3e007c01, "bvcl\t\t%b"}, + {0x00003000, 0x00007e00, "b!\t\t%b"}, + {0x08003c00, 0x3e007c01, "b\t\t%b"}, {0x30000000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, {0x30100000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, {0x30200000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, @@ -198,32 +169,36 @@ static struct score_opcode score_opcodes[] = {0x31e00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, {0x31f00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, {0x38000000, 0x3ff003ff, "mad\t\t%15-19r, %10-14r"}, - {0x38000020, 0x3ff003ff, "madu\t\t%15-19r, %10-14r"}, + {0x38000020, 0x3ff003ff, "madu\t\t%15-19r, %10-14r"}, {0x38000080, 0x3ff003ff, "mad.f\t\t%15-19r, %10-14r"}, - {0x38000001, 0x3ff003ff, "msb\t\t%15-19r, %10-14r"}, + {0x38000001, 0x3ff003ff, "msb\t\t%15-19r, %10-14r"}, {0x38000021, 0x3ff003ff, "msbu\t\t%15-19r, %10-14r"}, {0x38000081, 0x3ff003ff, "msb.f\t\t%15-19r, %10-14r"}, - {0x38000102, 0x3ff003ff, "mazl\t\t%15-19r, %10-14r"}, - {0x38000182, 0x3ff003ff, "mazl.f\t\t%15-19r, %10-14r"}, - {0x38000002, 0x3ff003ff, "madl\t\t%15-19r, %10-14r"}, - {0x380000c2, 0x3ff003ff, "madl.fs\t\t%15-19r, %10-14r"}, - {0x38000303, 0x3ff003ff, "mazh\t\t%15-19r, %10-14r"}, - {0x38000383, 0x3ff003ff, "mazh.f\t\t%15-19r, %10-14r"}, - {0x38000203, 0x3ff003ff, "madh\t\t%15-19r, %10-14r"}, - {0x380002c3, 0x3ff003ff, "madh.fs\t\t%15-19r, %10-14r"}, - {0x38000007, 0x3e0003ff, "max\t\t%20-24r, %15-19r, %10-14r"}, + {0x38000102, 0x3ff003ff, "mazl\t\t%15-19r, %10-14r"}, + {0x38000182, 0x3ff003ff, "mazl.f\t\t%15-19r, %10-14r"}, + {0x38000002, 0x3ff003ff, "madl\t\t%15-19r, %10-14r"}, + {0x380000c2, 0x3ff003ff, "madl.fs\t\t%15-19r, %10-14r"}, + {0x38000303, 0x3ff003ff, "mazh\t\t%15-19r, %10-14r"}, + {0x38000383, 0x3ff003ff, "mazh.f\t\t%15-19r, %10-14r"}, + {0x38000203, 0x3ff003ff, "madh\t\t%15-19r, %10-14r"}, + {0x380002c3, 0x3ff003ff, "madh.fs\t\t%15-19r, %10-14r"}, + {0x38000007, 0x3e0003ff, "max\t\t%20-24r, %15-19r, %10-14r"}, + + {0x00000064, 0x3e00007e, "mbitclr\t\t[%15-19r, %m], %10-14d"}, + {0x0000006c, 0x3e00007e, "mbitset\t\t[%20-24r, %m], %10-14d"}, + {0x38000006, 0x3e0003ff, "min\t\t%20-24r, %15-19r, %10-14r"}, - {0x38000104, 0x3ff003ff, "mszl\t\t%15-19r, %10-14r"}, - {0x38000184, 0x3ff003ff, "mszl.f\t\t%15-19r, %10-14r"}, - {0x38000004, 0x3ff003ff, "msbl\t\t%15-19r, %10-14r"}, + {0x38000104, 0x3ff003ff, "mszl\t\t%15-19r, %10-14r"}, + {0x38000184, 0x3ff003ff, "mszl.f\t\t%15-19r, %10-14r"}, + {0x38000004, 0x3ff003ff, "msbl\t\t%15-19r, %10-14r"}, {0x380000c4, 0x3ff003ff, "msbl.fs\t\t%15-19r, %10-14r"}, - {0x38000305, 0x3ff003ff, "mszh\t\t%15-19r, %10-14r"}, - {0x38000385, 0x3ff003ff, "mszh.f\t\t%15-19r, %10-14r"}, - {0x38000205, 0x3ff003ff, "msbh\t\t%15-19r, %10-14r"}, - {0x380002c5, 0x3ff003ff, "msbh.fs\t\t%15-19r, %10-14r"}, - {0x3800004e, 0x3e0003ff, "sll.s\t\t%20-24r, %15-19r, %10-14r"}, - {0x38000049, 0x3e0003ff, "sub.s\t\t%20-24r, %15-19r, %10-14r"}, - {0x3800000d, 0x3e007fff, "clz\t\t%20-24r, %15-19r"}, + {0x38000305, 0x3ff003ff, "mszh\t\t%15-19r, %10-14r"}, + {0x38000385, 0x3ff003ff, "mszh.f\t\t%15-19r, %10-14r"}, + {0x38000205, 0x3ff003ff, "msbh\t\t%15-19r, %10-14r"}, + {0x380002c5, 0x3ff003ff, "msbh.fs\t\t%15-19r, %10-14r"}, + {0x3800004e, 0x3e0003ff, "sll.s\t\t%20-24r, %15-19r, %10-14r"}, + {0x38000049, 0x3e0003ff, "sub.s\t\t%20-24r, %15-19r, %10-14r"}, + {0x0000001c, 0x3e007fff, "clz\t\t%20-24r, %15-19r"}, {0x38000000, 0x3e000000, "ceinst\t\t%20-24d, %15-19r, %10-14r, %5-9d, %0-4d"}, {0x00000019, 0x3ff003ff, "cmpteq.c\t\t%15-19r, %10-14r"}, {0x00100019, 0x3ff003ff, "cmptmi.c\t\t%15-19r, %10-14r"}, @@ -232,13 +207,22 @@ static struct score_opcode score_opcodes[] = {0x0010001b, 0x3ff07fff, "cmpztmi.c\t%15-19r"}, {0x0030001b, 0x3ff07fff, "cmpz.c\t\t%15-19r"}, {0x02040001, 0x3e0e0001, "cmpi.c\t\t%20-24r, %1-16i"}, - {0x00002003, 0x0000700f, "cmp!\t\t%8-11r, %4-7r"}, + {0x00004400, 0x00007c00, "cmp!\t\t%5-9r, %0-4r"}, + {0x00006000, 0x00007c00, "cmpi!\t\t%5-9r, %0-4i"}, {0x0c00000c, 0x3e00001f, "cop1\t\tc%20-24r, c%15-19r, c%10-14r, %5-9d"}, {0x0c000014, 0x3e00001f, "cop2\t\tc%20-24r, c%15-19r, c%10-14r, %5-9d"}, {0x0c00001c, 0x3e00001f, "cop3\t\tc%20-24r, c%15-19r, c%10-14r, %5-9d"}, {0x00000044, 0x3e0003ff, "div\t\t%15-19r, %10-14r"}, + {0x00000144, 0x3e0003ff, "divr.q\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000244, 0x3e0003ff, "divr.r\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000344, 0x3e0003ff, "divr\t\t%20-24r,%15-19r, %10-14r"}, {0x00000046, 0x3e0003ff, "divu\t\t%15-19r, %10-14r"}, - {0x0c0000a4, 0x3e0003ff, "drte" }, + {0x00000146, 0x3e0003ff, "divur.q\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000246, 0x3e0003ff, "divur.r\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000346, 0x3e0003ff, "divur\t\t%20-24r,%15-19r, %10-14r"}, + {0x0c0000a4, 0x3e0003ff, "drte"}, + {0x00e0, 0xffe1, "disint!"}, + {0x00e1, 0xffe1, "enint!"}, {0x00000058, 0x3e0003ff, "extsb\t\t%20-24r, %15-19r"}, {0x00000059, 0x3e0003ff, "extsb.c\t\t%20-24r, %15-19r"}, {0x0000005a, 0x3e0003ff, "extsh\t\t%20-24r, %15-19r"}, @@ -248,8 +232,6 @@ static struct score_opcode score_opcodes[] = {0x0000005e, 0x3e0003ff, "extzh\t\t%20-24r, %15-19r"}, {0x0000005f, 0x3e0003ff, "extzh.c\t\t%20-24r, %15-19r"}, {0x04000001, 0x3e000001, "jl\t\t%j"}, - {0x00003001, 0x00007001, "jl!\t\t%j" }, - {0x00003000, 0x00007001, "j!\t\t%j" }, {0x04000000, 0x3e000001, "j\t\t%j"}, {0x26000000, 0x3e000000, "lb\t\t%20-24r, [%15-19r, %0-14i]"}, {0x2c000000, 0x3e000000, "lbu\t\t%20-24r, [%15-19r, %0-14i]"}, @@ -257,41 +239,41 @@ static struct score_opcode score_opcodes[] = {0x06000006, 0x3e000007, "lbu\t\t%20-24r, [%15-19r, %3-14i]+"}, {0x0e000003, 0x3e000007, "lb\t\t%20-24r, [%15-19r]+, %3-14i"}, {0x0e000006, 0x3e000007, "lbu\t\t%20-24r, [%15-19r]+, %3-14i"}, - {0x0000200b, 0x0000700f, "lbu!\t\t%8-11r, [%4-7r]"}, - {0x00007003, 0x00007007, "lbup!\t\t%8-11r, %3-7d"}, {0x00000060, 0x3e0003ff, "lcb\t\t[%15-19r]+"}, {0x00000062, 0x3e0003ff, "lcw\t\t%20-24r, [%15-19r]+"}, {0x00000066, 0x3e0003ff, "lce\t\t%20-24r, [%15-19r]+"}, {0x0c00000a, 0x3e00001f, "ldc1\t\tc%15-19r, [%20-24r, %5-14i]"}, {0x0c000012, 0x3e00001f, "ldc2\t\tc%15-19r, [%20-24r, %5-14i]"}, {0x0c00001a, 0x3e00001f, "ldc3\t\tc%15-19r, [%20-24r, %5-14i]"}, + {0x000000000001LL, 0x1c000000001fLL, "ldi48\t\t%37-41r, %5-36i"}, {0x22000000, 0x3e000000, "lh\t\t%20-24r, [%15-19r, %0-14i]"}, {0x24000000, 0x3e000000, "lhu\t\t%20-24r, [%15-19r, %0-14i]"}, {0x06000001, 0x3e000007, "lh\t\t%20-24r, [%15-19r, %3-14i]+"}, {0x06000002, 0x3e000007, "lhu\t\t%20-24r, [%15-19r, %3-14i]+"}, {0x0e000001, 0x3e000007, "lh\t\t%20-24r, [%15-19r]+, %3-14i"}, {0x0e000002, 0x3e000007, "lhu\t\t%20-24r, [%15-19r]+, %3-14i"}, - {0x00002009, 0x0000700f, "lh!\t\t%8-11r, [%4-7r]"}, - {0x00007001, 0x00007007, "lhp!\t\t%8-11r, %3-7d1"}, {0x020c0000, 0x3e0e0000, "ldi\t\t%20-24r, 0x%1-16x(%1-16i)"}, {0x0a0c0000, 0x3e0e0000, "ldis\t\t%20-24r, 0x%1-16x(%1-16i)"}, - {0x00005000, 0x00007000, "ldiu!\t\t%8-11r, %0-7d"}, + {0x00006400, 0x00007c00, "ldiu!\t\t%5-9r, %0-4d"}, + {0x00000032, 0x3e0003ff, "ltbw\t\t%20-24r, [%15-19r, %10-14r]"}, + {0x00000132, 0x3e0003ff, "ltbh\t\t%20-24r, [%15-19r, %10-14r]"}, + {0x00000332, 0x3e0003ff, "ltbb\t\t%20-24r, [%15-19r, %10-14r]"}, {0x0000000c, 0x3e0003ff, "alw\t\t%20-24r, [%15-19r]"}, {0x20000000, 0x3e000000, "lw\t\t%20-24r, [%15-19r, %0-14i]"}, {0x06000000, 0x3e000007, "lw\t\t%20-24r, [%15-19r, %3-14i]+"}, {0x0e000000, 0x3e000007, "lw\t\t%20-24r, [%15-19r]+, %3-14i"}, - {0x00002008, 0x0000700f, "lw!\t\t%8-11r, [%4-7r]"}, - {0x00007000, 0x00007007, "lwp!\t\t%8-11r, %3-7d2"}, - {0x0000100b, 0x0000700f, "madh.fs!\t\t%8-11r, %4-7r"}, - {0x0000100a, 0x0000700f, "madl.fs!\t\t%8-11r, %4-7r"}, - {0x00001005, 0x0000700f, "madu!\t\t%8-11r, %4-7r"}, - {0x00001004, 0x0000700f, "mad.f!\t\t%8-11r, %4-7r"}, - {0x00001009, 0x0000700f, "mazh.f!\t\t%8-11r, %4-7r"}, - {0x00001008, 0x0000700f, "mazl.f!\t\t%8-11r, %4-7r"}, + {0x00001000, 0x00007000, "lw!\t\t%8-11r, [%5-7r,%0-4d2]"}, + {0x000000000002LL, 0x1c000000001fLL, "lw48\t\t%37-41r,[0x%7-36w]"}, + {0x00007b00, 0x00007f00, "madh.fs!\t\t%8-11r, %4-7r"}, + {0x00007a00, 0x00007f00, "madl.fs!\t\t%8-11r, %4-7r"}, + {0x00007500, 0x00007f00, "madu!\t\t%8-11r, %4-7r"}, + {0x00007400, 0x00007f00, "mad.f!\t\t%8-11r, %4-7r"}, + {0x00007900, 0x00007f00, "mazh.f!\t\t%8-11r, %4-7r"}, + {0x00007800, 0x00007f00, "mazl.f!\t\t%8-11r, %4-7r"}, {0x00000448, 0x3e007fff, "mfcel\t\t%20-24r"}, - {0x00001001, 0x00007f0f, "mfcel!\t\t%4-7r"}, + {0x00007100, 0x00007ff0, "mfcel!\t\t%4-7r"}, {0x00000848, 0x3e007fff, "mfceh\t\t%20-24r"}, - {0x00001101, 0x00007f0f, "mfceh!\t\t%4-7r"}, + {0x00007110, 0x00007ff0, "mfceh!\t\t%4-7r"}, {0x00000c48, 0x3e007fff, "mfcehl\t\t%20-24r, %15-19r"}, {0x00000048, 0x3e0003ff, "mfce\t\t%20-24r, er%10-14d"}, {0x00000050, 0x3e0003ff, "mfsr\t\t%20-24r, sr%10-14d"}, @@ -302,18 +284,21 @@ static struct score_opcode score_opcodes[] = {0x0c00000f, 0x3e00001f, "mfcc1\t\t%20-24r, c%15-19r"}, {0x0c000017, 0x3e00001f, "mfcc2\t\t%20-24r, c%15-19r"}, {0x0c00001f, 0x3e00001f, "mfcc3\t\t%20-24r, c%15-19r"}, - {0x00000002, 0x0000700f, "mhfl!\t\t%8-11R, %4-7r"}, - {0x00000001, 0x0000700f, "mlfh!\t\t%8-11r, %4-7R"}, - {0x00001006, 0x0000700f, "msb.f!\t\t%8-11r, %4-7r"}, - {0x0000100f, 0x0000700f, "msbh.fs!\t\t%8-11r, %4-7r"}, - {0x0000100e, 0x0000700f, "msbl.fs!\t\t%8-11r, %4-7r"}, - {0x00001007, 0x0000700f, "msbu!\t\t%8-11r, %4-7r"}, - {0x0000100d, 0x0000700f, "mszh.f!\t\t%8-11r, %4-7r"}, - {0x0000100c, 0x0000700f, "mszl.f!\t\t%8-11r, %4-7r"}, + /* confilct: push! mhfl!. */ + {0x00000040, 0x00007fe0, "pop!\t\t%0-4r"}, + {0x00000060, 0x00007fe0, "push!\t\t%0-4r"}, + {0x00006800, 0x00007c00, "rpop!\t\t%5-9r, %0-4d"}, + {0x00006c00, 0x00007c00, "rpush!\t\t%5-9r, %0-4d"}, + {0x00007600, 0x00007f00, "msb.f!\t\t%8-11r, %4-7r"}, + {0x00007f00, 0x00007f00, "msbh.fs!\t\t%8-11r, %4-7r"}, + {0x00007e00, 0x00007f00, "msbl.fs!\t\t%8-11r, %4-7r"}, + {0x00007700, 0x00007f00, "msbu!\t\t%8-11r, %4-7r"}, + {0x00007d00, 0x00007f00, "mszh.f!\t\t%8-11r, %4-7r"}, + {0x00007c00, 0x00007f00, "mszl.f!\t\t%8-11r, %4-7r"}, {0x0000044a, 0x3e007fff, "mtcel\t\t%20-24r"}, - {0x00001000, 0x00007f0f, "mtcel!\t\t%4-7r"}, + {0x00007000, 0x00007ff0, "mtcel!\t\t%4-7r"}, {0x0000084a, 0x3e007fff, "mtceh\t\t%20-24r"}, - {0x00001100, 0x00007f0f, "mtceh!\t\t%4-7r"}, + {0x00007010, 0x00007ff0, "mtceh!\t\t%4-7r"}, {0x00000c4a, 0x3e007fff, "mtcehl\t\t%20-24r, %15-19r"}, {0x0000004a, 0x3e0003ff, "mtce\t\t%20-24r, er%10-14d"}, {0x00000052, 0x3e0003ff, "mtsr\t\t%15-19r, sr%10-14d"}, @@ -325,13 +310,22 @@ static struct score_opcode score_opcodes[] = {0x0c000016, 0x3e00001f, "mtcc2\t\t%20-24r, c%15-19r"}, {0x0c00001e, 0x3e00001f, "mtcc3\t\t%20-24r, c%15-19r"}, {0x00000040, 0x3e0003ff, "mul\t\t%15-19r, %10-14r"}, - {0x00000040, 0x3e0003ff, "maz\t\t%15-19r, %10-14r"}, + {0x00000140, 0x3e0003ff, "mulr.l\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000240, 0x3e0003ff, "mulr.h\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000340, 0x3e0003ff, "mulr\t\t%20-24r,%15-19r, %10-14r"}, {0x00000041, 0x3e0003ff, "mul.f\t\t%15-19r, %10-14r"}, - {0x00000041, 0x3e0003ff, "maz.f\t\t%15-19r, %10-14r"}, - {0x00001002, 0x0000700f, "mul.f!\t\t%8-11r, %4-7r"}, + {0x00000141, 0x3e0003ff, "mulr.lf\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000241, 0x3e0003ff, "mulr.hf\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000341, 0x3e0003ff, "mulr.f\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000040, 0x3e0003ff, "maz\t\t%15-19r, %10-14r"}, + {0x00000041, 0x3e0003ff, "maz.f\t\t%15-19r, %10-14r"}, + {0x00007200, 0x00007f00, "mul.f!\t\t%8-11r, %4-7r"}, {0x00000042, 0x3e0003ff, "mulu\t\t%15-19r, %10-14r"}, + {0x00000142, 0x3e0003ff, "mulur.l\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000242, 0x3e0003ff, "mulur.h\t\t%20-24r,%15-19r, %10-14r"}, + {0x00000342, 0x3e0003ff, "mulur\t\t%20-24r,%15-19r, %10-14r"}, {0x00000042, 0x3e0003ff, "mazu\t\t%15-19r, %10-14r"}, - {0x00001003, 0x0000700f, "mulu!\t\t%8-11r, %4-7r"}, + {0x00007300, 0x00007f00, "mulu!\t\t%8-11r, %4-7r"}, {0x00000056, 0x3e007fff, "mvcs\t\t%20-24r, %15-19r"}, {0x00000456, 0x3e007fff, "mvcc\t\t%20-24r, %15-19r"}, {0x00000856, 0x3e007fff, "mvgtu\t\t%20-24r, %15-19r"}, @@ -347,29 +341,25 @@ static struct score_opcode score_opcodes[] = {0x00003056, 0x3e007fff, "mvvs\t\t%20-24r, %15-19r"}, {0x00003456, 0x3e007fff, "mvvc\t\t%20-24r, %15-19r"}, {0x00003c56, 0x3e007fff, "mv\t\t%20-24r, %15-19r"}, - {0x00000003, 0x0000700f, "mv!\t\t%8-11r, %4-7r"}, - {0x0000001e, 0x3e0003ff, "neg\t\t%20-24r, %10-14r" }, - {0x0000001f, 0x3e0003ff, "neg.c\t\t%20-24r, %10-14r" }, - {0x00002002, 0x0000700f, "neg!\t\t%8-11r, %4-7r"}, - {0x00000000, 0x3e0003ff, "nop" }, - {0x00000024, 0x3e0003ff, "not\t\t%20-24r, %15-19r" }, - {0x00000025, 0x3e0003ff, "not.c\t\t%20-24r, %15-19r" }, - {0x00000000, 0x0000700f, "nop!" }, - {0x00002006, 0x0000700f, "not!\t\t%8-11r, %4-7r"}, + {0x00004000, 0x00007c00, "mv!\t\t%5-9r, %0-4r"}, + {0x0000001e, 0x3e0003ff, "neg\t\t%20-24r, %10-14r"}, + {0x0000001f, 0x3e0003ff, "neg.c\t\t%20-24r, %10-14r"}, + {0x00000000, 0x3e0003ff, "nop"}, + {0x00000024, 0x3e0003ff, "not\t\t%20-24r, %15-19r"}, + {0x00000025, 0x3e0003ff, "not.c\t\t%20-24r, %15-19r"}, + {0x00000000, 0x00007fff, "nop!"}, {0x00000022, 0x3e0003ff, "or\t\t%20-24r, %15-19r, %10-14r"}, {0x00000023, 0x3e0003ff, "or.c\t\t%20-24r, %15-19r, %10-14r"}, - {0x020a0000, 0x3e0e0001, "ori\t\t%20-24r, 0x%1-16x"}, - {0x020a0001, 0x3e0e0001, "ori.c\t\t%20-24r, 0x%1-16x"}, + {0x020a0000, 0x3e0e0001, "ori\t\t%20-24r, 0x%1-16x"}, + {0x020a0001, 0x3e0e0001, "ori.c\t\t%20-24r, 0x%1-16x"}, {0x0a0a0000, 0x3e0e0001, "oris\t\t%20-24r, 0x%1-16x"}, {0x0a0a0001, 0x3e0e0001, "oris.c\t\t%20-24r, 0x%1-16x"}, {0x1a000000, 0x3e000001, "orri\t\t%20-24r, %15-19r, 0x%1-14x"}, {0x1a000001, 0x3e000001, "orri.c\t\t%20-24r, %15-19r, 0x%1-14x"}, - {0x00002005, 0x0000700f, "or!\t\t%8-11r, %4-7r"}, + {0x00004a00, 0x00007f00, "or!\t\t%4-7r, %0-3r"}, + {0x040000000002LL, 0x1c0000000003LL, "orri48\t\t%38-41r,%34-37r, 0x%2-33x"}, + {0x040000000003LL, 0x1c0000000003LL, "orri48.c\t\t%38-41r,%34-37r, 0x%2-33x"}, {0x0000000a, 0x3e0003ff, "pflush"}, - {0x0000208a, 0x0000708f, "pop!\t\t%8-11R, [%4-6r]"}, - {0x0000200a, 0x0000700f, "pop!\t\t%8-11r, [%4-7r]"}, - {0x0000208e, 0x0000708f, "push!\t\t%8-11R, [%4-6r]"}, - {0x0000200e, 0x0000700f, "push!\t\t%8-11r, [%4-7r]"}, {0x00000038, 0x3e0003ff, "ror\t\t%20-24r, %15-19r, %10-14r"}, {0x00000039, 0x3e0003ff, "ror.c\t\t%20-24r, %15-19r, %10-14r"}, {0x0000003b, 0x3e0003ff, "rorc.c\t\t%20-24r, %15-19r, %10-14r"}, @@ -382,30 +372,26 @@ static struct score_opcode score_opcodes[] = {0x0000007c, 0x3e0003ff, "roli\t\t%20-24r, %15-19r, %10-14d"}, {0x0000007d, 0x3e0003ff, "roli.c\t\t%20-24r, %15-19r, %10-14d"}, {0x0000007f, 0x3e0003ff, "rolic.c\t\t%20-24r, %15-19r, %10-14d"}, - {0x0c000084, 0x3e0003ff, "rte" }, + {0x0c000084, 0x3e0003ff, "rte"}, {0x2e000000, 0x3e000000, "sb\t\t%20-24r, [%15-19r, %0-14i]"}, {0x06000007, 0x3e000007, "sb\t\t%20-24r, [%15-19r, %3-14i]+"}, {0x0e000007, 0x3e000007, "sb\t\t%20-24r, [%15-19r]+, %3-14i"}, - {0x0000200f, 0x0000700f, "sb!\t\t%8-11r, [%4-7r]"}, - {0x00007007, 0x00007007, "sbp!\t\t%8-11r, %3-7d"}, {0x0000000e, 0x3e0003ff, "asw\t\t%20-24r, [%15-19r]"}, {0x00000068, 0x3e0003ff, "scb\t\t%20-24r, [%15-19r]+"}, {0x0000006a, 0x3e0003ff, "scw\t\t%20-24r, [%15-19r]+"}, {0x0000006e, 0x3e0003ff, "sce\t\t[%15-19r]+"}, {0x00000006, 0x3e0003ff, "sdbbp\t\t%15-19d"}, - {0x00006002, 0x00007007, "sdbbp!\t\t%3-7d"}, + {0x00000020, 0x00007fe0, "sdbbp!\t\t%0-4d"}, + {0x000000000000LL, 0x1c000000001fLL, "sdbbp48\t\t%5-9d"}, {0x2a000000, 0x3e000000, "sh\t\t%20-24r, [%15-19r, %0-14i]"}, {0x06000005, 0x3e000007, "sh\t\t%20-24r, [%15-19r, %3-14i]+"}, {0x0e000005, 0x3e000007, "sh\t\t%20-24r, [%15-19r]+, %3-14i"}, - {0x0000200d, 0x0000700f, "sh!\t\t%8-11r, [%4-7r]"}, - {0x00007005, 0x00007007, "shp!\t\t%8-11r, %3-7d1"}, - {0x0c0000c4, 0x3e0003ff, "sleep" }, + {0x0c0000c4, 0x3e0003ff, "sleep"}, {0x00000030, 0x3e0003ff, "sll\t\t%20-24r, %15-19r, %10-14r"}, {0x00000031, 0x3e0003ff, "sll.c\t\t%20-24r, %15-19r, %10-14r"}, {0x00000070, 0x3e0003ff, "slli\t\t%20-24r, %15-19r, %10-14d"}, {0x00000071, 0x3e0003ff, "slli.c\t\t%20-24r, %15-19r, %10-14d"}, - {0x00000008, 0x0000700f, "sll!\t\t%8-11r, %4-7r"}, - {0x00006001, 0x00007007, "slli!\t\t%8-11r, %3-7d"}, + {0x00005800, 0x00007e00, "slli!\t\t%5-8r, %0-4d"}, {0x00000034, 0x3e0003ff, "srl\t\t%20-24r, %15-19r, %10-14r"}, {0x00000035, 0x3e0003ff, "srl.c\t\t%20-24r, %15-19r, %10-14r"}, {0x00000036, 0x3e0003ff, "sra\t\t%20-24r, %15-19r, %10-14r"}, @@ -414,9 +400,7 @@ static struct score_opcode score_opcodes[] = {0x00000075, 0x3e0003ff, "srli.c\t\t%20-24r, %15-19r, %10-14d"}, {0x00000076, 0x3e0003ff, "srai\t\t%20-24r, %15-19r, %10-14d"}, {0x00000077, 0x3e0003ff, "srai.c\t\t%20-24r, %15-19r, %10-14d"}, - {0x0000000a, 0x0000700f, "srl!\t\t%8-11r, %4-7r"}, - {0x00006003, 0x00007007, "srli!\t\t%8-11r, %3-7d"}, - {0x0000000b, 0x0000700f, "sra!\t\t%8-11r, %4-7r"}, + {0x00005a00, 0x00007e00, "srli!\t\t%5-8r, %0-4d"}, {0x0c00000b, 0x3e00001f, "stc1\t\tc%15-19r, [%20-24r, %5-14i]"}, {0x0c000013, 0x3e00001f, "stc2\t\tc%15-19r, [%20-24r, %5-14i]"}, {0x0c00001b, 0x3e00001f, "stc3\t\tc%15-19r, [%20-24r, %5-14i]"}, @@ -424,44 +408,30 @@ static struct score_opcode score_opcodes[] = {0x00000015, 0x3e0003ff, "sub.c\t\t%20-24r, %15-19r, %10-14r"}, {0x00000016, 0x3e0003ff, "subc\t\t%20-24r, %15-19r, %10-14r"}, {0x00000017, 0x3e0003ff, "subc.c\t\t%20-24r, %15-19r, %10-14r"}, - {0x00002001, 0x0000700f, "sub!\t\t%8-11r, %4-7r"}, - {0x00006080, 0x00007087, "subei!\t\t%8-11r, %3-6d"}, + {0x00004900, 0x00007f00, "sub!\t\t%4-7r, %0-3r"}, {0x28000000, 0x3e000000, "sw\t\t%20-24r, [%15-19r, %0-14i]"}, {0x06000004, 0x3e000007, "sw\t\t%20-24r, [%15-19r, %3-14i]+"}, {0x0e000004, 0x3e000007, "sw\t\t%20-24r, [%15-19r]+, %3-14i"}, - {0x0000200c, 0x0000700f, "sw!\t\t%8-11r, [%4-7r]"}, - {0x00007004, 0x00007007, "swp!\t\t%8-11r, %3-7d2"}, + {0x00002000, 0x00007000, "sw!\t\t%8-11r, [%5-7r,%0-4d2]"}, + {0x000000000003LL, 0x1c000000001fLL, "sw48\t\t%37-41r, [0x%7-36w]"}, {0x00000002, 0x3e0003ff, "syscall\t\t%10-24d"}, - {0x00000054, 0x3e007fff, "tcs" }, - {0x00000454, 0x3e007fff, "tcc" }, - {0x00003854, 0x3e007fff, "tcnz" }, - {0x00000005, 0x00007f0f, "tcs!" }, - {0x00000105, 0x00007f0f, "tcc!" }, - {0x00000e05, 0x00007f0f, "tcnz!" }, - {0x00001054, 0x3e007fff, "teq" }, - {0x00000405, 0x00007f0f, "teq!" }, - {0x00000854, 0x3e007fff, "tgtu" }, - {0x00001854, 0x3e007fff, "tgt" }, - {0x00002054, 0x3e007fff, "tge" }, - {0x00000205, 0x00007f0f, "tgtu!" }, - {0x00000605, 0x00007f0f, "tgt!" }, - {0x00000805, 0x00007f0f, "tge!" }, - {0x00000c54, 0x3e007fff, "tleu" }, - {0x00001c54, 0x3e007fff, "tle" }, - {0x00002454, 0x3e007fff, "tlt" }, - {0x0c000004, 0x3e0003ff, "stlb" }, - {0x0c000024, 0x3e0003ff, "mftlb" }, - {0x0c000044, 0x3e0003ff, "mtptlb" }, - {0x0c000064, 0x3e0003ff, "mtrtlb" }, - {0x00000305, 0x00007f0f, "tleu!" }, - {0x00000705, 0x00007f0f, "tle!" }, - {0x00000905, 0x00007f0f, "tlt!" }, - {0x00002854, 0x3e007fff, "tmi" }, - {0x00000a05, 0x00007f0f, "tmi!" }, - {0x00001454, 0x3e007fff, "tne" }, - {0x00000505, 0x00007f0f, "tne!" }, - {0x00002c54, 0x3e007fff, "tpl" }, - {0x00000b05, 0x00007f0f, "tpl!" }, + {0x00000054, 0x3e007fff, "tcs"}, + {0x00000454, 0x3e007fff, "tcc"}, + {0x00003854, 0x3e007fff, "tcnz"}, + {0x00001054, 0x3e007fff, "teq"}, + {0x00000854, 0x3e007fff, "tgtu"}, + {0x00001854, 0x3e007fff, "tgt"}, + {0x00002054, 0x3e007fff, "tge"}, + {0x00000c54, 0x3e007fff, "tleu"}, + {0x00001c54, 0x3e007fff, "tle"}, + {0x00002454, 0x3e007fff, "tlt"}, + {0x0c000004, 0x3e0003ff, "stlb"}, + {0x0c000024, 0x3e0003ff, "mftlb"}, + {0x0c000044, 0x3e0003ff, "mtptlb"}, + {0x0c000064, 0x3e0003ff, "mtrtlb"}, + {0x00002854, 0x3e007fff, "tmi"}, + {0x00001454, 0x3e007fff, "tne"}, + {0x00002c54, 0x3e007fff, "tpl"}, {0x00000004, 0x3e007fff, "trapcs\t\t%15-19d"}, {0x00000404, 0x3e007fff, "trapcc\t\t%15-19d"}, {0x00000804, 0x3e007fff, "trapgtu\t\t%15-19d"}, @@ -477,13 +447,9 @@ static struct score_opcode score_opcodes[] = {0x00003004, 0x3e007fff, "trapvs\t\t%15-19d"}, {0x00003404, 0x3e007fff, "trapvc\t\t%15-19d"}, {0x00003c04, 0x3e007fff, "trap\t\t%15-19d"}, - {0x00003c54, 0x3e007fff, "tset" }, - {0x00000f05, 0x00007f0f, "tset!" }, - {0x00003054, 0x3e007fff, "tvs" }, - {0x00003454, 0x3e007fff, "tvc" }, - {0x00000c05, 0x00007f0f, "tvs!" }, - {0x00000d05, 0x00007f0f, "tvc!" }, + {0x00003c54, 0x3e007fff, "tset"}, + {0x00003054, 0x3e007fff, "tvs"}, + {0x00003454, 0x3e007fff, "tvc"}, {0x00000026, 0x3e0003ff, "xor\t\t%20-24r, %15-19r, %10-14r"}, {0x00000027, 0x3e0003ff, "xor.c\t\t%20-24r, %15-19r, %10-14r"}, - {0x00002007, 0x0000700f, "xor!\t\t%8-11r, %4-7r"} }; diff --git a/opcodes/score7-dis.c b/opcodes/score7-dis.c new file mode 100644 index 00000000000..70ff637d62c --- /dev/null +++ b/opcodes/score7-dis.c @@ -0,0 +1,972 @@ +/* Instruction printing code for Score + Copyright 2009 Free Software Foundation, Inc. + Contributed by: + Brain.lin (brain.lin@sunplusct.com) + Mei Ligang (ligang@sunnorth.com.cn) + Pei-Lin Tsai (pltsai@sunplus.com) + + This file is part of the GNU opcodes library. + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + It is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU General Public License + along with this file; see the file COPYING. If not, write to the + Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "sysdep.h" +#include "dis-asm.h" +#define DEFINE_TABLE +#include "opintl.h" +#include "bfd.h" + +/* FIXME: This shouldn't be done here. */ +#include "elf-bfd.h" +#include "elf/internal.h" +#include "elf/score.h" + +#ifndef streq +#define streq(a,b) (strcmp ((a), (b)) == 0) +#endif + +#ifndef strneq +#define strneq(a,b,n) (strncmp ((a), (b), (n)) == 0) +#endif + +#ifndef NUM_ELEM +#define NUM_ELEM(a) (sizeof (a) / sizeof (a)[0]) +#endif + +struct score_opcode +{ + unsigned long value; + unsigned long mask; /* Recognise instruction if (op & mask) == value. */ + char *assembler; /* Disassembly string. */ +}; + +/* Note: There is a partial ordering in this table - it must be searched from + the top to obtain a correct match. */ + +static struct score_opcode score_opcodes[] = +{ + /* Score Instructions. */ + {0x3800000a, 0x3e007fff, "abs\t\t%20-24r, %15-19r"}, + {0x3800004b, 0x3e007fff, "abs.s\t\t%20-24r, %15-19r"}, + {0x00000010, 0x3e0003ff, "add\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000011, 0x3e0003ff, "add.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x38000048, 0x3e0003ff, "add.s\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000012, 0x3e0003ff, "addc\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000013, 0x3e0003ff, "addc.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x02000000, 0x3e0e0001, "addi\t\t%20-24r, %1-16i"}, + {0x02000001, 0x3e0e0001, "addi.c\t\t%20-24r, %1-16i"}, + {0x0a000000, 0x3e0e0001, "addis\t\t%20-24r, %1-16d(0x%1-16x)"}, + {0x0a000001, 0x3e0e0001, "addis.c\t\t%20-24r, %1-16d(0x%1-16x)"}, + {0x10000000, 0x3e000001, "addri\t\t%20-24r, %15-19r, %1-14i"}, + {0x10000001, 0x3e000001, "addri.c\t\t%20-24r, %15-19r, %1-14i"}, + {0x00000009, 0x0000700f, "addc!\t\t%8-11r, %4-7r"}, + {0x00002000, 0x0000700f, "add!\t\t%8-11r, %4-7r"}, + {0x00006000, 0x00007087, "addei!\t\t%8-11r, %3-6d"}, + {0x00000020, 0x3e0003ff, "and\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000021, 0x3e0003ff, "and.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x02080000, 0x3e0e0001, "andi\t\t%20-24r, 0x%1-16x"}, + {0x02080001, 0x3e0e0001, "andi.c\t\t%20-24r, 0x%1-16x"}, + {0x0a080000, 0x3e0e0001, "andis\t\t%20-24r, 0x%1-16x"}, + {0x0a080001, 0x3e0e0001, "andis.c\t\t%20-24r, 0x%1-16x"}, + {0x18000000, 0x3e000001, "andri\t\t%20-24r, %15-19r, 0x%1-14x"}, + {0x18000001, 0x3e000001, "andri.c\t\t%20-24r, %15-19r,0x%1-14x"}, + {0x00002004, 0x0000700f, "and!\t\t%8-11r, %4-7r"}, + {0x08000000, 0x3e007c01, "bcs\t\t%b"}, + {0x08000400, 0x3e007c01, "bcc\t\t%b"}, + {0x08003800, 0x3e007c01, "bcnz\t\t%b"}, + {0x08000001, 0x3e007c01, "bcsl\t\t%b"}, + {0x08000401, 0x3e007c01, "bccl\t\t%b"}, + {0x08003801, 0x3e007c01, "bcnzl\t\t%b"}, + {0x00004000, 0x00007f00, "bcs!\t\t%b"}, + {0x00004100, 0x00007f00, "bcc!\t\t%b"}, + {0x00004e00, 0x00007f00, "bcnz!\t\t%b"}, + {0x08001000, 0x3e007c01, "beq\t\t%b"}, + {0x08001001, 0x3e007c01, "beql\t\t%b"}, + {0x00004400, 0x00007f00, "beq!\t\t%b"}, + {0x08000800, 0x3e007c01, "bgtu\t\t%b"}, + {0x08001800, 0x3e007c01, "bgt\t\t%b"}, + {0x08002000, 0x3e007c01, "bge\t\t%b"}, + {0x08000801, 0x3e007c01, "bgtul\t\t%b"}, + {0x08001801, 0x3e007c01, "bgtl\t\t%b"}, + {0x08002001, 0x3e007c01, "bgel\t\t%b"}, + {0x00004200, 0x00007f00, "bgtu!\t\t%b"}, + {0x00004600, 0x00007f00, "bgt!\t\t%b"}, + {0x00004800, 0x00007f00, "bge!\t\t%b"}, + {0x00000029, 0x3e0003ff, "bitclr.c\t%20-24r, %15-19r, 0x%10-14x"}, + {0x0000002b, 0x3e0003ff, "bitset.c\t%20-24r, %15-19r, 0x%10-14x"}, + {0x0000002d, 0x3e0003ff, "bittst.c\t%15-19r, 0x%10-14x"}, + {0x0000002f, 0x3e0003ff, "bittgl.c\t%20-24r, %15-19r, 0x%10-14x"}, + {0x00006004, 0x00007007, "bitclr!\t\t%8-11r, 0x%3-7x"}, + {0x3800000c, 0x3e0003ff, "bitrev\t\t%20-24r, %15-19r,%10-14r"}, + {0x00006005, 0x00007007, "bitset!\t\t%8-11r, 0x%3-7x"}, + {0x00006006, 0x00007007, "bittst!\t\t%8-11r, 0x%3-7x"}, + {0x00006007, 0x00007007, "bittgl!\t\t%8-11r, 0x%3-7x"}, + {0x08000c00, 0x3e007c01, "bleu\t\t%b"}, + {0x08001c00, 0x3e007c01, "ble\t\t%b"}, + {0x08002400, 0x3e007c01, "blt\t\t%b"}, + {0x08000c01, 0x3e007c01, "bleul\t\t%b"}, + {0x08001c01, 0x3e007c01, "blel\t\t%b"}, + {0x08002401, 0x3e007c01, "bltl\t\t%b"}, + {0x08003c01, 0x3e007c01, "bl\t\t%b"}, + {0x00004300, 0x00007f00, "bleu!\t\t%b"}, + {0x00004700, 0x00007f00, "ble!\t\t%b"}, + {0x00004900, 0x00007f00, "blt!\t\t%b"}, + {0x08002800, 0x3e007c01, "bmi\t\t%b"}, + {0x08002801, 0x3e007c01, "bmil\t\t%b"}, + {0x00004a00, 0x00007f00, "bmi!\t\t%b"}, + {0x08001400, 0x3e007c01, "bne\t\t%b"}, + {0x08001401, 0x3e007c01, "bnel\t\t%b"}, + {0x00004500, 0x00007f00, "bne!\t\t%b"}, + {0x08002c00, 0x3e007c01, "bpl\t\t%b"}, + {0x08002c01, 0x3e007c01, "bpll\t\t%b"}, + {0x00004b00, 0x00007f00, "bpl!\t\t%b"}, + {0x00000008, 0x3e007fff, "brcs\t\t%15-19r"}, + {0x00000408, 0x3e007fff, "brcc\t\t%15-19r"}, + {0x00000808, 0x3e007fff, "brgtu\t\t%15-19r"}, + {0x00000c08, 0x3e007fff, "brleu\t\t%15-19r"}, + {0x00001008, 0x3e007fff, "breq\t\t%15-19r"}, + {0x00001408, 0x3e007fff, "brne\t\t%15-19r"}, + {0x00001808, 0x3e007fff, "brgt\t\t%15-19r"}, + {0x00001c08, 0x3e007fff, "brle\t\t%15-19r"}, + {0x00002008, 0x3e007fff, "brge\t\t%15-19r"}, + {0x00002408, 0x3e007fff, "brlt\t\t%15-19r"}, + {0x00002808, 0x3e007fff, "brmi\t\t%15-19r"}, + {0x00002c08, 0x3e007fff, "brpl\t\t%15-19r"}, + {0x00003008, 0x3e007fff, "brvs\t\t%15-19r"}, + {0x00003408, 0x3e007fff, "brvc\t\t%15-19r"}, + {0x00003808, 0x3e007fff, "brcnz\t\t%15-19r"}, + {0x00003c08, 0x3e007fff, "br\t\t%15-19r"}, + {0x00000009, 0x3e007fff, "brcsl\t\t%15-19r"}, + {0x00000409, 0x3e007fff, "brccl\t\t%15-19r"}, + {0x00000809, 0x3e007fff, "brgtul\t\t%15-19r"}, + {0x00000c09, 0x3e007fff, "brleul\t\t%15-19r"}, + {0x00001009, 0x3e007fff, "breql\t\t%15-19r"}, + {0x00001409, 0x3e007fff, "brnel\t\t%15-19r"}, + {0x00001809, 0x3e007fff, "brgtl\t\t%15-19r"}, + {0x00001c09, 0x3e007fff, "brlel\t\t%15-19r"}, + {0x00002009, 0x3e007fff, "brgel\t\t%15-19r"}, + {0x00002409, 0x3e007fff, "brltl\t\t%15-19r"}, + {0x00002809, 0x3e007fff, "brmil\t\t%15-19r"}, + {0x00002c09, 0x3e007fff, "brpll\t\t%15-19r"}, + {0x00003009, 0x3e007fff, "brvsl\t\t%15-19r"}, + {0x00003409, 0x3e007fff, "brvcl\t\t%15-19r"}, + {0x00003809, 0x3e007fff, "brcnzl\t\t%15-19r"}, + {0x00003c09, 0x3e007fff, "brl\t\t%15-19r"}, + {0x00000004, 0x00007f0f, "brcs!\t\t%4-7r"}, + {0x00000104, 0x00007f0f, "brcc!\t\t%4-7r"}, + {0x00000204, 0x00007f0f, "brgtu!\t\t%4-7r"}, + {0x00000304, 0x00007f0f, "brleu!\t\t%4-7r"}, + {0x00000404, 0x00007f0f, "breq!\t\t%4-7r"}, + {0x00000504, 0x00007f0f, "brne!\t\t%4-7r"}, + {0x00000604, 0x00007f0f, "brgt!\t\t%4-7r"}, + {0x00000704, 0x00007f0f, "brle!\t\t%4-7r"}, + {0x00000804, 0x00007f0f, "brge!\t\t%4-7r"}, + {0x00000904, 0x00007f0f, "brlt!\t\t%4-7r"}, + {0x00000a04, 0x00007f0f, "brmi!\t\t%4-7r"}, + {0x00000b04, 0x00007f0f, "brpl!\t\t%4-7r"}, + {0x00000c04, 0x00007f0f, "brvs!\t\t%4-7r"}, + {0x00000d04, 0x00007f0f, "brvc!\t\t%4-7r"}, + {0x00000e04, 0x00007f0f, "brcnz!\t\t%4-7r"}, + {0x00000f04, 0x00007f0f, "br!\t\t%4-7r"}, + {0x0000000c, 0x00007f0f, "brcsl!\t\t%4-7r"}, + {0x0000010c, 0x00007f0f, "brccl!\t\t%4-7r"}, + {0x0000020c, 0x00007f0f, "brgtul!\t\t%4-7r"}, + {0x0000030c, 0x00007f0f, "brleul!\t\t%4-7r"}, + {0x0000040c, 0x00007f0f, "breql!\t\t%4-7r"}, + {0x0000050c, 0x00007f0f, "brnel!\t\t%4-7r"}, + {0x0000060c, 0x00007f0f, "brgtl!\t\t%4-7r"}, + {0x0000070c, 0x00007f0f, "brlel!\t\t%4-7r"}, + {0x0000080c, 0x00007f0f, "brgel!\t\t%4-7r"}, + {0x0000090c, 0x00007f0f, "brltl!\t\t%4-7r"}, + {0x00000a0c, 0x00007f0f, "brmil!\t\t%4-7r"}, + {0x00000b0c, 0x00007f0f, "brpll!\t\t%4-7r"}, + {0x00000c0c, 0x00007f0f, "brvsl!\t\t%4-7r"}, + {0x00000d0c, 0x00007f0f, "brvcl!\t\t%4-7r"}, + {0x00000e0c, 0x00007f0f, "brcnzl!\t\t%4-7r"}, + {0x00000f0c, 0x00007f0f, "brl!\t\t%4-7r"}, + {0x08003000, 0x3e007c01, "bvs\t\t%b"}, + {0x08003400, 0x3e007c01, "bvc\t\t%b"}, + {0x08003001, 0x3e007c01, "bvsl\t\t%b"}, + {0x08003401, 0x3e007c01, "bvcl\t\t%b"}, + {0x00004c00, 0x00007f00, "bvs!\t\t%b"}, + {0x00004d00, 0x00007f00, "bvc!\t\t%b"}, + {0x00004f00, 0x00007f00, "b!\t\t%b"}, + {0x08003c00, 0x3e007c01, "b\t\t%b"}, + {0x30000000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30100000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30200000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30300000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30400000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30800000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30900000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30a00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30b00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30c00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30d00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x30e00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x31000000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x31100000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x31800000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x31a00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x31b00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x31c00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x31d00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x31e00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x31f00000, 0x3ff00000, "cache\t\t%20-24d, [%15-19r, %0-14i]"}, + {0x38000000, 0x3ff003ff, "mad\t\t%15-19r, %10-14r"}, + {0x38000020, 0x3ff003ff, "madu\t\t%15-19r, %10-14r"}, + {0x38000080, 0x3ff003ff, "mad.f\t\t%15-19r, %10-14r"}, + {0x38000001, 0x3ff003ff, "msb\t\t%15-19r, %10-14r"}, + {0x38000021, 0x3ff003ff, "msbu\t\t%15-19r, %10-14r"}, + {0x38000081, 0x3ff003ff, "msb.f\t\t%15-19r, %10-14r"}, + {0x38000102, 0x3ff003ff, "mazl\t\t%15-19r, %10-14r"}, + {0x38000182, 0x3ff003ff, "mazl.f\t\t%15-19r, %10-14r"}, + {0x38000002, 0x3ff003ff, "madl\t\t%15-19r, %10-14r"}, + {0x380000c2, 0x3ff003ff, "madl.fs\t\t%15-19r, %10-14r"}, + {0x38000303, 0x3ff003ff, "mazh\t\t%15-19r, %10-14r"}, + {0x38000383, 0x3ff003ff, "mazh.f\t\t%15-19r, %10-14r"}, + {0x38000203, 0x3ff003ff, "madh\t\t%15-19r, %10-14r"}, + {0x380002c3, 0x3ff003ff, "madh.fs\t\t%15-19r, %10-14r"}, + {0x38000007, 0x3e0003ff, "max\t\t%20-24r, %15-19r, %10-14r"}, + {0x38000006, 0x3e0003ff, "min\t\t%20-24r, %15-19r, %10-14r"}, + {0x38000104, 0x3ff003ff, "mszl\t\t%15-19r, %10-14r"}, + {0x38000184, 0x3ff003ff, "mszl.f\t\t%15-19r, %10-14r"}, + {0x38000004, 0x3ff003ff, "msbl\t\t%15-19r, %10-14r"}, + {0x380000c4, 0x3ff003ff, "msbl.fs\t\t%15-19r, %10-14r"}, + {0x38000305, 0x3ff003ff, "mszh\t\t%15-19r, %10-14r"}, + {0x38000385, 0x3ff003ff, "mszh.f\t\t%15-19r, %10-14r"}, + {0x38000205, 0x3ff003ff, "msbh\t\t%15-19r, %10-14r"}, + {0x380002c5, 0x3ff003ff, "msbh.fs\t\t%15-19r, %10-14r"}, + {0x3800004e, 0x3e0003ff, "sll.s\t\t%20-24r, %15-19r, %10-14r"}, + {0x38000049, 0x3e0003ff, "sub.s\t\t%20-24r, %15-19r, %10-14r"}, + {0x3800000d, 0x3e007fff, "clz\t\t%20-24r, %15-19r"}, + {0x38000000, 0x3e000000, "ceinst\t\t%20-24d, %15-19r, %10-14r, %5-9d, %0-4d"}, + {0x00000019, 0x3ff003ff, "cmpteq.c\t\t%15-19r, %10-14r"}, + {0x00100019, 0x3ff003ff, "cmptmi.c\t\t%15-19r, %10-14r"}, + {0x00300019, 0x3ff003ff, "cmp.c\t\t%15-19r, %10-14r"}, + {0x0000001b, 0x3ff07fff, "cmpzteq.c\t%15-19r"}, + {0x0010001b, 0x3ff07fff, "cmpztmi.c\t%15-19r"}, + {0x0030001b, 0x3ff07fff, "cmpz.c\t\t%15-19r"}, + {0x02040001, 0x3e0e0001, "cmpi.c\t\t%20-24r, %1-16i"}, + {0x00002003, 0x0000700f, "cmp!\t\t%8-11r, %4-7r"}, + {0x0c00000c, 0x3e00001f, "cop1\t\tc%20-24r, c%15-19r, c%10-14r, %5-9d"}, + {0x0c000014, 0x3e00001f, "cop2\t\tc%20-24r, c%15-19r, c%10-14r, %5-9d"}, + {0x0c00001c, 0x3e00001f, "cop3\t\tc%20-24r, c%15-19r, c%10-14r, %5-9d"}, + {0x00000044, 0x3e0003ff, "div\t\t%15-19r, %10-14r"}, + {0x00000046, 0x3e0003ff, "divu\t\t%15-19r, %10-14r"}, + {0x0c0000a4, 0x3e0003ff, "drte"}, + {0x00000058, 0x3e0003ff, "extsb\t\t%20-24r, %15-19r"}, + {0x00000059, 0x3e0003ff, "extsb.c\t\t%20-24r, %15-19r"}, + {0x0000005a, 0x3e0003ff, "extsh\t\t%20-24r, %15-19r"}, + {0x0000005b, 0x3e0003ff, "extsh.c\t\t%20-24r, %15-19r"}, + {0x0000005c, 0x3e0003ff, "extzb\t\t%20-24r, %15-19r"}, + {0x0000005d, 0x3e0003ff, "extzb.c\t\t%20-24r, %15-19r"}, + {0x0000005e, 0x3e0003ff, "extzh\t\t%20-24r, %15-19r"}, + {0x0000005f, 0x3e0003ff, "extzh.c\t\t%20-24r, %15-19r"}, + {0x04000001, 0x3e000001, "jl\t\t%j"}, + {0x00003001, 0x00007001, "jl!\t\t%j"}, + {0x00003000, 0x00007001, "j!\t\t%j"}, + {0x04000000, 0x3e000001, "j\t\t%j"}, + {0x26000000, 0x3e000000, "lb\t\t%20-24r, [%15-19r, %0-14i]"}, + {0x2c000000, 0x3e000000, "lbu\t\t%20-24r, [%15-19r, %0-14i]"}, + {0x06000003, 0x3e000007, "lb\t\t%20-24r, [%15-19r, %3-14i]+"}, + {0x06000006, 0x3e000007, "lbu\t\t%20-24r, [%15-19r, %3-14i]+"}, + {0x0e000003, 0x3e000007, "lb\t\t%20-24r, [%15-19r]+, %3-14i"}, + {0x0e000006, 0x3e000007, "lbu\t\t%20-24r, [%15-19r]+, %3-14i"}, + {0x0000200b, 0x0000700f, "lbu!\t\t%8-11r, [%4-7r]"}, + {0x00007003, 0x00007007, "lbup!\t\t%8-11r, %3-7d"}, + {0x00000060, 0x3e0003ff, "lcb\t\t[%15-19r]+"}, + {0x00000062, 0x3e0003ff, "lcw\t\t%20-24r, [%15-19r]+"}, + {0x00000066, 0x3e0003ff, "lce\t\t%20-24r, [%15-19r]+"}, + {0x0c00000a, 0x3e00001f, "ldc1\t\tc%15-19r, [%20-24r, %5-14i]"}, + {0x0c000012, 0x3e00001f, "ldc2\t\tc%15-19r, [%20-24r, %5-14i]"}, + {0x0c00001a, 0x3e00001f, "ldc3\t\tc%15-19r, [%20-24r, %5-14i]"}, + {0x22000000, 0x3e000000, "lh\t\t%20-24r, [%15-19r, %0-14i]"}, + {0x24000000, 0x3e000000, "lhu\t\t%20-24r, [%15-19r, %0-14i]"}, + {0x06000001, 0x3e000007, "lh\t\t%20-24r, [%15-19r, %3-14i]+"}, + {0x06000002, 0x3e000007, "lhu\t\t%20-24r, [%15-19r, %3-14i]+"}, + {0x0e000001, 0x3e000007, "lh\t\t%20-24r, [%15-19r]+, %3-14i"}, + {0x0e000002, 0x3e000007, "lhu\t\t%20-24r, [%15-19r]+, %3-14i"}, + {0x00002009, 0x0000700f, "lh!\t\t%8-11r, [%4-7r]"}, + {0x00007001, 0x00007007, "lhp!\t\t%8-11r, %3-7d1"}, + {0x020c0000, 0x3e0e0000, "ldi\t\t%20-24r, 0x%1-16x(%1-16i)"}, + {0x0a0c0000, 0x3e0e0000, "ldis\t\t%20-24r, 0x%1-16x(%1-16i)"}, + {0x00005000, 0x00007000, "ldiu!\t\t%8-11r, %0-7d"}, + {0x0000000c, 0x3e0003ff, "alw\t\t%20-24r, [%15-19r]"}, + {0x20000000, 0x3e000000, "lw\t\t%20-24r, [%15-19r, %0-14i]"}, + {0x06000000, 0x3e000007, "lw\t\t%20-24r, [%15-19r, %3-14i]+"}, + {0x0e000000, 0x3e000007, "lw\t\t%20-24r, [%15-19r]+, %3-14i"}, + {0x00002008, 0x0000700f, "lw!\t\t%8-11r, [%4-7r]"}, + {0x00007000, 0x00007007, "lwp!\t\t%8-11r, %3-7d2"}, + {0x0000100b, 0x0000700f, "madh.fs!\t\t%8-11r, %4-7r"}, + {0x0000100a, 0x0000700f, "madl.fs!\t\t%8-11r, %4-7r"}, + {0x00001005, 0x0000700f, "madu!\t\t%8-11r, %4-7r"}, + {0x00001004, 0x0000700f, "mad.f!\t\t%8-11r, %4-7r"}, + {0x00001009, 0x0000700f, "mazh.f!\t\t%8-11r, %4-7r"}, + {0x00001008, 0x0000700f, "mazl.f!\t\t%8-11r, %4-7r"}, + {0x00000448, 0x3e007fff, "mfcel\t\t%20-24r"}, + {0x00001001, 0x00007f0f, "mfcel!\t\t%4-7r"}, + {0x00000848, 0x3e007fff, "mfceh\t\t%20-24r"}, + {0x00001101, 0x00007f0f, "mfceh!\t\t%4-7r"}, + {0x00000c48, 0x3e007fff, "mfcehl\t\t%20-24r, %15-19r"}, + {0x00000048, 0x3e0003ff, "mfce\t\t%20-24r, er%10-14d"}, + {0x00000050, 0x3e0003ff, "mfsr\t\t%20-24r, sr%10-14d"}, + {0x0c000001, 0x3e00001f, "mfcr\t\t%20-24r, c%15-19r"}, + {0x0c000009, 0x3e00001f, "mfc1\t\t%20-24r, c%15-19r"}, + {0x0c000011, 0x3e00001f, "mfc2\t\t%20-24r, c%15-19r"}, + {0x0c000019, 0x3e00001f, "mfc3\t\t%20-24r, c%15-19r"}, + {0x0c00000f, 0x3e00001f, "mfcc1\t\t%20-24r, c%15-19r"}, + {0x0c000017, 0x3e00001f, "mfcc2\t\t%20-24r, c%15-19r"}, + {0x0c00001f, 0x3e00001f, "mfcc3\t\t%20-24r, c%15-19r"}, + {0x00000002, 0x0000700f, "mhfl!\t\t%8-11R, %4-7r"}, + {0x00000001, 0x0000700f, "mlfh!\t\t%8-11r, %4-7R"}, + {0x00001006, 0x0000700f, "msb.f!\t\t%8-11r, %4-7r"}, + {0x0000100f, 0x0000700f, "msbh.fs!\t\t%8-11r, %4-7r"}, + {0x0000100e, 0x0000700f, "msbl.fs!\t\t%8-11r, %4-7r"}, + {0x00001007, 0x0000700f, "msbu!\t\t%8-11r, %4-7r"}, + {0x0000100d, 0x0000700f, "mszh.f!\t\t%8-11r, %4-7r"}, + {0x0000100c, 0x0000700f, "mszl.f!\t\t%8-11r, %4-7r"}, + {0x0000044a, 0x3e007fff, "mtcel\t\t%20-24r"}, + {0x00001000, 0x00007f0f, "mtcel!\t\t%4-7r"}, + {0x0000084a, 0x3e007fff, "mtceh\t\t%20-24r"}, + {0x00001100, 0x00007f0f, "mtceh!\t\t%4-7r"}, + {0x00000c4a, 0x3e007fff, "mtcehl\t\t%20-24r, %15-19r"}, + {0x0000004a, 0x3e0003ff, "mtce\t\t%20-24r, er%10-14d"}, + {0x00000052, 0x3e0003ff, "mtsr\t\t%15-19r, sr%10-14d"}, + {0x0c000000, 0x3e00001f, "mtcr\t\t%20-24r, c%15-19r"}, + {0x0c000008, 0x3e00001f, "mtc1\t\t%20-24r, c%15-19r"}, + {0x0c000010, 0x3e00001f, "mtc2\t\t%20-24r, c%15-19r"}, + {0x0c000018, 0x3e00001f, "mtc3\t\t%20-24r, c%15-19r"}, + {0x0c00000e, 0x3e00001f, "mtcc1\t\t%20-24r, c%15-19r"}, + {0x0c000016, 0x3e00001f, "mtcc2\t\t%20-24r, c%15-19r"}, + {0x0c00001e, 0x3e00001f, "mtcc3\t\t%20-24r, c%15-19r"}, + {0x00000040, 0x3e0003ff, "mul\t\t%15-19r, %10-14r"}, + {0x00000040, 0x3e0003ff, "maz\t\t%15-19r, %10-14r"}, + {0x00000041, 0x3e0003ff, "mul.f\t\t%15-19r, %10-14r"}, + {0x00000041, 0x3e0003ff, "maz.f\t\t%15-19r, %10-14r"}, + {0x00001002, 0x0000700f, "mul.f!\t\t%8-11r, %4-7r"}, + {0x00000042, 0x3e0003ff, "mulu\t\t%15-19r, %10-14r"}, + {0x00000042, 0x3e0003ff, "mazu\t\t%15-19r, %10-14r"}, + {0x00001003, 0x0000700f, "mulu!\t\t%8-11r, %4-7r"}, + {0x00000056, 0x3e007fff, "mvcs\t\t%20-24r, %15-19r"}, + {0x00000456, 0x3e007fff, "mvcc\t\t%20-24r, %15-19r"}, + {0x00000856, 0x3e007fff, "mvgtu\t\t%20-24r, %15-19r"}, + {0x00000c56, 0x3e007fff, "mvleu\t\t%20-24r, %15-19r"}, + {0x00001056, 0x3e007fff, "mveq\t\t%20-24r, %15-19r"}, + {0x00001456, 0x3e007fff, "mvne\t\t%20-24r, %15-19r"}, + {0x00001856, 0x3e007fff, "mvgt\t\t%20-24r, %15-19r"}, + {0x00001c56, 0x3e007fff, "mvle\t\t%20-24r, %15-19r"}, + {0x00002056, 0x3e007fff, "mvge\t\t%20-24r, %15-19r"}, + {0x00002456, 0x3e007fff, "mvlt\t\t%20-24r, %15-19r"}, + {0x00002856, 0x3e007fff, "mvmi\t\t%20-24r, %15-19r"}, + {0x00002c56, 0x3e007fff, "mvpl\t\t%20-24r, %15-19r"}, + {0x00003056, 0x3e007fff, "mvvs\t\t%20-24r, %15-19r"}, + {0x00003456, 0x3e007fff, "mvvc\t\t%20-24r, %15-19r"}, + {0x00003c56, 0x3e007fff, "mv\t\t%20-24r, %15-19r"}, + {0x00000003, 0x0000700f, "mv!\t\t%8-11r, %4-7r"}, + {0x0000001e, 0x3e0003ff, "neg\t\t%20-24r, %10-14r"}, + {0x0000001f, 0x3e0003ff, "neg.c\t\t%20-24r, %10-14r"}, + {0x00002002, 0x0000700f, "neg!\t\t%8-11r, %4-7r"}, + {0x00000000, 0x3e0003ff, "nop"}, + {0x00000024, 0x3e0003ff, "not\t\t%20-24r, %15-19r"}, + {0x00000025, 0x3e0003ff, "not.c\t\t%20-24r, %15-19r"}, + {0x00000000, 0x0000700f, "nop!"}, + {0x00002006, 0x0000700f, "not!\t\t%8-11r, %4-7r"}, + {0x00000022, 0x3e0003ff, "or\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000023, 0x3e0003ff, "or.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x020a0000, 0x3e0e0001, "ori\t\t%20-24r, 0x%1-16x"}, + {0x020a0001, 0x3e0e0001, "ori.c\t\t%20-24r, 0x%1-16x"}, + {0x0a0a0000, 0x3e0e0001, "oris\t\t%20-24r, 0x%1-16x"}, + {0x0a0a0001, 0x3e0e0001, "oris.c\t\t%20-24r, 0x%1-16x"}, + {0x1a000000, 0x3e000001, "orri\t\t%20-24r, %15-19r, 0x%1-14x"}, + {0x1a000001, 0x3e000001, "orri.c\t\t%20-24r, %15-19r, 0x%1-14x"}, + {0x00002005, 0x0000700f, "or!\t\t%8-11r, %4-7r"}, + {0x0000000a, 0x3e0003ff, "pflush"}, + {0x0000208a, 0x0000708f, "pop!\t\t%8-11R, [%4-6r]"}, + {0x0000200a, 0x0000700f, "pop!\t\t%8-11r, [%4-7r]"}, + {0x0000208e, 0x0000708f, "push!\t\t%8-11R, [%4-6r]"}, + {0x0000200e, 0x0000700f, "push!\t\t%8-11r, [%4-7r]"}, + {0x00000038, 0x3e0003ff, "ror\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000039, 0x3e0003ff, "ror.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x0000003b, 0x3e0003ff, "rorc.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x0000003c, 0x3e0003ff, "rol\t\t%20-24r, %15-19r, %10-14r"}, + {0x0000003d, 0x3e0003ff, "rol.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x0000003f, 0x3e0003ff, "rolc.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000078, 0x3e0003ff, "rori\t\t%20-24r, %15-19r, %10-14d"}, + {0x00000079, 0x3e0003ff, "rori.c\t\t%20-24r, %15-19r, %10-14d"}, + {0x0000007b, 0x3e0003ff, "roric.c\t\t%20-24r, %15-19r, %10-14d"}, + {0x0000007c, 0x3e0003ff, "roli\t\t%20-24r, %15-19r, %10-14d"}, + {0x0000007d, 0x3e0003ff, "roli.c\t\t%20-24r, %15-19r, %10-14d"}, + {0x0000007f, 0x3e0003ff, "rolic.c\t\t%20-24r, %15-19r, %10-14d"}, + {0x0c000084, 0x3e0003ff, "rte"}, + {0x2e000000, 0x3e000000, "sb\t\t%20-24r, [%15-19r, %0-14i]"}, + {0x06000007, 0x3e000007, "sb\t\t%20-24r, [%15-19r, %3-14i]+"}, + {0x0e000007, 0x3e000007, "sb\t\t%20-24r, [%15-19r]+, %3-14i"}, + {0x0000200f, 0x0000700f, "sb!\t\t%8-11r, [%4-7r]"}, + {0x00007007, 0x00007007, "sbp!\t\t%8-11r, %3-7d"}, + {0x0000000e, 0x3e0003ff, "asw\t\t%20-24r, [%15-19r]"}, + {0x00000068, 0x3e0003ff, "scb\t\t%20-24r, [%15-19r]+"}, + {0x0000006a, 0x3e0003ff, "scw\t\t%20-24r, [%15-19r]+"}, + {0x0000006e, 0x3e0003ff, "sce\t\t[%15-19r]+"}, + {0x00000006, 0x3e0003ff, "sdbbp\t\t%15-19d"}, + {0x00006002, 0x00007007, "sdbbp!\t\t%3-7d"}, + {0x2a000000, 0x3e000000, "sh\t\t%20-24r, [%15-19r, %0-14i]"}, + {0x06000005, 0x3e000007, "sh\t\t%20-24r, [%15-19r, %3-14i]+"}, + {0x0e000005, 0x3e000007, "sh\t\t%20-24r, [%15-19r]+, %3-14i"}, + {0x0000200d, 0x0000700f, "sh!\t\t%8-11r, [%4-7r]"}, + {0x00007005, 0x00007007, "shp!\t\t%8-11r, %3-7d1"}, + {0x0c0000c4, 0x3e0003ff, "sleep"}, + {0x00000030, 0x3e0003ff, "sll\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000031, 0x3e0003ff, "sll.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000070, 0x3e0003ff, "slli\t\t%20-24r, %15-19r, %10-14d"}, + {0x00000071, 0x3e0003ff, "slli.c\t\t%20-24r, %15-19r, %10-14d"}, + {0x00000008, 0x0000700f, "sll!\t\t%8-11r, %4-7r"}, + {0x00006001, 0x00007007, "slli!\t\t%8-11r, %3-7d"}, + {0x00000034, 0x3e0003ff, "srl\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000035, 0x3e0003ff, "srl.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000036, 0x3e0003ff, "sra\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000037, 0x3e0003ff, "sra.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000074, 0x3e0003ff, "srli\t\t%20-24r, %15-19r, %10-14d"}, + {0x00000075, 0x3e0003ff, "srli.c\t\t%20-24r, %15-19r, %10-14d"}, + {0x00000076, 0x3e0003ff, "srai\t\t%20-24r, %15-19r, %10-14d"}, + {0x00000077, 0x3e0003ff, "srai.c\t\t%20-24r, %15-19r, %10-14d"}, + {0x0000000a, 0x0000700f, "srl!\t\t%8-11r, %4-7r"}, + {0x00006003, 0x00007007, "srli!\t\t%8-11r, %3-7d"}, + {0x0000000b, 0x0000700f, "sra!\t\t%8-11r, %4-7r"}, + {0x0c00000b, 0x3e00001f, "stc1\t\tc%15-19r, [%20-24r, %5-14i]"}, + {0x0c000013, 0x3e00001f, "stc2\t\tc%15-19r, [%20-24r, %5-14i]"}, + {0x0c00001b, 0x3e00001f, "stc3\t\tc%15-19r, [%20-24r, %5-14i]"}, + {0x00000014, 0x3e0003ff, "sub\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000015, 0x3e0003ff, "sub.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000016, 0x3e0003ff, "subc\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000017, 0x3e0003ff, "subc.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x00002001, 0x0000700f, "sub!\t\t%8-11r, %4-7r"}, + {0x00006080, 0x00007087, "subei!\t\t%8-11r, %3-6d"}, + {0x28000000, 0x3e000000, "sw\t\t%20-24r, [%15-19r, %0-14i]"}, + {0x06000004, 0x3e000007, "sw\t\t%20-24r, [%15-19r, %3-14i]+"}, + {0x0e000004, 0x3e000007, "sw\t\t%20-24r, [%15-19r]+, %3-14i"}, + {0x0000200c, 0x0000700f, "sw!\t\t%8-11r, [%4-7r]"}, + {0x00007004, 0x00007007, "swp!\t\t%8-11r, %3-7d2"}, + {0x00000002, 0x3e0003ff, "syscall\t\t%10-24d"}, + {0x00000054, 0x3e007fff, "tcs"}, + {0x00000454, 0x3e007fff, "tcc"}, + {0x00003854, 0x3e007fff, "tcnz"}, + {0x00000005, 0x00007f0f, "tcs!"}, + {0x00000105, 0x00007f0f, "tcc!"}, + {0x00000e05, 0x00007f0f, "tcnz!"}, + {0x00001054, 0x3e007fff, "teq"}, + {0x00000405, 0x00007f0f, "teq!"}, + {0x00000854, 0x3e007fff, "tgtu"}, + {0x00001854, 0x3e007fff, "tgt"}, + {0x00002054, 0x3e007fff, "tge"}, + {0x00000205, 0x00007f0f, "tgtu!"}, + {0x00000605, 0x00007f0f, "tgt!"}, + {0x00000805, 0x00007f0f, "tge!"}, + {0x00000c54, 0x3e007fff, "tleu"}, + {0x00001c54, 0x3e007fff, "tle"}, + {0x00002454, 0x3e007fff, "tlt"}, + {0x0c000004, 0x3e0003ff, "stlb"}, + {0x0c000024, 0x3e0003ff, "mftlb"}, + {0x0c000044, 0x3e0003ff, "mtptlb"}, + {0x0c000064, 0x3e0003ff, "mtrtlb"}, + {0x00000305, 0x00007f0f, "tleu!"}, + {0x00000705, 0x00007f0f, "tle!"}, + {0x00000905, 0x00007f0f, "tlt!"}, + {0x00002854, 0x3e007fff, "tmi"}, + {0x00000a05, 0x00007f0f, "tmi!"}, + {0x00001454, 0x3e007fff, "tne"}, + {0x00000505, 0x00007f0f, "tne!"}, + {0x00002c54, 0x3e007fff, "tpl"}, + {0x00000b05, 0x00007f0f, "tpl!"}, + {0x00000004, 0x3e007fff, "trapcs\t\t%15-19d"}, + {0x00000404, 0x3e007fff, "trapcc\t\t%15-19d"}, + {0x00000804, 0x3e007fff, "trapgtu\t\t%15-19d"}, + {0x00000c04, 0x3e007fff, "trapleu\t\t%15-19d"}, + {0x00001004, 0x3e007fff, "trapeq\t\t%15-19d"}, + {0x00001404, 0x3e007fff, "trapne\t\t%15-19d"}, + {0x00001804, 0x3e007fff, "trapgt\t\t%15-19d"}, + {0x00001c04, 0x3e007fff, "traple\t\t%15-19d"}, + {0x00002004, 0x3e007fff, "trapge\t\t%15-19d"}, + {0x00002404, 0x3e007fff, "traplt\t\t%15-19d"}, + {0x00002804, 0x3e007fff, "trapmi\t\t%15-19d"}, + {0x00002c04, 0x3e007fff, "trappl\t\t%15-19d"}, + {0x00003004, 0x3e007fff, "trapvs\t\t%15-19d"}, + {0x00003404, 0x3e007fff, "trapvc\t\t%15-19d"}, + {0x00003c04, 0x3e007fff, "trap\t\t%15-19d"}, + {0x00003c54, 0x3e007fff, "tset"}, + {0x00000f05, 0x00007f0f, "tset!"}, + {0x00003054, 0x3e007fff, "tvs"}, + {0x00003454, 0x3e007fff, "tvc"}, + {0x00000c05, 0x00007f0f, "tvs!"}, + {0x00000d05, 0x00007f0f, "tvc!"}, + {0x00000026, 0x3e0003ff, "xor\t\t%20-24r, %15-19r, %10-14r"}, + {0x00000027, 0x3e0003ff, "xor.c\t\t%20-24r, %15-19r, %10-14r"}, + {0x00002007, 0x0000700f, "xor!\t\t%8-11r, %4-7r"} +}; + +typedef struct +{ + const char *name; + const char *description; + const char *reg_names[32]; +} score_regname; + +static score_regname regnames[] = +{ + {"gcc", "Select register names used by GCC", + {"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", + "r11", "r12", "r13", "r14", "r15", "r16", "r17", "r18", "r19", "r20", + "r21", "r22", "r23", "r24", "r25", "r26", "r27", "gp", "r29", "r30", "r31"}}, +}; + +static unsigned int regname_selected = 0; + +#define NUM_SCORE_REGNAMES NUM_ELEM (regnames) +#define score_regnames regnames[regname_selected].reg_names + +/* s3_s7: opcodes and export prototypes. */ +int +s7_print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little); + +/* Print one instruction from PC on INFO->STREAM. + Return the size of the instruction. */ +static int +print_insn_score32 (bfd_vma pc, struct disassemble_info *info, long given) +{ + struct score_opcode *insn; + void *stream = info->stream; + fprintf_ftype func = info->fprintf_func; + + for (insn = score_opcodes; insn->assembler; insn++) + { + if ((insn->mask & 0xffff0000) && (given & insn->mask) == insn->value) + { + char *c; + + for (c = insn->assembler; *c; c++) + { + if (*c == '%') + { + switch (*++c) + { + case 'j': + { + int target; + + if (info->flags & INSN_HAS_RELOC) + pc = 0; + target = (pc & 0xfe000000) | (given & 0x01fffffe); + (*info->print_address_func) (target, info); + } + break; + case 'b': + { + /* Sign-extend a 20-bit number. */ +#define SEXT20(x) ((((x) & 0xfffff) ^ (~ 0x7ffff)) + 0x80000) + int disp = ((given & 0x01ff8000) >> 5) | (given & 0x3fe); + int target = (pc + SEXT20 (disp)); + + (*info->print_address_func) (target, info); + } + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + int bitstart = *c++ - '0'; + int bitend = 0; + + while (*c >= '0' && *c <= '9') + bitstart = (bitstart * 10) + *c++ - '0'; + + switch (*c) + { + case '-': + c++; + while (*c >= '0' && *c <= '9') + bitend = (bitend * 10) + *c++ - '0'; + + if (!bitend) + abort (); + + switch (*c) + { + case 'r': + { + long reg; + + reg = given >> bitstart; + reg &= (2 << (bitend - bitstart)) - 1; + + func (stream, "%s", score_regnames[reg]); + } + break; + case 'd': + { + long reg; + + reg = given >> bitstart; + reg &= (2 << (bitend - bitstart)) - 1; + + func (stream, "%ld", reg); + } + break; + case 'i': + { + long reg; + + reg = given >> bitstart; + reg &= (2 << (bitend - bitstart)) - 1; + reg = ((reg ^ (1 << (bitend - bitstart))) - + (1 << (bitend - bitstart))); + + if (((given & insn->mask) == 0x0c00000a) /* ldc1 */ + || ((given & insn->mask) == 0x0c000012) /* ldc2 */ + || ((given & insn->mask) == 0x0c00001c) /* ldc3 */ + || ((given & insn->mask) == 0x0c00000b) /* stc1 */ + || ((given & insn->mask) == 0x0c000013) /* stc2 */ + || ((given & insn->mask) == 0x0c00001b)) /* stc3 */ + reg <<= 2; + + func (stream, "%ld", reg); + } + break; + case 'x': + { + long reg; + + reg = given >> bitstart; + reg &= (2 << (bitend - bitstart)) - 1; + + func (stream, "%lx", reg); + } + break; + default: + abort (); + } + break; + case '`': + c++; + if ((given & (1 << bitstart)) == 0) + func (stream, "%c", *c); + break; + case '\'': + c++; + if ((given & (1 << bitstart)) != 0) + func (stream, "%c", *c); + break; + default: + abort (); + } + break; + + default: + abort (); + } + } + } + else + func (stream, "%c", *c); + } + return 4; + } + } + +#if (SCORE_SIMULATOR_ACTIVE) + func (stream, _("")); + return 4; +#endif + + abort (); +} + +static void +print_insn_parallel_sym (struct disassemble_info *info) +{ + void *stream = info->stream; + fprintf_ftype func = info->fprintf_func; + + /* 10: 0000 nop! + 4 space + 1 colon + 1 space + 1 tab + 8 opcode + 2 space + 1 tab. + FIXME: the space number is not accurate. */ + func (stream, "%s", " ||\n \t \t"); +} + +/* Print one instruction from PC on INFO->STREAM. + Return the size of the instruction. */ +static int +print_insn_score16 (bfd_vma pc, struct disassemble_info *info, long given) +{ + struct score_opcode *insn; + void *stream = info->stream; + fprintf_ftype func = info->fprintf_func; + + given &= 0xffff; + for (insn = score_opcodes; insn->assembler; insn++) + { + if (!(insn->mask & 0xffff0000) && (given & insn->mask) == insn->value) + { + char *c = insn->assembler; + + info->bytes_per_chunk = 2; + info->bytes_per_line = 4; + given &= 0xffff; + + for (; *c; c++) + { + if (*c == '%') + { + switch (*++c) + { + + case 'j': + { + int target; + + if (info->flags & INSN_HAS_RELOC) + pc = 0; + + target = (pc & 0xfffff000) | (given & 0x00000ffe); + (*info->print_address_func) (target, info); + } + break; + case 'b': + { + /* Sign-extend a 9-bit number. */ +#define SEXT9(x) ((((x) & 0x1ff) ^ (~ 0xff)) + 0x100) + int disp = (given & 0xff) << 1; + int target = (pc + SEXT9 (disp)); + + (*info->print_address_func) (target, info); + } + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + int bitstart = *c++ - '0'; + int bitend = 0; + + while (*c >= '0' && *c <= '9') + bitstart = (bitstart * 10) + *c++ - '0'; + + switch (*c) + { + case '-': + { + long reg; + + c++; + while (*c >= '0' && *c <= '9') + bitend = (bitend * 10) + *c++ - '0'; + if (!bitend) + abort (); + reg = given >> bitstart; + reg &= (2 << (bitend - bitstart)) - 1; + switch (*c) + { + case 'R': + func (stream, "%s", score_regnames[reg + 16]); + break; + case 'r': + func (stream, "%s", score_regnames[reg]); + break; + case 'd': + if (*(c + 1) == '\0') + func (stream, "%ld", reg); + else + { + c++; + if (*c == '1') + func (stream, "%ld", reg << 1); + else if (*c == '2') + func (stream, "%ld", reg << 2); + } + break; + + case 'x': + if (*(c + 1) == '\0') + func (stream, "%lx", reg); + else + { + c++; + if (*c == '1') + func (stream, "%lx", reg << 1); + else if (*c == '2') + func (stream, "%lx", reg << 2); + } + break; + case 'i': + reg = ((reg ^ (1 << bitend)) - (1 << bitend)); + func (stream, "%ld", reg); + break; + default: + abort (); + } + } + break; + + case '\'': + c++; + if ((given & (1 << bitstart)) != 0) + func (stream, "%c", *c); + break; + default: + abort (); + } + } + break; + default: + abort (); + } + } + else + func (stream, "%c", *c); + } + + return 2; + } + } +#if (SCORE_SIMULATOR_ACTIVE) + func (stream, _("")); + return 2; +#endif + /* No match. */ + abort (); +} + +/*****************************************************************************/ +/* s3_s7: exported functions. */ + +/* NOTE: There are no checks in these routines that + the relevant number of data bytes exist. */ +int +s7_print_insn (bfd_vma pc, struct disassemble_info *info, bfd_boolean little) +{ + unsigned char b[4]; + long given; + long ridparity; + int status; + bfd_boolean insn_pce_p = FALSE; + bfd_boolean insn_16_p = FALSE; + + info->display_endian = little ? BFD_ENDIAN_LITTLE : BFD_ENDIAN_BIG; + + if (pc & 0x2) + { + info->bytes_per_chunk = 2; + status = info->read_memory_func (pc, (bfd_byte *) b, 2, info); + b[3] = b[2] = 0; + insn_16_p = TRUE; + } + else + { + info->bytes_per_chunk = 4; + status = info->read_memory_func (pc, (bfd_byte *) & b[0], 4, info); + if (status != 0) + { + info->bytes_per_chunk = 2; + status = info->read_memory_func (pc, (bfd_byte *) b, 2, info); + b[3] = b[2] = 0; + insn_16_p = TRUE; + } + } + + if (status != 0) + { + info->memory_error_func (status, pc, info); + return -1; + } + + if (little) + { + given = (b[0]) | (b[1] << 8) | (b[2] << 16) | (b[3] << 24); + } + else + { + given = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | (b[3]); + } + + if ((given & 0x80008000) == 0x80008000) + { + insn_pce_p = FALSE; + insn_16_p = FALSE; + } + else if ((given & 0x8000) == 0x8000) + { + insn_pce_p = TRUE; + } + else + { + insn_16_p = TRUE; + } + + /* 16 bit instruction. */ + if (insn_16_p) + { + if (little) + { + given = b[0] | (b[1] << 8); + } + else + { + given = (b[0] << 8) | b[1]; + } + + status = print_insn_score16 (pc, info, given); + } + /* pce instruction. */ + else if (insn_pce_p) + { + long other; + + other = given & 0xFFFF; + given = (given & 0xFFFF0000) >> 16; + + status = print_insn_score16 (pc, info, given); + print_insn_parallel_sym (info); + status += print_insn_score16 (pc, info, other); + /* disassemble_bytes() will output 4 byte per chunk for pce instructio. */ + info->bytes_per_chunk = 4; + } + /* 32 bit instruction. */ + else + { + /* Get rid of parity. */ + ridparity = (given & 0x7FFF); + ridparity |= (given & 0x7FFF0000) >> 1; + given = ridparity; + status = print_insn_score32 (pc, info, given); + } + + return status; +} + +/*****************************************************************************/ -- 2.30.2