Commit | Line | Data |
---|---|---|
025b0302 ME |
1 | /* tc-sh.c -- Assemble code for the Hitachi Super-H |
2 | ||
71dd3c40 | 3 | Copyright (C) 1993, 94, 95, 1996 Free Software Foundation. |
025b0302 ME |
4 | |
5 | This file is part of GAS, the GNU Assembler. | |
6 | ||
7 | GAS is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 2, or (at your option) | |
10 | any later version. | |
11 | ||
12 | GAS is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with GAS; see the file COPYING. If not, write to | |
68d04794 JL |
19 | the Free Software Foundation, 59 Temple Place - Suite 330, |
20 | Boston, MA 02111-1307, USA. */ | |
025b0302 ME |
21 | |
22 | /* | |
351efc81 SC |
23 | Written By Steve Chamberlain |
24 | sac@cygnus.com | |
25 | */ | |
025b0302 ME |
26 | |
27 | #include <stdio.h> | |
28 | #include "as.h" | |
29 | #include "bfd.h" | |
30 | #include "subsegs.h" | |
31 | #define DEFINE_TABLE | |
9cc7c60b | 32 | #include "opcodes/sh-opc.h" |
025b0302 | 33 | #include <ctype.h> |
025b0302 ME |
34 | const char comment_chars[] = "!"; |
35 | const char line_separator_chars[] = ";"; | |
d6905776 | 36 | const char line_comment_chars[] = "!#"; |
025b0302 | 37 | |
68d04794 JL |
38 | static void s_uses PARAMS ((int)); |
39 | ||
025b0302 ME |
40 | /* This table describes all the machine specific pseudo-ops the assembler |
41 | has to support. The fields are: | |
42 | pseudo-op name without dot | |
43 | function to call to execute this pseudo-op | |
44 | Integer arg to pass to the function | |
351efc81 | 45 | */ |
025b0302 ME |
46 | |
47 | void cons (); | |
48 | void s_align_bytes (); | |
49 | ||
d6905776 KR |
50 | int shl = 0; |
51 | ||
68d04794 JL |
52 | static void |
53 | little (ignore) | |
54 | int ignore; | |
d6905776 KR |
55 | { |
56 | shl = 1; | |
10c8c95e | 57 | target_big_endian = 0; |
d6905776 KR |
58 | } |
59 | ||
025b0302 ME |
60 | const pseudo_typeS md_pseudo_table[] = |
61 | { | |
62 | {"int", cons, 4}, | |
63 | {"word", cons, 2}, | |
64 | {"form", listing_psize, 0}, | |
68d04794 | 65 | {"little", little, 0}, |
025b0302 ME |
66 | {"heading", listing_title, 0}, |
67 | {"import", s_ignore, 0}, | |
68 | {"page", listing_eject, 0}, | |
69 | {"program", s_ignore, 0}, | |
68d04794 | 70 | {"uses", s_uses, 0}, |
025b0302 ME |
71 | {0, 0, 0} |
72 | }; | |
73 | ||
351efc81 | 74 | /*int md_reloc_size; */ |
025b0302 | 75 | |
68d04794 | 76 | int sh_relax; /* set if -relax seen */ |
025b0302 ME |
77 | |
78 | const char EXP_CHARS[] = "eE"; | |
79 | ||
80 | /* Chars that mean this number is a floating point constant */ | |
81 | /* As in 0f12.456 */ | |
82 | /* or 0d1.2345e12 */ | |
83 | const char FLT_CHARS[] = "rRsSfFdDxXpP"; | |
84 | ||
85 | #define C(a,b) ENCODE_RELAX(a,b) | |
86 | ||
87 | #define JREG 14 /* Register used as a temp when relaxing */ | |
88 | #define ENCODE_RELAX(what,length) (((what) << 4) + (length)) | |
89 | #define GET_WHAT(x) ((x>>4)) | |
90 | ||
91 | /* These are the two types of relaxable instrction */ | |
92 | #define COND_JUMP 1 | |
93 | #define UNCOND_JUMP 2 | |
94 | ||
95 | #define UNDEF_DISP 0 | |
96 | #define COND8 1 | |
97 | #define COND12 2 | |
98 | #define COND32 3 | |
99 | #define UNCOND12 1 | |
100 | #define UNCOND32 2 | |
101 | #define UNDEF_WORD_DISP 4 | |
102 | #define END 5 | |
103 | ||
104 | #define UNCOND12 1 | |
105 | #define UNCOND32 2 | |
106 | ||
68d04794 JL |
107 | /* Branch displacements are from the address of the branch plus |
108 | four, thus all minimum and maximum values have 4 added to them. */ | |
109 | #define COND8_F 258 | |
110 | #define COND8_M -252 | |
025b0302 | 111 | #define COND8_LENGTH 2 |
68d04794 JL |
112 | |
113 | /* There is one extra instruction before the branch, so we must add | |
114 | two more bytes to account for it. */ | |
115 | #define COND12_F 4100 | |
116 | #define COND12_M -4090 | |
025b0302 | 117 | #define COND12_LENGTH 6 |
68d04794 JL |
118 | |
119 | /* ??? The minimum and maximum values are wrong, but this does not matter | |
120 | since this relocation type is not supported yet. */ | |
025b0302 ME |
121 | #define COND32_F (1<<30) |
122 | #define COND32_M -(1<<30) | |
123 | #define COND32_LENGTH 14 | |
124 | ||
68d04794 JL |
125 | #define UNCOND12_F 4098 |
126 | #define UNCOND12_M -4092 | |
025b0302 ME |
127 | #define UNCOND12_LENGTH 2 |
128 | ||
68d04794 JL |
129 | /* ??? The minimum and maximum values are wrong, but this does not matter |
130 | since this relocation type is not supported yet. */ | |
025b0302 ME |
131 | #define UNCOND32_F (1<<30) |
132 | #define UNCOND32_M -(1<<30) | |
133 | #define UNCOND32_LENGTH 14 | |
134 | ||
d6905776 KR |
135 | const relax_typeS md_relax_table[C (END, 0)] = { |
136 | { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, | |
137 | { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, | |
138 | ||
139 | { 0 }, | |
140 | /* C (COND_JUMP, COND8) */ | |
141 | { COND8_F, COND8_M, COND8_LENGTH, C (COND_JUMP, COND12) }, | |
142 | /* C (COND_JUMP, COND12) */ | |
143 | { COND12_F, COND12_M, COND12_LENGTH, C (COND_JUMP, COND32), }, | |
144 | /* C (COND_JUMP, COND32) */ | |
145 | { COND32_F, COND32_M, COND32_LENGTH, 0, }, | |
146 | { 0 }, { 0 }, { 0 }, { 0 }, | |
147 | { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, | |
148 | ||
149 | { 0 }, | |
150 | /* C (UNCOND_JUMP, UNCOND12) */ | |
151 | { UNCOND12_F, UNCOND12_M, UNCOND12_LENGTH, C (UNCOND_JUMP, UNCOND32), }, | |
152 | /* C (UNCOND_JUMP, UNCOND32) */ | |
153 | { UNCOND32_F, UNCOND32_M, UNCOND32_LENGTH, 0, }, | |
154 | { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, | |
155 | { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, | |
156 | }; | |
025b0302 ME |
157 | |
158 | static struct hash_control *opcode_hash_control; /* Opcode mnemonics */ | |
159 | ||
160 | /* | |
351efc81 SC |
161 | This function is called once, at assembler startup time. This should |
162 | set up all the tables, etc that the MD part of the assembler needs | |
163 | */ | |
025b0302 ME |
164 | |
165 | void | |
166 | md_begin () | |
167 | { | |
168 | sh_opcode_info *opcode; | |
169 | char *prev_name = ""; | |
170 | ||
10c8c95e JW |
171 | if (! shl) |
172 | target_big_endian = 1; | |
173 | ||
025b0302 ME |
174 | opcode_hash_control = hash_new (); |
175 | ||
176 | /* Insert unique names into hash table */ | |
177 | for (opcode = sh_table; opcode->name; opcode++) | |
178 | { | |
179 | if (strcmp (prev_name, opcode->name)) | |
180 | { | |
181 | prev_name = opcode->name; | |
182 | hash_insert (opcode_hash_control, opcode->name, (char *) opcode); | |
183 | } | |
184 | else | |
185 | { | |
186 | /* Make all the opcodes with the same name point to the same | |
351efc81 | 187 | string */ |
025b0302 ME |
188 | opcode->name = prev_name; |
189 | } | |
190 | } | |
025b0302 ME |
191 | } |
192 | ||
193 | static int reg_m; | |
194 | static int reg_n; | |
10c8c95e JW |
195 | static int reg_b; |
196 | ||
025b0302 ME |
197 | static expressionS immediate; /* absolute expression */ |
198 | ||
199 | typedef struct | |
351efc81 SC |
200 | { |
201 | sh_arg_type type; | |
202 | int reg; | |
203 | } | |
025b0302 ME |
204 | |
205 | sh_operand_info; | |
206 | ||
207 | /* try and parse a reg name, returns number of chars consumed */ | |
208 | static int | |
209 | parse_reg (src, mode, reg) | |
210 | char *src; | |
211 | int *mode; | |
212 | int *reg; | |
213 | { | |
9addcbb1 ILT |
214 | /* We use !isalnum for the next character after the register name, to |
215 | make sure that we won't accidentally recognize a symbol name such as | |
216 | 'sram' as being a reference to the register 'sr'. */ | |
217 | ||
218 | if (src[0] == 'r') | |
10c8c95e | 219 | { |
9addcbb1 ILT |
220 | if (src[1] >= '0' && src[1] <= '7' && strncmp(&src[2], "_bank", 5) == 0 |
221 | && ! isalnum (src[7])) | |
10c8c95e JW |
222 | { |
223 | *mode = A_REG_B; | |
224 | *reg = (src[1] - '0'); | |
225 | return 7; | |
226 | } | |
227 | } | |
228 | ||
025b0302 ME |
229 | if (src[0] == 'r') |
230 | { | |
231 | if (src[1] == '1') | |
232 | { | |
9addcbb1 | 233 | if (src[2] >= '0' && src[2] <= '5' && ! isalnum (src[3])) |
025b0302 ME |
234 | { |
235 | *mode = A_REG_N; | |
236 | *reg = 10 + src[2] - '0'; | |
237 | return 3; | |
238 | } | |
239 | } | |
9addcbb1 | 240 | if (src[1] >= '0' && src[1] <= '9' && ! isalnum (src[2])) |
025b0302 ME |
241 | { |
242 | *mode = A_REG_N; | |
243 | *reg = (src[1] - '0'); | |
244 | return 2; | |
245 | } | |
246 | } | |
247 | ||
9addcbb1 | 248 | if (src[0] == 's' && src[1] == 's' && src[2] == 'r' && ! isalnum (src[3])) |
10c8c95e JW |
249 | { |
250 | *mode = A_SSR; | |
251 | return 3; | |
252 | } | |
253 | ||
9addcbb1 | 254 | if (src[0] == 's' && src[1] == 'p' && src[2] == 'c' && ! isalnum (src[3])) |
10c8c95e JW |
255 | { |
256 | *mode = A_SPC; | |
257 | return 3; | |
258 | } | |
259 | ||
9addcbb1 | 260 | if (src[0] == 's' && src[1] == 'r' && ! isalnum (src[2])) |
025b0302 ME |
261 | { |
262 | *mode = A_SR; | |
263 | return 2; | |
264 | } | |
265 | ||
9addcbb1 | 266 | if (src[0] == 's' && src[1] == 'p' && ! isalnum (src[2])) |
025b0302 ME |
267 | { |
268 | *mode = A_REG_N; | |
269 | *reg = 15; | |
270 | return 2; | |
271 | } | |
272 | ||
9addcbb1 | 273 | if (src[0] == 'p' && src[1] == 'r' && ! isalnum (src[2])) |
025b0302 ME |
274 | { |
275 | *mode = A_PR; | |
276 | return 2; | |
277 | } | |
9addcbb1 | 278 | if (src[0] == 'p' && src[1] == 'c' && ! isalnum (src[2])) |
025b0302 ME |
279 | { |
280 | *mode = A_DISP_PC; | |
281 | return 2; | |
282 | } | |
9addcbb1 | 283 | if (src[0] == 'g' && src[1] == 'b' && src[2] == 'r' && ! isalnum (src[3])) |
025b0302 ME |
284 | { |
285 | *mode = A_GBR; | |
286 | return 3; | |
287 | } | |
9addcbb1 | 288 | if (src[0] == 'v' && src[1] == 'b' && src[2] == 'r' && ! isalnum (src[3])) |
025b0302 ME |
289 | { |
290 | *mode = A_VBR; | |
291 | return 3; | |
292 | } | |
293 | ||
9addcbb1 | 294 | if (src[0] == 'm' && src[1] == 'a' && src[2] == 'c' && ! isalnum (src[4])) |
025b0302 ME |
295 | { |
296 | if (src[3] == 'l') | |
297 | { | |
298 | *mode = A_MACL; | |
299 | return 4; | |
300 | } | |
301 | if (src[3] == 'h') | |
302 | { | |
303 | *mode = A_MACH; | |
304 | return 4; | |
305 | } | |
306 | } | |
68d04794 JL |
307 | if (src[0] == 'f' && src[1] == 'r') |
308 | { | |
309 | if (src[2] == '1') | |
310 | { | |
9addcbb1 | 311 | if (src[3] >= '0' && src[3] <= '5' && ! isalnum (src[4])) |
68d04794 JL |
312 | { |
313 | *mode = F_REG_N; | |
314 | *reg = 10 + src[3] - '0'; | |
315 | return 4; | |
316 | } | |
317 | } | |
9addcbb1 | 318 | if (src[2] >= '0' && src[2] <= '9' && ! isalnum (src[3])) |
68d04794 JL |
319 | { |
320 | *mode = F_REG_N; | |
321 | *reg = (src[2] - '0'); | |
322 | return 3; | |
323 | } | |
324 | } | |
9addcbb1 ILT |
325 | if (src[0] == 'f' && src[1] == 'p' && src[2] == 'u' && src[3] == 'l' |
326 | && ! isalnum (src[4])) | |
68d04794 JL |
327 | { |
328 | *mode = FPUL_N; | |
329 | return 4; | |
330 | } | |
331 | ||
9addcbb1 ILT |
332 | if (src[0] == 'f' && src[1] == 'p' && src[2] == 's' && src[3] == 'c' |
333 | && src[4] == 'r' && ! isalnum (src[5])) | |
68d04794 JL |
334 | { |
335 | *mode = FPSCR_N; | |
336 | return 5; | |
337 | } | |
025b0302 ME |
338 | |
339 | return 0; | |
340 | } | |
341 | ||
351efc81 SC |
342 | static symbolS *dot() |
343 | { | |
344 | const char *fake; | |
345 | ||
346 | /* JF: '.' is pseudo symbol with value of current location | |
347 | in current segment. */ | |
348 | fake = FAKE_LABEL_NAME; | |
349 | return symbol_new (fake, | |
350 | now_seg, | |
351 | (valueT) frag_now_fix (), | |
352 | frag_now); | |
353 | ||
354 | } | |
355 | ||
356 | ||
025b0302 ME |
357 | static |
358 | char * | |
359 | parse_exp (s) | |
360 | char *s; | |
361 | { | |
362 | char *save; | |
363 | char *new; | |
025b0302 ME |
364 | |
365 | save = input_line_pointer; | |
025b0302 | 366 | input_line_pointer = s; |
351efc81 SC |
367 | expression (&immediate); |
368 | if (immediate.X_op == O_absent) | |
369 | as_bad ("missing operand"); | |
025b0302 ME |
370 | new = input_line_pointer; |
371 | input_line_pointer = save; | |
351efc81 | 372 | return new; |
025b0302 ME |
373 | } |
374 | ||
375 | ||
376 | /* The many forms of operand: | |
377 | ||
351efc81 SC |
378 | Rn Register direct |
379 | @Rn Register indirect | |
380 | @Rn+ Autoincrement | |
381 | @-Rn Autodecrement | |
025b0302 ME |
382 | @(disp:4,Rn) |
383 | @(disp:8,GBR) | |
384 | @(disp:8,PC) | |
385 | ||
386 | @(R0,Rn) | |
387 | @(R0,GBR) | |
388 | ||
389 | disp:8 | |
390 | disp:12 | |
391 | #imm8 | |
392 | pr, gbr, vbr, macl, mach | |
393 | ||
394 | */ | |
395 | ||
396 | static | |
397 | char * | |
398 | parse_at (src, op) | |
399 | char *src; | |
400 | sh_operand_info *op; | |
401 | { | |
402 | int len; | |
403 | int mode; | |
404 | src++; | |
405 | if (src[0] == '-') | |
406 | { | |
407 | /* Must be predecrement */ | |
408 | src++; | |
409 | ||
410 | len = parse_reg (src, &mode, &(op->reg)); | |
411 | if (mode != A_REG_N) | |
412 | as_bad ("illegal register after @-"); | |
413 | ||
414 | op->type = A_DEC_N; | |
415 | src += len; | |
416 | } | |
417 | else if (src[0] == '(') | |
418 | { | |
419 | /* Could be @(disp, rn), @(disp, gbr), @(disp, pc), @(r0, gbr) or | |
351efc81 | 420 | @(r0, rn) */ |
025b0302 ME |
421 | src++; |
422 | len = parse_reg (src, &mode, &(op->reg)); | |
423 | if (len && mode == A_REG_N) | |
424 | { | |
425 | src += len; | |
426 | if (op->reg != 0) | |
427 | { | |
428 | as_bad ("must be @(r0,...)"); | |
429 | } | |
430 | if (src[0] == ',') | |
431 | src++; | |
432 | /* Now can be rn or gbr */ | |
433 | len = parse_reg (src, &mode, &(op->reg)); | |
434 | if (mode == A_GBR) | |
435 | { | |
436 | op->type = A_R0_GBR; | |
437 | } | |
438 | else if (mode == A_REG_N) | |
439 | { | |
440 | op->type = A_IND_R0_REG_N; | |
441 | } | |
442 | else | |
443 | { | |
444 | as_bad ("syntax error in @(r0,...)"); | |
445 | } | |
446 | } | |
447 | else | |
448 | { | |
449 | /* Must be an @(disp,.. thing) */ | |
450 | src = parse_exp (src); | |
451 | if (src[0] == ',') | |
452 | src++; | |
453 | /* Now can be rn, gbr or pc */ | |
454 | len = parse_reg (src, &mode, &op->reg); | |
455 | if (len) | |
456 | { | |
457 | if (mode == A_REG_N) | |
458 | { | |
459 | op->type = A_DISP_REG_N; | |
460 | } | |
461 | else if (mode == A_GBR) | |
462 | { | |
463 | op->type = A_DISP_GBR; | |
464 | } | |
465 | else if (mode == A_DISP_PC) | |
466 | { | |
351efc81 SC |
467 | /* Turn a plain @(4,pc) into @(.+4,pc) */ |
468 | if (immediate.X_op == O_constant) { | |
469 | immediate.X_add_symbol = dot(); | |
470 | immediate.X_op = O_symbol; | |
471 | } | |
025b0302 ME |
472 | op->type = A_DISP_PC; |
473 | } | |
474 | else | |
475 | { | |
476 | as_bad ("syntax error in @(disp,[Rn, gbr, pc])"); | |
477 | } | |
478 | } | |
479 | else | |
480 | { | |
481 | as_bad ("syntax error in @(disp,[Rn, gbr, pc])"); | |
482 | } | |
483 | } | |
484 | src += len; | |
485 | if (src[0] != ')') | |
486 | as_bad ("expecting )"); | |
487 | else | |
488 | src++; | |
489 | } | |
490 | else | |
491 | { | |
492 | src += parse_reg (src, &mode, &(op->reg)); | |
493 | if (mode != A_REG_N) | |
494 | { | |
495 | as_bad ("illegal register after @"); | |
496 | } | |
497 | if (src[0] == '+') | |
498 | { | |
499 | op->type = A_INC_N; | |
500 | src++; | |
501 | } | |
502 | else | |
503 | { | |
504 | op->type = A_IND_N; | |
505 | } | |
506 | } | |
507 | return src; | |
508 | } | |
509 | ||
510 | static void | |
511 | get_operand (ptr, op) | |
512 | char **ptr; | |
513 | sh_operand_info *op; | |
514 | { | |
515 | char *src = *ptr; | |
516 | int mode = -1; | |
517 | unsigned int len; | |
518 | ||
519 | if (src[0] == '#') | |
520 | { | |
521 | src++; | |
522 | *ptr = parse_exp (src); | |
523 | op->type = A_IMM; | |
524 | return; | |
525 | } | |
526 | ||
527 | else if (src[0] == '@') | |
528 | { | |
529 | *ptr = parse_at (src, op); | |
530 | return; | |
531 | } | |
532 | len = parse_reg (src, &mode, &(op->reg)); | |
533 | if (len) | |
534 | { | |
535 | *ptr = src + len; | |
536 | op->type = mode; | |
537 | return; | |
538 | } | |
539 | else | |
540 | { | |
541 | /* Not a reg, the only thing left is a displacement */ | |
542 | *ptr = parse_exp (src); | |
543 | op->type = A_DISP_PC; | |
544 | return; | |
545 | } | |
546 | } | |
547 | ||
548 | static | |
549 | char * | |
550 | get_operands (info, args, operand) | |
551 | sh_opcode_info *info; | |
552 | char *args; | |
553 | sh_operand_info *operand; | |
554 | ||
555 | { | |
556 | char *ptr = args; | |
557 | if (info->arg[0]) | |
558 | { | |
559 | ptr++; | |
560 | ||
561 | get_operand (&ptr, operand + 0); | |
562 | if (info->arg[1]) | |
563 | { | |
564 | if (*ptr == ',') | |
565 | { | |
566 | ptr++; | |
567 | } | |
568 | get_operand (&ptr, operand + 1); | |
10c8c95e JW |
569 | if (info->arg[2]) |
570 | { | |
571 | if (*ptr == ',') | |
572 | { | |
573 | ptr++; | |
574 | } | |
575 | get_operand (&ptr, operand + 2); | |
576 | } | |
577 | else | |
578 | { | |
579 | operand[2].type = 0; | |
580 | } | |
025b0302 ME |
581 | } |
582 | else | |
583 | { | |
584 | operand[1].type = 0; | |
10c8c95e | 585 | operand[2].type = 0; |
025b0302 ME |
586 | } |
587 | } | |
588 | else | |
589 | { | |
590 | operand[0].type = 0; | |
591 | operand[1].type = 0; | |
10c8c95e | 592 | operand[2].type = 0; |
025b0302 ME |
593 | } |
594 | return ptr; | |
595 | } | |
596 | ||
597 | /* Passed a pointer to a list of opcodes which use different | |
598 | addressing modes, return the opcode which matches the opcodes | |
599 | provided | |
351efc81 | 600 | */ |
025b0302 ME |
601 | |
602 | static | |
603 | sh_opcode_info * | |
604 | get_specific (opcode, operands) | |
605 | sh_opcode_info *opcode; | |
606 | sh_operand_info *operands; | |
607 | { | |
608 | sh_opcode_info *this_try = opcode; | |
609 | char *name = opcode->name; | |
025b0302 ME |
610 | int n = 0; |
611 | while (opcode->name) | |
612 | { | |
613 | this_try = opcode++; | |
614 | if (this_try->name != name) | |
615 | { | |
616 | /* We've looked so far down the table that we've run out of | |
617 | opcodes with the same name */ | |
618 | return 0; | |
619 | } | |
620 | /* look at both operands needed by the opcodes and provided by | |
351efc81 SC |
621 | the user - since an arg test will often fail on the same arg |
622 | again and again, we'll try and test the last failing arg the | |
623 | first on each opcode try */ | |
025b0302 ME |
624 | |
625 | for (n = 0; this_try->arg[n]; n++) | |
626 | { | |
10c8c95e JW |
627 | sh_operand_info *user = operands + n; |
628 | sh_arg_type arg = this_try->arg[n]; | |
025b0302 ME |
629 | switch (arg) |
630 | { | |
631 | case A_IMM: | |
632 | case A_BDISP12: | |
633 | case A_BDISP8: | |
634 | case A_DISP_GBR: | |
635 | case A_DISP_PC: | |
636 | case A_MACH: | |
637 | case A_PR: | |
638 | case A_MACL: | |
639 | if (user->type != arg) | |
640 | goto fail; | |
641 | break; | |
642 | case A_R0: | |
643 | /* opcode needs r0 */ | |
644 | if (user->type != A_REG_N || user->reg != 0) | |
645 | goto fail; | |
646 | break; | |
647 | case A_R0_GBR: | |
648 | if (user->type != A_R0_GBR || user->reg != 0) | |
649 | goto fail; | |
650 | break; | |
10c8c95e JW |
651 | case F_FR0: |
652 | if (user->type != F_REG_N || user->reg != 0) | |
653 | goto fail; | |
654 | break; | |
025b0302 ME |
655 | |
656 | case A_REG_N: | |
657 | case A_INC_N: | |
658 | case A_DEC_N: | |
659 | case A_IND_N: | |
660 | case A_IND_R0_REG_N: | |
661 | case A_DISP_REG_N: | |
68d04794 JL |
662 | case F_REG_N: |
663 | case FPUL_N: | |
664 | case FPSCR_N: | |
025b0302 ME |
665 | /* Opcode needs rn */ |
666 | if (user->type != arg) | |
667 | goto fail; | |
668 | reg_n = user->reg; | |
669 | break; | |
670 | case A_GBR: | |
671 | case A_SR: | |
672 | case A_VBR: | |
10c8c95e JW |
673 | case A_SSR: |
674 | case A_SPC: | |
025b0302 ME |
675 | if (user->type != arg) |
676 | goto fail; | |
677 | break; | |
678 | ||
10c8c95e JW |
679 | case A_REG_B: |
680 | if (user->type != arg) | |
681 | goto fail; | |
682 | reg_b = user->reg; | |
683 | break; | |
684 | ||
025b0302 ME |
685 | case A_REG_M: |
686 | case A_INC_M: | |
687 | case A_DEC_M: | |
688 | case A_IND_M: | |
689 | case A_IND_R0_REG_M: | |
690 | case A_DISP_REG_M: | |
691 | /* Opcode needs rn */ | |
692 | if (user->type != arg - A_REG_M + A_REG_N) | |
693 | goto fail; | |
694 | reg_m = user->reg; | |
695 | break; | |
68d04794 | 696 | |
68d04794 JL |
697 | case F_REG_M: |
698 | case FPUL_M: | |
699 | case FPSCR_M: | |
700 | /* Opcode needs rn */ | |
701 | if (user->type != arg - F_REG_M + F_REG_N) | |
702 | goto fail; | |
703 | reg_m = user->reg; | |
704 | break; | |
68d04794 | 705 | |
025b0302 ME |
706 | default: |
707 | printf ("unhandled %d\n", arg); | |
708 | goto fail; | |
709 | } | |
025b0302 ME |
710 | } |
711 | return this_try; | |
712 | fail:; | |
713 | } | |
714 | ||
715 | return 0; | |
716 | } | |
717 | ||
718 | int | |
719 | check (operand, low, high) | |
720 | expressionS *operand; | |
721 | int low; | |
722 | int high; | |
723 | { | |
351efc81 | 724 | if (operand->X_op != O_constant |
025b0302 ME |
725 | || operand->X_add_number < low |
726 | || operand->X_add_number > high) | |
727 | { | |
728 | as_bad ("operand must be absolute in range %d..%d", low, high); | |
729 | } | |
730 | return operand->X_add_number; | |
731 | } | |
732 | ||
733 | ||
734 | static void | |
735 | insert (where, how, pcrel) | |
736 | char *where; | |
737 | int how; | |
738 | int pcrel; | |
739 | { | |
351efc81 SC |
740 | fix_new_exp (frag_now, |
741 | where - frag_now->fr_literal, | |
68d04794 | 742 | 2, |
351efc81 SC |
743 | &immediate, |
744 | pcrel, | |
745 | how); | |
025b0302 ME |
746 | } |
747 | ||
748 | static void | |
749 | build_relax (opcode) | |
750 | sh_opcode_info *opcode; | |
751 | { | |
10c8c95e | 752 | int high_byte = target_big_endian ? 0 : 1; |
025b0302 | 753 | char *p; |
d6905776 | 754 | |
025b0302 ME |
755 | if (opcode->arg[0] == A_BDISP8) |
756 | { | |
757 | p = frag_var (rs_machine_dependent, | |
758 | md_relax_table[C (COND_JUMP, COND32)].rlx_length, | |
68d04794 | 759 | md_relax_table[C (COND_JUMP, COND8)].rlx_length, |
025b0302 ME |
760 | C (COND_JUMP, 0), |
761 | immediate.X_add_symbol, | |
762 | immediate.X_add_number, | |
763 | 0); | |
d6905776 | 764 | p[high_byte] = (opcode->nibbles[0] << 4) | (opcode->nibbles[1]); |
025b0302 ME |
765 | } |
766 | else if (opcode->arg[0] == A_BDISP12) | |
767 | { | |
768 | p = frag_var (rs_machine_dependent, | |
769 | md_relax_table[C (UNCOND_JUMP, UNCOND32)].rlx_length, | |
68d04794 | 770 | md_relax_table[C (UNCOND_JUMP, UNCOND12)].rlx_length, |
025b0302 ME |
771 | C (UNCOND_JUMP, 0), |
772 | immediate.X_add_symbol, | |
773 | immediate.X_add_number, | |
774 | 0); | |
d6905776 | 775 | p[high_byte] = (opcode->nibbles[0] << 4); |
025b0302 ME |
776 | } |
777 | ||
778 | } | |
779 | ||
780 | /* Now we know what sort of opcodes it is, lets build the bytes - | |
781 | */ | |
782 | static void | |
783 | build_Mytes (opcode, operand) | |
784 | sh_opcode_info *opcode; | |
785 | sh_operand_info *operand; | |
786 | ||
787 | { | |
788 | int index; | |
789 | char nbuf[4]; | |
790 | char *output = frag_more (2); | |
10c8c95e | 791 | int low_byte = target_big_endian ? 1 : 0; |
025b0302 ME |
792 | nbuf[0] = 0; |
793 | nbuf[1] = 0; | |
794 | nbuf[2] = 0; | |
795 | nbuf[3] = 0; | |
796 | ||
797 | for (index = 0; index < 4; index++) | |
798 | { | |
799 | sh_nibble_type i = opcode->nibbles[index]; | |
800 | if (i < 16) | |
801 | { | |
802 | nbuf[index] = i; | |
803 | } | |
804 | else | |
805 | { | |
806 | switch (i) | |
807 | { | |
808 | case REG_N: | |
809 | nbuf[index] = reg_n; | |
810 | break; | |
811 | case REG_M: | |
812 | nbuf[index] = reg_m; | |
813 | break; | |
10c8c95e JW |
814 | case REG_B: |
815 | nbuf[index] = reg_b | 0x08; | |
816 | break; | |
025b0302 | 817 | case DISP_4: |
d6905776 | 818 | insert (output + low_byte, R_SH_IMM4, 0); |
025b0302 ME |
819 | break; |
820 | case IMM_4BY4: | |
d6905776 | 821 | insert (output + low_byte, R_SH_IMM4BY4, 0); |
025b0302 ME |
822 | break; |
823 | case IMM_4BY2: | |
d6905776 | 824 | insert (output + low_byte, R_SH_IMM4BY2, 0); |
025b0302 ME |
825 | break; |
826 | case IMM_4: | |
d6905776 | 827 | insert (output + low_byte, R_SH_IMM4, 0); |
025b0302 ME |
828 | break; |
829 | case IMM_8BY4: | |
d6905776 | 830 | insert (output + low_byte, R_SH_IMM8BY4, 0); |
025b0302 ME |
831 | break; |
832 | case IMM_8BY2: | |
d6905776 | 833 | insert (output + low_byte, R_SH_IMM8BY2, 0); |
025b0302 ME |
834 | break; |
835 | case IMM_8: | |
d6905776 | 836 | insert (output + low_byte, R_SH_IMM8, 0); |
025b0302 ME |
837 | break; |
838 | case PCRELIMM_8BY4: | |
d6905776 | 839 | insert (output, R_SH_PCRELIMM8BY4, 1); |
025b0302 ME |
840 | break; |
841 | case PCRELIMM_8BY2: | |
d6905776 | 842 | insert (output, R_SH_PCRELIMM8BY2, 1); |
025b0302 ME |
843 | break; |
844 | default: | |
845 | printf ("failed for %d\n", i); | |
846 | } | |
847 | } | |
848 | } | |
10c8c95e | 849 | if (! target_big_endian) { |
d6905776 KR |
850 | output[1] = (nbuf[0] << 4) | (nbuf[1]); |
851 | output[0] = (nbuf[2] << 4) | (nbuf[3]); | |
852 | } | |
853 | else { | |
854 | output[0] = (nbuf[0] << 4) | (nbuf[1]); | |
855 | output[1] = (nbuf[2] << 4) | (nbuf[3]); | |
856 | } | |
025b0302 ME |
857 | } |
858 | ||
859 | /* This is the guts of the machine-dependent assembler. STR points to a | |
860 | machine dependent instruction. This function is supposed to emit | |
861 | the frags/bytes it assembles to. | |
351efc81 | 862 | */ |
025b0302 ME |
863 | |
864 | void | |
865 | md_assemble (str) | |
866 | char *str; | |
867 | { | |
868 | unsigned char *op_start; | |
869 | unsigned char *op_end; | |
10c8c95e | 870 | sh_operand_info operand[3]; |
025b0302 | 871 | sh_opcode_info *opcode; |
351efc81 | 872 | char name[20]; |
025b0302 | 873 | int nlen = 0; |
025b0302 ME |
874 | /* Drop leading whitespace */ |
875 | while (*str == ' ') | |
876 | str++; | |
877 | ||
878 | /* find the op code end */ | |
351efc81 SC |
879 | for (op_start = op_end = (unsigned char *) (str); |
880 | *op_end | |
881 | && nlen < 20 | |
882 | && !is_end_of_line[*op_end] && *op_end != ' '; | |
025b0302 ME |
883 | op_end++) |
884 | { | |
351efc81 | 885 | name[nlen] = op_start[nlen]; |
025b0302 ME |
886 | nlen++; |
887 | } | |
888 | name[nlen] = 0; | |
889 | ||
351efc81 | 890 | if (nlen == 0) |
025b0302 ME |
891 | { |
892 | as_bad ("can't find opcode "); | |
893 | } | |
894 | ||
895 | opcode = (sh_opcode_info *) hash_find (opcode_hash_control, name); | |
896 | ||
897 | if (opcode == NULL) | |
898 | { | |
899 | as_bad ("unknown opcode"); | |
900 | return; | |
901 | } | |
902 | ||
bccbc0aa ILT |
903 | if (sh_relax |
904 | && ! seg_info (now_seg)->tc_segment_info_data.in_code) | |
905 | { | |
906 | /* Output a CODE reloc to tell the linker that the following | |
907 | bytes are instructions, not data. */ | |
908 | fix_new (frag_now, frag_now_fix (), 2, &abs_symbol, 0, 0, R_SH_CODE); | |
909 | seg_info (now_seg)->tc_segment_info_data.in_code = 1; | |
910 | } | |
911 | ||
025b0302 ME |
912 | if (opcode->arg[0] == A_BDISP12 |
913 | || opcode->arg[0] == A_BDISP8) | |
914 | { | |
351efc81 | 915 | parse_exp (op_end + 1); |
025b0302 ME |
916 | build_relax (opcode); |
917 | } | |
918 | else | |
919 | { | |
351efc81 SC |
920 | if (opcode->arg[0] != A_END) |
921 | { | |
922 | get_operands (opcode, op_end, operand); | |
923 | } | |
025b0302 ME |
924 | opcode = get_specific (opcode, operand); |
925 | ||
926 | if (opcode == 0) | |
927 | { | |
928 | /* Couldn't find an opcode which matched the operands */ | |
929 | char *where = frag_more (2); | |
930 | ||
931 | where[0] = 0x0; | |
932 | where[1] = 0x0; | |
933 | as_bad ("invalid operands for opcode"); | |
934 | return; | |
935 | } | |
936 | ||
937 | build_Mytes (opcode, operand); | |
938 | } | |
939 | ||
940 | } | |
941 | ||
bccbc0aa ILT |
942 | /* This routine is called each time a label definition is seen. It |
943 | emits a R_SH_LABEL reloc if necessary. */ | |
944 | ||
945 | void | |
946 | sh_frob_label () | |
947 | { | |
948 | if (sh_relax | |
949 | && seg_info (now_seg)->tc_segment_info_data.in_code) | |
950 | fix_new (frag_now, frag_now_fix (), 2, &abs_symbol, 0, 0, R_SH_LABEL); | |
951 | } | |
952 | ||
953 | /* This routine is called when the assembler is about to output some | |
954 | data. It emits a R_SH_DATA reloc if necessary. */ | |
955 | ||
956 | void | |
957 | sh_flush_pending_output () | |
958 | { | |
959 | if (sh_relax | |
960 | && seg_info (now_seg)->tc_segment_info_data.in_code) | |
961 | { | |
962 | fix_new (frag_now, frag_now_fix (), 2, &abs_symbol, 0, 0, R_SH_DATA); | |
963 | seg_info (now_seg)->tc_segment_info_data.in_code = 0; | |
964 | } | |
965 | } | |
966 | ||
025b0302 ME |
967 | void |
968 | DEFUN (tc_crawl_symbol_chain, (headers), | |
969 | object_headers * headers) | |
970 | { | |
971 | printf ("call to tc_crawl_symbol_chain \n"); | |
972 | } | |
973 | ||
974 | symbolS * | |
975 | DEFUN (md_undefined_symbol, (name), | |
976 | char *name) | |
977 | { | |
978 | return 0; | |
979 | } | |
980 | ||
981 | void | |
982 | DEFUN (tc_headers_hook, (headers), | |
983 | object_headers * headers) | |
984 | { | |
985 | printf ("call to tc_headers_hook \n"); | |
986 | } | |
987 | ||
025b0302 ME |
988 | /* Various routines to kill one day */ |
989 | /* Equal to MAX_PRECISION in atof-ieee.c */ | |
990 | #define MAX_LITTLENUMS 6 | |
991 | ||
992 | /* Turn a string in input_line_pointer into a floating point constant of type | |
993 | type, and store the appropriate bytes in *litP. The number of LITTLENUMS | |
994 | emitted is stored in *sizeP . An error message is returned, or NULL on OK. | |
351efc81 | 995 | */ |
025b0302 ME |
996 | char * |
997 | md_atof (type, litP, sizeP) | |
d6905776 | 998 | int type; |
025b0302 ME |
999 | char *litP; |
1000 | int *sizeP; | |
1001 | { | |
1002 | int prec; | |
d6905776 | 1003 | LITTLENUM_TYPE words[4]; |
025b0302 | 1004 | char *t; |
d6905776 | 1005 | int i; |
025b0302 ME |
1006 | |
1007 | switch (type) | |
1008 | { | |
1009 | case 'f': | |
025b0302 ME |
1010 | prec = 2; |
1011 | break; | |
1012 | ||
1013 | case 'd': | |
025b0302 ME |
1014 | prec = 4; |
1015 | break; | |
1016 | ||
025b0302 ME |
1017 | default: |
1018 | *sizeP = 0; | |
d6905776 | 1019 | return "bad call to md_atof"; |
025b0302 | 1020 | } |
d6905776 | 1021 | |
025b0302 ME |
1022 | t = atof_ieee (input_line_pointer, type, words); |
1023 | if (t) | |
1024 | input_line_pointer = t; | |
1025 | ||
d6905776 KR |
1026 | *sizeP = prec * 2; |
1027 | ||
10c8c95e | 1028 | if (! target_big_endian) |
025b0302 | 1029 | { |
d6905776 KR |
1030 | for (i = prec - 1; i >= 0; i--) |
1031 | { | |
1032 | md_number_to_chars (litP, (valueT) words[i], 2); | |
1033 | litP += 2; | |
1034 | } | |
025b0302 | 1035 | } |
d6905776 KR |
1036 | else |
1037 | { | |
1038 | for (i = 0; i < prec; i++) | |
1039 | { | |
1040 | md_number_to_chars (litP, (valueT) words[i], 2); | |
1041 | litP += 2; | |
1042 | } | |
1043 | } | |
1044 | ||
1045 | return NULL; | |
025b0302 | 1046 | } |
d6905776 | 1047 | |
68d04794 JL |
1048 | /* Handle the .uses pseudo-op. This pseudo-op is used just before a |
1049 | call instruction. It refers to a label of the instruction which | |
1050 | loads the register which the call uses. We use it to generate a | |
1051 | special reloc for the linker. */ | |
1052 | ||
1053 | static void | |
1054 | s_uses (ignore) | |
1055 | int ignore; | |
1056 | { | |
1057 | expressionS ex; | |
1058 | ||
1059 | if (! sh_relax) | |
1060 | as_warn (".uses pseudo-op seen when not relaxing"); | |
1061 | ||
1062 | expression (&ex); | |
1063 | ||
1064 | if (ex.X_op != O_symbol || ex.X_add_number != 0) | |
1065 | { | |
1066 | as_bad ("bad .uses format"); | |
1067 | ignore_rest_of_line (); | |
1068 | return; | |
1069 | } | |
1070 | ||
1071 | fix_new_exp (frag_now, frag_now_fix (), 2, &ex, 1, R_SH_USES); | |
d6905776 | 1072 | |
68d04794 JL |
1073 | demand_empty_rest_of_line (); |
1074 | } | |
351efc81 SC |
1075 | \f |
1076 | CONST char *md_shortopts = ""; | |
1077 | struct option md_longopts[] = { | |
d6905776 KR |
1078 | |
1079 | #define OPTION_RELAX (OPTION_MD_BASE) | |
1080 | #define OPTION_LITTLE (OPTION_MD_BASE+1) | |
1081 | ||
351efc81 | 1082 | {"relax", no_argument, NULL, OPTION_RELAX}, |
d6905776 | 1083 | {"little", no_argument, NULL, OPTION_LITTLE}, |
351efc81 SC |
1084 | {NULL, no_argument, NULL, 0} |
1085 | }; | |
1086 | size_t md_longopts_size = sizeof(md_longopts); | |
025b0302 ME |
1087 | |
1088 | int | |
351efc81 SC |
1089 | md_parse_option (c, arg) |
1090 | int c; | |
1091 | char *arg; | |
025b0302 | 1092 | { |
351efc81 | 1093 | switch (c) |
025b0302 | 1094 | { |
351efc81 | 1095 | case OPTION_RELAX: |
68d04794 | 1096 | sh_relax = 1; |
351efc81 | 1097 | break; |
d6905776 KR |
1098 | case OPTION_LITTLE: |
1099 | shl = 1; | |
10c8c95e | 1100 | target_big_endian = 0; |
d6905776 | 1101 | break; |
351efc81 SC |
1102 | |
1103 | default: | |
1104 | return 0; | |
025b0302 | 1105 | } |
351efc81 | 1106 | |
025b0302 ME |
1107 | return 1; |
1108 | } | |
1109 | ||
351efc81 SC |
1110 | void |
1111 | md_show_usage (stream) | |
1112 | FILE *stream; | |
1113 | { | |
1114 | fprintf(stream, "\ | |
1115 | SH options:\n\ | |
68d04794 | 1116 | -little generate little endian code\n\ |
351efc81 SC |
1117 | -relax alter jump instructions for long displacements\n"); |
1118 | } | |
1119 | \f | |
025b0302 ME |
1120 | int md_short_jump_size; |
1121 | ||
1122 | void | |
1123 | tc_Nout_fix_to_chars () | |
1124 | { | |
1125 | printf ("call to tc_Nout_fix_to_chars \n"); | |
1126 | abort (); | |
1127 | } | |
1128 | ||
1129 | void | |
1130 | md_create_short_jump (ptr, from_Nddr, to_Nddr, frag, to_symbol) | |
1131 | char *ptr; | |
1132 | addressT from_Nddr; | |
1133 | addressT to_Nddr; | |
1134 | fragS *frag; | |
1135 | symbolS *to_symbol; | |
1136 | { | |
1137 | as_fatal ("failed sanity check."); | |
1138 | } | |
1139 | ||
1140 | void | |
1141 | md_create_long_jump (ptr, from_Nddr, to_Nddr, frag, to_symbol) | |
1142 | char *ptr; | |
1143 | addressT from_Nddr, to_Nddr; | |
1144 | fragS *frag; | |
1145 | symbolS *to_symbol; | |
1146 | { | |
1147 | as_fatal ("failed sanity check."); | |
1148 | } | |
1149 | ||
68d04794 JL |
1150 | /* This is function is called after the symbol table has been |
1151 | completed, but before md_convert_frag has been called. If we have | |
1152 | seen any .uses pseudo-ops, they point to an instruction which loads | |
1153 | a register with the address of a function. We look through the | |
1154 | fixups to find where the function address is being loaded from. We | |
1155 | then generate a COUNT reloc giving the number of times that | |
1156 | function address is referred to. The linker uses this information | |
1157 | when doing relaxing, to decide when it can eliminate the stored | |
1158 | function address entirely. */ | |
1159 | ||
1160 | void | |
1161 | sh_coff_frob_file () | |
1162 | { | |
1163 | int iseg; | |
1164 | ||
1165 | if (! sh_relax) | |
1166 | return; | |
1167 | ||
1168 | for (iseg = SEG_E0; iseg < SEG_UNKNOWN; iseg++) | |
1169 | { | |
1170 | fixS *fix; | |
1171 | ||
1172 | for (fix = segment_info[iseg].fix_root; fix != NULL; fix = fix->fx_next) | |
1173 | { | |
1174 | symbolS *sym; | |
1175 | bfd_vma val; | |
68d04794 JL |
1176 | fixS *fscan; |
1177 | int iscan; | |
1178 | int count; | |
1179 | ||
1180 | if (fix->fx_r_type != R_SH_USES) | |
1181 | continue; | |
1182 | ||
1183 | /* The R_SH_USES reloc should refer to a defined local | |
1184 | symbol in the same section. */ | |
1185 | sym = fix->fx_addsy; | |
1186 | if (sym == NULL | |
1187 | || fix->fx_subsy != NULL | |
1188 | || fix->fx_addnumber != 0 | |
1189 | || S_GET_SEGMENT (sym) != iseg | |
1190 | || S_GET_STORAGE_CLASS (sym) == C_EXT) | |
1191 | { | |
1192 | as_warn_where (fix->fx_file, fix->fx_line, | |
1193 | ".uses does not refer to a local symbol in the same section"); | |
1194 | continue; | |
1195 | } | |
1196 | ||
1197 | /* Look through the fixups again, this time looking for one | |
1198 | at the same location as sym. */ | |
1199 | val = S_GET_VALUE (sym); | |
68d04794 JL |
1200 | for (fscan = segment_info[iseg].fix_root; |
1201 | fscan != NULL; | |
1202 | fscan = fscan->fx_next) | |
bccbc0aa ILT |
1203 | if (val == fscan->fx_frag->fr_address + fscan->fx_where |
1204 | && fscan->fx_r_type != R_SH_ALIGN | |
1205 | && fscan->fx_r_type != R_SH_CODE | |
1206 | && fscan->fx_r_type != R_SH_DATA | |
1207 | && fscan->fx_r_type != R_SH_LABEL) | |
68d04794 JL |
1208 | break; |
1209 | if (fscan == NULL) | |
1210 | { | |
1211 | as_warn_where (fix->fx_file, fix->fx_line, | |
1212 | "can't find fixup pointed to by .uses"); | |
1213 | continue; | |
1214 | } | |
1215 | ||
1216 | if (fscan->fx_tcbit) | |
1217 | { | |
1218 | /* We've already done this one. */ | |
1219 | continue; | |
1220 | } | |
1221 | ||
1222 | /* fscan should also be a fixup to a local symbol in the same | |
1223 | section. */ | |
1224 | sym = fscan->fx_addsy; | |
1225 | if (sym == NULL | |
1226 | || fscan->fx_subsy != NULL | |
1227 | || fscan->fx_addnumber != 0 | |
1228 | || S_GET_SEGMENT (sym) != iseg | |
1229 | || S_GET_STORAGE_CLASS (sym) == C_EXT) | |
1230 | { | |
1231 | as_warn_where (fix->fx_file, fix->fx_line, | |
1232 | ".uses target does not refer to a local symbol in the same section"); | |
1233 | continue; | |
1234 | } | |
1235 | ||
1236 | /* Now we look through all the fixups of all the sections, | |
1237 | counting the number of times we find a reference to sym. */ | |
1238 | count = 0; | |
1239 | for (iscan = SEG_E0; iscan < SEG_UNKNOWN; iscan++) | |
1240 | { | |
68d04794 JL |
1241 | for (fscan = segment_info[iscan].fix_root; |
1242 | fscan != NULL; | |
1243 | fscan = fscan->fx_next) | |
1244 | { | |
1245 | if (fscan->fx_addsy == sym) | |
1246 | { | |
1247 | ++count; | |
1248 | fscan->fx_tcbit = 1; | |
1249 | } | |
1250 | } | |
1251 | } | |
1252 | ||
1253 | if (count < 1) | |
1254 | abort (); | |
1255 | ||
1256 | /* Generate a R_SH_COUNT fixup at the location of sym. We | |
1257 | have already adjusted the value of sym to include the | |
1258 | fragment address, so we undo that adjustment here. */ | |
1259 | subseg_change (iseg, 0); | |
1260 | fix_new (sym->sy_frag, S_GET_VALUE (sym) - sym->sy_frag->fr_address, | |
1261 | 4, &abs_symbol, count, 0, R_SH_COUNT); | |
1262 | } | |
1263 | } | |
1264 | } | |
1265 | ||
1266 | /* Called after relaxing. Set the correct sizes of the fragments, and | |
1267 | create relocs so that md_apply_fix will fill in the correct values. */ | |
1268 | ||
025b0302 | 1269 | void |
68d04794 | 1270 | md_convert_frag (headers, seg, fragP) |
025b0302 | 1271 | object_headers *headers; |
68d04794 | 1272 | segT seg; |
025b0302 | 1273 | fragS *fragP; |
025b0302 | 1274 | { |
025b0302 | 1275 | int donerelax = 0; |
68d04794 | 1276 | |
025b0302 ME |
1277 | switch (fragP->fr_subtype) |
1278 | { | |
1279 | case C (COND_JUMP, COND8): | |
68d04794 JL |
1280 | subseg_change (seg, 0); |
1281 | fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset, | |
1282 | 1, R_SH_PCDISP8BY2); | |
1283 | fragP->fr_fix += 2; | |
1284 | fragP->fr_var = 0; | |
025b0302 ME |
1285 | break; |
1286 | ||
1287 | case C (UNCOND_JUMP, UNCOND12): | |
68d04794 JL |
1288 | subseg_change (seg, 0); |
1289 | fix_new (fragP, fragP->fr_fix, 2, fragP->fr_symbol, fragP->fr_offset, | |
1290 | 1, R_SH_PCDISP); | |
1291 | fragP->fr_fix += 2; | |
1292 | fragP->fr_var = 0; | |
025b0302 ME |
1293 | break; |
1294 | ||
1295 | case C (UNCOND_JUMP, UNCOND32): | |
1296 | case C (UNCOND_JUMP, UNDEF_WORD_DISP): | |
68d04794 JL |
1297 | if (fragP->fr_symbol == NULL) |
1298 | as_bad ("at 0x%lx, displacement overflows 12-bit field", | |
1299 | (unsigned long) fragP->fr_address); | |
1300 | else | |
1301 | as_bad ("at 0x%lx, displacement to %sdefined symbol %s overflows 12-bit field", | |
1302 | (unsigned long) fragP->fr_address, | |
1303 | S_IS_DEFINED (fragP->fr_symbol) ? "" : "un", | |
1304 | S_GET_NAME (fragP->fr_symbol)); | |
1305 | ||
1306 | #if 0 /* This code works, but generates poor code and the compiler | |
1307 | should never produce a sequence that requires it to be used. */ | |
1308 | ||
1309 | /* A jump wont fit in 12 bits, make code which looks like | |
1310 | bra foo | |
1311 | mov.w @(0, PC), r14 | |
1312 | .long disp | |
1313 | foo: bra @r14 | |
351efc81 | 1314 | */ |
68d04794 | 1315 | int t = buffer[0] & 0x10; |
025b0302 | 1316 | |
68d04794 JL |
1317 | buffer[highbyte] = 0xa0; /* branch over move and disp */ |
1318 | buffer[lowbyte] = 3; | |
1319 | buffer[highbyte+2] = 0xd0 | JREG; /* Build mov insn */ | |
1320 | buffer[lowbyte+2] = 0x00; | |
1321 | ||
1322 | buffer[highbyte+4] = 0; /* space for 32 bit jump disp */ | |
1323 | buffer[lowbyte+4] = 0; | |
1324 | buffer[highbyte+6] = 0; | |
1325 | buffer[lowbyte+6] = 0; | |
1326 | ||
1327 | buffer[highbyte+8] = 0x40 | JREG; /* Build jmp @JREG */ | |
1328 | buffer[lowbyte+8] = t ? 0xb : 0x2b; | |
1329 | ||
1330 | buffer[highbyte+10] = 0x20; /* build nop */ | |
1331 | buffer[lowbyte+10] = 0x0b; | |
1332 | ||
1333 | /* Make reloc for the long disp */ | |
1334 | fix_new (fragP, | |
1335 | fragP->fr_fix + 4, | |
1336 | 4, | |
1337 | fragP->fr_symbol, | |
1338 | fragP->fr_offset, | |
1339 | 0, | |
1340 | R_SH_IMM32); | |
1341 | fragP->fr_fix += UNCOND32_LENGTH; | |
1342 | fragP->fr_var = 0; | |
1343 | donerelax = 1; | |
1344 | #endif | |
025b0302 | 1345 | |
025b0302 ME |
1346 | break; |
1347 | ||
1348 | case C (COND_JUMP, COND12): | |
68d04794 | 1349 | /* A bcond won't fit, so turn it into a b!cond; bra disp; nop */ |
025b0302 | 1350 | { |
68d04794 JL |
1351 | unsigned char *buffer = |
1352 | (unsigned char *) (fragP->fr_fix + fragP->fr_literal); | |
10c8c95e JW |
1353 | int highbyte = target_big_endian ? 0 : 1; |
1354 | int lowbyte = target_big_endian ? 1 : 0; | |
68d04794 JL |
1355 | |
1356 | /* Toggle the true/false bit of the bcond. */ | |
1357 | buffer[highbyte] ^= 0x2; | |
1358 | ||
1359 | /* Build a relocation to six bytes farther on. */ | |
1360 | subseg_change (seg, 0); | |
1361 | fix_new (fragP, fragP->fr_fix, 2, | |
1362 | segment_info[seg].dot, | |
1363 | fragP->fr_address + fragP->fr_fix + 6, | |
1364 | 1, R_SH_PCDISP8BY2); | |
1365 | ||
1366 | /* Set up a jump instruction. */ | |
1367 | buffer[highbyte + 2] = 0xa0; | |
1368 | buffer[lowbyte + 2] = 0; | |
1369 | fix_new (fragP, fragP->fr_fix + 2, 2, fragP->fr_symbol, | |
1370 | fragP->fr_offset, 1, R_SH_PCDISP); | |
1371 | ||
1372 | /* Fill in a NOP instruction. */ | |
1373 | buffer[highbyte + 4] = 0x0; | |
1374 | buffer[lowbyte + 4] = 0x9; | |
1375 | ||
025b0302 ME |
1376 | fragP->fr_fix += 6; |
1377 | fragP->fr_var = 0; | |
1378 | donerelax = 1; | |
1379 | } | |
1380 | break; | |
1381 | ||
1382 | case C (COND_JUMP, COND32): | |
1383 | case C (COND_JUMP, UNDEF_WORD_DISP): | |
68d04794 | 1384 | if (fragP->fr_symbol == NULL) |
bccbc0aa | 1385 | as_bad ("at 0x%lx, displacement overflows 8-bit field", |
68d04794 JL |
1386 | (unsigned long) fragP->fr_address); |
1387 | else | |
1388 | as_bad ("at 0x%lx, displacement to %sdefined symbol %s overflows 8-bit field ", | |
1389 | (unsigned long) fragP->fr_address, | |
1390 | S_IS_DEFINED (fragP->fr_symbol) ? "" : "un", | |
1391 | S_GET_NAME (fragP->fr_symbol)); | |
1392 | ||
1393 | #if 0 /* This code works, but generates poor code, and the compiler | |
1394 | should never produce a sequence that requires it to be used. */ | |
1395 | ||
1396 | /* A bcond won't fit and it won't go into a 12 bit | |
1397 | displacement either, the code sequence looks like: | |
1398 | b!cond foop | |
1399 | mov.w @(n, PC), r14 | |
1400 | jmp @r14 | |
1401 | nop | |
1402 | .long where | |
1403 | foop: | |
351efc81 | 1404 | */ |
025b0302 | 1405 | |
68d04794 | 1406 | buffer[0] ^= 0x2; /* Toggle T/F bit */ |
025b0302 | 1407 | #define JREG 14 |
68d04794 JL |
1408 | buffer[1] = 5; /* branch over mov, jump, nop and ptr */ |
1409 | buffer[2] = 0xd0 | JREG; /* Build mov insn */ | |
1410 | buffer[3] = 0x2; | |
1411 | buffer[4] = 0x40 | JREG; /* Build jmp @JREG */ | |
1412 | buffer[5] = 0x0b; | |
1413 | buffer[6] = 0x20; /* build nop */ | |
1414 | buffer[7] = 0x0b; | |
1415 | buffer[8] = 0; /* space for 32 bit jump disp */ | |
1416 | buffer[9] = 0; | |
1417 | buffer[10] = 0; | |
1418 | buffer[11] = 0; | |
1419 | buffer[12] = 0; | |
1420 | buffer[13] = 0; | |
1421 | /* Make reloc for the long disp */ | |
1422 | fix_new (fragP, | |
1423 | fragP->fr_fix + 8, | |
1424 | 4, | |
1425 | fragP->fr_symbol, | |
1426 | fragP->fr_offset, | |
1427 | 0, | |
1428 | R_SH_IMM32); | |
1429 | fragP->fr_fix += COND32_LENGTH; | |
1430 | fragP->fr_var = 0; | |
1431 | donerelax = 1; | |
1432 | #endif | |
1433 | ||
025b0302 ME |
1434 | break; |
1435 | ||
1436 | default: | |
1437 | abort (); | |
1438 | } | |
1439 | ||
68d04794 JL |
1440 | if (donerelax && !sh_relax) |
1441 | as_warn ("Offset doesn't fit at 0x%lx, trying to get to %s+0x%lx", | |
1442 | (unsigned long) fragP->fr_address, | |
1443 | fragP->fr_symbol ? S_GET_NAME(fragP->fr_symbol): "", | |
1444 | (unsigned long) fragP->fr_offset); | |
025b0302 ME |
1445 | } |
1446 | ||
1447 | valueT | |
1448 | DEFUN (md_section_align, (seg, size), | |
1449 | segT seg AND | |
1450 | valueT size) | |
1451 | { | |
1452 | return ((size + (1 << section_alignment[(int) seg]) - 1) | |
1453 | & (-1 << section_alignment[(int) seg])); | |
1454 | ||
1455 | } | |
1456 | ||
68d04794 JL |
1457 | /* When relaxing, we need to output a reloc for any .align directive |
1458 | that requests alignment to a four byte boundary or larger. */ | |
1459 | ||
1460 | void | |
1461 | sh_handle_align (frag) | |
1462 | fragS *frag; | |
1463 | { | |
1464 | if (sh_relax | |
1465 | && frag->fr_type == rs_align | |
1466 | && frag->fr_address + frag->fr_fix > 0 | |
8a2e1fdd ILT |
1467 | && frag->fr_offset > 1 |
1468 | && now_seg != bss_section) | |
68d04794 JL |
1469 | fix_new (frag, frag->fr_fix, 2, &abs_symbol, frag->fr_offset, 0, |
1470 | R_SH_ALIGN); | |
1471 | } | |
1472 | ||
1473 | /* This macro decides whether a particular reloc is an entry in a | |
1474 | switch table. It is used when relaxing, because the linker needs | |
1475 | to know about all such entries so that it can adjust them if | |
1476 | necessary. */ | |
1477 | ||
1478 | #define SWITCH_TABLE(fix) \ | |
1479 | ((fix)->fx_addsy != NULL \ | |
1480 | && (fix)->fx_subsy != NULL \ | |
1481 | && S_GET_SEGMENT ((fix)->fx_addsy) == text_section \ | |
1482 | && S_GET_SEGMENT ((fix)->fx_subsy) == text_section \ | |
1483 | && ((fix)->fx_r_type == R_SH_IMM32 \ | |
1484 | || (fix)->fx_r_type == R_SH_IMM16 \ | |
1485 | || ((fix)->fx_r_type == 0 \ | |
1486 | && ((fix)->fx_size == 2 \ | |
1487 | || (fix)->fx_size == 4)))) | |
1488 | ||
1489 | /* See whether we need to force a relocation into the output file. | |
1490 | This is used to force out switch and PC relative relocations when | |
1491 | relaxing. */ | |
1492 | ||
1493 | int | |
1494 | sh_force_relocation (fix) | |
1495 | fixS *fix; | |
1496 | { | |
1497 | if (! sh_relax) | |
1498 | return 0; | |
1499 | ||
1500 | return (fix->fx_pcrel | |
1501 | || SWITCH_TABLE (fix) | |
1502 | || fix->fx_r_type == R_SH_COUNT | |
bccbc0aa ILT |
1503 | || fix->fx_r_type == R_SH_ALIGN |
1504 | || fix->fx_r_type == R_SH_CODE | |
1505 | || fix->fx_r_type == R_SH_DATA | |
1506 | || fix->fx_r_type == R_SH_LABEL); | |
68d04794 JL |
1507 | } |
1508 | ||
1509 | /* Apply a fixup to the object file. */ | |
1510 | ||
025b0302 ME |
1511 | void |
1512 | md_apply_fix (fixP, val) | |
1513 | fixS *fixP; | |
1514 | long val; | |
1515 | { | |
1516 | char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; | |
10c8c95e JW |
1517 | int lowbyte = target_big_endian ? 1 : 0; |
1518 | int highbyte = target_big_endian ? 0 : 1; | |
68d04794 | 1519 | |
025b0302 ME |
1520 | if (fixP->fx_r_type == 0) |
1521 | { | |
351efc81 SC |
1522 | if (fixP->fx_size == 2) |
1523 | fixP->fx_r_type = R_SH_IMM16; | |
68d04794 | 1524 | else if (fixP->fx_size == 4) |
351efc81 | 1525 | fixP->fx_r_type = R_SH_IMM32; |
68d04794 JL |
1526 | else if (fixP->fx_size == 1) |
1527 | fixP->fx_r_type = R_SH_IMM8; | |
1528 | else | |
1529 | abort (); | |
025b0302 ME |
1530 | } |
1531 | ||
1532 | switch (fixP->fx_r_type) | |
1533 | { | |
025b0302 ME |
1534 | case R_SH_IMM4: |
1535 | *buf = (*buf & 0xf0) | (val & 0xf); | |
1536 | break; | |
1537 | ||
1538 | case R_SH_IMM4BY2: | |
1539 | *buf = (*buf & 0xf0) | ((val >> 1) & 0xf); | |
1540 | break; | |
1541 | ||
1542 | case R_SH_IMM4BY4: | |
1543 | *buf = (*buf & 0xf0) | ((val >> 2) & 0xf); | |
1544 | break; | |
1545 | ||
1546 | case R_SH_IMM8BY2: | |
1547 | *buf = val >> 1; | |
1548 | break; | |
1549 | ||
1550 | case R_SH_IMM8BY4: | |
1551 | *buf = val >> 2; | |
1552 | break; | |
1553 | ||
1554 | case R_SH_IMM8: | |
1555 | *buf++ = val; | |
1556 | break; | |
1557 | ||
1558 | case R_SH_PCRELIMM8BY4: | |
68d04794 JL |
1559 | /* The lower two bits of the PC are cleared before the |
1560 | displacement is added in. We can assume that the destination | |
1561 | is on a 4 byte bounday. If this instruction is also on a 4 | |
1562 | byte boundary, then we want | |
1563 | (target - here) / 4 | |
1564 | and target - here is a multiple of 4. | |
1565 | Otherwise, we are on a 2 byte boundary, and we want | |
1566 | (target - (here - 2)) / 4 | |
1567 | and target - here is not a multiple of 4. Computing | |
1568 | (target - (here - 2)) / 4 == (target - here + 2) / 4 | |
1569 | works for both cases, since in the first case the addition of | |
1570 | 2 will be removed by the division. target - here is in the | |
1571 | variable val. */ | |
1572 | val = (val + 2) / 4; | |
025b0302 | 1573 | if (val & ~0xff) |
10c8c95e | 1574 | as_bad_where (fixP->fx_file, fixP->fx_line, "pcrel too far"); |
d6905776 | 1575 | buf[lowbyte] = val; |
025b0302 ME |
1576 | break; |
1577 | ||
1578 | case R_SH_PCRELIMM8BY2: | |
025b0302 ME |
1579 | val /= 2; |
1580 | if (val & ~0xff) | |
10c8c95e | 1581 | as_bad_where (fixP->fx_file, fixP->fx_line, "pcrel too far"); |
d6905776 | 1582 | buf[lowbyte] = val; |
025b0302 ME |
1583 | break; |
1584 | ||
68d04794 JL |
1585 | case R_SH_PCDISP8BY2: |
1586 | val /= 2; | |
1587 | if (val < -0x80 || val > 0x7f) | |
10c8c95e | 1588 | as_bad_where (fixP->fx_file, fixP->fx_line, "pcrel too far"); |
68d04794 JL |
1589 | buf[lowbyte] = val; |
1590 | break; | |
1591 | ||
1592 | case R_SH_PCDISP: | |
1593 | val /= 2; | |
1594 | if (val < -0x800 || val >= 0x7ff) | |
10c8c95e | 1595 | as_bad_where (fixP->fx_file, fixP->fx_line, "pcrel too far"); |
68d04794 JL |
1596 | buf[lowbyte] = val & 0xff; |
1597 | buf[highbyte] |= (val >> 8) & 0xf; | |
1598 | break; | |
1599 | ||
025b0302 | 1600 | case R_SH_IMM32: |
10c8c95e | 1601 | if (! target_big_endian) |
d6905776 KR |
1602 | { |
1603 | *buf++ = val >> 0; | |
1604 | *buf++ = val >> 8; | |
1605 | *buf++ = val >> 16; | |
1606 | *buf++ = val >> 24; | |
1607 | } | |
1608 | else | |
1609 | { | |
1610 | *buf++ = val >> 24; | |
1611 | *buf++ = val >> 16; | |
1612 | *buf++ = val >> 8; | |
1613 | *buf++ = val >> 0; | |
1614 | } | |
025b0302 ME |
1615 | break; |
1616 | ||
351efc81 | 1617 | case R_SH_IMM16: |
10c8c95e | 1618 | if (! target_big_endian) |
d6905776 KR |
1619 | { |
1620 | *buf++ = val >> 0; | |
1621 | *buf++ = val >> 8; | |
1622 | } | |
1623 | else | |
1624 | { | |
1625 | *buf++ = val >> 8; | |
1626 | *buf++ = val >> 0; | |
1627 | } | |
351efc81 SC |
1628 | break; |
1629 | ||
68d04794 JL |
1630 | case R_SH_USES: |
1631 | /* Pass the value into sh_coff_reloc_mangle. */ | |
1632 | fixP->fx_addnumber = val; | |
1633 | break; | |
1634 | ||
1635 | case R_SH_COUNT: | |
1636 | case R_SH_ALIGN: | |
bccbc0aa ILT |
1637 | case R_SH_CODE: |
1638 | case R_SH_DATA: | |
1639 | case R_SH_LABEL: | |
68d04794 JL |
1640 | /* Nothing to do here. */ |
1641 | break; | |
1642 | ||
025b0302 ME |
1643 | default: |
1644 | abort (); | |
1645 | } | |
1646 | } | |
1647 | ||
025b0302 ME |
1648 | int md_long_jump_size; |
1649 | ||
68d04794 JL |
1650 | /* Called just before address relaxation. Return the length |
1651 | by which a fragment must grow to reach it's destination. */ | |
1652 | ||
025b0302 ME |
1653 | int |
1654 | md_estimate_size_before_relax (fragP, segment_type) | |
1655 | register fragS *fragP; | |
1656 | register segT segment_type; | |
1657 | { | |
1658 | switch (fragP->fr_subtype) | |
1659 | { | |
1660 | case C (UNCOND_JUMP, UNDEF_DISP): | |
1661 | /* used to be a branch to somewhere which was unknown */ | |
1662 | if (!fragP->fr_symbol) | |
1663 | { | |
1664 | fragP->fr_subtype = C (UNCOND_JUMP, UNCOND12); | |
1665 | fragP->fr_var = md_relax_table[C (UNCOND_JUMP, UNCOND12)].rlx_length; | |
1666 | } | |
1667 | else if (S_GET_SEGMENT (fragP->fr_symbol) == segment_type) | |
1668 | { | |
1669 | fragP->fr_subtype = C (UNCOND_JUMP, UNCOND12); | |
1670 | fragP->fr_var = md_relax_table[C (UNCOND_JUMP, UNCOND12)].rlx_length; | |
1671 | } | |
1672 | else | |
1673 | { | |
1674 | fragP->fr_subtype = C (UNCOND_JUMP, UNDEF_WORD_DISP); | |
1675 | fragP->fr_var = md_relax_table[C (UNCOND_JUMP, UNCOND32)].rlx_length; | |
1676 | return md_relax_table[C (UNCOND_JUMP, UNCOND32)].rlx_length; | |
1677 | } | |
1678 | break; | |
1679 | ||
1680 | default: | |
1681 | abort (); | |
1682 | case C (COND_JUMP, UNDEF_DISP): | |
1683 | /* used to be a branch to somewhere which was unknown */ | |
1684 | if (fragP->fr_symbol | |
1685 | && S_GET_SEGMENT (fragP->fr_symbol) == segment_type) | |
1686 | { | |
1687 | /* Got a symbol and it's defined in this segment, become byte | |
351efc81 | 1688 | sized - maybe it will fix up */ |
025b0302 ME |
1689 | fragP->fr_subtype = C (COND_JUMP, COND8); |
1690 | fragP->fr_var = md_relax_table[C (COND_JUMP, COND8)].rlx_length; | |
1691 | } | |
1692 | else if (fragP->fr_symbol) | |
1693 | { | |
1694 | /* Its got a segment, but its not ours, so it will always be long */ | |
1695 | fragP->fr_subtype = C (COND_JUMP, UNDEF_WORD_DISP); | |
1696 | fragP->fr_var = md_relax_table[C (COND_JUMP, COND32)].rlx_length; | |
1697 | return md_relax_table[C (COND_JUMP, COND32)].rlx_length; | |
1698 | } | |
1699 | else | |
1700 | { | |
1701 | /* We know the abs value */ | |
1702 | fragP->fr_subtype = C (COND_JUMP, COND8); | |
1703 | fragP->fr_var = md_relax_table[C (COND_JUMP, COND8)].rlx_length; | |
1704 | } | |
1705 | ||
1706 | break; | |
1707 | } | |
1708 | return fragP->fr_var; | |
1709 | } | |
1710 | ||
1711 | /* Put number into target byte order */ | |
1712 | ||
1713 | void | |
1714 | md_number_to_chars (ptr, use, nbytes) | |
1715 | char *ptr; | |
1716 | valueT use; | |
1717 | int nbytes; | |
1718 | { | |
10c8c95e | 1719 | if (! target_big_endian) |
d6905776 KR |
1720 | number_to_chars_littleendian (ptr, use, nbytes); |
1721 | else | |
1722 | number_to_chars_bigendian (ptr, use, nbytes); | |
025b0302 | 1723 | } |
351efc81 | 1724 | |
025b0302 ME |
1725 | long |
1726 | md_pcrel_from (fixP) | |
1727 | fixS *fixP; | |
025b0302 | 1728 | { |
68d04794 JL |
1729 | return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address + 2; |
1730 | } | |
1731 | ||
1732 | int | |
1733 | tc_coff_sizemachdep (frag) | |
1734 | fragS *frag; | |
1735 | { | |
1736 | return md_relax_table[frag->fr_subtype].rlx_length; | |
025b0302 ME |
1737 | } |
1738 | ||
9addcbb1 ILT |
1739 | /* When we align the .text section, insert the correct NOP pattern. */ |
1740 | ||
1741 | int | |
71dd3c40 | 1742 | sh_do_align (n, fill, len) |
9addcbb1 ILT |
1743 | int n; |
1744 | const char *fill; | |
71dd3c40 | 1745 | int len; |
9addcbb1 | 1746 | { |
71dd3c40 | 1747 | if ((fill == NULL || (*fill == 0 && len == 1)) |
9addcbb1 ILT |
1748 | && (now_seg == text_section |
1749 | #ifdef BFD_ASSEMBLER | |
1750 | || (now_seg->flags & SEC_CODE) != 0 | |
1751 | #endif | |
bccbc0aa ILT |
1752 | || strcmp (obj_segment_name (now_seg), ".init") == 0) |
1753 | && n > 1) | |
9addcbb1 ILT |
1754 | { |
1755 | static const unsigned char big_nop_pattern[] = { 0x00, 0x09 }; | |
1756 | static const unsigned char little_nop_pattern[] = { 0x09, 0x00 }; | |
1757 | ||
fcee3e24 ILT |
1758 | /* First align to a 2 byte boundary, in case there is an odd |
1759 | .byte. */ | |
6a413d6f | 1760 | frag_align (1, 0); |
9addcbb1 ILT |
1761 | if (target_big_endian) |
1762 | frag_align_pattern (n, big_nop_pattern, sizeof big_nop_pattern); | |
1763 | else | |
1764 | frag_align_pattern (n, little_nop_pattern, sizeof little_nop_pattern); | |
1765 | return 1; | |
1766 | } | |
1767 | ||
1768 | return 0; | |
1769 | } | |
1770 | ||
68d04794 JL |
1771 | #ifdef OBJ_COFF |
1772 | ||
1773 | /* Adjust a reloc for the SH. This is similar to the generic code, | |
1774 | but does some minor tweaking. */ | |
1775 | ||
1776 | void | |
1777 | sh_coff_reloc_mangle (seg, fix, intr, paddr) | |
1778 | segment_info_type *seg; | |
1779 | fixS *fix; | |
1780 | struct internal_reloc *intr; | |
1781 | unsigned int paddr; | |
025b0302 | 1782 | { |
68d04794 JL |
1783 | symbolS *symbol_ptr = fix->fx_addsy; |
1784 | symbolS *dot; | |
1785 | ||
1786 | intr->r_vaddr = paddr + fix->fx_frag->fr_address + fix->fx_where; | |
1787 | ||
1788 | if (! SWITCH_TABLE (fix)) | |
1789 | { | |
1790 | intr->r_type = fix->fx_r_type; | |
1791 | intr->r_offset = 0; | |
1792 | } | |
1793 | else | |
1794 | { | |
1795 | know (sh_relax); | |
1796 | ||
1797 | if (fix->fx_r_type == R_SH_IMM16) | |
1798 | intr->r_type = R_SH_SWITCH16; | |
1799 | else if (fix->fx_r_type == R_SH_IMM32) | |
1800 | intr->r_type = R_SH_SWITCH32; | |
1801 | else | |
1802 | abort (); | |
1803 | ||
1804 | /* For a switch reloc, we set r_offset to the difference between | |
1805 | the reloc address and the subtrahend. When the linker is | |
1806 | doing relaxing, it can use the determine the starting and | |
1807 | ending points of the switch difference expression. */ | |
1808 | intr->r_offset = intr->r_vaddr - S_GET_VALUE (fix->fx_subsy); | |
1809 | } | |
1810 | ||
1811 | /* PC relative relocs are always against the current section. */ | |
1812 | if (symbol_ptr == NULL) | |
025b0302 | 1813 | { |
68d04794 | 1814 | switch (fix->fx_r_type) |
025b0302 | 1815 | { |
68d04794 JL |
1816 | case R_SH_PCRELIMM8BY2: |
1817 | case R_SH_PCRELIMM8BY4: | |
1818 | case R_SH_PCDISP8BY2: | |
1819 | case R_SH_PCDISP: | |
1820 | case R_SH_USES: | |
1821 | symbol_ptr = seg->dot; | |
025b0302 ME |
1822 | break; |
1823 | default: | |
68d04794 | 1824 | break; |
025b0302 ME |
1825 | } |
1826 | } | |
025b0302 | 1827 | |
68d04794 JL |
1828 | if (fix->fx_r_type == R_SH_USES) |
1829 | { | |
1830 | /* We can't store the offset in the object file, since this | |
1831 | reloc does not take up any space, so we store it in r_offset. | |
1832 | The fx_addnumber field was set in md_apply_fix. */ | |
1833 | intr->r_offset = fix->fx_addnumber; | |
1834 | } | |
1835 | else if (fix->fx_r_type == R_SH_COUNT) | |
1836 | { | |
1837 | /* We can't store the count in the object file, since this reloc | |
1838 | does not take up any space, so we store it in r_offset. The | |
1839 | fx_offset field was set when the fixup was created in | |
1840 | sh_coff_frob_file. */ | |
1841 | intr->r_offset = fix->fx_offset; | |
1842 | /* This reloc is always absolute. */ | |
1843 | symbol_ptr = NULL; | |
1844 | } | |
1845 | else if (fix->fx_r_type == R_SH_ALIGN) | |
1846 | { | |
1847 | /* Store the alignment in the r_offset field. */ | |
1848 | intr->r_offset = fix->fx_offset; | |
1849 | /* This reloc is always absolute. */ | |
1850 | symbol_ptr = NULL; | |
1851 | } | |
bccbc0aa ILT |
1852 | else if (fix->fx_r_type == R_SH_CODE |
1853 | || fix->fx_r_type == R_SH_DATA | |
1854 | || fix->fx_r_type == R_SH_LABEL) | |
1855 | { | |
1856 | /* These relocs are always absolute. */ | |
1857 | symbol_ptr = NULL; | |
1858 | } | |
68d04794 JL |
1859 | |
1860 | /* Turn the segment of the symbol into an offset. */ | |
1861 | if (symbol_ptr != NULL) | |
1862 | { | |
1863 | dot = segment_info[S_GET_SEGMENT (symbol_ptr)].dot; | |
1864 | if (dot != NULL) | |
1865 | intr->r_symndx = dot->sy_number; | |
1866 | else | |
1867 | intr->r_symndx = symbol_ptr->sy_number; | |
1868 | } | |
1869 | else | |
1870 | intr->r_symndx = -1; | |
025b0302 | 1871 | } |
68d04794 JL |
1872 | |
1873 | #endif |