tc-moxie.c revision 1.1.1.7 1 1.1 christos /* tc-moxie.c -- Assemble code for moxie
2 1.1.1.7 christos Copyright (C) 2009-2024 Free Software Foundation, Inc.
3 1.1 christos
4 1.1 christos This file is part of GAS, the GNU Assembler.
5 1.1 christos
6 1.1 christos GAS is free software; you can redistribute it and/or modify
7 1.1 christos it under the terms of the GNU General Public License as published by
8 1.1 christos the Free Software Foundation; either version 3, or (at your option)
9 1.1 christos any later version.
10 1.1 christos
11 1.1 christos GAS is distributed in the hope that it will be useful,
12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 1.1 christos GNU General Public License for more details.
15 1.1 christos
16 1.1 christos You should have received a copy of the GNU General Public License
17 1.1 christos along with GAS; see the file COPYING. If not, write to
18 1.1 christos the Free Software Foundation, 51 Franklin Street - Fifth Floor,
19 1.1 christos Boston, MA 02110-1301, USA. */
20 1.1 christos
21 1.1 christos /* Contributed by Anthony Green <green (at) moxielogic.com>. */
22 1.1 christos
23 1.1 christos #include "as.h"
24 1.1 christos #include "safe-ctype.h"
25 1.1 christos #include "opcode/moxie.h"
26 1.1 christos #include "elf/moxie.h"
27 1.1 christos
28 1.1 christos extern const moxie_opc_info_t moxie_opc_info[128];
29 1.1 christos
30 1.1 christos const char comment_chars[] = "#";
31 1.1 christos const char line_separator_chars[] = ";";
32 1.1 christos const char line_comment_chars[] = "#";
33 1.1 christos
34 1.1 christos static int pending_reloc;
35 1.1.1.6 christos static htab_t opcode_hash_control;
36 1.1 christos
37 1.1 christos const pseudo_typeS md_pseudo_table[] =
38 1.1 christos {
39 1.1 christos {0, 0, 0}
40 1.1 christos };
41 1.1 christos
42 1.1 christos const char FLT_CHARS[] = "rRsSfFdDxXpP";
43 1.1 christos const char EXP_CHARS[] = "eE";
44 1.1 christos
45 1.1.1.2 christos static valueT md_chars_to_number (char * buf, int n);
46 1.1.1.2 christos
47 1.1.1.2 christos /* Byte order. */
48 1.1.1.2 christos extern int target_big_endian;
49 1.1 christos
50 1.1 christos void
51 1.1 christos md_operand (expressionS *op __attribute__((unused)))
52 1.1 christos {
53 1.1 christos /* Empty for now. */
54 1.1 christos }
55 1.1 christos
56 1.1 christos /* This function is called once, at assembler startup time. It sets
57 1.1 christos up the hash table with all the opcodes in it, and also initializes
58 1.1 christos some aliases for compatibility with other assemblers. */
59 1.1 christos
60 1.1 christos void
61 1.1 christos md_begin (void)
62 1.1 christos {
63 1.1 christos int count;
64 1.1 christos const moxie_opc_info_t *opcode;
65 1.1.1.6 christos opcode_hash_control = str_htab_create ();
66 1.1 christos
67 1.1 christos /* Insert names into hash table. */
68 1.1 christos for (count = 0, opcode = moxie_form1_opc_info; count++ < 64; opcode++)
69 1.1.1.6 christos str_hash_insert (opcode_hash_control, opcode->name, opcode, 0);
70 1.1 christos
71 1.1 christos for (count = 0, opcode = moxie_form2_opc_info; count++ < 4; opcode++)
72 1.1.1.6 christos str_hash_insert (opcode_hash_control, opcode->name, opcode, 0);
73 1.1 christos
74 1.1 christos for (count = 0, opcode = moxie_form3_opc_info; count++ < 10; opcode++)
75 1.1.1.6 christos str_hash_insert (opcode_hash_control, opcode->name, opcode, 0);
76 1.1.1.2 christos
77 1.1 christos bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
78 1.1 christos }
79 1.1 christos
80 1.1 christos /* Parse an expression and then restore the input line pointer. */
81 1.1 christos
82 1.1 christos static char *
83 1.1 christos parse_exp_save_ilp (char *s, expressionS *op)
84 1.1 christos {
85 1.1 christos char *save = input_line_pointer;
86 1.1 christos
87 1.1 christos input_line_pointer = s;
88 1.1 christos expression (op);
89 1.1 christos s = input_line_pointer;
90 1.1 christos input_line_pointer = save;
91 1.1 christos return s;
92 1.1 christos }
93 1.1 christos
94 1.1 christos static int
95 1.1 christos parse_register_operand (char **ptr)
96 1.1 christos {
97 1.1 christos int reg;
98 1.1 christos char *s = *ptr;
99 1.1 christos
100 1.1 christos if (*s != '$')
101 1.1 christos {
102 1.1 christos as_bad (_("expecting register"));
103 1.1 christos ignore_rest_of_line ();
104 1.1 christos return -1;
105 1.1 christos }
106 1.1 christos if (s[1] == 'f' && s[2] == 'p')
107 1.1 christos {
108 1.1 christos *ptr += 3;
109 1.1 christos return 0;
110 1.1 christos }
111 1.1 christos if (s[1] == 's' && s[2] == 'p')
112 1.1 christos {
113 1.1 christos *ptr += 3;
114 1.1 christos return 1;
115 1.1 christos }
116 1.1 christos if (s[1] == 'r')
117 1.1 christos {
118 1.1 christos reg = s[2] - '0';
119 1.1 christos if ((reg < 0) || (reg > 9))
120 1.1 christos {
121 1.1 christos as_bad (_("illegal register number"));
122 1.1 christos ignore_rest_of_line ();
123 1.1 christos return -1;
124 1.1 christos }
125 1.1 christos if (reg == 1)
126 1.1 christos {
127 1.1 christos int r2 = s[3] - '0';
128 1.1 christos if ((r2 >= 0) && (r2 <= 3))
129 1.1 christos {
130 1.1 christos reg = 10 + r2;
131 1.1 christos *ptr += 1;
132 1.1 christos }
133 1.1 christos }
134 1.1 christos }
135 1.1 christos else
136 1.1 christos {
137 1.1 christos as_bad (_("illegal register number"));
138 1.1 christos ignore_rest_of_line ();
139 1.1 christos return -1;
140 1.1 christos }
141 1.1 christos
142 1.1 christos *ptr += 3;
143 1.1 christos
144 1.1 christos return reg + 2;
145 1.1 christos }
146 1.1 christos
147 1.1 christos /* This is the guts of the machine-dependent assembler. STR points to
148 1.1 christos a machine dependent instruction. This function is supposed to emit
149 1.1 christos the frags/bytes it assembles to. */
150 1.1 christos
151 1.1 christos void
152 1.1 christos md_assemble (char *str)
153 1.1 christos {
154 1.1 christos char *op_start;
155 1.1 christos char *op_end;
156 1.1 christos
157 1.1 christos moxie_opc_info_t *opcode;
158 1.1 christos char *p;
159 1.1 christos char pend;
160 1.1 christos
161 1.1 christos unsigned short iword = 0;
162 1.1 christos
163 1.1 christos int nlen = 0;
164 1.1 christos
165 1.1 christos /* Drop leading whitespace. */
166 1.1 christos while (*str == ' ')
167 1.1 christos str++;
168 1.1 christos
169 1.1 christos /* Find the op code end. */
170 1.1 christos op_start = str;
171 1.1 christos for (op_end = str;
172 1.1 christos *op_end && !is_end_of_line[*op_end & 0xff] && *op_end != ' ';
173 1.1 christos op_end++)
174 1.1 christos nlen++;
175 1.1 christos
176 1.1 christos pend = *op_end;
177 1.1 christos *op_end = 0;
178 1.1 christos
179 1.1 christos if (nlen == 0)
180 1.1 christos as_bad (_("can't find opcode "));
181 1.1.1.6 christos opcode = (moxie_opc_info_t *) str_hash_find (opcode_hash_control, op_start);
182 1.1 christos *op_end = pend;
183 1.1 christos
184 1.1 christos if (opcode == NULL)
185 1.1 christos {
186 1.1 christos as_bad (_("unknown opcode %s"), op_start);
187 1.1 christos return;
188 1.1 christos }
189 1.1 christos
190 1.1 christos p = frag_more (2);
191 1.1 christos
192 1.1 christos switch (opcode->itype)
193 1.1 christos {
194 1.1 christos case MOXIE_F2_A8V:
195 1.1 christos iword = (1<<15) | (opcode->opcode << 12);
196 1.1 christos while (ISSPACE (*op_end))
197 1.1 christos op_end++;
198 1.1 christos {
199 1.1 christos expressionS arg;
200 1.1 christos int reg;
201 1.1 christos reg = parse_register_operand (&op_end);
202 1.1 christos iword += (reg << 8);
203 1.1 christos if (*op_end != ',')
204 1.1 christos as_warn (_("expecting comma delimited register operands"));
205 1.1 christos op_end++;
206 1.1 christos op_end = parse_exp_save_ilp (op_end, &arg);
207 1.1 christos fix_new_exp (frag_now,
208 1.1.1.2 christos ((p + (target_big_endian ? 1 : 0)) - frag_now->fr_literal),
209 1.1 christos 1,
210 1.1 christos &arg,
211 1.1 christos 0,
212 1.1 christos BFD_RELOC_8);
213 1.1 christos }
214 1.1 christos break;
215 1.1 christos case MOXIE_F1_AB:
216 1.1 christos iword = opcode->opcode << 8;
217 1.1 christos while (ISSPACE (*op_end))
218 1.1 christos op_end++;
219 1.1 christos {
220 1.1 christos int dest, src;
221 1.1 christos dest = parse_register_operand (&op_end);
222 1.1 christos if (*op_end != ',')
223 1.1 christos as_warn (_("expecting comma delimited register operands"));
224 1.1 christos op_end++;
225 1.1 christos src = parse_register_operand (&op_end);
226 1.1 christos iword += (dest << 4) + src;
227 1.1 christos while (ISSPACE (*op_end))
228 1.1 christos op_end++;
229 1.1 christos if (*op_end != 0)
230 1.1 christos as_warn (_("extra stuff on line ignored"));
231 1.1 christos }
232 1.1 christos break;
233 1.1 christos case MOXIE_F1_A4:
234 1.1 christos iword = opcode->opcode << 8;
235 1.1 christos while (ISSPACE (*op_end))
236 1.1 christos op_end++;
237 1.1 christos {
238 1.1 christos expressionS arg;
239 1.1 christos char *where;
240 1.1 christos int regnum;
241 1.1 christos
242 1.1 christos regnum = parse_register_operand (&op_end);
243 1.1 christos while (ISSPACE (*op_end))
244 1.1 christos op_end++;
245 1.1 christos
246 1.1 christos iword += (regnum << 4);
247 1.1 christos
248 1.1 christos if (*op_end != ',')
249 1.1 christos {
250 1.1 christos as_bad (_("expecting comma delimited operands"));
251 1.1 christos ignore_rest_of_line ();
252 1.1 christos return;
253 1.1 christos }
254 1.1 christos op_end++;
255 1.1 christos
256 1.1 christos op_end = parse_exp_save_ilp (op_end, &arg);
257 1.1 christos where = frag_more (4);
258 1.1 christos fix_new_exp (frag_now,
259 1.1 christos (where - frag_now->fr_literal),
260 1.1 christos 4,
261 1.1 christos &arg,
262 1.1 christos 0,
263 1.1 christos BFD_RELOC_32);
264 1.1 christos }
265 1.1 christos break;
266 1.1 christos case MOXIE_F1_M:
267 1.1 christos case MOXIE_F1_4:
268 1.1 christos iword = opcode->opcode << 8;
269 1.1 christos while (ISSPACE (*op_end))
270 1.1 christos op_end++;
271 1.1 christos {
272 1.1 christos expressionS arg;
273 1.1 christos char *where;
274 1.1 christos
275 1.1 christos op_end = parse_exp_save_ilp (op_end, &arg);
276 1.1 christos where = frag_more (4);
277 1.1 christos fix_new_exp (frag_now,
278 1.1 christos (where - frag_now->fr_literal),
279 1.1 christos 4,
280 1.1 christos &arg,
281 1.1 christos 0,
282 1.1 christos BFD_RELOC_32);
283 1.1 christos }
284 1.1 christos break;
285 1.1 christos case MOXIE_F1_NARG:
286 1.1 christos iword = opcode->opcode << 8;
287 1.1 christos while (ISSPACE (*op_end))
288 1.1 christos op_end++;
289 1.1 christos if (*op_end != 0)
290 1.1 christos as_warn (_("extra stuff on line ignored"));
291 1.1 christos break;
292 1.1 christos case MOXIE_F1_A:
293 1.1 christos iword = opcode->opcode << 8;
294 1.1 christos while (ISSPACE (*op_end))
295 1.1 christos op_end++;
296 1.1 christos {
297 1.1 christos int reg;
298 1.1 christos reg = parse_register_operand (&op_end);
299 1.1 christos while (ISSPACE (*op_end))
300 1.1 christos op_end++;
301 1.1 christos if (*op_end != 0)
302 1.1 christos as_warn (_("extra stuff on line ignored"));
303 1.1 christos iword += (reg << 4);
304 1.1 christos }
305 1.1 christos break;
306 1.1 christos case MOXIE_F1_ABi:
307 1.1 christos iword = opcode->opcode << 8;
308 1.1 christos while (ISSPACE (*op_end))
309 1.1 christos op_end++;
310 1.1 christos {
311 1.1 christos int a, b;
312 1.1 christos a = parse_register_operand (&op_end);
313 1.1 christos if (*op_end != ',')
314 1.1 christos as_warn (_("expecting comma delimited register operands"));
315 1.1 christos op_end++;
316 1.1 christos if (*op_end != '(')
317 1.1 christos {
318 1.1 christos as_bad (_("expecting indirect register `($rA)'"));
319 1.1 christos ignore_rest_of_line ();
320 1.1 christos return;
321 1.1 christos }
322 1.1 christos op_end++;
323 1.1 christos b = parse_register_operand (&op_end);
324 1.1 christos if (*op_end != ')')
325 1.1 christos {
326 1.1 christos as_bad (_("missing closing parenthesis"));
327 1.1 christos ignore_rest_of_line ();
328 1.1 christos return;
329 1.1 christos }
330 1.1 christos op_end++;
331 1.1 christos iword += (a << 4) + b;
332 1.1 christos while (ISSPACE (*op_end))
333 1.1 christos op_end++;
334 1.1 christos if (*op_end != 0)
335 1.1 christos as_warn (_("extra stuff on line ignored"));
336 1.1 christos }
337 1.1 christos break;
338 1.1 christos case MOXIE_F1_AiB:
339 1.1 christos iword = opcode->opcode << 8;
340 1.1 christos while (ISSPACE (*op_end))
341 1.1 christos op_end++;
342 1.1 christos {
343 1.1 christos int a, b;
344 1.1 christos if (*op_end != '(')
345 1.1 christos {
346 1.1 christos as_bad (_("expecting indirect register `($rA)'"));
347 1.1 christos ignore_rest_of_line ();
348 1.1 christos return;
349 1.1 christos }
350 1.1 christos op_end++;
351 1.1 christos a = parse_register_operand (&op_end);
352 1.1 christos if (*op_end != ')')
353 1.1 christos {
354 1.1 christos as_bad (_("missing closing parenthesis"));
355 1.1 christos ignore_rest_of_line ();
356 1.1 christos return;
357 1.1 christos }
358 1.1 christos op_end++;
359 1.1 christos if (*op_end != ',')
360 1.1 christos as_warn (_("expecting comma delimited register operands"));
361 1.1 christos op_end++;
362 1.1 christos b = parse_register_operand (&op_end);
363 1.1 christos iword += (a << 4) + b;
364 1.1 christos while (ISSPACE (*op_end))
365 1.1 christos op_end++;
366 1.1 christos if (*op_end != 0)
367 1.1 christos as_warn (_("extra stuff on line ignored"));
368 1.1 christos }
369 1.1 christos break;
370 1.1 christos case MOXIE_F1_4A:
371 1.1 christos iword = opcode->opcode << 8;
372 1.1 christos while (ISSPACE (*op_end))
373 1.1 christos op_end++;
374 1.1 christos {
375 1.1 christos expressionS arg;
376 1.1 christos char *where;
377 1.1 christos int a;
378 1.1 christos
379 1.1 christos op_end = parse_exp_save_ilp (op_end, &arg);
380 1.1 christos where = frag_more (4);
381 1.1 christos fix_new_exp (frag_now,
382 1.1 christos (where - frag_now->fr_literal),
383 1.1 christos 4,
384 1.1 christos &arg,
385 1.1 christos 0,
386 1.1 christos BFD_RELOC_32);
387 1.1 christos
388 1.1 christos if (*op_end != ',')
389 1.1 christos {
390 1.1 christos as_bad (_("expecting comma delimited operands"));
391 1.1 christos ignore_rest_of_line ();
392 1.1 christos return;
393 1.1 christos }
394 1.1 christos op_end++;
395 1.1 christos
396 1.1 christos a = parse_register_operand (&op_end);
397 1.1 christos while (ISSPACE (*op_end))
398 1.1 christos op_end++;
399 1.1 christos if (*op_end != 0)
400 1.1 christos as_warn (_("extra stuff on line ignored"));
401 1.1 christos
402 1.1 christos iword += (a << 4);
403 1.1 christos }
404 1.1 christos break;
405 1.1.1.2 christos case MOXIE_F1_ABi2:
406 1.1 christos iword = opcode->opcode << 8;
407 1.1 christos while (ISSPACE (*op_end))
408 1.1 christos op_end++;
409 1.1 christos {
410 1.1 christos expressionS arg;
411 1.1 christos char *offset;
412 1.1 christos int a, b;
413 1.1 christos
414 1.1 christos a = parse_register_operand (&op_end);
415 1.1 christos while (ISSPACE (*op_end))
416 1.1 christos op_end++;
417 1.1 christos
418 1.1 christos if (*op_end != ',')
419 1.1 christos {
420 1.1 christos as_bad (_("expecting comma delimited operands"));
421 1.1 christos ignore_rest_of_line ();
422 1.1 christos return;
423 1.1 christos }
424 1.1 christos op_end++;
425 1.1 christos
426 1.1 christos op_end = parse_exp_save_ilp (op_end, &arg);
427 1.1.1.2 christos offset = frag_more (2);
428 1.1 christos fix_new_exp (frag_now,
429 1.1 christos (offset - frag_now->fr_literal),
430 1.1.1.2 christos 2,
431 1.1 christos &arg,
432 1.1 christos 0,
433 1.1.1.2 christos BFD_RELOC_16);
434 1.1 christos
435 1.1 christos if (*op_end != '(')
436 1.1 christos {
437 1.1 christos as_bad (_("expecting indirect register `($rX)'"));
438 1.1 christos ignore_rest_of_line ();
439 1.1 christos return;
440 1.1 christos }
441 1.1 christos op_end++;
442 1.1 christos b = parse_register_operand (&op_end);
443 1.1 christos if (*op_end != ')')
444 1.1 christos {
445 1.1 christos as_bad (_("missing closing parenthesis"));
446 1.1 christos ignore_rest_of_line ();
447 1.1 christos return;
448 1.1 christos }
449 1.1 christos op_end++;
450 1.1 christos
451 1.1 christos while (ISSPACE (*op_end))
452 1.1 christos op_end++;
453 1.1 christos if (*op_end != 0)
454 1.1 christos as_warn (_("extra stuff on line ignored"));
455 1.1 christos
456 1.1 christos iword += (a << 4) + b;
457 1.1 christos }
458 1.1 christos break;
459 1.1.1.2 christos case MOXIE_F1_AiB2:
460 1.1 christos iword = opcode->opcode << 8;
461 1.1 christos while (ISSPACE (*op_end))
462 1.1 christos op_end++;
463 1.1 christos {
464 1.1 christos expressionS arg;
465 1.1 christos char *offset;
466 1.1 christos int a, b;
467 1.1 christos
468 1.1 christos op_end = parse_exp_save_ilp (op_end, &arg);
469 1.1.1.2 christos offset = frag_more (2);
470 1.1 christos fix_new_exp (frag_now,
471 1.1 christos (offset - frag_now->fr_literal),
472 1.1.1.2 christos 2,
473 1.1 christos &arg,
474 1.1 christos 0,
475 1.1.1.2 christos BFD_RELOC_16);
476 1.1 christos
477 1.1 christos if (*op_end != '(')
478 1.1 christos {
479 1.1 christos as_bad (_("expecting indirect register `($rX)'"));
480 1.1 christos ignore_rest_of_line ();
481 1.1 christos return;
482 1.1 christos }
483 1.1 christos op_end++;
484 1.1 christos a = parse_register_operand (&op_end);
485 1.1 christos if (*op_end != ')')
486 1.1 christos {
487 1.1 christos as_bad (_("missing closing parenthesis"));
488 1.1 christos ignore_rest_of_line ();
489 1.1 christos return;
490 1.1 christos }
491 1.1 christos op_end++;
492 1.1 christos
493 1.1 christos if (*op_end != ',')
494 1.1 christos {
495 1.1 christos as_bad (_("expecting comma delimited operands"));
496 1.1 christos ignore_rest_of_line ();
497 1.1 christos return;
498 1.1 christos }
499 1.1 christos op_end++;
500 1.1 christos
501 1.1 christos b = parse_register_operand (&op_end);
502 1.1 christos while (ISSPACE (*op_end))
503 1.1 christos op_end++;
504 1.1 christos
505 1.1 christos while (ISSPACE (*op_end))
506 1.1 christos op_end++;
507 1.1 christos if (*op_end != 0)
508 1.1 christos as_warn (_("extra stuff on line ignored"));
509 1.1 christos
510 1.1 christos iword += (a << 4) + b;
511 1.1 christos }
512 1.1 christos break;
513 1.1 christos case MOXIE_F2_NARG:
514 1.1 christos iword = opcode->opcode << 12;
515 1.1 christos while (ISSPACE (*op_end))
516 1.1 christos op_end++;
517 1.1 christos if (*op_end != 0)
518 1.1 christos as_warn (_("extra stuff on line ignored"));
519 1.1 christos break;
520 1.1 christos case MOXIE_F3_PCREL:
521 1.1 christos iword = (3<<14) | (opcode->opcode << 10);
522 1.1 christos while (ISSPACE (*op_end))
523 1.1 christos op_end++;
524 1.1 christos {
525 1.1 christos expressionS arg;
526 1.1 christos
527 1.1 christos op_end = parse_exp_save_ilp (op_end, &arg);
528 1.1 christos fix_new_exp (frag_now,
529 1.1 christos (p - frag_now->fr_literal),
530 1.1 christos 2,
531 1.1 christos &arg,
532 1.1.1.6 christos true,
533 1.1 christos BFD_RELOC_MOXIE_10_PCREL);
534 1.1 christos }
535 1.1 christos break;
536 1.1.1.4 christos case MOXIE_BAD:
537 1.1.1.4 christos iword = 0;
538 1.1.1.4 christos while (ISSPACE (*op_end))
539 1.1.1.4 christos op_end++;
540 1.1.1.4 christos if (*op_end != 0)
541 1.1.1.4 christos as_warn (_("extra stuff on line ignored"));
542 1.1.1.4 christos break;
543 1.1 christos default:
544 1.1 christos abort ();
545 1.1 christos }
546 1.1 christos
547 1.1 christos md_number_to_chars (p, iword, 2);
548 1.1.1.3 christos dwarf2_emit_insn (2);
549 1.1 christos
550 1.1 christos while (ISSPACE (*op_end))
551 1.1 christos op_end++;
552 1.1 christos
553 1.1 christos if (*op_end != 0)
554 1.1 christos as_warn (_("extra stuff on line ignored"));
555 1.1 christos
556 1.1 christos if (pending_reloc)
557 1.1 christos as_bad (_("Something forgot to clean up\n"));
558 1.1 christos }
559 1.1 christos
560 1.1 christos /* Turn a string in input_line_pointer into a floating point constant
561 1.1 christos of type type, and store the appropriate bytes in *LITP. The number
562 1.1 christos of LITTLENUMS emitted is stored in *SIZEP . An error message is
563 1.1 christos returned, or NULL on OK. */
564 1.1 christos
565 1.1.1.3 christos const char *
566 1.1 christos md_atof (int type, char *litP, int *sizeP)
567 1.1 christos {
568 1.1 christos int prec;
569 1.1 christos LITTLENUM_TYPE words[4];
570 1.1 christos char *t;
571 1.1 christos int i;
572 1.1 christos
573 1.1 christos switch (type)
574 1.1 christos {
575 1.1 christos case 'f':
576 1.1 christos prec = 2;
577 1.1 christos break;
578 1.1 christos
579 1.1 christos case 'd':
580 1.1 christos prec = 4;
581 1.1 christos break;
582 1.1 christos
583 1.1 christos default:
584 1.1 christos *sizeP = 0;
585 1.1 christos return _("bad call to md_atof");
586 1.1 christos }
587 1.1 christos
588 1.1 christos t = atof_ieee (input_line_pointer, type, words);
589 1.1 christos if (t)
590 1.1 christos input_line_pointer = t;
591 1.1 christos
592 1.1 christos *sizeP = prec * 2;
593 1.1 christos
594 1.1 christos for (i = prec - 1; i >= 0; i--)
595 1.1 christos {
596 1.1 christos md_number_to_chars (litP, (valueT) words[i], 2);
597 1.1 christos litP += 2;
598 1.1 christos }
599 1.1 christos
600 1.1 christos return NULL;
601 1.1 christos }
602 1.1.1.2 christos
603 1.1.1.2 christos enum options
604 1.1.1.2 christos {
605 1.1.1.2 christos OPTION_EB = OPTION_MD_BASE,
606 1.1.1.2 christos OPTION_EL,
607 1.1.1.2 christos };
608 1.1 christos
609 1.1 christos struct option md_longopts[] =
610 1.1 christos {
611 1.1.1.2 christos { "EB", no_argument, NULL, OPTION_EB},
612 1.1.1.2 christos { "EL", no_argument, NULL, OPTION_EL},
613 1.1.1.2 christos { NULL, no_argument, NULL, 0}
614 1.1 christos };
615 1.1.1.2 christos
616 1.1 christos size_t md_longopts_size = sizeof (md_longopts);
617 1.1.1.2 christos
618 1.1.1.2 christos const char *md_shortopts = "";
620 1.1 christos
621 1.1.1.3 christos int
622 1.1 christos md_parse_option (int c ATTRIBUTE_UNUSED, const char *arg ATTRIBUTE_UNUSED)
623 1.1.1.2 christos {
624 1.1.1.2 christos switch (c)
625 1.1.1.2 christos {
626 1.1.1.2 christos case OPTION_EB:
627 1.1.1.2 christos target_big_endian = 1;
628 1.1.1.2 christos break;
629 1.1.1.2 christos case OPTION_EL:
630 1.1.1.2 christos target_big_endian = 0;
631 1.1.1.2 christos break;
632 1.1.1.2 christos default:
633 1.1.1.2 christos return 0;
634 1.1.1.2 christos }
635 1.1.1.2 christos
636 1.1 christos return 1;
637 1.1 christos }
638 1.1 christos
639 1.1 christos void
640 1.1 christos md_show_usage (FILE *stream ATTRIBUTE_UNUSED)
641 1.1.1.2 christos {
642 1.1.1.2 christos fprintf (stream, _("\
643 1.1.1.2 christos -EB assemble for a big endian system (default)\n\
644 1.1 christos -EL assemble for a little endian system\n"));
645 1.1 christos }
646 1.1 christos
647 1.1 christos /* Apply a fixup to the object file. */
648 1.1 christos
649 1.1.1.2 christos void
650 1.1 christos md_apply_fix (fixS *fixP ATTRIBUTE_UNUSED,
651 1.1 christos valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED)
652 1.1 christos {
653 1.1 christos char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
654 1.1 christos long val = *valP;
655 1.1 christos long newval;
656 1.1 christos long max, min;
657 1.1 christos
658 1.1 christos max = min = 0;
659 1.1 christos switch (fixP->fx_r_type)
660 1.1 christos {
661 1.1.1.2 christos case BFD_RELOC_32:
662 1.1.1.2 christos if (target_big_endian)
663 1.1.1.2 christos {
664 1.1.1.2 christos buf[0] = val >> 24;
665 1.1.1.2 christos buf[1] = val >> 16;
666 1.1.1.2 christos buf[2] = val >> 8;
667 1.1.1.2 christos buf[3] = val >> 0;
668 1.1.1.2 christos }
669 1.1.1.2 christos else
670 1.1.1.2 christos {
671 1.1.1.2 christos buf[3] = val >> 24;
672 1.1.1.2 christos buf[2] = val >> 16;
673 1.1.1.2 christos buf[1] = val >> 8;
674 1.1.1.2 christos buf[0] = val >> 0;
675 1.1.1.2 christos }
676 1.1 christos buf += 4;
677 1.1 christos break;
678 1.1 christos
679 1.1.1.2 christos case BFD_RELOC_16:
680 1.1.1.2 christos if (target_big_endian)
681 1.1.1.2 christos {
682 1.1.1.2 christos buf[0] = val >> 8;
683 1.1.1.2 christos buf[1] = val >> 0;
684 1.1.1.2 christos }
685 1.1.1.2 christos else
686 1.1.1.2 christos {
687 1.1.1.2 christos buf[1] = val >> 8;
688 1.1.1.2 christos buf[0] = val >> 0;
689 1.1.1.2 christos }
690 1.1 christos buf += 2;
691 1.1 christos break;
692 1.1 christos
693 1.1 christos case BFD_RELOC_8:
694 1.1 christos *buf++ = val;
695 1.1 christos break;
696 1.1 christos
697 1.1 christos case BFD_RELOC_MOXIE_10_PCREL:
698 1.1 christos if (!val)
699 1.1 christos break;
700 1.1 christos if (val < -1024 || val > 1022)
701 1.1 christos as_bad_where (fixP->fx_file, fixP->fx_line,
702 1.1 christos _("pcrel too far BFD_RELOC_MOXIE_10"));
703 1.1 christos /* 11 bit offset even numbered, so we remove right bit. */
704 1.1 christos val >>= 1;
705 1.1 christos newval = md_chars_to_number (buf, 2);
706 1.1 christos newval |= val & 0x03ff;
707 1.1 christos md_number_to_chars (buf, newval, 2);
708 1.1 christos break;
709 1.1 christos
710 1.1 christos default:
711 1.1 christos abort ();
712 1.1 christos }
713 1.1 christos
714 1.1 christos if (max != 0 && (val < min || val > max))
715 1.1 christos as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range"));
716 1.1 christos
717 1.1 christos if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0)
718 1.1 christos fixP->fx_done = 1;
719 1.1 christos }
720 1.1.1.2 christos
721 1.1 christos /* Put number into target byte order. */
722 1.1 christos
723 1.1.1.2 christos void
724 1.1 christos md_number_to_chars (char * ptr, valueT use, int nbytes)
725 1.1.1.2 christos {
726 1.1.1.2 christos if (target_big_endian)
727 1.1.1.2 christos number_to_chars_bigendian (ptr, use, nbytes);
728 1.1.1.2 christos else
729 1.1 christos number_to_chars_littleendian (ptr, use, nbytes);
730 1.1 christos }
731 1.1 christos
732 1.1 christos /* Convert from target byte order to host byte order. */
733 1.1.1.2 christos
734 1.1.1.2 christos static valueT
735 1.1 christos md_chars_to_number (char * buf, int n)
736 1.1.1.2 christos {
737 1.1.1.2 christos valueT result = 0;
738 1.1 christos unsigned char * where = (unsigned char *) buf;
739 1.1.1.2 christos
740 1.1.1.2 christos if (target_big_endian)
741 1.1.1.2 christos {
742 1.1.1.2 christos while (n--)
743 1.1.1.2 christos {
744 1.1.1.2 christos result <<= 8;
745 1.1.1.2 christos result |= (*where++ & 255);
746 1.1.1.2 christos }
747 1.1.1.2 christos }
748 1.1 christos else
749 1.1.1.2 christos {
750 1.1.1.2 christos while (n--)
751 1.1.1.2 christos {
752 1.1.1.2 christos result <<= 8;
753 1.1.1.2 christos result |= (where[n] & 255);
754 1.1 christos }
755 1.1 christos }
756 1.1.1.2 christos
757 1.1 christos return result;
758 1.1 christos }
759 1.1 christos
760 1.1 christos /* Generate a machine-dependent relocation. */
761 1.1 christos arelent *
762 1.1 christos tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
763 1.1 christos {
764 1.1 christos arelent *relP;
765 1.1 christos bfd_reloc_code_real_type code;
766 1.1 christos
767 1.1 christos switch (fixP->fx_r_type)
768 1.1 christos {
769 1.1 christos case BFD_RELOC_32:
770 1.1 christos code = fixP->fx_r_type;
771 1.1 christos break;
772 1.1 christos case BFD_RELOC_MOXIE_10_PCREL:
773 1.1 christos code = fixP->fx_r_type;
774 1.1 christos break;
775 1.1 christos default:
776 1.1 christos as_bad_where (fixP->fx_file, fixP->fx_line,
777 1.1 christos _("Semantics error. This type of operand can not be relocated, it must be an assembly-time constant"));
778 1.1 christos return 0;
779 1.1 christos }
780 1.1.1.3 christos
781 1.1.1.3 christos relP = XNEW (arelent);
782 1.1 christos relP->sym_ptr_ptr = XNEW (asymbol *);
783 1.1 christos *relP->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
784 1.1 christos relP->address = fixP->fx_frag->fr_address + fixP->fx_where;
785 1.1 christos
786 1.1 christos relP->addend = fixP->fx_offset;
787 1.1 christos
788 1.1 christos /* This is the standard place for KLUDGEs to work around bugs in
789 1.1 christos bfd_install_relocation (first such note in the documentation
790 1.1 christos appears with binutils-2.8).
791 1.1 christos
792 1.1 christos That function bfd_install_relocation does the wrong thing with
793 1.1 christos putting stuff into the addend of a reloc (it should stay out) for a
794 1.1 christos weak symbol. The really bad thing is that it adds the
795 1.1 christos "segment-relative offset" of the symbol into the reloc. In this
796 1.1 christos case, the reloc should instead be relative to the symbol with no
797 1.1 christos other offset than the assembly code shows; and since the symbol is
798 1.1 christos weak, any local definition should be ignored until link time (or
799 1.1 christos thereafter).
800 1.1 christos To wit: weaksym+42 should be weaksym+42 in the reloc,
801 1.1 christos not weaksym+(offset_from_segment_of_local_weaksym_definition)
802 1.1 christos
803 1.1 christos To "work around" this, we subtract the segment-relative offset of
804 1.1 christos "known" weak symbols. This evens out the extra offset.
805 1.1 christos
806 1.1 christos That happens for a.out but not for ELF, since for ELF,
807 1.1 christos bfd_install_relocation uses the "special function" field of the
808 1.1 christos howto, and does not execute the code that needs to be undone. */
809 1.1 christos
810 1.1 christos if (OUTPUT_FLAVOR == bfd_target_aout_flavour
811 1.1 christos && fixP->fx_addsy && S_IS_WEAK (fixP->fx_addsy)
812 1.1 christos && ! bfd_is_und_section (S_GET_SEGMENT (fixP->fx_addsy)))
813 1.1 christos {
814 1.1 christos relP->addend -= S_GET_VALUE (fixP->fx_addsy);
815 1.1 christos }
816 1.1 christos
817 1.1 christos relP->howto = bfd_reloc_type_lookup (stdoutput, code);
818 1.1 christos if (! relP->howto)
819 1.1 christos {
820 1.1 christos const char *name;
821 1.1 christos
822 1.1 christos name = S_GET_NAME (fixP->fx_addsy);
823 1.1 christos if (name == NULL)
824 1.1 christos name = _("<unknown>");
825 1.1 christos as_fatal (_("Cannot generate relocation type for symbol %s, code %s"),
826 1.1 christos name, bfd_get_reloc_code_name (code));
827 1.1 christos }
828 1.1 christos
829 1.1 christos return relP;
830 1.1 christos }
831 1.1 christos
832 1.1 christos /* Decide from what point a pc-relative relocation is relative to,
833 1.1 christos relative to the pc-relative fixup. Er, relatively speaking. */
834 1.1 christos long
835 1.1 christos md_pcrel_from (fixS *fixP)
836 1.1 christos {
837 1.1 christos valueT addr = fixP->fx_where + fixP->fx_frag->fr_address;
838 1.1 christos
839 1.1 christos switch (fixP->fx_r_type)
840 1.1 christos {
841 1.1 christos case BFD_RELOC_32:
842 1.1 christos return addr + 4;
843 1.1.1.2 christos case BFD_RELOC_MOXIE_10_PCREL:
844 1.1.1.2 christos /* Offset is from the end of the instruction. */
845 1.1 christos return addr + 2;
846 1.1 christos default:
847 1.1 christos abort ();
848 1.1 christos return addr;
849 1.1 christos }
850 }
851