12159047fSniklas /* BFD back-end for ns32k a.out-ish binaries.
2c074d1c9Sdrahn Copyright 1990, 1991, 1992, 1994, 1995, 1996, 1998, 2000, 2001, 2002, 2003
3b55d4692Sfgsch Free Software Foundation, Inc.
42159047fSniklas Contributed by Ian Dall (idall@eleceng.adelaide.edu.au).
52159047fSniklas
62159047fSniklas This file is part of BFD, the Binary File Descriptor library.
72159047fSniklas
82159047fSniklas This program is free software; you can redistribute it and/or modify
92159047fSniklas it under the terms of the GNU General Public License as published by
102159047fSniklas the Free Software Foundation; either version 2 of the License, or
112159047fSniklas (at your option) any later version.
122159047fSniklas
132159047fSniklas This program is distributed in the hope that it will be useful,
142159047fSniklas but WITHOUT ANY WARRANTY; without even the implied warranty of
152159047fSniklas MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
162159047fSniklas GNU General Public License for more details.
172159047fSniklas
182159047fSniklas You should have received a copy of the GNU General Public License
192159047fSniklas along with this program; if not, write to the Free Software
202159047fSniklas Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
212159047fSniklas
222159047fSniklas #include "bfd.h"
232159047fSniklas #include "aout/aout64.h"
24c88b1d6cSniklas #include "ns32k.h"
252159047fSniklas
26c074d1c9Sdrahn /* Do not "beautify" the CONCAT* macro args. Traditional C will not
27c074d1c9Sdrahn remove whitespace added here, and thus will fail to concatenate
28c074d1c9Sdrahn the tokens. */
29c074d1c9Sdrahn #define MYNS(OP) CONCAT2 (ns32kaout_,OP)
30c074d1c9Sdrahn
312159047fSniklas reloc_howto_type *
322159047fSniklas MYNS(bfd_reloc_type_lookup)
332159047fSniklas PARAMS((bfd *abfd AND
342159047fSniklas bfd_reloc_code_real_type code));
352159047fSniklas
36c074d1c9Sdrahn bfd_boolean
372159047fSniklas MYNS(write_object_contents)
382159047fSniklas PARAMS((bfd *abfd));
392159047fSniklas
40c074d1c9Sdrahn /* Avoid multiple definitions from aoutx if supporting
41c074d1c9Sdrahn standard a.out format(s) as well as this one. */
42c074d1c9Sdrahn #define NAME(x,y) CONCAT3 (ns32kaout,_32_,y)
432159047fSniklas
442159047fSniklas void bfd_ns32k_arch PARAMS ((void));
452159047fSniklas
462159047fSniklas #include "libaout.h"
472159047fSniklas
482159047fSniklas #define MY(OP) MYNS(OP)
492159047fSniklas
502159047fSniklas #define MY_swap_std_reloc_in MY(swap_std_reloc_in)
512159047fSniklas #define MY_swap_std_reloc_out MY(swap_std_reloc_out)
522159047fSniklas
532159047fSniklas static void
54c074d1c9Sdrahn MY_swap_std_reloc_in PARAMS ((bfd *, struct reloc_std_external *,
55c074d1c9Sdrahn arelent *, asymbol **,
56c074d1c9Sdrahn bfd_size_type));
572159047fSniklas static void
58c074d1c9Sdrahn MY_swap_std_reloc_out PARAMS ((bfd *, arelent *,
59c074d1c9Sdrahn struct reloc_std_external *));
60c074d1c9Sdrahn reloc_howto_type *
61c074d1c9Sdrahn MY(reloc_howto) PARAMS ((bfd *, struct reloc_std_external *,
62c074d1c9Sdrahn int *, int *, int *));
63c074d1c9Sdrahn void
64c074d1c9Sdrahn MY(put_reloc) PARAMS ((bfd *, int, int, bfd_vma, reloc_howto_type *,
65c074d1c9Sdrahn struct reloc_std_external *));
662159047fSniklas
672159047fSniklas /* The ns32k series is ah, unusual, when it comes to relocation.
68*007c2a45Smiod There are three storage methods for relocatable objects. There
69c074d1c9Sdrahn are displacements, immediate operands and ordinary twos complement
70c074d1c9Sdrahn data. Of these, only the last fits into the standard relocation
71c074d1c9Sdrahn scheme. Immediate operands are stored huffman encoded and
72c074d1c9Sdrahn immediate operands are stored big endian (where as the natural byte
73*007c2a45Smiod order is little endian for this architecture).
742159047fSniklas
75c074d1c9Sdrahn Note that the ns32k displacement storage method is orthogonal to
76c074d1c9Sdrahn whether the relocation is pc relative or not. The "displacement"
77c074d1c9Sdrahn storage scheme is used for essentially all address constants. The
78c074d1c9Sdrahn displacement can be relative to zero (absolute displacement),
79c074d1c9Sdrahn relative to the pc (pc relative), the stack pointer, the frame
80c074d1c9Sdrahn pointer, the static base register and general purpose register etc.
812159047fSniklas
82c074d1c9Sdrahn For example:
83c074d1c9Sdrahn
84c074d1c9Sdrahn sym1: .long . # pc relative 2's complement
85c074d1c9Sdrahn sym1: .long foo # 2's complement not pc relative
86c074d1c9Sdrahn
87c074d1c9Sdrahn self: movd @self, r0 # pc relative displacement
88c074d1c9Sdrahn movd foo, r0 # non pc relative displacement
89c074d1c9Sdrahn
90c074d1c9Sdrahn self: movd self, r0 # pc relative immediate
91c074d1c9Sdrahn movd foo, r0 # non pc relative immediate
92c074d1c9Sdrahn
93c074d1c9Sdrahn In addition, for historical reasons the encoding of the relocation types
94c074d1c9Sdrahn in the a.out format relocation entries is such that even the relocation
95c074d1c9Sdrahn methods which are standard are not encoded the standard way. */
962159047fSniklas
972159047fSniklas reloc_howto_type MY(howto_table)[] =
982159047fSniklas {
99c074d1c9Sdrahn /* type rs size bsz pcrel bitpos ovrf sf name part_inpl readmask setmask pcdone */
100c074d1c9Sdrahn /* ns32k immediate operands. */
101c074d1c9Sdrahn HOWTO (BFD_RELOC_NS32K_IMM_8, 0, 0, 8, FALSE, 0, complain_overflow_signed,
102c88b1d6cSniklas _bfd_ns32k_reloc_imm, "NS32K_IMM_8",
103c074d1c9Sdrahn TRUE, 0x000000ff,0x000000ff, FALSE),
104c074d1c9Sdrahn HOWTO (BFD_RELOC_NS32K_IMM_16, 0, 1, 16, FALSE, 0, complain_overflow_signed,
105c88b1d6cSniklas _bfd_ns32k_reloc_imm, "NS32K_IMM_16",
106c074d1c9Sdrahn TRUE, 0x0000ffff,0x0000ffff, FALSE),
107c074d1c9Sdrahn HOWTO (BFD_RELOC_NS32K_IMM_32, 0, 2, 32, FALSE, 0, complain_overflow_signed,
108c88b1d6cSniklas _bfd_ns32k_reloc_imm, "NS32K_IMM_32",
109c074d1c9Sdrahn TRUE, 0xffffffff,0xffffffff, FALSE),
110c074d1c9Sdrahn HOWTO (BFD_RELOC_NS32K_IMM_8_PCREL, 0, 0, 8, TRUE, 0, complain_overflow_signed,
111c88b1d6cSniklas _bfd_ns32k_reloc_imm, "PCREL_NS32K_IMM_8",
112c074d1c9Sdrahn TRUE, 0x000000ff, 0x000000ff, FALSE),
113c074d1c9Sdrahn HOWTO (BFD_RELOC_NS32K_IMM_16_PCREL, 0, 1, 16, TRUE, 0, complain_overflow_signed,
114c88b1d6cSniklas _bfd_ns32k_reloc_imm, "PCREL_NS32K_IMM_16",
115c074d1c9Sdrahn TRUE, 0x0000ffff,0x0000ffff, FALSE),
116c074d1c9Sdrahn HOWTO (BFD_RELOC_NS32K_IMM_32_PCREL, 0, 2, 32, TRUE, 0, complain_overflow_signed,
117c88b1d6cSniklas _bfd_ns32k_reloc_imm, "PCREL_NS32K_IMM_32",
118c074d1c9Sdrahn TRUE, 0xffffffff,0xffffffff, FALSE),
1192159047fSniklas
120c074d1c9Sdrahn /* ns32k displacements. */
121c074d1c9Sdrahn HOWTO (BFD_RELOC_NS32K_DISP_8, 0, 0, 7, FALSE, 0, complain_overflow_signed,
122c88b1d6cSniklas _bfd_ns32k_reloc_disp, "NS32K_DISP_8",
123c074d1c9Sdrahn TRUE, 0x000000ff,0x000000ff, FALSE),
124c074d1c9Sdrahn HOWTO (BFD_RELOC_NS32K_DISP_16, 0, 1, 14, FALSE, 0, complain_overflow_signed,
125c88b1d6cSniklas _bfd_ns32k_reloc_disp, "NS32K_DISP_16",
126c074d1c9Sdrahn TRUE, 0x0000ffff, 0x0000ffff, FALSE),
127c074d1c9Sdrahn HOWTO (BFD_RELOC_NS32K_DISP_32, 0, 2, 30, FALSE, 0, complain_overflow_signed,
128c88b1d6cSniklas _bfd_ns32k_reloc_disp, "NS32K_DISP_32",
129c074d1c9Sdrahn TRUE, 0xffffffff, 0xffffffff, FALSE),
130c074d1c9Sdrahn HOWTO (BFD_RELOC_NS32K_DISP_8_PCREL, 0, 0, 7, TRUE, 0, complain_overflow_signed,
131c88b1d6cSniklas _bfd_ns32k_reloc_disp, "PCREL_NS32K_DISP_8",
132c074d1c9Sdrahn TRUE, 0x000000ff,0x000000ff, FALSE),
133c074d1c9Sdrahn HOWTO (BFD_RELOC_NS32K_DISP_16_PCREL, 0, 1, 14, TRUE, 0, complain_overflow_signed,
134c88b1d6cSniklas _bfd_ns32k_reloc_disp, "PCREL_NS32K_DISP_16",
135c074d1c9Sdrahn TRUE, 0x0000ffff,0x0000ffff, FALSE),
136c074d1c9Sdrahn HOWTO (BFD_RELOC_NS32K_DISP_32_PCREL, 0, 2, 30, TRUE, 0, complain_overflow_signed,
137c88b1d6cSniklas _bfd_ns32k_reloc_disp, "PCREL_NS32K_DISP_32",
138c074d1c9Sdrahn TRUE, 0xffffffff,0xffffffff, FALSE),
1392159047fSniklas
140c074d1c9Sdrahn /* Normal 2's complement. */
141c074d1c9Sdrahn HOWTO (BFD_RELOC_8, 0, 0, 8, FALSE, 0, complain_overflow_bitfield,0,
142c074d1c9Sdrahn "8", TRUE, 0x000000ff,0x000000ff, FALSE),
143c074d1c9Sdrahn HOWTO (BFD_RELOC_16, 0, 1, 16, FALSE, 0, complain_overflow_bitfield,0,
144c074d1c9Sdrahn "16", TRUE, 0x0000ffff,0x0000ffff, FALSE),
145c074d1c9Sdrahn HOWTO (BFD_RELOC_32, 0, 2, 32, FALSE, 0, complain_overflow_bitfield,0,
146c074d1c9Sdrahn "32", TRUE, 0xffffffff,0xffffffff, FALSE),
147c074d1c9Sdrahn HOWTO (BFD_RELOC_8_PCREL, 0, 0, 8, TRUE, 0, complain_overflow_signed, 0,
148c074d1c9Sdrahn "PCREL_8", TRUE, 0x000000ff,0x000000ff, FALSE),
149c074d1c9Sdrahn HOWTO (BFD_RELOC_16_PCREL, 0, 1, 16, TRUE, 0, complain_overflow_signed, 0,
150c074d1c9Sdrahn "PCREL_16", TRUE, 0x0000ffff,0x0000ffff, FALSE),
151c074d1c9Sdrahn HOWTO (BFD_RELOC_32_PCREL, 0, 2, 32, TRUE, 0, complain_overflow_signed, 0,
152c074d1c9Sdrahn "PCREL_32", TRUE, 0xffffffff,0xffffffff, FALSE),
1532159047fSniklas };
1542159047fSniklas
1552159047fSniklas #define CTOR_TABLE_RELOC_HOWTO(BFD) (MY(howto_table) + 14)
1562159047fSniklas
1572159047fSniklas #define RELOC_STD_BITS_NS32K_TYPE_BIG 0x06
1582159047fSniklas #define RELOC_STD_BITS_NS32K_TYPE_LITTLE 0x60
1592159047fSniklas #define RELOC_STD_BITS_NS32K_TYPE_SH_BIG 1
1602159047fSniklas #define RELOC_STD_BITS_NS32K_TYPE_SH_LITTLE 5
1612159047fSniklas
1622159047fSniklas reloc_howto_type *
1632159047fSniklas MY(reloc_howto) (abfd, rel, r_index, r_extern, r_pcrel)
164b305b0f1Sespie bfd *abfd ATTRIBUTE_UNUSED;
1652159047fSniklas struct reloc_std_external *rel;
1662159047fSniklas int *r_index;
1672159047fSniklas int *r_extern;
1682159047fSniklas int *r_pcrel;
1692159047fSniklas {
1702159047fSniklas unsigned int r_length;
1712159047fSniklas int r_ns32k_type;
172c074d1c9Sdrahn
173c88b1d6cSniklas /* BFD_ASSERT(bfd_header_little_endian (abfd)); */
1742159047fSniklas *r_index = ((rel->r_index[2] << 16)
1752159047fSniklas | (rel->r_index[1] << 8)
1762159047fSniklas | rel->r_index[0] );
1772159047fSniklas *r_extern = (0 != (rel->r_type[0] & RELOC_STD_BITS_EXTERN_LITTLE));
1782159047fSniklas *r_pcrel = (0 != (rel->r_type[0] & RELOC_STD_BITS_PCREL_LITTLE));
1792159047fSniklas r_length = ((rel->r_type[0] & RELOC_STD_BITS_LENGTH_LITTLE)
1802159047fSniklas >> RELOC_STD_BITS_LENGTH_SH_LITTLE);
1812159047fSniklas r_ns32k_type = ((rel->r_type[0] & RELOC_STD_BITS_NS32K_TYPE_LITTLE)
1822159047fSniklas >> RELOC_STD_BITS_NS32K_TYPE_SH_LITTLE);
1832159047fSniklas return (MY(howto_table) + r_length + 3 * (*r_pcrel) + 6 * r_ns32k_type);
1842159047fSniklas }
1852159047fSniklas
186c074d1c9Sdrahn #define MY_reloc_howto(BFD, REL, IN, EX, PC) \
187c074d1c9Sdrahn MY(reloc_howto) (BFD, REL, &IN, &EX, &PC)
1882159047fSniklas
1892159047fSniklas void
1902159047fSniklas MY(put_reloc) (abfd, r_extern, r_index, value, howto, reloc)
1912159047fSniklas bfd *abfd;
1922159047fSniklas int r_extern;
1932159047fSniklas int r_index;
194c074d1c9Sdrahn bfd_vma value;
1952159047fSniklas reloc_howto_type *howto;
1962159047fSniklas struct reloc_std_external *reloc;
1972159047fSniklas {
1982159047fSniklas unsigned int r_length;
1992159047fSniklas int r_pcrel;
2002159047fSniklas int r_ns32k_type;
201c074d1c9Sdrahn
2022159047fSniklas PUT_WORD (abfd, value, reloc->r_address);
203c074d1c9Sdrahn r_length = howto->size ; /* Size as a power of two. */
2042159047fSniklas r_pcrel = (int) howto->pc_relative; /* Relative to PC? */
2052159047fSniklas r_ns32k_type = (howto - MY(howto_table) )/6;
206c074d1c9Sdrahn
207c88b1d6cSniklas /* BFD_ASSERT (bfd_header_little_endian (abfd)); */
2082159047fSniklas reloc->r_index[2] = r_index >> 16;
2092159047fSniklas reloc->r_index[1] = r_index >> 8;
2102159047fSniklas reloc->r_index[0] = r_index;
2112159047fSniklas reloc->r_type[0] =
2122159047fSniklas (r_extern? RELOC_STD_BITS_EXTERN_LITTLE: 0)
2132159047fSniklas | (r_pcrel? RELOC_STD_BITS_PCREL_LITTLE: 0)
2142159047fSniklas | (r_length << RELOC_STD_BITS_LENGTH_SH_LITTLE)
2152159047fSniklas | (r_ns32k_type << RELOC_STD_BITS_NS32K_TYPE_SH_LITTLE);
2162159047fSniklas }
2172159047fSniklas
2182159047fSniklas #define MY_put_reloc(BFD, EXT, IDX, VAL, HOWTO, RELOC) \
2192159047fSniklas MY(put_reloc) (BFD, EXT, IDX, VAL, HOWTO, RELOC)
2202159047fSniklas
2212159047fSniklas #define STAT_FOR_EXEC
2222159047fSniklas
223c88b1d6cSniklas #define MY_final_link_relocate _bfd_ns32k_final_link_relocate
224c88b1d6cSniklas #define MY_relocate_contents _bfd_ns32k_relocate_contents
2252159047fSniklas
226c074d1c9Sdrahn #include "aoutx.h"
2272159047fSniklas
2282159047fSniklas reloc_howto_type *
2292159047fSniklas MY(bfd_reloc_type_lookup) (abfd,code)
2302159047fSniklas bfd *abfd;
2312159047fSniklas bfd_reloc_code_real_type code;
2322159047fSniklas {
2332159047fSniklas
2342159047fSniklas #define ENTRY(i,j) case i: return &MY(howto_table)[j]
2352159047fSniklas
2362159047fSniklas int ext = obj_reloc_entry_size (abfd) == RELOC_EXT_SIZE;
2372159047fSniklas
2382159047fSniklas BFD_ASSERT(ext == 0);
2392159047fSniklas if (code == BFD_RELOC_CTOR)
2402159047fSniklas switch (bfd_get_arch_info (abfd)->bits_per_address)
2412159047fSniklas {
2422159047fSniklas case 32:
2432159047fSniklas code = BFD_RELOC_32;
2442159047fSniklas break;
245c074d1c9Sdrahn default:
246c074d1c9Sdrahn break;
2472159047fSniklas }
2482159047fSniklas switch (code)
2492159047fSniklas {
2502159047fSniklas ENTRY(BFD_RELOC_NS32K_IMM_8, 0);
2512159047fSniklas ENTRY(BFD_RELOC_NS32K_IMM_16, 1);
2522159047fSniklas ENTRY(BFD_RELOC_NS32K_IMM_32, 2);
2532159047fSniklas ENTRY(BFD_RELOC_NS32K_IMM_8_PCREL, 3);
2542159047fSniklas ENTRY(BFD_RELOC_NS32K_IMM_16_PCREL, 4);
2552159047fSniklas ENTRY(BFD_RELOC_NS32K_IMM_32_PCREL, 5);
2562159047fSniklas ENTRY(BFD_RELOC_NS32K_DISP_8, 6);
2572159047fSniklas ENTRY(BFD_RELOC_NS32K_DISP_16, 7);
2582159047fSniklas ENTRY(BFD_RELOC_NS32K_DISP_32, 8);
2592159047fSniklas ENTRY(BFD_RELOC_NS32K_DISP_8_PCREL, 9);
2602159047fSniklas ENTRY(BFD_RELOC_NS32K_DISP_16_PCREL, 10);
2612159047fSniklas ENTRY(BFD_RELOC_NS32K_DISP_32_PCREL, 11);
2622159047fSniklas ENTRY(BFD_RELOC_8, 12);
2632159047fSniklas ENTRY(BFD_RELOC_16, 13);
2642159047fSniklas ENTRY(BFD_RELOC_32, 14);
2652159047fSniklas ENTRY(BFD_RELOC_8_PCREL, 15);
2662159047fSniklas ENTRY(BFD_RELOC_16_PCREL, 16);
2672159047fSniklas ENTRY(BFD_RELOC_32_PCREL, 17);
268c074d1c9Sdrahn default:
269c074d1c9Sdrahn return (reloc_howto_type *) NULL;
2702159047fSniklas }
2712159047fSniklas #undef ENTRY
2722159047fSniklas }
2732159047fSniklas
2742159047fSniklas static void
MY_swap_std_reloc_in(abfd,bytes,cache_ptr,symbols,symcount)2752159047fSniklas MY_swap_std_reloc_in (abfd, bytes, cache_ptr, symbols, symcount)
2762159047fSniklas bfd *abfd;
2772159047fSniklas struct reloc_std_external *bytes;
2782159047fSniklas arelent *cache_ptr;
2792159047fSniklas asymbol **symbols;
280b305b0f1Sespie bfd_size_type symcount ATTRIBUTE_UNUSED;
2812159047fSniklas {
2822159047fSniklas int r_index;
2832159047fSniklas int r_extern;
2842159047fSniklas int r_pcrel;
2852159047fSniklas struct aoutdata *su = &(abfd->tdata.aout_data->a);
2862159047fSniklas
287c074d1c9Sdrahn cache_ptr->address = H_GET_32 (abfd, bytes->r_address);
2882159047fSniklas
289c074d1c9Sdrahn /* Now the fun stuff. */
2902159047fSniklas cache_ptr->howto = MY_reloc_howto(abfd, bytes, r_index, r_extern, r_pcrel);
2912159047fSniklas
2922159047fSniklas MOVE_ADDRESS (0);
2932159047fSniklas }
2942159047fSniklas
2952159047fSniklas static void
MY_swap_std_reloc_out(abfd,g,natptr)2962159047fSniklas MY_swap_std_reloc_out (abfd, g, natptr)
2972159047fSniklas bfd *abfd;
2982159047fSniklas arelent *g;
2992159047fSniklas struct reloc_std_external *natptr;
3002159047fSniklas {
3012159047fSniklas int r_index;
3022159047fSniklas asymbol *sym = *(g->sym_ptr_ptr);
3032159047fSniklas int r_extern;
3042159047fSniklas unsigned int r_addend;
3052159047fSniklas asection *output_section = sym->section->output_section;
3062159047fSniklas
3072159047fSniklas r_addend = g->addend + (*(g->sym_ptr_ptr))->section->output_section->vma;
3082159047fSniklas
309c074d1c9Sdrahn /* Name was clobbered by aout_write_syms to be symbol index. */
3102159047fSniklas
3112159047fSniklas /* If this relocation is relative to a symbol then set the
3122159047fSniklas r_index to the symbols index, and the r_extern bit.
3132159047fSniklas
3142159047fSniklas Absolute symbols can come in in two ways, either as an offset
3152159047fSniklas from the abs section, or as a symbol which has an abs value.
3162159047fSniklas Check for that here. */
3172159047fSniklas if (bfd_is_com_section (output_section)
3182159047fSniklas || output_section == &bfd_abs_section
3192159047fSniklas || output_section == &bfd_und_section)
3202159047fSniklas {
3212159047fSniklas if (bfd_abs_section.symbol == sym)
3222159047fSniklas {
3232159047fSniklas /* Whoops, looked like an abs symbol, but is really an offset
324c074d1c9Sdrahn from the abs section. */
3252159047fSniklas r_index = 0;
3262159047fSniklas r_extern = 0;
3272159047fSniklas }
3282159047fSniklas else
3292159047fSniklas {
330c074d1c9Sdrahn /* Fill in symbol. */
3312159047fSniklas r_extern = 1;
3322159047fSniklas #undef KEEPIT
3332159047fSniklas #define KEEPIT udata.i
3342159047fSniklas r_index = (*(g->sym_ptr_ptr))->KEEPIT;
3352159047fSniklas #undef KEEPIT
3362159047fSniklas }
3372159047fSniklas }
3382159047fSniklas else
3392159047fSniklas {
340c074d1c9Sdrahn /* Just an ordinary section. */
3412159047fSniklas r_extern = 0;
3422159047fSniklas r_index = output_section->target_index;
3432159047fSniklas }
3442159047fSniklas
3452159047fSniklas MY_put_reloc (abfd, r_extern, r_index, g->address, g->howto, natptr);
3462159047fSniklas }
3472159047fSniklas
3482159047fSniklas bfd_reloc_status_type
_bfd_ns32k_relocate_contents(howto,input_bfd,relocation,location)349c88b1d6cSniklas _bfd_ns32k_relocate_contents (howto, input_bfd, relocation, location)
3502159047fSniklas reloc_howto_type *howto;
3512159047fSniklas bfd *input_bfd;
3522159047fSniklas bfd_vma relocation;
3532159047fSniklas bfd_byte *location;
3542159047fSniklas {
3552159047fSniklas int r_ns32k_type = (howto - MY(howto_table)) / 6;
356c074d1c9Sdrahn bfd_vma (*get_data) PARAMS ((bfd_byte *, int));
357c074d1c9Sdrahn void (*put_data) PARAMS ((bfd_vma, bfd_byte *, int));
3582159047fSniklas
3592159047fSniklas switch (r_ns32k_type)
3602159047fSniklas {
3612159047fSniklas case 0:
362c88b1d6cSniklas get_data = _bfd_ns32k_get_immediate;
363c88b1d6cSniklas put_data = _bfd_ns32k_put_immediate;
3642159047fSniklas break;
3652159047fSniklas case 1:
366c88b1d6cSniklas get_data = _bfd_ns32k_get_displacement;
367c88b1d6cSniklas put_data = _bfd_ns32k_put_displacement;
3682159047fSniklas break;
3692159047fSniklas case 2:
3702159047fSniklas return _bfd_relocate_contents (howto, input_bfd, relocation,
3712159047fSniklas location);
3722159047fSniklas /* NOT REACHED */
3732159047fSniklas break;
374b305b0f1Sespie default:
375b305b0f1Sespie return bfd_reloc_notsupported;
3762159047fSniklas }
377c88b1d6cSniklas return _bfd_do_ns32k_reloc_contents (howto, input_bfd, relocation,
3782159047fSniklas location, get_data, put_data);
3792159047fSniklas }
380