1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24: #include "sysdep.h"
25: #include "bfd.h"
26: #include "libbfd.h"
27: #include "bfdlink.h"
28: #include "coff/h8500.h"
29: #include "coff/internal.h"
30: #include "libcoff.h"
31:
32: static int coff_h8500_select_reloc PARAMS ((reloc_howto_type *));
33: static void rtype2howto PARAMS ((arelent *, struct internal_reloc *));
34: static void reloc_processing PARAMS ((arelent *, struct internal_reloc *, asymbol **, bfd *, asection *));
35: static void extra_case PARAMS ((bfd *, struct bfd_link_info *, struct bfd_link_order *, arelent *, bfd_byte *, unsigned int *, unsigned int *));
36:
37: #define COFF_DEFAULT_SECTION_ALIGNMENT_POWER (1)
38:
39: static reloc_howto_type r_imm8 =
40: HOWTO (R_H8500_IMM8, 0, 1, 8, FALSE, 0,
41: complain_overflow_bitfield, 0, "r_imm8", TRUE, 0x000000ff, 0x000000ff, FALSE);
42:
43: static reloc_howto_type r_imm16 =
44: HOWTO (R_H8500_IMM16, 0, 1, 16, FALSE, 0,
45: complain_overflow_bitfield, 0, "r_imm16", TRUE, 0x0000ffff, 0x0000ffff, FALSE);
46:
47: static reloc_howto_type r_imm24 =
48: HOWTO (R_H8500_IMM24, 0, 1, 24, FALSE, 0,
49: complain_overflow_bitfield, 0, "r_imm24", TRUE, 0x00ffffff, 0x00ffffff, FALSE);
50:
51: static reloc_howto_type r_imm32 =
52: HOWTO (R_H8500_IMM32, 0, 1, 32, FALSE, 0,
53: complain_overflow_bitfield, 0, "r_imm32", TRUE, 0xffffffff, 0xffffffff, FALSE);
54:
55: static reloc_howto_type r_high8 =
56: HOWTO (R_H8500_HIGH8, 0, 1, 8, FALSE, 0,
57: complain_overflow_dont, 0, "r_high8", TRUE, 0x000000ff, 0x000000ff, FALSE);
58:
59: static reloc_howto_type r_low16 =
60: HOWTO (R_H8500_LOW16, 0, 1, 16, FALSE, 0,
61: complain_overflow_dont, 0, "r_low16", TRUE, 0x0000ffff, 0x0000ffff, FALSE);
62:
63: static reloc_howto_type r_pcrel8 =
64: HOWTO (R_H8500_PCREL8, 0, 1, 8, TRUE, 0, complain_overflow_signed, 0, "r_pcrel8", TRUE, 0, 0, TRUE);
65:
66: static reloc_howto_type r_pcrel16 =
67: HOWTO (R_H8500_PCREL16, 0, 1, 16, TRUE, 0, complain_overflow_signed, 0, "r_pcrel16", TRUE, 0, 0, TRUE);
68:
69: static reloc_howto_type r_high16 =
70: HOWTO (R_H8500_HIGH16, 0, 1, 8, FALSE, 0,
71: complain_overflow_dont, 0, "r_high16", TRUE, 0x000ffff, 0x0000ffff, FALSE);
72: ^L
73:
74:
75: static int
76: coff_h8500_select_reloc (howto)
77: reloc_howto_type *howto;
78: {
79: return howto->type;
80: }
81:
82: #define SELECT_RELOC(x,howto) x.r_type = coff_h8500_select_reloc(howto)
83:
84: #define BADMAG(x) H8500BADMAG(x)
85: #define H8500 1
86:
87: #define __A_MAGIC_SET__
88:
89:
90: #define SWAP_IN_RELOC_OFFSET H_GET_32
91: #define SWAP_OUT_RELOC_OFFSET H_PUT_32
92: #define SWAP_OUT_RELOC_EXTRA(abfd, src, dst) \
93: dst->r_stuff[0] = 'S'; \
94: dst->r_stuff[1] = 'C';
95:
96:
97:
98: static void
99: rtype2howto (internal, dst)
100: arelent * internal;
101: struct internal_reloc *dst;
102: {
103: switch (dst->r_type)
104: {
105: default:
106: abort ();
107: break;
108: case R_H8500_IMM8:
109: internal->howto = &r_imm8;
110: break;
111: case R_H8500_IMM16:
112: internal->howto = &r_imm16;
113: break;
114: case R_H8500_IMM24:
115: internal->howto = &r_imm24;
116: break;
117: case R_H8500_IMM32:
118: internal->howto = &r_imm32;
119: break;
120: case R_H8500_PCREL8:
121: internal->howto = &r_pcrel8;
122: break;
123: case R_H8500_PCREL16:
124: internal->howto = &r_pcrel16;
125: break;
126: case R_H8500_HIGH8:
127: internal->howto = &r_high8;
128: break;
129: case R_H8500_HIGH16:
130: internal->howto = &r_high16;
131: break;
132: case R_H8500_LOW16:
133: internal->howto = &r_low16;
134: break;
135: }
136: }
137:
138: #define RTYPE2HOWTO(internal, relocentry) rtype2howto(internal,relocentry)
139:
140:
141:
142: #define CALC_ADDEND(abfd, symbol, ext_reloc, cache_ptr) \
143: cache_ptr->addend = ext_reloc.r_offset;
144:
145: #define RELOC_PROCESSING(relent,reloc,symbols,abfd,section) \
146: reloc_processing(relent, reloc, symbols, abfd, section)
147:
148: static void reloc_processing (relent, reloc, symbols, abfd, section)
149: arelent * relent;
150: struct internal_reloc *reloc;
151: asymbol ** symbols;
152: bfd * abfd;
153: asection * section;
154: {
155: relent->address = reloc->r_vaddr;
156: rtype2howto (relent, reloc);
157:
158: if (reloc->r_symndx > 0)
159: relent->sym_ptr_ptr = symbols + obj_convert (abfd)[reloc->r_symndx];
160: else
161: relent->sym_ptr_ptr = bfd_abs_section_ptr->symbol_ptr_ptr;
162:
163: relent->addend = reloc->r_offset;
164: relent->address -= section->vma;
165: }
166:
167: static void
168: extra_case (in_abfd, link_info, link_order, reloc, data, src_ptr, dst_ptr)
169: bfd *in_abfd;
170: struct bfd_link_info *link_info;
171: struct bfd_link_order *link_order;
172: arelent *reloc;
173: bfd_byte *data;
174: unsigned int *src_ptr;
175: unsigned int *dst_ptr;
176: {
177: bfd_byte *d = data+*dst_ptr;
178: asection *input_section = link_order->u.indirect.section;
179:
180: switch (reloc->howto->type)
181: {
182: case R_H8500_IMM8:
183: bfd_put_8 (in_abfd,
184: bfd_coff_reloc16_get_value (reloc, link_info, input_section),
185: d);
186: (*dst_ptr) += 1;
187: (*src_ptr) += 1;
188: break;
189:
190: case R_H8500_HIGH8:
191: bfd_put_8 (in_abfd,
192: (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
193: >> 16),
194: d);
195: (*dst_ptr) += 1;
196: (*src_ptr) += 1;
197: break;
198:
199: case R_H8500_IMM16:
200: bfd_put_16 (in_abfd,
201: bfd_coff_reloc16_get_value (reloc, link_info, input_section),
202: d);
203: (*dst_ptr) += 2;
204: (*src_ptr) += 2;
205: break;
206:
207: case R_H8500_LOW16:
208: bfd_put_16 (in_abfd,
209: bfd_coff_reloc16_get_value (reloc, link_info, input_section),
210: d);
211:
212: (*dst_ptr) += 2;
213: (*src_ptr) += 2;
214: break;
215:
216: case R_H8500_HIGH16:
217: bfd_put_16 (in_abfd,
218: (bfd_coff_reloc16_get_value (reloc, link_info, input_section)
219: >> 16),
220: d);
221:
222: (*dst_ptr) += 2;
223: (*src_ptr) += 2;
224: break;
225:
226: case R_H8500_IMM24:
227: {
228: int v = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
229: int o = bfd_get_32 (in_abfd, data+ *dst_ptr -1);
230: v = (v & 0x00ffffff) | (o & 0xff00000);
231: bfd_put_32 (in_abfd, (bfd_vma) v, data + *dst_ptr -1);
232: (*dst_ptr) += 3;
233: (*src_ptr) += 3;;
234: }
235: break;
236: case R_H8500_IMM32:
237: {
238: int v = bfd_coff_reloc16_get_value (reloc, link_info, input_section);
239: bfd_put_32 (in_abfd, (bfd_vma) v, data + *dst_ptr);
240: (*dst_ptr) += 4;
241: (*src_ptr) += 4;;
242: }
243: break;
244:
245: case R_H8500_PCREL8:
246: {
247: bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
248: input_section);
249: bfd_vma dot = (*dst_ptr
250: + input_section->output_offset
251: + input_section->output_section->vma);
252: int gap = dst - dot - 1;
253:
254:
255: if (gap > 128 || gap < -128)
256: {
257: if (! ((*link_info->callbacks->reloc_overflow)
258: (link_info, NULL,
259: bfd_asymbol_name (*reloc->sym_ptr_ptr),
260: reloc->howto->name, reloc->addend, input_section->owner,
261: input_section, reloc->address)))
262: abort ();
263: }
264: bfd_put_8 (in_abfd, gap, data + *dst_ptr);
265: (*dst_ptr)++;
266: (*src_ptr)++;
267: break;
268: }
269: case R_H8500_PCREL16:
270: {
271: bfd_vma dst = bfd_coff_reloc16_get_value (reloc, link_info,
272: input_section);
273: bfd_vma dot = (*dst_ptr
274: + input_section->output_offset
275: + input_section->output_section->vma);
276: int gap = dst - dot - 1;
277:
278:
279: if (gap > 32767 || gap < -32768)
280: {
281: if (! ((*link_info->callbacks->reloc_overflow)
282: (link_info, NULL,
283: bfd_asymbol_name (*reloc->sym_ptr_ptr),
284: reloc->howto->name, reloc->addend, input_section->owner,
285: input_section, reloc->address)))
286: abort ();
287: }
288: bfd_put_16 (in_abfd, (bfd_vma) gap, data + *dst_ptr);
289: (*dst_ptr) += 2;
290: (*src_ptr) += 2;
291: break;
292: }
293:
294: default:
295: abort ();
296: }
297: }
298:
299: #define coff_reloc16_extra_cases extra_case
300:
301: #include "coffcode.h"
302:
303: #undef coff_bfd_get_relocated_section_contents
304: #undef coff_bfd_relax_section
305: #define coff_bfd_get_relocated_section_contents \
306: bfd_coff_reloc16_get_relocated_section_contents
307: #define coff_bfd_relax_section bfd_coff_reloc16_relax_section
308:
309: CREATE_BIG_COFF_TARGET_VEC (h8500coff_vec, "coff-h8500", 0, 0, '_', NULL, COFF_SWAP_TABLE)