+#ifdef TARGET_h8300
+ case R_H8_DIR24R8:
+ if (sym_reloc_size != 4) {
+ printf("R_H8_DIR24R8 size %d\n", sym_reloc_size);
+ bad_relocs++;
+ continue;
+ }
+ relocation_needed = 1;
+ sym_addr = (*(q->sym_ptr_ptr))->value;
+ q->address -= 1;
+ r_mem -= 1; /* tracks q->address */
+ sym_vma = bfd_section_vma(abs_bfd, sym_section);
+ sym_addr += sym_vma + q->addend;
+ sym_addr |= (*(unsigned char *)r_mem<<24);
+ break;
+ case R_H8_DIR24A8:
+ if (sym_reloc_size != 4) {
+ printf("R_H8_DIR24A8 size %d\n", sym_reloc_size);
+ bad_relocs++;
+ continue;
+ }
+ /* Absolute symbol done not relocation */
+ relocation_needed = !bfd_is_abs_section(sym_section);
+ sym_addr = (*(q->sym_ptr_ptr))->value;
+ sym_vma = bfd_section_vma(abs_bfd, sym_section);
+ sym_addr += sym_vma + q->addend;
+ break;
+ case R_H8_DIR32:
+ case R_H8_DIR32A16: /* currently 32, could be made 16 */
+ if (sym_reloc_size != 4) {
+ printf("R_H8_DIR32 size %d\n", sym_reloc_size);
+ bad_relocs++;
+ continue;
+ }
+ relocation_needed = 1;
+ sym_addr = (*(q->sym_ptr_ptr))->value;
+ sym_vma = bfd_section_vma(abs_bfd, sym_section);
+ sym_addr += sym_vma + q->addend;
+ break;
+ case R_H8_PCREL16:
+ sym_vma = 0;
+ sym_addr = (*(q->sym_ptr_ptr))->value;
+ sym_addr += sym_vma + q->addend;
+ sym_addr -= (q->address + 2);
+ if (bfd_big_endian(abs_bfd))
+ *(unsigned short *)r_mem =
+ bfd_big_endian(abs_bfd) ? htons(sym_addr) : sym_addr;
+ continue;
+ case R_H8_PCREL8:
+ sym_vma = 0;
+ sym_addr = (*(q->sym_ptr_ptr))->value;
+ sym_addr += sym_vma + q->addend;
+ sym_addr -= (q->address + 1);
+ *(unsigned char *)r_mem = sym_addr;
+ continue;
+#endif
+
+#ifdef TARGET_microblaze
+ case R_MICROBLAZE_64:
+ /* The symbol is split over two consecutive instructions.
+ Flag this to the flat loader by setting the high bit of
+ the relocation symbol. */
+ {
+ unsigned char *p = r_mem;
+ unsigned long offset;
+ pflags=0x80000000;
+
+ /* work out the relocation */
+ sym_vma = bfd_section_vma(abs_bfd, sym_section);
+ /* grab any offset from the text */
+ offset = (p[2]<<24) + (p[3] << 16) + (p[6] << 8) + (p[7]);
+ /* Update the address */
+ sym_addr += offset + sym_vma + q->addend;
+ /* Write relocated pointer back */
+ p[2] = (sym_addr >> 24) & 0xff;
+ p[3] = (sym_addr >> 16) & 0xff;
+ p[6] = (sym_addr >> 8) & 0xff;
+ p[7] = sym_addr & 0xff;
+
+ /* create a new reloc entry */
+ flat_relocs = realloc(flat_relocs,
+ (flat_reloc_count + 1) * sizeof(uint32_t));
+ flat_relocs[flat_reloc_count] = pflags | (section_vma + q->address);
+ flat_reloc_count++;
+ relocation_needed = 0;
+ pflags = 0;
+ sprintf(&addstr[0], "+0x%x", sym_addr - (*(q->sym_ptr_ptr))->value -
+ bfd_section_vma(abs_bfd, sym_section));
+ if (verbose)
+ printf(" RELOC[%d]: offset=0x%x symbol=%s%s "
+ "section=%s size=%d "
+ "fixup=0x%x (reloc=0x%x)\n", flat_reloc_count,
+ q->address, sym_name, addstr,
+ section_name, sym_reloc_size,
+ sym_addr, section_vma + q->address);
+ if (verbose)
+ printf("reloc[%d] = 0x%x\n", flat_reloc_count,
+ section_vma + q->address);
+
+ continue;
+ }
+ case R_MICROBLAZE_32:
+ {
+ unsigned char *p = r_mem;
+ unsigned long offset;
+
+ /* grab any offset from the text */
+ offset = (p[0]<<24) + (p[1] << 16) + (p[2] << 8) + (p[3]);
+ sym_vma = bfd_section_vma(abs_bfd, sym_section);
+ /* This is a horrible kludge. For some
+ reason, *sometimes* the offset is in
+ both addend and the code. Detect
+ it, and cancel the effect. Otherwise
+ the offset gets added twice - ouch.
+ There should be a better test
+ for this condition, based on the
+ BFD data structures */
+ if(offset==q->addend)
+ offset=0;
+
+ sym_addr += offset + sym_vma + q->addend;
+ relocation_needed = 1;
+ break;
+ }
+ case R_MICROBLAZE_64_PCREL:
+ sym_vma = 0;
+ //sym_addr = (*(q->sym_ptr_ptr))->value;
+ sym_addr += sym_vma + q->addend;
+ sym_addr -= (q->address + 4);
+ sym_addr = htonl(sym_addr);
+ /* insert 16 MSB */
+ * ((unsigned short *) (r_mem+2)) |= (sym_addr) & 0xFFFF;
+ /* then 16 LSB */
+ * ((unsigned short *) (r_mem+6)) |= (sym_addr >> 16) & 0xFFFF;
+ /* We've done all the work, so continue
+ to next reloc instead of break */
+ 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 */
+