#define R_MICROBLAZE_32_SYM_OP_SYM 10
#define R_MICROBLAZE_GNU_VTINHERIT 11
#define R_MICROBLAZE_GNU_VTENTRY 12
-
+
#define R_MICROBLAZE_NUM 13
+/* Altera NIOS specific definitions. */
+
+#define FLAT_NIOS2_R_32 0 /* Normal 32-bit reloc */
+#define FLAT_NIOS2_R_HI_LO 1
+#define FLAT_NIOS2_R_HIADJ_LO 2
+#define FLAT_NIOS2_R_CALL26 4
+
+/* NIOS relocations. */
+#define R_NIOS_NONE 0
+#define R_NIOS_32 1 /* A 32 bit absolute relocation.*/
+#define R_NIOS_LO16_LO5 2 /* A LO-16 5 bit absolute relocation. */
+#define R_NIOS_LO16_HI11 3 /* A LO-16 top 11 bit absolute relocation. */
+#define R_NIOS_HI16_LO5 4 /* A HI-16 5 bit absolute relocation. */
+#define R_NIOS_HI16_HI11 5 /* A HI-16 top 11 bit absolute relocation. */
+#define R_NIOS_PCREL6 6 /* A 6 bit relative relocation. */
+#define R_NIOS_PCREL8 7 /* An 8 bit relative relocation. */
+#define R_NIOS_PCREL11 8 /* An 11 bit relative relocation. */
+#define R_NIOS_16 9 /* A 16 bit absolute relocation. */
+#define R_NIOS_H_LO5 10 /* Low 5-bits of absolute relocation in halfwords. */
+#define R_NIOS_H_HI11 11 /* Top 11 bits of 16-bit absolute relocation in halfwords. */
+#define R_NIOS_H_XLO5 12 /* Low 5 bits of top 16-bits of 32-bit absolute relocation in halfwords. */
+#define R_NIOS_H_XHI11 13 /* Top 11 bits of top 16-bits of 32-bit absolute relocation in halfwords. */
+#define R_NIOS_H_16 14 /* Half-word @h value */
+#define R_NIOS_H_32 15 /* Word @h value */
+#define R_NIOS_GNU_VTINHERIT 200 /* GNU extension to record C++ vtable hierarchy */
+#define R_NIOS_GNU_VTENTRY 201 /* GNU extension to record C++ vtable member usage */
+/* Keep this the last entry. */
+#define R_NIOS_NUM 202
+
+/* NIOS II relocations */
+#define R_NIOS2_NONE 0
+#define R_NIOS2_S16 1
+#define R_NIOS2_U16 2
+#define R_NIOS2_PCREL16 3
+#define R_NIOS2_CALL26 4
+#define R_NIOS2_IMM5 5
+#define R_NIOS2_CACHE_OPX 6
+#define R_NIOS2_IMM6 7
+#define R_NIOS2_IMM8 8
+#define R_NIOS2_HI16 9
+#define R_NIOS2_LO16 10
+#define R_NIOS2_HIADJ16 11
+#define R_NIOS2_BFD_RELOC_32 12
+#define R_NIOS2_BFD_RELOC_16 13
+#define R_NIOS2_BFD_RELOC_8 14
+#define R_NIOS2_GPREL 15
+#define R_NIOS2_GNU_VTINHERIT 16
+#define R_NIOS2_GNU_VTENTRY 17
+#define R_NIOS2_UJMP 18
+#define R_NIOS2_CJMP 19
+#define R_NIOS2_CALLR 20
+#define R_NIOS2_ALIGN 21
+/* Keep this the last entry. */
+#define R_NIOS2_NUM 22
#endif /* elf.h */
* ELF format file handling. Extended relocation support for all of
* text and data.
*
+ * (c) 2004, Nios II support, Wentao Xu <wentao@microtronix.com>
* (c) 2003, H8 support, ktrace <davidm@snapgear.com>
* (c) 2003-2004, MicroBlaze support, John Williams <jwilliams@itee.uq.edu.au>
* (c) 2001-2003, arm/arm-pic/arm-big-endian support <davidm@snapgear.com>
#if defined(TARGET_h8300)
#include <elf/h8.h> /* TARGET_* ELF support for the BFD library */
-#elif defined(__CYGWIN__) || defined(__MINGW32__)
+#elif defined(__CYGWIN__) || defined(__MINGW32__) || defined(TARGET_nios) || defined(TARGET_nios2)
#include "cygwin-elf.h" /* Cygwin uses a local copy */
#elif defined(TARGET_microblaze)
#include <elf/microblaze.h> /* TARGET_* ELF support for the BFD library */
#define FLAT_RELOC_PART_LO 0
#define FLAT_RELOC_PART_HI 1
#define PCREL24_MAGIC_OFFSET -1
+#elif defined(TARGET_nios)
+#define ARCH "nios"
+#elif defined(TARGET_nios2)
+#define ARCH "nios2"
#else
#error "Don't know how to support your CPU architecture??"
#endif
+long
+get_gp_value(asymbol **symbol_table, long number_of_symbols)
+{
+ long i;
+ for (i=0; i<number_of_symbols; i++) {
+ if (!strcmp(symbol_table[i]->name, "_gp"))
+ return symbol_table[i]->value;
+ }
+ return -1;
+}
+
+
+
long
add_com_to_bss(asymbol **symbol_table, long number_of_symbols, long bss_len)
{
continue;
}
#endif /* TARGET_microblaze */
-
+
+#ifdef TARGET_nios2
+#define htoniosl(x) (x)
+#define niostohl(x) (x)
+ switch ((*p)->howto->type)
+ {
+ case R_NIOS2_BFD_RELOC_32:
+ relocation_needed = 1;
+ pflags = (FLAT_NIOS2_R_32 << 28);
+ sym_vma = bfd_section_vma(abs_bfd, sym_section);
+ sym_addr += sym_vma + q->addend;
+ /* modify target, in target order */
+ *(unsigned long *)r_mem = htoniosl(sym_addr);
+ break;
+ case R_NIOS2_CALL26:
+ {
+ unsigned long exist_val;
+ relocation_needed = 1;
+ pflags = (FLAT_NIOS2_R_CALL26 << 28);
+ sym_vma = bfd_section_vma(abs_bfd, sym_section);
+ sym_addr += sym_vma + q->addend;
+
+ /* modify target, in target order */
+ // exist_val = niostohl(*(unsigned long *)r_mem);
+ exist_val = ((sym_addr >> 2) << 6);
+ *(unsigned long *)r_mem = htoniosl(exist_val);
+ break;
+ }
+ case R_NIOS2_HIADJ16:
+ case R_NIOS2_HI16:
+ {
+ unsigned long exist_val;
+ int r2_type;
+ /* handle the adjacent HI/LO pairs */
+ if (relcount == 0)
+ r2_type = R_NIOS2_NONE;
+ else
+ r2_type = p[1]->howto->type;
+ if ((r2_type == R_NIOS2_LO16)
+ && (p[0]->sym_ptr_ptr == p[1]->sym_ptr_ptr)
+ && (p[0]->addend == p[1]->addend))
+ {
+ unsigned char * r2_mem = sectionp + p[1]->address;
+ if (p[1]->address - q->address!=4)
+ printf("Err: HI/LO not adjacent %d\n", p[1]->address - q->address);
+ relocation_needed = 1;
+ pflags = (q->howto->type == R_NIOS2_HIADJ16)
+ ? FLAT_NIOS2_R_HIADJ_LO : FLAT_NIOS2_R_HI_LO;
+ pflags <<= 28;
+
+ sym_vma = bfd_section_vma(abs_bfd, sym_section);
+ sym_addr += sym_vma + q->addend;
+
+ /* modify high 16 bits, in target order */
+ exist_val = niostohl(*(unsigned long *)r_mem);
+ exist_val = ((exist_val >> 22) << 22) | (exist_val & 0x3f);
+ if (q->howto->type == R_NIOS2_HIADJ16)
+ exist_val |= ((((sym_addr >> 16) + ((sym_addr >> 15) & 1)) & 0xFFFF) << 6);
+ else
+ exist_val |= (((sym_addr >> 16) & 0xFFFF) << 6);
+ *(unsigned long *)r_mem = htoniosl(exist_val);
+
+ /* modify low 16 bits, in target order */
+ exist_val = niostohl(*(unsigned long *)r2_mem);
+ exist_val = ((exist_val >> 22) << 22) | (exist_val & 0x3f);
+ exist_val |= ((sym_addr & 0xFFFF) << 6);
+ *(unsigned long *)r2_mem = htoniosl(exist_val);
+
+ } else
+ goto NIOS2_RELOC_ERR;
+ }
+ break;
+
+ case R_NIOS2_GPREL:
+ {
+ unsigned long exist_val, temp;
+ //long gp = get_symbol_offset("_gp", sym_section, symbols, number_of_symbols);
+ long gp = get_gp_value(symbols, number_of_symbols);
+ if (gp == -1) {
+ printf("Err: unresolved symbol _gp when relocating %s\n", sym_name);
+ goto NIOS2_RELOC_ERR;
+ }
+ /* _gp holds a absolute value, otherwise the ld cannot generate correct code */
+ sym_vma = bfd_section_vma(abs_bfd, sym_section);
+ //printf("sym=%x, %d, _gp=%x, %d\n", sym_addr+sym_vma, sym_addr+sym_vma, gp, gp);
+ sym_addr += sym_vma + q->addend;
+ sym_addr -= gp;
+ //printf("sym - _gp=%x, %d\n", sym_addr, sym_addr);
+ /* modify the target, in target order (little_endian) */
+ exist_val = niostohl(*(unsigned long *)r_mem);
+ temp = ((exist_val >> 6) & 0x3ff0000) | (sym_addr & 0xffff);
+ temp <<= 6;
+ temp |= (exist_val & 0x3f);
+ *(unsigned long *)r_mem = htoniosl(temp);
+ if (verbose)
+ printf("omit: offset=0x%x symbol=%s%s "
+ "section=%s size=%d "
+ "fixup=0x%x (reloc=0x%x) GPREL\n",
+ q->address, sym_name, addstr,
+ section_name, sym_reloc_size,
+ sym_addr, section_vma + q->address);
+ continue;
+ }
+ case R_NIOS2_PCREL16:
+ {
+ unsigned long exist_val;
+ sym_vma = 0;
+ sym_addr += sym_vma + q->addend;
+ sym_addr -= (q->address + 4);
+ /* modify the target, in target order (little_endian) */
+ exist_val = niostohl(*(unsigned long *)r_mem);
+ exist_val = ((exist_val >> 22) << 22) | (exist_val & 0x3f);
+ exist_val |= ((sym_addr & 0xFFFF) << 6);
+ *(unsigned long *)r_mem = htoniosl(exist_val);
+ if (verbose)
+ printf("omit: offset=0x%x symbol=%s%s "
+ "section=%s size=%d "
+ "fixup=0x%x (reloc=0x%x) PCREL\n",
+ q->address, sym_name, addstr,
+ section_name, sym_reloc_size,
+ sym_addr, section_vma + q->address);
+ continue;
+ }
+
+ case R_NIOS2_LO16:
+ /* check if this is actually the 2nd half of a pair */
+ if ((p > relpp)
+ && ((p[-1]->howto->type == R_NIOS2_HIADJ16)
+ || (p[-1]->howto->type == R_NIOS2_HI16))
+ && (p[-1]->sym_ptr_ptr == p[0]->sym_ptr_ptr)
+ && (p[-1]->addend == p[0]->addend)) {
+ if (verbose)
+ printf("omit: offset=0x%x symbol=%s%s "
+ "section=%s size=%d LO16\n",
+ q->address, sym_name, addstr,
+ section_name, sym_reloc_size);
+ continue;
+ }
+
+ /* error, fall through */
+
+ case R_NIOS2_S16:
+ case R_NIOS2_U16:
+ case R_NIOS2_CACHE_OPX:
+ case R_NIOS2_IMM5:
+ case R_NIOS2_IMM6:
+ case R_NIOS2_IMM8:
+ case R_NIOS2_BFD_RELOC_16:
+ case R_NIOS2_BFD_RELOC_8:
+ case R_NIOS2_GNU_VTINHERIT:
+ case R_NIOS2_GNU_VTENTRY:
+ case R_NIOS2_UJMP:
+ case R_NIOS2_CJMP:
+ case R_NIOS2_CALLR:
+NIOS2_RELOC_ERR:
+ printf("Err: unexpected reloc type %s(%d)\n", q->howto->name, q->howto->type);
+ bad_relocs++;
+ continue;
+ }
+#endif /* TARGET_nios2 */
+
#ifdef TARGET_v850
/* Skip this relocation entirely if possible (we
do this early, before doing any other
loaders knows about it. */
break;
#endif /* TARGET_V850 */
+
+#ifdef TARGET_nios2
+ case R_NIOS2_BFD_RELOC_32:
+ case R_NIOS2_CALL26:
+ case R_NIOS2_HIADJ16:
+ case R_NIOS2_HI16:
+ /* do nothing */
+ break;
+#endif /* TARGET_nios2 */
+
default:
/* The alignment of the build host
might be stricter than that of the