3a69b3ac |
1 | /* tc-a29k.c -- Assemble for the AMD 29000. |
2 | Copyright (C) 1989, 1990, 1991 Free Software Foundation, Inc. |
3 | |
4 | This file is part of GAS, the GNU Assembler. |
5 | |
6 | GAS is free software; you can redistribute it and/or modify |
7 | it under the terms of the GNU General Public License as published by |
8 | the Free Software Foundation; either version 1, or (at your option) |
9 | any later version. |
10 | |
11 | GAS is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | GNU General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU General Public License |
17 | along with GAS; see the file COPYING. If not, write to |
18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ |
19 | |
20 | /* $Id$ */ |
21 | |
22 | /* John Gilmore has reorganized this module somewhat, to make it easier |
23 | to convert it to new machines' assemblers as desired. There was too |
24 | much bloody rewriting required before. There still probably is. */ |
25 | |
26 | #include "as.h" |
27 | |
28 | #include "a29k-opcode.h" |
29 | |
30 | /* Make it easier to clone this machine desc into another one. */ |
31 | #define machine_opcode a29k_opcode |
32 | #define machine_opcodes a29k_opcodes |
33 | #define machine_ip a29k_ip |
34 | #define machine_it a29k_it |
35 | |
36 | const relax_typeS md_relax_table[] = { 0 }; |
37 | |
38 | #define IMMEDIATE_BIT 0x01000000 /* Turns RB into Immediate */ |
39 | #define ABSOLUTE_BIT 0x01000000 /* Turns PC-relative to Absolute */ |
40 | #define CE_BIT 0x00800000 /* Coprocessor enable in LOAD */ |
41 | #define UI_BIT 0x00000080 /* Unsigned integer in CONVERT */ |
42 | |
43 | /* handle of the OPCODE hash table */ |
44 | static struct hash_control *op_hash = NULL; |
45 | |
46 | struct machine_it { |
47 | char *error; |
48 | unsigned long opcode; |
49 | struct nlist *nlistp; |
50 | expressionS exp; |
51 | int pcrel; |
52 | int reloc_offset; /* Offset of reloc within insn */ |
53 | enum reloc_type reloc; |
54 | } the_insn; |
55 | |
56 | #ifdef __STDC__ |
57 | |
58 | /* static int getExpression(char *str); */ |
59 | static void machine_ip(char *str); |
60 | /* static void print_insn(struct machine_it *insn); */ |
61 | static void s_data1(void); |
62 | static void s_use(void); |
63 | |
64 | #else /* __STDC__ */ |
65 | |
66 | /* static int getExpression(); */ |
67 | static void machine_ip(); |
68 | /* static void print_insn(); */ |
69 | static void s_data1(); |
70 | static void s_use(); |
71 | |
72 | #endif /* __STDC__ */ |
73 | |
74 | const pseudo_typeS |
75 | md_pseudo_table[] = { |
76 | { "align", s_align_bytes, 4 }, |
77 | { "block", s_space, 0 }, |
78 | { "cputype", s_ignore, 0 }, /* CPU as 29000 or 29050 */ |
79 | { "file", s_ignore, 0 }, /* COFF File name for debug info? */ |
80 | { "line", s_ignore, 0 }, /* Line number of coff symbol */ |
81 | { "reg", s_lsym, 0 }, /* Register equate, same as equ */ |
82 | { "space", s_ignore, 0 }, /* Listing control */ |
83 | { "sect", s_ignore, 0 }, /* Creation of coff sections */ |
84 | { "use", s_use, 0 }, |
85 | { "word", cons, 4 }, |
86 | { NULL, 0, 0 }, |
87 | }; |
88 | |
89 | int md_short_jump_size = 4; |
90 | int md_long_jump_size = 4; |
91 | int md_reloc_size = 12; |
92 | |
93 | /* This array holds the chars that always start a comment. If the |
94 | pre-processor is disabled, these aren't very useful */ |
95 | char comment_chars[] = ";"; |
96 | |
97 | /* This array holds the chars that only start a comment at the beginning of |
98 | a line. If the line seems to have the form '# 123 filename' |
99 | .line and .file directives will appear in the pre-processed output */ |
100 | /* Note that input_file.c hand checks for '#' at the beginning of the |
101 | first line of the input file. This is because the compiler outputs |
102 | #NO_APP at the beginning of its output. */ |
103 | /* Also note that comments like this one will always work */ |
104 | char line_comment_chars[] = "#"; |
105 | |
106 | /* We needed an unused char for line separation to work around the |
107 | lack of macros, using sed and such. */ |
108 | char line_separator_chars[] = "@"; |
109 | |
110 | /* Chars that can be used to separate mant from exp in floating point nums */ |
111 | char EXP_CHARS[] = "eE"; |
112 | |
113 | /* Chars that mean this number is a floating point constant */ |
114 | /* As in 0f12.456 */ |
115 | /* or 0d1.2345e12 */ |
116 | char FLT_CHARS[] = "rRsSfFdDxXpP"; |
117 | |
118 | /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be |
119 | changed in read.c . Ideally it shouldn't have to know about it at all, |
120 | but nothing is ideal around here. |
121 | */ |
122 | |
123 | static unsigned char octal[256]; |
124 | #define isoctal(c) octal[c] |
125 | static unsigned char toHex[256]; |
126 | |
127 | /* |
128 | * anull bit - causes the branch delay slot instructions to not be executed |
129 | */ |
130 | #define ANNUL (1 << 29) |
131 | |
132 | static void |
133 | s_use() |
134 | { |
135 | |
136 | if (strncmp(input_line_pointer, ".text", 5) == 0) { |
137 | input_line_pointer += 5; |
138 | s_text(); |
139 | return; |
140 | } |
141 | if (strncmp(input_line_pointer, ".data", 5) == 0) { |
142 | input_line_pointer += 5; |
143 | s_data(); |
144 | return; |
145 | } |
146 | if (strncmp(input_line_pointer, ".data1", 6) == 0) { |
147 | input_line_pointer += 6; |
148 | s_data1(); |
149 | return; |
150 | } |
151 | /* Literals can't go in the text segment because you can't read |
152 | from instruction memory on some 29k's. So, into initialized data. */ |
153 | if (strncmp(input_line_pointer, ".lit", 4) == 0) { |
154 | input_line_pointer += 4; |
155 | subseg_new(SEG_DATA, 200); |
156 | demand_empty_rest_of_line(); |
157 | return; |
158 | } |
159 | |
160 | as_bad("Unknown segment type"); |
161 | demand_empty_rest_of_line(); |
162 | return; |
163 | } |
164 | |
165 | static void |
166 | s_data1() |
167 | { |
168 | subseg_new(SEG_DATA, 1); |
169 | demand_empty_rest_of_line(); |
170 | return; |
171 | } |
172 | |
173 | /* Install symbol definition that maps REGNAME to REGNO. |
174 | FIXME-SOON: These are not recognized in mixed case. */ |
175 | |
176 | static void |
177 | insert_sreg (regname, regnum) |
178 | char *regname; |
179 | int regnum; |
180 | { |
181 | /* FIXME-SOON, put something in these syms so they won't be output to the symbol |
182 | table of the resulting object file. */ |
183 | |
184 | /* Must be large enough to hold the names of the special registers. */ |
185 | char buf[80]; |
186 | int i; |
187 | |
188 | symbol_table_insert(symbol_new(regname, SEG_REGISTER, regnum, &zero_address_frag)); |
189 | for (i = 0; regname[i]; i++) |
190 | buf[i] = islower (regname[i]) ? toupper (regname[i]) : regname[i]; |
191 | buf[i] = '\0'; |
192 | |
193 | symbol_table_insert(symbol_new(buf, SEG_REGISTER, regnum, &zero_address_frag)); |
194 | } /* insert_sreg() */ |
195 | |
196 | /* Install symbol definitions for assorted special registers. |
197 | See ASM29K Ref page 2-9. */ |
198 | |
199 | void define_some_regs() { |
200 | #define SREG 256 |
201 | |
202 | /* Protected special-purpose register names */ |
203 | insert_sreg ("vab", SREG+0); |
204 | insert_sreg ("ops", SREG+1); |
205 | insert_sreg ("cps", SREG+2); |
206 | insert_sreg ("cfg", SREG+3); |
207 | insert_sreg ("cha", SREG+4); |
208 | insert_sreg ("chd", SREG+5); |
209 | insert_sreg ("chc", SREG+6); |
210 | insert_sreg ("rbp", SREG+7); |
211 | insert_sreg ("tmc", SREG+8); |
212 | insert_sreg ("tmr", SREG+9); |
213 | insert_sreg ("pc0", SREG+10); |
214 | insert_sreg ("pc1", SREG+11); |
215 | insert_sreg ("pc2", SREG+12); |
216 | insert_sreg ("mmu", SREG+13); |
217 | insert_sreg ("lru", SREG+14); |
218 | |
219 | /* Unprotected special-purpose register names */ |
220 | insert_sreg ("ipc", SREG+128); |
221 | insert_sreg ("ipa", SREG+129); |
222 | insert_sreg ("ipb", SREG+130); |
223 | insert_sreg ("q", SREG+131); |
224 | insert_sreg ("alu", SREG+132); |
225 | insert_sreg ("bp", SREG+133); |
226 | insert_sreg ("fc", SREG+134); |
227 | insert_sreg ("cr", SREG+135); |
228 | insert_sreg ("fpe", SREG+160); |
229 | insert_sreg ("inte",SREG+161); |
230 | insert_sreg ("fps", SREG+162); |
231 | /* "", SREG+163); Reserved */ |
232 | insert_sreg ("exop",SREG+164); |
233 | } /* define_some_regs() */ |
234 | |
235 | /* This function is called once, at assembler startup time. It should |
236 | set up all the tables, etc. that the MD part of the assembler will need. */ |
237 | void |
238 | md_begin() |
239 | { |
240 | register char *retval = NULL; |
241 | int lose = 0; |
242 | register int skipnext = 0; |
243 | register unsigned int i; |
244 | register char *strend, *strend2; |
245 | |
246 | /* Hash up all the opcodes for fast use later. */ |
247 | |
248 | op_hash = hash_new(); |
249 | if (op_hash == NULL) |
250 | as_fatal("Virtual memory exhausted"); |
251 | |
252 | for (i = 0; i < num_opcodes; i++) |
253 | { |
254 | const char *name = machine_opcodes[i].name; |
255 | |
256 | if (skipnext) { |
257 | skipnext = 0; |
258 | continue; |
259 | } |
260 | |
261 | /* Hack to avoid multiple opcode entries. We pre-locate all the |
262 | variations (b/i field and P/A field) and handle them. */ |
263 | |
264 | if (!strcmp (name, machine_opcodes[i+1].name)) { |
265 | if ((machine_opcodes[i].opcode ^ machine_opcodes[i+1].opcode) |
266 | != 0x01000000) |
267 | goto bad_table; |
268 | strend = machine_opcodes[i ].args+strlen(machine_opcodes[i ].args)-1; |
269 | strend2 = machine_opcodes[i+1].args+strlen(machine_opcodes[i+1].args)-1; |
270 | switch (*strend) { |
271 | case 'b': |
272 | if (*strend2 != 'i') goto bad_table; |
273 | break; |
274 | case 'i': |
275 | if (*strend2 != 'b') goto bad_table; |
276 | break; |
277 | case 'P': |
278 | if (*strend2 != 'A') goto bad_table; |
279 | break; |
280 | case 'A': |
281 | if (*strend2 != 'P') goto bad_table; |
282 | break; |
283 | default: |
284 | bad_table: |
285 | fprintf (stderr, "internal error: can't handle opcode %s\n", name); |
286 | lose = 1; |
287 | } |
288 | |
289 | /* OK, this is an i/b or A/P pair. We skip the higher-valued one, |
290 | and let the code for operand checking handle OR-ing in the bit. */ |
291 | if (machine_opcodes[i].opcode & 1) |
292 | continue; |
293 | else |
294 | skipnext = 1; |
295 | } |
296 | |
297 | retval = hash_insert (op_hash, name, &machine_opcodes[i]); |
298 | if (retval != NULL && *retval != '\0') |
299 | { |
300 | fprintf (stderr, "internal error: can't hash `%s': %s\n", |
301 | machine_opcodes[i].name, retval); |
302 | lose = 1; |
303 | } |
304 | } |
305 | |
306 | if (lose) |
307 | as_fatal("Broken assembler. No assembly attempted."); |
308 | |
309 | for (i = '0'; i < '8'; ++i) |
310 | octal[i] = 1; |
311 | for (i = '0'; i <= '9'; ++i) |
312 | toHex[i] = i - '0'; |
313 | for (i = 'a'; i <= 'f'; ++i) |
314 | toHex[i] = i + 10 - 'a'; |
315 | for (i = 'A'; i <= 'F'; ++i) |
316 | toHex[i] = i + 10 - 'A'; |
317 | |
318 | define_some_regs (); |
319 | } |
320 | |
321 | void md_end() { |
322 | return; |
323 | } |
324 | |
325 | /* Assemble a single instruction. Its label has already been handled |
326 | by the generic front end. We just parse opcode and operands, and |
327 | produce the bytes of data and relocation. */ |
328 | |
329 | void md_assemble(str) |
330 | char *str; |
331 | { |
332 | char *toP; |
333 | /* !!!! int rsd; */ |
334 | |
335 | know(str); |
336 | machine_ip(str); |
337 | toP = frag_more(4); |
338 | /* put out the opcode */ |
339 | md_number_to_chars(toP, the_insn.opcode, 4); |
340 | |
341 | /* put out the symbol-dependent stuff */ |
342 | if (the_insn.reloc != NO_RELOC) { |
343 | fix_new( |
344 | frag_now, /* which frag */ |
345 | (toP - frag_now->fr_literal + the_insn.reloc_offset), /* where */ |
346 | 4, /* size */ |
347 | the_insn.exp.X_add_symbol, |
348 | the_insn.exp.X_subtract_symbol, |
349 | the_insn.exp.X_add_number, |
350 | the_insn.pcrel, |
351 | the_insn.reloc |
352 | ); |
353 | } |
354 | } |
355 | |
356 | char * |
357 | parse_operand (s, operandp) |
358 | char *s; |
359 | expressionS *operandp; |
360 | { |
361 | char *save = input_line_pointer; |
362 | char *new; |
363 | segT seg; |
364 | |
365 | input_line_pointer = s; |
366 | seg = expr (0, operandp); |
367 | new = input_line_pointer; |
368 | input_line_pointer = save; |
369 | |
370 | switch (seg) { |
371 | case SEG_ABSOLUTE: |
372 | case SEG_TEXT: |
373 | case SEG_DATA: |
374 | case SEG_BSS: |
375 | case SEG_UNKNOWN: |
376 | case SEG_DIFFERENCE: |
377 | case SEG_BIG: |
378 | case SEG_REGISTER: |
379 | return new; |
380 | |
381 | case SEG_ABSENT: |
382 | as_bad("Missing operand"); |
383 | return new; |
384 | |
385 | default: |
386 | as_bad("Don't understand operand of type %s", segment_name (seg)); |
387 | return new; |
388 | } |
389 | } |
390 | |
391 | /* Instruction parsing. Takes a string containing the opcode. |
392 | Operands are at input_line_pointer. Output is in the_insn. |
393 | Warnings or errors are generated. */ |
394 | |
395 | static void |
396 | machine_ip(str) |
397 | char *str; |
398 | { |
399 | char *s; |
400 | const char *args; |
401 | /* !!!! char c; */ |
402 | /* !!!! unsigned long i; */ |
403 | struct machine_opcode *insn; |
404 | char *argsStart; |
405 | unsigned long opcode; |
406 | /* !!!! unsigned int mask; */ |
407 | expressionS the_operand; |
408 | expressionS *operand = &the_operand; |
409 | unsigned int reg; |
410 | |
411 | /* Must handle `div0' opcode. */ |
412 | s = str; |
413 | if (isalpha(*s)) |
414 | for (; isalnum(*s); ++s) |
415 | if (isupper (*s)) |
416 | *s = tolower (*s); |
417 | |
418 | switch (*s) { |
419 | case '\0': |
420 | break; |
421 | |
422 | case ' ': /* FIXME-SOMEDAY more whitespace */ |
423 | *s++ = '\0'; |
424 | break; |
425 | |
426 | default: |
427 | as_bad("Unknown opcode: `%s'", str); |
428 | return; |
429 | } |
430 | if ((insn = (struct machine_opcode *) hash_find(op_hash, str)) == NULL) { |
431 | as_bad("Unknown opcode `%s'.", str); |
432 | return; |
433 | } |
434 | argsStart = s; |
435 | opcode = insn->opcode; |
436 | bzero(&the_insn, sizeof(the_insn)); |
437 | the_insn.reloc = NO_RELOC; |
438 | |
439 | /* |
440 | * Build the opcode, checking as we go to make |
441 | * sure that the operands match. |
442 | * |
443 | * If an operand matches, we modify the_insn or opcode appropriately, |
444 | * and do a "continue". If an operand fails to match, we "break". |
445 | */ |
446 | if (insn->args[0] != '\0') |
447 | s = parse_operand (s, operand); /* Prime the pump */ |
448 | |
449 | for (args = insn->args; ; ++args) { |
450 | switch (*args) { |
451 | |
452 | case '\0': /* end of args */ |
453 | if (*s == '\0') { |
454 | /* We are truly done. */ |
455 | the_insn.opcode = opcode; |
456 | return; |
457 | } |
458 | as_bad("Too many operands: %s", s); |
459 | break; |
460 | |
461 | case ',': /* Must match a comma */ |
462 | if (*s++ == ',') { |
463 | s = parse_operand (s, operand); /* Parse next opnd */ |
464 | continue; |
465 | } |
466 | break; |
467 | |
468 | case 'v': /* Trap numbers (immediate field) */ |
469 | if (operand->X_seg == SEG_ABSOLUTE) { |
470 | if (operand->X_add_number < 256) { |
471 | opcode |= (operand->X_add_number << 16); |
472 | continue; |
473 | } else { |
474 | as_bad("Immediate value of %d is too large", |
475 | operand->X_add_number); |
476 | continue; |
477 | } |
478 | } |
479 | the_insn.reloc = RELOC_8; |
480 | the_insn.reloc_offset = 1; /* BIG-ENDIAN Byte 1 of insn */ |
481 | the_insn.exp = *operand; |
482 | continue; |
483 | |
484 | case 'b': /* A general register or 8-bit immediate */ |
485 | case 'i': |
486 | /* We treat the two cases identically since we mashed |
487 | them together in the opcode table. */ |
488 | if (operand->X_seg == SEG_REGISTER) |
489 | goto general_reg; |
490 | |
491 | opcode |= IMMEDIATE_BIT; |
492 | if (operand->X_seg == SEG_ABSOLUTE) { |
493 | if (operand->X_add_number < 256) { |
494 | opcode |= operand->X_add_number; |
495 | continue; |
496 | } else { |
497 | as_bad("Immediate value of %d is too large", |
498 | operand->X_add_number); |
499 | continue; |
500 | } |
501 | } |
502 | the_insn.reloc = RELOC_8; |
503 | the_insn.reloc_offset = 3; /* BIG-ENDIAN Byte 3 of insn */ |
504 | the_insn.exp = *operand; |
505 | continue; |
506 | |
507 | case 'a': /* next operand must be a register */ |
508 | case 'c': |
509 | general_reg: |
510 | /* lrNNN or grNNN or %%expr or a user-def register name */ |
511 | if (operand->X_seg != SEG_REGISTER) |
512 | break; /* Only registers */ |
513 | know (operand->X_add_symbol == 0); |
514 | know (operand->X_subtract_symbol == 0); |
515 | reg = operand->X_add_number; |
516 | if (reg >= SREG) |
517 | break; /* No special registers */ |
518 | |
519 | /* |
520 | * Got the register, now figure out where |
521 | * it goes in the opcode. |
522 | */ |
523 | switch (*args) { |
524 | case 'a': |
525 | opcode |= reg << 8; |
526 | continue; |
527 | |
528 | case 'b': |
529 | case 'i': |
530 | opcode |= reg; |
531 | continue; |
532 | |
533 | case 'c': |
534 | opcode |= reg << 16; |
535 | continue; |
536 | } |
537 | abort(); |
538 | break; |
539 | |
540 | case 'x': /* 16 bit constant, zero-extended */ |
541 | case 'X': /* 16 bit constant, one-extended */ |
542 | if (operand->X_seg == SEG_ABSOLUTE) { |
543 | opcode |= (operand->X_add_number & 0xFF) << 0 | |
544 | ((operand->X_add_number & 0xFF00) << 8); |
545 | continue; |
546 | } |
547 | the_insn.reloc = RELOC_CONST; |
548 | the_insn.exp = *operand; |
549 | continue; |
550 | |
551 | case 'h': |
552 | if (operand->X_seg == SEG_ABSOLUTE) { |
553 | opcode |= (operand->X_add_number & 0x00FF0000) >> 16 | |
554 | (((unsigned long)operand->X_add_number |
555 | /* avoid sign ext */ & 0xFF000000) >> 8); |
556 | continue; |
557 | } |
558 | the_insn.reloc = RELOC_CONSTH; |
559 | the_insn.exp = *operand; |
560 | continue; |
561 | |
562 | case 'P': /* PC-relative jump address */ |
563 | case 'A': /* Absolute jump address */ |
564 | /* These two are treated together since we folded the |
565 | opcode table entries together. */ |
566 | if (operand->X_seg == SEG_ABSOLUTE) { |
567 | opcode |= ABSOLUTE_BIT | |
568 | (operand->X_add_number & 0x0003FC00) << 6 | |
569 | ((operand->X_add_number & 0x000003FC) >> 2); |
570 | continue; |
571 | } |
572 | the_insn.reloc = RELOC_JUMPTARG; |
573 | the_insn.exp = *operand; |
574 | the_insn.pcrel = 1; /* Assume PC-relative jump */ |
575 | /* FIXME-SOON, Do we figure out whether abs later, after know sym val? */ |
576 | continue; |
577 | |
578 | case 'e': /* Coprocessor enable bit for LOAD/STORE insn */ |
579 | if (operand->X_seg == SEG_ABSOLUTE) { |
580 | if (operand->X_add_number == 0) |
581 | continue; |
582 | if (operand->X_add_number == 1) { |
583 | opcode |= CE_BIT; |
584 | continue; |
585 | } |
586 | } |
587 | break; |
588 | |
589 | case 'n': /* Control bits for LOAD/STORE instructions */ |
590 | if (operand->X_seg == SEG_ABSOLUTE && |
591 | operand->X_add_number < 128) { |
592 | opcode |= (operand->X_add_number << 16); |
593 | continue; |
594 | } |
595 | break; |
596 | |
597 | case 's': /* Special register number */ |
598 | if (operand->X_seg != SEG_REGISTER) |
599 | break; /* Only registers */ |
600 | if (operand->X_add_number < SREG) |
601 | break; /* Not a special register */ |
602 | opcode |= (operand->X_add_number & 0xFF) << 8; |
603 | continue; |
604 | |
605 | case 'u': /* UI bit of CONVERT */ |
606 | if (operand->X_seg == SEG_ABSOLUTE) { |
607 | if (operand->X_add_number == 0) |
608 | continue; |
609 | if (operand->X_add_number == 1) { |
610 | opcode |= UI_BIT; |
611 | continue; |
612 | } |
613 | } |
614 | break; |
615 | |
616 | case 'r': /* RND bits of CONVERT */ |
617 | if (operand->X_seg == SEG_ABSOLUTE && |
618 | operand->X_add_number < 8) { |
619 | opcode |= operand->X_add_number << 4; |
620 | continue; |
621 | } |
622 | break; |
623 | |
624 | case 'd': /* FD bits of CONVERT */ |
625 | if (operand->X_seg == SEG_ABSOLUTE && |
626 | operand->X_add_number < 4) { |
627 | opcode |= operand->X_add_number << 2; |
628 | continue; |
629 | } |
630 | break; |
631 | |
632 | |
633 | case 'f': /* FS bits of CONVERT */ |
634 | if (operand->X_seg == SEG_ABSOLUTE && |
635 | operand->X_add_number < 4) { |
636 | opcode |= operand->X_add_number << 0; |
637 | continue; |
638 | } |
639 | break; |
640 | |
641 | case 'C': |
642 | if (operand->X_seg == SEG_ABSOLUTE && |
643 | operand->X_add_number < 4) { |
644 | opcode |= operand->X_add_number << 16; |
645 | continue; |
646 | } |
647 | break; |
648 | |
649 | case 'F': |
650 | if (operand->X_seg == SEG_ABSOLUTE && |
651 | operand->X_add_number < 16) { |
652 | opcode |= operand->X_add_number << 18; |
653 | continue; |
654 | } |
655 | break; |
656 | |
657 | default: |
658 | BAD_CASE (*args); |
659 | } |
660 | /* Types or values of args don't match. */ |
661 | as_bad("Invalid operands"); |
662 | return; |
663 | } |
664 | } |
665 | |
666 | /* |
667 | This is identical to the md_atof in m68k.c. I think this is right, |
668 | but I'm not sure. |
669 | |
670 | Turn a string in input_line_pointer into a floating point constant of type |
671 | type, and store the appropriate bytes in *litP. The number of LITTLENUMS |
672 | emitted is stored in *sizeP . An error message is returned, or NULL on OK. |
673 | */ |
674 | |
675 | /* Equal to MAX_PRECISION in atof-ieee.c */ |
676 | #define MAX_LITTLENUMS 6 |
677 | |
678 | char * |
679 | md_atof(type,litP,sizeP) |
680 | char type; |
681 | char *litP; |
682 | int *sizeP; |
683 | { |
684 | int prec; |
685 | LITTLENUM_TYPE words[MAX_LITTLENUMS]; |
686 | LITTLENUM_TYPE *wordP; |
687 | char *t; |
688 | |
689 | switch(type) { |
690 | |
691 | case 'f': |
692 | case 'F': |
693 | case 's': |
694 | case 'S': |
695 | prec = 2; |
696 | break; |
697 | |
698 | case 'd': |
699 | case 'D': |
700 | case 'r': |
701 | case 'R': |
702 | prec = 4; |
703 | break; |
704 | |
705 | case 'x': |
706 | case 'X': |
707 | prec = 6; |
708 | break; |
709 | |
710 | case 'p': |
711 | case 'P': |
712 | prec = 6; |
713 | break; |
714 | |
715 | default: |
716 | *sizeP=0; |
717 | return "Bad call to MD_ATOF()"; |
718 | } |
719 | t=atof_ieee(input_line_pointer,type,words); |
720 | if(t) |
721 | input_line_pointer=t; |
722 | *sizeP=prec * sizeof(LITTLENUM_TYPE); |
723 | for(wordP=words;prec--;) { |
724 | md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE)); |
725 | litP+=sizeof(LITTLENUM_TYPE); |
726 | } |
727 | return ""; /* Someone should teach Dean about null pointers */ |
728 | } |
729 | |
730 | /* |
731 | * Write out big-endian. |
732 | */ |
733 | void |
734 | md_number_to_chars(buf,val,n) |
735 | char *buf; |
736 | long val; |
737 | int n; |
738 | { |
739 | |
740 | switch(n) { |
741 | |
742 | case 4: |
743 | *buf++ = val >> 24; |
744 | *buf++ = val >> 16; |
745 | case 2: |
746 | *buf++ = val >> 8; |
747 | case 1: |
748 | *buf = val; |
749 | break; |
750 | |
751 | default: |
752 | abort(); |
753 | } |
754 | return; |
755 | } |
756 | |
757 | void md_apply_fix(fixP, val) |
758 | fixS *fixP; |
759 | long val; |
760 | { |
761 | char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; |
762 | |
763 | fixP->fx_addnumber = val; /* Remember value for emit_reloc */ |
764 | |
765 | if (fixP->fx_r_type == NO_RELOC) { |
766 | abort(); /* FIXME-SOON, if this is never used, remove */ |
767 | switch (fixP->fx_size) { |
768 | case 1: |
769 | *buf = val; |
770 | break; |
771 | case 2: |
772 | *buf++ = (val>>8); |
773 | *buf = val; |
774 | break; |
775 | case 4: |
776 | *buf++ = (val>>24); |
777 | *buf++ = (val>>16); |
778 | *buf++ = (val>>8); |
779 | *buf = val; |
780 | break; |
781 | default: |
782 | abort(); |
783 | } |
784 | return; |
785 | } |
786 | |
787 | know(fixP->fx_size == 4); |
788 | know(fixP->fx_r_type < NO_RELOC); |
789 | |
790 | /* |
791 | * This is a hack. There should be a better way to |
792 | * handle this. |
793 | */ |
794 | if (fixP->fx_r_type == RELOC_WDISP30 && fixP->fx_addsy) { |
795 | val += fixP->fx_where + fixP->fx_frag->fr_address; |
796 | } |
797 | |
798 | switch (fixP->fx_r_type) { |
799 | |
800 | case RELOC_32: |
801 | buf[0] = val >> 24; |
802 | buf[1] = val >> 16; |
803 | buf[2] = val >> 8; |
804 | buf[3] = val; |
805 | break; |
806 | |
807 | case RELOC_8: |
808 | buf[0] = val; |
809 | break; |
810 | |
811 | case RELOC_WDISP30: |
812 | val = (val >>= 2) + 1; |
813 | buf[0] |= (val >> 24) & 0x3f; |
814 | buf[1]= (val >> 16); |
815 | buf[2] = val >> 8; |
816 | buf[3] = val; |
817 | break; |
818 | |
819 | case RELOC_HI22: |
820 | buf[1] |= (val >> 26) & 0x3f; |
821 | buf[2] = val >> 18; |
822 | buf[3] = val >> 10; |
823 | break; |
824 | |
825 | case RELOC_LO10: |
826 | buf[2] |= (val >> 8) & 0x03; |
827 | buf[3] = val; |
828 | break; |
829 | |
830 | case RELOC_BASE13: |
831 | buf[2] |= (val >> 8) & 0x1f; |
832 | buf[3] = val; |
833 | break; |
834 | |
835 | case RELOC_WDISP22: |
836 | val = (val >>= 2) + 1; |
837 | /* FALLTHROUGH */ |
838 | case RELOC_BASE22: |
839 | buf[1] |= (val >> 16) & 0x3f; |
840 | buf[2] = val >> 8; |
841 | buf[3] = val; |
842 | break; |
843 | |
844 | #if 0 |
845 | case RELOC_PC10: |
846 | case RELOC_PC22: |
847 | case RELOC_JMP_TBL: |
848 | case RELOC_SEGOFF16: |
849 | case RELOC_GLOB_DAT: |
850 | case RELOC_JMP_SLOT: |
851 | case RELOC_RELATIVE: |
852 | #endif |
853 | case RELOC_JUMPTARG: /* 00XX00XX pattern in a word */ |
854 | buf[1] = val >> 10; /* Holds bits 0003FFFC of address */ |
855 | buf[3] = val >> 2; |
856 | break; |
857 | |
858 | case RELOC_CONST: /* 00XX00XX pattern in a word */ |
859 | buf[1] = val >> 8; /* Holds bits 0000XXXX */ |
860 | buf[3] = val; |
861 | break; |
862 | |
863 | case RELOC_CONSTH: /* 00XX00XX pattern in a word */ |
864 | buf[1] = val >> 24; /* Holds bits XXXX0000 */ |
865 | buf[3] = val >> 16; |
866 | break; |
867 | |
868 | case NO_RELOC: |
869 | default: |
870 | as_bad("bad relocation type: 0x%02x", fixP->fx_r_type); |
871 | break; |
872 | } |
873 | return; |
874 | } |
875 | |
876 | #ifdef OBJ_COFF |
877 | short tc_coff_fix2rtype(fixP) |
878 | fixS *fixP; |
879 | { |
880 | |
881 | /* FIXME-NOW: relocation type handling is not yet written for |
882 | a29k. */ |
883 | |
884 | know(0); |
885 | switch (fixP->fx_r_type) { |
886 | case RELOC_32: return(R_WORD); |
887 | case RELOC_8: return(R_BYTE); |
888 | default: know(0); |
889 | } /* switch on type */ |
890 | |
891 | return(0); |
892 | } /* tc_coff_fix2rtype() */ |
893 | #endif /* OBJ_COFF */ |
894 | |
895 | /* should never be called for sparc */ |
896 | void md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol) |
897 | char *ptr; |
898 | long from_addr, to_addr; |
899 | fragS *frag; |
900 | symbolS *to_symbol; |
901 | { |
902 | fprintf(stderr, "a29k_create_short_jmp\n"); |
903 | abort(); |
904 | } |
905 | |
906 | /* Translate internal representation of relocation info to target format. |
907 | |
908 | On sparc/29k: first 4 bytes are normal unsigned long address, next three |
909 | bytes are index, most sig. byte first. Byte 7 is broken up with |
910 | bit 7 as external, bits 6 & 5 unused, and the lower |
911 | five bits as relocation type. Next 4 bytes are long addend. */ |
912 | /* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */ |
913 | void |
914 | md_ri_to_chars(the_bytes, ri) |
915 | char *the_bytes; |
916 | struct reloc_info_generic *ri; |
917 | { |
918 | /* this is easy */ |
919 | md_number_to_chars(the_bytes, ri->r_address, 4); |
920 | /* now the fun stuff */ |
921 | the_bytes[4] = (ri->r_index >> 16) & 0x0ff; |
922 | the_bytes[5] = (ri->r_index >> 8) & 0x0ff; |
923 | the_bytes[6] = ri->r_index & 0x0ff; |
924 | the_bytes[7] = ((ri->r_extern << 7) & 0x80) | (0 & 0x60) | (ri->r_type & 0x1F); |
925 | /* Also easy */ |
926 | md_number_to_chars(&the_bytes[8], ri->r_addend, 4); |
927 | } |
928 | |
929 | /* should never be called for 29k */ |
930 | void md_convert_frag(fragP) |
931 | register fragS *fragP; |
932 | { |
933 | fprintf(stderr, "sparc_convert_frag\n"); |
934 | abort(); |
935 | } |
936 | |
937 | /* should never be called for 29k */ |
938 | void md_create_long_jump(ptr, from_addr, to_addr, frag, to_symbol) |
939 | char *ptr; |
940 | long from_addr, |
941 | to_addr; |
942 | fragS *frag; |
943 | symbolS *to_symbol; |
944 | { |
945 | fprintf(stderr, "sparc_create_long_jump\n"); |
946 | abort(); |
947 | } |
948 | |
949 | /* should never be called for sparc */ |
950 | int md_estimate_size_before_relax(fragP, segtype) |
951 | register fragS *fragP; |
952 | segT segtype; |
953 | { |
954 | fprintf(stderr, "sparc_estimate_size_before_relax\n"); |
955 | abort(); |
956 | return 0; |
957 | } |
958 | |
959 | #if 0 |
960 | /* for debugging only */ |
961 | static void |
962 | print_insn(insn) |
963 | struct machine_it *insn; |
964 | { |
965 | char *Reloc[] = { |
966 | "RELOC_8", |
967 | "RELOC_16", |
968 | "RELOC_32", |
969 | "RELOC_DISP8", |
970 | "RELOC_DISP16", |
971 | "RELOC_DISP32", |
972 | "RELOC_WDISP30", |
973 | "RELOC_WDISP22", |
974 | "RELOC_HI22", |
975 | "RELOC_22", |
976 | "RELOC_13", |
977 | "RELOC_LO10", |
978 | "RELOC_SFA_BASE", |
979 | "RELOC_SFA_OFF13", |
980 | "RELOC_BASE10", |
981 | "RELOC_BASE13", |
982 | "RELOC_BASE22", |
983 | "RELOC_PC10", |
984 | "RELOC_PC22", |
985 | "RELOC_JMP_TBL", |
986 | "RELOC_SEGOFF16", |
987 | "RELOC_GLOB_DAT", |
988 | "RELOC_JMP_SLOT", |
989 | "RELOC_RELATIVE", |
990 | "NO_RELOC" |
991 | }; |
992 | |
993 | if (insn->error) { |
994 | fprintf(stderr, "ERROR: %s\n"); |
995 | } |
996 | fprintf(stderr, "opcode=0x%08x\n", insn->opcode); |
997 | fprintf(stderr, "reloc = %s\n", Reloc[insn->reloc]); |
998 | fprintf(stderr, "exp = {\n"); |
999 | fprintf(stderr, "\t\tX_add_symbol = %s\n", |
1000 | insn->exp.X_add_symbol ? |
1001 | (S_GET_NAME(insn->exp.X_add_symbol) ? |
1002 | S_GET_NAME(insn->exp.X_add_symbol) : "???") : "0"); |
1003 | fprintf(stderr, "\t\tX_sub_symbol = %s\n", |
1004 | insn->exp.X_subtract_symbol ? |
1005 | (S_GET_NAME(insn->exp.X_subtract_symbol) ? |
1006 | S_GET_NAME(insn->exp.X_subtract_symbol) : "???") : "0"); |
1007 | fprintf(stderr, "\t\tX_add_number = %d\n", |
1008 | insn->exp.X_add_number); |
1009 | fprintf(stderr, "}\n"); |
1010 | return; |
1011 | } |
1012 | #endif |
1013 | |
1014 | /* |
1015 | * Sparc/A29K relocations are completely different, so it needs |
1016 | * this machine dependent routine to emit them. |
1017 | */ |
1018 | #ifdef OBJ_AOUT |
1019 | static void emit_machine_reloc(fixP, segment_address_in_file) |
1020 | register fixS *fixP; |
1021 | relax_addressT segment_address_in_file; |
1022 | { |
1023 | struct reloc_info_generic ri; |
1024 | register symbolS *symbolP; |
1025 | extern char *next_object_file_charP; |
1026 | /* !!!! long add_number; */ |
1027 | |
1028 | bzero((char *) &ri, sizeof(ri)); |
1029 | for (; fixP; fixP = fixP->fx_next) { |
1030 | |
1031 | if (fixP->fx_r_type >= NO_RELOC) { |
1032 | fprintf(stderr, "fixP->fx_r_type = %d\n", fixP->fx_r_type); |
1033 | abort(); |
1034 | } |
1035 | |
1036 | if ((symbolP = fixP->fx_addsy) != NULL) { |
1037 | ri.r_address = fixP->fx_frag->fr_address + |
1038 | fixP->fx_where - segment_address_in_file; |
1039 | ri.r_addend = fixP->fx_addnumber; |
1040 | if (!S_IS_DEFINED(symbolP)) { |
1041 | ri.r_extern = 1; |
1042 | ri.r_index = symbolP->sy_number; |
1043 | } else { |
1044 | ri.r_extern = 0; |
1045 | ri.r_index = S_GET_TYPE(symbolP); |
1046 | } |
1047 | ri.r_type = fixP->fx_r_type; |
1048 | |
1049 | md_ri_to_chars (next_object_file_charP, &ri); |
1050 | next_object_file_charP += md_reloc_size; |
1051 | } |
1052 | } |
1053 | } /* emit_machine_reloc() */ |
1054 | |
1055 | void (*md_emit_relocations)() = emit_machine_reloc; |
1056 | |
1057 | #endif /* OBJ_AOUT */ |
1058 | |
1059 | int |
1060 | md_parse_option(argP,cntP,vecP) |
1061 | char **argP; |
1062 | int *cntP; |
1063 | char ***vecP; |
1064 | { |
1065 | return 1; |
1066 | } |
1067 | |
1068 | |
1069 | /* Default the values of symbols known that should be "predefined". We |
1070 | don't bother to predefine them unless you actually use one, since there |
1071 | are a lot of them. */ |
1072 | |
1073 | symbolS *md_undefined_symbol (name) |
1074 | char *name; |
1075 | { |
1076 | long regnum; |
1077 | char testbuf[5+ /*SLOP*/ 5]; |
1078 | |
1079 | if (name[0] == 'g' || name[0] == 'G' || name[0] == 'l' || name[0] == 'L') |
1080 | { |
1081 | /* Perhaps a global or local register name */ |
1082 | if (name[1] == 'r' || name[1] == 'R') |
1083 | { |
1084 | /* Parse the number, make sure it has no extra zeroes or trailing |
1085 | chars */ |
1086 | regnum = atol(&name[2]); |
1087 | if (regnum > 127) |
1088 | return 0; |
1089 | sprintf(testbuf, "%ld", regnum); |
1090 | if (strcmp (testbuf, &name[2]) != 0) |
1091 | return 0; /* gr007 or lr7foo or whatever */ |
1092 | |
1093 | /* We have a wiener! Define and return a new symbol for it. */ |
1094 | if (name[0] == 'l' || name[0] == 'L') |
1095 | regnum += 128; |
1096 | return(symbol_new(name, SEG_REGISTER, regnum, &zero_address_frag)); |
1097 | } |
1098 | } |
1099 | |
1100 | return 0; |
1101 | } |
1102 | |
1103 | /* Parse an operand that is machine-specific. */ |
1104 | |
1105 | void md_operand(expressionP) |
1106 | expressionS *expressionP; |
1107 | { |
1108 | |
1109 | if (input_line_pointer[0] == '%' && input_line_pointer[1] == '%') |
1110 | { |
1111 | /* We have a numeric register expression. No biggy. */ |
1112 | input_line_pointer += 2; /* Skip %% */ |
1113 | (void)expression (expressionP); |
1114 | if (expressionP->X_seg != SEG_ABSOLUTE |
1115 | || expressionP->X_add_number > 255) |
1116 | as_bad("Invalid expression after %%%%\n"); |
1117 | expressionP->X_seg = SEG_REGISTER; |
1118 | } |
1119 | else if (input_line_pointer[0] == '&') |
1120 | { |
1121 | /* We are taking the 'address' of a register...this one is not |
1122 | in the manual, but it *is* in traps/fpsymbol.h! What they |
1123 | seem to want is the register number, as an absolute number. */ |
1124 | input_line_pointer++; /* Skip & */ |
1125 | (void)expression (expressionP); |
1126 | if (expressionP->X_seg != SEG_REGISTER) |
1127 | as_bad("Invalid register in & expression"); |
1128 | else |
1129 | expressionP->X_seg = SEG_ABSOLUTE; |
1130 | } |
1131 | } |
1132 | |
1133 | /* Round up a section size to the appropriate boundary. */ |
1134 | long |
1135 | md_section_align (segment, size) |
1136 | segT segment; |
1137 | long size; |
1138 | { |
1139 | return size; /* Byte alignment is fine */ |
1140 | } |
1141 | |
1142 | /* Exactly what point is a PC-relative offset relative TO? |
1143 | On the 29000, they're relative to the address of the instruction, |
1144 | which we have set up as the address of the fixup too. */ |
1145 | long md_pcrel_from (fixP) |
1146 | fixS *fixP; |
1147 | { |
1148 | return fixP->fx_where + fixP->fx_frag->fr_address; |
1149 | } |
1150 | |
1151 | /* |
1152 | * Local Variables: |
1153 | * comment-column: 0 |
1154 | * End: |
1155 | */ |
1156 | |
1157 | /* end of tc-a29k.c */ |