fighting bitrot in a major way
[binutils-gdb.git] / gas / config / tc-i860.c
1 /* tc-i860.c -- Assemble for the I860
2 Copyright (C) 1989, 1992 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 2, 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 #include "as.h"
21
22 #include "opcode/i860.h"
23
24 /* incorporated from i860.h */
25 enum reloc_type /* NOTE: three bits max, see struct reloc_info_i860.r_type */
26 {
27 NO_RELOC = 0, BRADDR, LOW0, LOW1, LOW2, LOW3, LOW4, SPLIT0, SPLIT1, SPLIT2, RELOC_32,
28 };
29
30 enum highlow_type /* NOTE: two bits max, see reloc_info_i860.r_type */
31 {
32 NO_SPEC = 0, PAIR, HIGH, HIGHADJ,
33 };
34
35 struct reloc_info_i860
36 {
37 unsigned long r_address;
38 /*
39 * Using bit fields here is a bad idea because the order is not portable. :-(
40 */
41 unsigned int r_symbolnum: 24;
42 unsigned int r_pcrel : 1;
43 unsigned int r_extern : 1;
44 /* combining the two field simplifies the argument passing in "new_fix()" */
45 /* and is compatible with the existing Sparc #ifdef's */
46 /* r_type: highlow_type - bits 5,4; reloc_type - bits 3-0 */
47 unsigned int r_type : 6;
48 long r_addend;
49 };
50
51 #define relocation_info reloc_info_i860
52
53
54 void md_begin();
55 void md_end();
56 void md_number_to_chars();
57 void md_assemble();
58 char *md_atof();
59 void md_convert_frag();
60 void md_create_short_jump();
61 void md_create_long_jump();
62 int md_estimate_size_before_relax();
63 void md_number_to_imm();
64 void md_number_to_disp();
65 void md_number_to_field();
66 void md_ri_to_chars();
67 static void i860_ip();
68 void emit_machine_reloc();
69
70 int md_reloc_size = sizeof(struct relocation_info);
71
72 void (*md_emit_relocations)() = emit_machine_reloc;
73
74 const relax_typeS md_relax_table[] = { 0 };
75
76 /* handle of the OPCODE hash table */
77 static struct hash_control *op_hash = NULL;
78
79 static void s_dual(), s_enddual();
80 static void s_atmp();
81
82 const pseudo_typeS
83 md_pseudo_table[] = {
84 { "dual", s_dual, 4 },
85 { "enddual", s_enddual, 4 },
86 { "atmp", s_atmp, 4 },
87 { NULL, 0, 0 },
88 };
89
90 int md_short_jump_size = 4;
91 int md_long_jump_size = 4;
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[] = "!/"; /* JF removed '|' from 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 /* Chars that can be used to separate mant from exp in floating point nums */
107 char EXP_CHARS[] = "eE";
108
109 /* Chars that mean this number is a floating point constant */
110 /* As in 0f12.456 */
111 /* or 0d1.2345e12 */
112 char FLT_CHARS[] = "rRsSfFdDxXpP";
113
114 /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
115 changed in read.c . Ideally it shouldn't have to know about it at all,
116 but nothing is ideal around here.
117 */
118 int size_reloc_info = sizeof(struct relocation_info);
119
120 static unsigned char octal[256];
121 #define isoctal(c) octal[c]
122 static unsigned char toHex[256];
123
124 struct i860_it {
125 char *error;
126 unsigned long opcode;
127 struct nlist *nlistp;
128 expressionS exp;
129 int pcrel;
130 enum expand_type expand;
131 enum highlow_type highlow;
132 enum reloc_type reloc;
133 } the_insn;
134
135 #if __STDC__ == 1
136
137 static void print_insn(struct i860_it *insn);
138 static int getExpression(char *str);
139
140 #else /* not __STDC__ */
141
142 static void print_insn();
143 static int getExpression();
144
145 #endif /* not __STDC__ */
146
147 static char *expr_end;
148 static char last_expand; /* error if expansion after branch */
149
150 enum dual
151 {
152 DUAL_OFF = 0, DUAL_ON, DUAL_DDOT, DUAL_ONDDOT,
153 };
154 static enum dual dual_mode = DUAL_OFF; /* dual-instruction mode */
155
156 static void
157 s_dual() /* floating point instructions have dual set */
158 {
159 dual_mode = DUAL_ON;
160 }
161
162 static void
163 s_enddual() /* floating point instructions have dual set */
164 {
165 dual_mode = DUAL_OFF;
166 }
167
168 static int atmp = 31; /* temporary register for pseudo's */
169
170 static void
171 s_atmp()
172 {
173 register int temp;
174 if (strncmp(input_line_pointer, "sp", 2) == 0) {
175 input_line_pointer += 2;
176 atmp = 2;
177 }
178 else if (strncmp(input_line_pointer, "fp", 2) == 0) {
179 input_line_pointer += 2;
180 atmp = 3;
181 }
182 else if (strncmp(input_line_pointer, "r", 1) == 0) {
183 input_line_pointer += 1;
184 temp = get_absolute_expression();
185 if (temp >= 0 && temp <= 31)
186 atmp = temp;
187 else
188 as_bad("Unknown temporary pseudo register");
189 }
190 else {
191 as_bad("Unknown temporary pseudo register");
192 }
193 demand_empty_rest_of_line();
194 return;
195 }
196
197 /* This function is called once, at assembler startup time. It should
198 set up all the tables, etc. that the MD part of the assembler will need. */
199 void
200 md_begin()
201 {
202 register char *retval = NULL;
203 int lose = 0;
204 register unsigned int i = 0;
205
206 op_hash = hash_new();
207 if (op_hash == NULL)
208 as_fatal("Virtual memory exhausted");
209
210 while (i < NUMOPCODES)
211 {
212 const char *name = i860_opcodes[i].name;
213 retval = hash_insert(op_hash, name, &i860_opcodes[i]);
214 if(retval != NULL && *retval != '\0')
215 {
216 fprintf (stderr, "internal error: can't hash `%s': %s\n",
217 i860_opcodes[i].name, retval);
218 lose = 1;
219 }
220 do
221 {
222 if (i860_opcodes[i].match & i860_opcodes[i].lose)
223 {
224 fprintf (stderr, "internal error: losing opcode: `%s' \"%s\"\n",
225 i860_opcodes[i].name, i860_opcodes[i].args);
226 lose = 1;
227 }
228 ++i;
229 } while (i < NUMOPCODES
230 && !strcmp(i860_opcodes[i].name, name));
231 }
232
233 if (lose)
234 as_fatal("Broken assembler. No assembly attempted.");
235
236 for (i = '0'; i < '8'; ++i)
237 octal[i] = 1;
238 for (i = '0'; i <= '9'; ++i)
239 toHex[i] = i - '0';
240 for (i = 'a'; i <= 'f'; ++i)
241 toHex[i] = i + 10 - 'a';
242 for (i = 'A'; i <= 'F'; ++i)
243 toHex[i] = i + 10 - 'A';
244 }
245
246 void
247 md_end()
248 {
249 return;
250 }
251
252 void
253 md_assemble(str)
254 char *str;
255 {
256 char *toP;
257 int rsd;
258 int no_opcodes = 1;
259 int i;
260 struct i860_it pseudo[3];
261
262 assert(str);
263 i860_ip(str);
264
265 /* check for expandable flag to produce pseudo-instructions */
266 if (the_insn.expand != 0 && the_insn.highlow == NO_SPEC) {
267 for (i = 0; i < 3; i++)
268 pseudo[i] = the_insn;
269
270 switch (the_insn.expand) {
271
272 case E_DELAY:
273 no_opcodes = 1;
274 break;
275
276 case E_MOV:
277 if (the_insn.exp.X_add_symbol == NULL &&
278 the_insn.exp.X_subtract_symbol == NULL &&
279 (the_insn.exp.X_add_number < (1 << 15) &&
280 the_insn.exp.X_add_number >= -(1 << 15)))
281 break;
282 /* or l%const,r0,ireg_dest */
283 pseudo[0].opcode = (the_insn.opcode & 0x001f0000) | 0xe4000000;
284 pseudo[0].highlow = PAIR;
285 /* orh h%const,ireg_dest,ireg_dest */
286 pseudo[1].opcode = (the_insn.opcode & 0x03ffffff) | 0xec000000 |
287 ((the_insn.opcode & 0x001f0000) << 5);
288 pseudo[1].highlow = HIGH;
289 no_opcodes = 2;
290 break;
291
292 case E_ADDR:
293 if (the_insn.exp.X_add_symbol == NULL &&
294 the_insn.exp.X_subtract_symbol == NULL)
295 break;
296 /* orh ha%addr_expr,r0,r31 */
297 pseudo[0].opcode = 0xec000000 | (atmp<<16);
298 pseudo[0].highlow = HIGHADJ;
299 pseudo[0].reloc = LOW0; /* must overwrite */
300 /* l%addr_expr(r31),ireg_dest */
301 pseudo[1].opcode = (the_insn.opcode & ~0x003e0000) | (atmp << 21);
302 pseudo[1].highlow = PAIR;
303 no_opcodes = 2;
304 break;
305
306 case E_U32: /* 2nd version emulates Intel as, not doc. */
307 if (the_insn.exp.X_add_symbol == NULL &&
308 the_insn.exp.X_subtract_symbol == NULL &&
309 (the_insn.exp.X_add_number < (1 << 16) &&
310 the_insn.exp.X_add_number >= 0))
311 break;
312 /* $(opcode)h h%const,ireg_src2,ireg_dest
313 pseudo[0].opcode = (the_insn.opcode & 0xf3ffffff) | 0x0c000000; */
314 /* $(opcode)h h%const,ireg_src2,r31 */
315 pseudo[0].opcode = (the_insn.opcode & 0xf3e0ffff) | 0x0c000000 |
316 (atmp << 16);
317 pseudo[0].highlow = HIGH;
318 /* $(opcode) l%const,ireg_dest,ireg_dest
319 pseudo[1].opcode = (the_insn.opcode & 0xf01f0000) | 0x04000000 |
320 ((the_insn.opcode & 0x001f0000) << 5); */
321 /* $(opcode) l%const,r31,ireg_dest */
322 pseudo[1].opcode = (the_insn.opcode & 0xf01f0000) | 0x04000000 |
323 (atmp << 21);
324 pseudo[1].highlow = PAIR;
325 no_opcodes = 2;
326 break;
327
328 case E_AND: /* 2nd version emulates Intel as, not doc. */
329 if (the_insn.exp.X_add_symbol == NULL &&
330 the_insn.exp.X_subtract_symbol == NULL &&
331 (the_insn.exp.X_add_number < (1 << 16) &&
332 the_insn.exp.X_add_number >= 0))
333 break;
334 /* andnot h%const,ireg_src2,ireg_dest
335 pseudo[0].opcode = (the_insn.opcode & 0x03ffffff) | 0xd4000000; */
336 /* andnot h%const,ireg_src2,r31 */
337 pseudo[0].opcode = (the_insn.opcode & 0x03e0ffff) | 0xd4000000 |
338 (atmp << 16);
339 pseudo[0].highlow = HIGH;
340 pseudo[0].exp.X_add_number = -1 - the_insn.exp.X_add_number;
341 /* andnot l%const,ireg_dest,ireg_dest
342 pseudo[1].opcode = (the_insn.opcode & 0x001f0000) | 0xd4000000 |
343 ((the_insn.opcode & 0x001f0000) << 5); */
344 /* andnot l%const,r31,ireg_dest */
345 pseudo[1].opcode = (the_insn.opcode & 0x001f0000) | 0xd4000000 |
346 (atmp << 21);
347 pseudo[1].highlow = PAIR;
348 pseudo[1].exp.X_add_number = -1 - the_insn.exp.X_add_number;
349 no_opcodes = 2;
350 break;
351
352 case E_S32:
353 if (the_insn.exp.X_add_symbol == NULL &&
354 the_insn.exp.X_subtract_symbol == NULL &&
355 (the_insn.exp.X_add_number < (1 << 15) &&
356 the_insn.exp.X_add_number >= -(1 << 15)))
357 break;
358 /* orh h%const,r0,r31 */
359 pseudo[0].opcode = 0xec000000 | (atmp << 16);
360 pseudo[0].highlow = HIGH;
361 /* or l%const,r31,r31 */
362 pseudo[1].opcode = 0xe4000000 | (atmp << 21) | (atmp << 16);
363 pseudo[1].highlow = PAIR;
364 /* r31,ireg_src2,ireg_dest */
365 pseudo[2].opcode = (the_insn.opcode & ~0x0400ffff) | (atmp << 11);
366 pseudo[2].reloc = NO_RELOC;
367 no_opcodes = 3;
368 break;
369
370 default:
371 as_fatal("failed sanity check.");
372 }
373
374 the_insn = pseudo[0];
375 /* check for expanded opcode after branch or in dual */
376 if (no_opcodes > 1 && last_expand == 1)
377 as_warn("Expanded opcode after delayed branch: `%s'", str);
378 if (no_opcodes > 1 && dual_mode != DUAL_OFF)
379 as_warn("Expanded opcode in dual mode: `%s'", str);
380 }
381
382 i = 0;
383 do { /* always produce at least one opcode */
384 toP = frag_more(4);
385 /* put out the opcode */
386 md_number_to_chars(toP, the_insn.opcode, 4);
387
388 /* check for expanded opcode after branch or in dual */
389 last_expand = the_insn.pcrel;
390
391 /* put out the symbol-dependent stuff */
392 if (the_insn.reloc != NO_RELOC) {
393 fix_new(
394 frag_now, /* which frag */
395 (toP - frag_now->fr_literal), /* where */
396 4, /* size */
397 the_insn.exp.X_add_symbol,
398 the_insn.exp.X_subtract_symbol,
399 the_insn.exp.X_add_number,
400 the_insn.pcrel,
401 /* merge bit fields into one argument */
402 (int)(((the_insn.highlow & 0x3) << 4) | (the_insn.reloc & 0xf))
403 );
404 }
405 the_insn = pseudo[++i];
406 } while (--no_opcodes > 0);
407
408 }
409
410 static void
411 i860_ip(str)
412 char *str;
413 {
414 char *s;
415 const char *args;
416 char c;
417 unsigned long i;
418 struct i860_opcode *insn;
419 char *argsStart;
420 unsigned long opcode;
421 unsigned int mask;
422 int match = 0;
423 int comma = 0;
424
425
426 for (s = str; islower(*s) || *s == '.' || *s == '3'; ++s)
427 ;
428 switch (*s) {
429
430 case '\0':
431 break;
432
433 case ',':
434 comma = 1;
435
436 /*FALLTHROUGH*/
437
438 case ' ':
439 *s++ = '\0';
440 break;
441
442 default:
443 as_bad("Unknown opcode: `%s'", str);
444 exit(1);
445 }
446
447 if (strncmp(str, "d.", 2) == 0) { /* check for d. opcode prefix */
448 if (dual_mode == DUAL_ON)
449 dual_mode = DUAL_ONDDOT;
450 else
451 dual_mode = DUAL_DDOT;
452 str += 2;
453 }
454
455 if ((insn = (struct i860_opcode *) hash_find(op_hash, str)) == NULL) {
456 if (dual_mode == DUAL_DDOT || dual_mode == DUAL_ONDDOT)
457 str -= 2;
458 as_bad("Unknown opcode: `%s'", str);
459 return;
460 }
461 if (comma) {
462 *--s = ',';
463 }
464 argsStart = s;
465 for (;;) {
466 opcode = insn->match;
467 memset(&the_insn, '\0', sizeof(the_insn));
468 the_insn.reloc = NO_RELOC;
469
470 /*
471 * Build the opcode, checking as we go to make
472 * sure that the operands match
473 */
474 for (args = insn->args; ; ++args) {
475 switch (*args) {
476
477 case '\0': /* end of args */
478 if (*s == '\0') {
479 match = 1;
480 }
481 break;
482
483 case '+':
484 case '(': /* these must match exactly */
485 case ')':
486 case ',':
487 case ' ':
488 if (*s++ == *args)
489 continue;
490 break;
491
492 case '#': /* must be at least one digit */
493 if (isdigit(*s++)) {
494 while (isdigit(*s)) {
495 ++s;
496 }
497 continue;
498 }
499 break;
500
501 case '1': /* next operand must be a register */
502 case '2':
503 case 'd':
504 switch (*s) {
505
506 case 'f': /* frame pointer */
507 s++;
508 if (*s++ == 'p') {
509 mask = 0x3;
510 break;
511 }
512 goto error;
513
514 case 's': /* stack pointer */
515 s++;
516 if (*s++ == 'p') {
517 mask= 0x2;
518 break;
519 }
520 goto error;
521
522 case 'r': /* any register */
523 s++;
524 if (!isdigit(c = *s++)) {
525 goto error;
526 }
527 if (isdigit(*s)) {
528 if ((c = 10 * (c - '0') + (*s++ - '0')) >= 32) {
529 goto error;
530 }
531 } else {
532 c -= '0';
533 }
534 mask= c;
535 break;
536
537 default: /* not this opcode */
538 goto error;
539 }
540 /*
541 * Got the register, now figure out where
542 * it goes in the opcode.
543 */
544 switch (*args) {
545
546 case '1':
547 opcode |= mask << 11;
548 continue;
549
550 case '2':
551 opcode |= mask << 21;
552 continue;
553
554 case 'd':
555 opcode |= mask << 16;
556 continue;
557
558 }
559 break;
560
561 case 'e': /* next operand is a floating point register */
562 case 'f':
563 case 'g':
564 if (*s++ == 'f' && isdigit(*s)) {
565 mask = *s++;
566 if (isdigit(*s)) {
567 mask = 10 * (mask - '0') + (*s++ - '0');
568 if (mask >= 32) {
569 break;
570 }
571 } else {
572 mask -= '0';
573 }
574 switch (*args) {
575
576 case 'e':
577 opcode |= mask << 11;
578 continue;
579
580 case 'f':
581 opcode |= mask << 21;
582 continue;
583
584 case 'g':
585 opcode |= mask << 16;
586 if (dual_mode != DUAL_OFF)
587 opcode |= (1 << 9); /* dual mode instruction */
588 if (dual_mode == DUAL_DDOT)
589 dual_mode = DUAL_OFF;
590 if (dual_mode == DUAL_ONDDOT)
591 dual_mode = DUAL_ON;
592 if ((opcode & (1 << 10)) && (mask == ((opcode >> 11) & 0x1f)))
593 as_warn("Fsr1 equals fdest with Pipelining");
594 continue;
595 }
596 }
597 break;
598
599 case 'c': /* next operand must be a control register */
600 if (strncmp(s, "fir", 3) == 0) {
601 opcode |= 0x0 << 21;
602 s += 3;
603 continue;
604 }
605 if (strncmp(s, "psr", 3) == 0) {
606 opcode |= 0x1 << 21;
607 s += 3;
608 continue;
609 }
610 if (strncmp(s, "dirbase", 7) == 0) {
611 opcode |= 0x2 << 21;
612 s += 7;
613 continue;
614 }
615 if (strncmp(s, "db", 2) == 0) {
616 opcode |= 0x3 << 21;
617 s += 2;
618 continue;
619 }
620 if (strncmp(s, "fsr", 3) == 0) {
621 opcode |= 0x4 << 21;
622 s += 3;
623 continue;
624 }
625 if (strncmp(s, "epsr", 4) == 0) {
626 opcode |= 0x5 << 21;
627 s += 4;
628 continue;
629 }
630 break;
631
632 case '5': /* 5 bit immediate in src1 */
633 memset(&the_insn, '\0', sizeof(the_insn));
634 if ( !getExpression(s)) {
635 s = expr_end;
636 if (the_insn.exp.X_add_number & ~0x1f)
637 as_bad("5-bit immediate too large");
638 opcode |= (the_insn.exp.X_add_number & 0x1f) << 11;
639 memset(&the_insn, '\0', sizeof(the_insn));
640 the_insn.reloc = NO_RELOC;
641 continue;
642 }
643 break;
644
645 case 'l': /* 26 bit immediate, relative branch */
646 the_insn.reloc = BRADDR;
647 the_insn.pcrel = 1;
648 goto immediate;
649
650 case 's': /* 16 bit immediate, split relative branch */
651 /* upper 5 bits of offset in dest field */
652 the_insn.pcrel = 1;
653 the_insn.reloc = SPLIT0;
654 goto immediate;
655
656 case 'S': /* 16 bit immediate, split (st), aligned */
657 if (opcode & (1 << 28))
658 if (opcode & 0x1)
659 the_insn.reloc = SPLIT2;
660 else
661 the_insn.reloc = SPLIT1;
662 else
663 the_insn.reloc = SPLIT0;
664 goto immediate;
665
666 case 'I': /* 16 bit immediate, aligned */
667 if (opcode & (1 << 28))
668 if (opcode & 0x1)
669 the_insn.reloc = LOW2;
670 else
671 the_insn.reloc = LOW1;
672 else
673 the_insn.reloc = LOW0;
674 goto immediate;
675
676 case 'i': /* 16 bit immediate */
677 the_insn.reloc = LOW0;
678
679 /*FALLTHROUGH*/
680
681 immediate:
682 if(*s==' ')
683 s++;
684 if (strncmp(s, "ha%", 3) == 0) {
685 the_insn.highlow = HIGHADJ;
686 s += 3;
687 } else if (strncmp(s, "h%", 2) == 0) {
688 the_insn.highlow = HIGH;
689 s += 2;
690 } else if (strncmp(s, "l%", 2) == 0) {
691 the_insn.highlow = PAIR;
692 s += 2;
693 }
694 the_insn.expand = insn->expand;
695
696 /* Note that if the getExpression() fails, we will still have
697 created U entries in the symbol table for the 'symbols'
698 in the input string. Try not to create U symbols for
699 registers, etc. */
700
701 if ( !getExpression(s)) {
702 s = expr_end;
703 continue;
704 }
705 break;
706
707 default:
708 as_fatal("failed sanity check.");
709 }
710 break;
711 }
712 error:
713 if (match == 0)
714 {
715 /* Args don't match. */
716 if (&insn[1] - i860_opcodes < NUMOPCODES
717 && !strcmp(insn->name, insn[1].name))
718 {
719 ++insn;
720 s = argsStart;
721 continue;
722 }
723 else
724 {
725 as_bad("Illegal operands");
726 return;
727 }
728 }
729 break;
730 }
731
732 the_insn.opcode = opcode;
733 return;
734 }
735
736 static int
737 getExpression(str)
738 char *str;
739 {
740 char *save_in;
741 segT seg;
742
743 save_in = input_line_pointer;
744 input_line_pointer = str;
745 switch (seg = expression(&the_insn.exp)) {
746
747 case SEG_ABSOLUTE:
748 case SEG_TEXT:
749 case SEG_DATA:
750 case SEG_BSS:
751 case SEG_UNKNOWN:
752 case SEG_DIFFERENCE:
753 case SEG_BIG:
754 case SEG_ABSENT:
755 break;
756
757 default:
758 the_insn.error = "bad segment";
759 expr_end = input_line_pointer;
760 input_line_pointer=save_in;
761 return 1;
762 }
763 expr_end = input_line_pointer;
764 input_line_pointer = save_in;
765 return 0;
766 }
767
768
769 /*
770 This is identical to the md_atof in m68k.c. I think this is right,
771 but I'm not sure.
772
773 Turn a string in input_line_pointer into a floating point constant of type
774 type, and store the appropriate bytes in *litP. The number of LITTLENUMS
775 emitted is stored in *sizeP . An error message is returned, or NULL on OK.
776 */
777
778 /* Equal to MAX_PRECISION in atof-ieee.c */
779 #define MAX_LITTLENUMS 6
780
781 char *
782 md_atof(type,litP,sizeP)
783 char type;
784 char *litP;
785 int *sizeP;
786 {
787 int prec;
788 LITTLENUM_TYPE words[MAX_LITTLENUMS];
789 LITTLENUM_TYPE *wordP;
790 char *t;
791 char *atof_ieee();
792
793 switch(type) {
794
795 case 'f':
796 case 'F':
797 case 's':
798 case 'S':
799 prec = 2;
800 break;
801
802 case 'd':
803 case 'D':
804 case 'r':
805 case 'R':
806 prec = 4;
807 break;
808
809 case 'x':
810 case 'X':
811 prec = 6;
812 break;
813
814 case 'p':
815 case 'P':
816 prec = 6;
817 break;
818
819 default:
820 *sizeP=0;
821 return "Bad call to MD_ATOF()";
822 }
823 t=atof_ieee(input_line_pointer,type,words);
824 if(t)
825 input_line_pointer=t;
826 *sizeP=prec * sizeof(LITTLENUM_TYPE);
827 for(wordP=words;prec--;) {
828 md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));
829 litP+=sizeof(LITTLENUM_TYPE);
830 }
831 return ""; /* Someone should teach Dean about null pointers */
832 }
833
834 /*
835 * Write out big-endian.
836 */
837 void
838 md_number_to_chars(buf,val,n)
839 char *buf;
840 long val;
841 int n;
842 {
843 switch(n) {
844
845 case 4:
846 *buf++ = val >> 24;
847 *buf++ = val >> 16;
848 case 2:
849 *buf++ = val >> 8;
850 case 1:
851 *buf = val;
852 break;
853
854 default:
855 as_fatal("failed sanity check.");
856 }
857 return;
858 }
859
860 void md_number_to_imm(buf,val,n, fixP)
861 char *buf;
862 long val;
863 int n;
864 fixS *fixP;
865 {
866 enum reloc_type reloc = fixP->fx_r_type & 0xf;
867 enum highlow_type highlow = (fixP->fx_r_type >> 4) & 0x3;
868
869 assert(buf);
870 assert(n == 4); /* always on i860 */
871
872 switch(highlow)
873 {
874
875 case HIGHADJ: /* adjusts the high-order 16-bits */
876 if (val & (1 << 15))
877 val += (1 << 16);
878
879 /*FALLTHROUGH*/
880
881 case HIGH: /* selects the high-order 16-bits */
882 val >>= 16;
883 break;
884
885 case PAIR: /* selects the low-order 16-bits */
886 val = val & 0xffff;
887 break;
888
889 default:
890 break;
891 }
892
893 switch(reloc)
894 {
895
896 case BRADDR: /* br,call,bc,bc.t,bnc,bnc.t w/26-bit immediate */
897 if (fixP->fx_pcrel != 1)
898 as_bad("26-bit branch w/o pc relative set: 0x%08x", val);
899 val >>= 2; /* align pcrel offset, see manual */
900
901 if (val >= (1 << 25) || val < -(1 << 25)) /* check for overflow */
902 as_bad("26-bit branch offset overflow: 0x%08x", val);
903 buf[0] = (buf[0] & 0xfc) | ((val >> 24) & 0x3);
904 buf[1] = val >> 16;
905 buf[2] = val >> 8;
906 buf[3] = val;
907 break;
908
909 case SPLIT2: /* 16 bit immediate, 4-byte aligned */
910 if (val & 0x3)
911 as_bad("16-bit immediate 4-byte alignment error: 0x%08x", val);
912 val &= ~0x3; /* 4-byte align value */
913 /*FALLTHROUGH*/
914 case SPLIT1: /* 16 bit immediate, 2-byte aligned */
915 if (val & 0x1)
916 as_bad("16-bit immediate 2-byte alignment error: 0x%08x", val);
917 val &= ~0x1; /* 2-byte align value */
918 /*FALLTHROUGH*/
919 case SPLIT0: /* st,bla,bte,btne w/16-bit immediate */
920 if (fixP->fx_pcrel == 1)
921 val >>= 2; /* align pcrel offset, see manual */
922 /* check for bounds */
923 if (highlow != PAIR && (val >= (1 << 16) || val < -(1 << 15)))
924 as_bad("16-bit branch offset overflow: 0x%08x", val);
925 buf[1] = (buf[1] & ~0x1f) | ((val >> 11) & 0x1f);
926 buf[2] = (buf[2] & ~0x7) | ((val >> 8) & 0x7);
927 buf[3] |= val; /* perserve bottom opcode bits */
928 break;
929
930 case LOW4: /* fld,pfld,pst,flush 16-byte aligned */
931 if (val & 0xf)
932 as_bad("16-bit immediate 16-byte alignment error: 0x%08x", val);
933 val &= ~0xf; /* 16-byte align value */
934 /*FALLTHROUGH*/
935 case LOW3: /* fld,pfld,pst,flush 8-byte aligned */
936 if (val & 0x7)
937 as_bad("16-bit immediate 8-byte alignment error: 0x%08x", val);
938 val &= ~0x7; /* 8-byte align value */
939 /*FALLTHROUGH*/
940 case LOW2: /* 16 bit immediate, 4-byte aligned */
941 if (val & 0x3)
942 as_bad("16-bit immediate 4-byte alignment error: 0x%08x", val);
943 val &= ~0x3; /* 4-byte align value */
944 /*FALLTHROUGH*/
945 case LOW1: /* 16 bit immediate, 2-byte aligned */
946 if (val & 0x1)
947 as_bad("16-bit immediate 2-byte alignment error: 0x%08x", val);
948 val &= ~0x1; /* 2-byte align value */
949 /*FALLTHROUGH*/
950 case LOW0: /* 16 bit immediate, byte aligned */
951 /* check for bounds */
952 if (highlow != PAIR && (val >= (1 << 16) || val < -(1 << 15)))
953 as_bad("16-bit immediate overflow: 0x%08x", val);
954 buf[2] = val >> 8;
955 buf[3] |= val; /* perserve bottom opcode bits */
956 break;
957
958 case NO_RELOC:
959 default:
960 as_bad("bad relocation type: 0x%02x", reloc);
961 break;
962 }
963 return;
964 }
965
966 /* should never be called for i860 */
967 void
968 md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol)
969 char *ptr;
970 long from_addr, to_addr;
971 fragS *frag;
972 symbolS *to_symbol;
973 {
974 as_fatal("i860_create_short_jmp\n");
975 }
976
977 /* should never be called for i860 */
978 void
979 md_number_to_disp(buf,val,n)
980 char *buf;
981 long val;
982 {
983 as_fatal("md_number_to_disp\n");
984 }
985
986 /* should never be called for i860 */
987 void
988 md_number_to_field(buf,val,fix)
989 char *buf;
990 long val;
991 void *fix;
992 {
993 as_fatal("i860_number_to_field\n");
994 }
995
996 /* the bit-field entries in the relocation_info struct plays hell
997 with the byte-order problems of cross-assembly. So as a hack,
998 I added this mach. dependent ri twiddler. Ugly, but it gets
999 you there. -KWK */
1000 /* on i860: first 4 bytes are normal unsigned long address, next three
1001 bytes are index, most sig. byte first. Byte 7 is broken up with
1002 bit 7 as pcrel, bit 6 as extern, and the lower six bits as
1003 relocation type (highlow 5-4). Next 4 bytes are long addend. */
1004 /* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */
1005 void
1006 md_ri_to_chars(ri_p, ri)
1007 struct relocation_info *ri_p, ri;
1008 {
1009 #if 0
1010 unsigned char the_bytes[sizeof(*ri_p)];
1011
1012 /* this is easy */
1013 md_number_to_chars(the_bytes, ri.r_address, sizeof(ri.r_address));
1014 /* now the fun stuff */
1015 the_bytes[4] = (ri.r_index >> 16) & 0x0ff;
1016 the_bytes[5] = (ri.r_index >> 8) & 0x0ff;
1017 the_bytes[6] = ri.r_index & 0x0ff;
1018 the_bytes[7] = ((ri.r_extern << 7) & 0x80) | (0 & 0x60) | (ri.r_type & 0x1F);
1019 /* Also easy */
1020 md_number_to_chars(&the_bytes[8], ri.r_addend, sizeof(ri.r_addend));
1021 /* now put it back where you found it, Junior... */
1022 memcpy((char *) ri_p, the_bytes, sizeof(*ri_p));
1023 #endif
1024 }
1025
1026 /* should never be called for i860 */
1027 void
1028 md_convert_frag(headers, fragP)
1029 object_headers *headers;
1030 register fragS *fragP;
1031 {
1032 as_fatal("i860_convert_frag\n");
1033 }
1034
1035 /* should never be called for i860 */
1036 void
1037 md_create_long_jump(ptr, from_addr, to_addr, frag, to_symbol)
1038 char *ptr;
1039 long from_addr,
1040 to_addr;
1041 fragS *frag;
1042 symbolS *to_symbol;
1043 {
1044 as_fatal("i860_create_long_jump\n");
1045 }
1046
1047 /* should never be called for i860 */
1048 int
1049 md_estimate_size_before_relax(fragP, segtype)
1050 register fragS *fragP;
1051 segT segtype;
1052 {
1053 as_fatal("i860_estimate_size_before_relax\n");
1054 }
1055
1056 /* for debugging only, must match enum reloc_type */
1057 static char *Reloc[] = {
1058 "NO_RELOC",
1059 "BRADDR",
1060 "LOW0",
1061 "LOW1",
1062 "LOW2",
1063 "LOW3",
1064 "LOW4",
1065 "SPLIT0",
1066 "SPLIT1",
1067 "SPLIT2",
1068 "RELOC_32",
1069 };
1070 static char *Highlow[] = {
1071 "NO_SPEC",
1072 "PAIR",
1073 "HIGH",
1074 "HIGHADJ",
1075 };
1076 static void
1077 print_insn(insn)
1078 struct i860_it *insn;
1079 {
1080 if (insn->error) {
1081 fprintf(stderr, "ERROR: %s\n");
1082 }
1083 fprintf(stderr, "opcode=0x%08x\t", insn->opcode);
1084 fprintf(stderr, "expand=0x%08x\t", insn->expand);
1085 fprintf(stderr, "reloc = %s\t", Reloc[insn->reloc]);
1086 fprintf(stderr, "highlow = %s\n", Highlow[insn->highlow]);
1087 fprintf(stderr, "exp = {\n");
1088 fprintf(stderr, "\t\tX_add_symbol = %s\n",
1089 insn->exp.X_add_symbol ?
1090 (S_GET_NAME(insn->exp.X_add_symbol) ?
1091 S_GET_NAME(insn->exp.X_add_symbol) : "???") : "0");
1092 fprintf(stderr, "\t\tX_sub_symbol = %s\n",
1093 insn->exp.X_subtract_symbol ?
1094 (S_GET_NAME(insn->exp.X_subtract_symbol) ?
1095 S_GET_NAME(insn->exp.X_subtract_symbol) : "???") : "0");
1096 fprintf(stderr, "\t\tX_add_number = %d\n",
1097 insn->exp.X_add_number);
1098 fprintf(stderr, "}\n");
1099 return;
1100 }
1101
1102 int
1103 md_parse_option(argP,cntP,vecP)
1104 char **argP;
1105 int *cntP;
1106 char ***vecP;
1107 {
1108 return 1;
1109 }
1110
1111 /*
1112 * I860 relocations are completely different, so it needs
1113 * this machine dependent routine to emit them.
1114 */
1115 void
1116 emit_machine_reloc(fixP, segment_address_in_file)
1117 register fixS *fixP;
1118 relax_addressT segment_address_in_file;
1119 {
1120 struct reloc_info_i860 ri;
1121 register symbolS *symbolP;
1122 extern char *next_object_file_charP;
1123 long add_number;
1124
1125 memset((char *) &ri, '\0', sizeof(ri));
1126 for (; fixP; fixP = fixP->fx_next) {
1127
1128 if (fixP->fx_r_type & ~0x3f) {
1129 as_fatal("fixP->fx_r_type = %d\n", fixP->fx_r_type);
1130 }
1131 ri.r_pcrel = fixP->fx_pcrel;
1132 ri.r_type = fixP->fx_r_type;
1133
1134 if ((symbolP = fixP->fx_addsy) != NULL) {
1135 ri.r_address = fixP->fx_frag->fr_address +
1136 fixP->fx_where - segment_address_in_file;
1137 if ((symbolP->sy_type & N_TYPE) == N_UNDF) {
1138 ri.r_extern = 1;
1139 ri.r_symbolnum = symbolP->sy_number;
1140 } else {
1141 ri.r_extern = 0;
1142 ri.r_symbolnum = symbolP->sy_type & N_TYPE;
1143 }
1144 if (symbolP && symbolP->sy_frag) {
1145 ri.r_addend = symbolP->sy_frag->fr_address;
1146 }
1147 ri.r_type = fixP->fx_r_type;
1148 if (fixP->fx_pcrel) {
1149 /* preserve actual offset vs. pc + 4 */
1150 ri.r_addend -= (ri.r_address + 4);
1151 } else {
1152 ri.r_addend = fixP->fx_addnumber;
1153 }
1154
1155 md_ri_to_chars((char *) &ri, ri);
1156 append(&next_object_file_charP, (char *)& ri, sizeof(ri));
1157 }
1158 }
1159 return;
1160 }
1161
1162 /* Parse an operand that is machine-specific.
1163 We just return without modifying the expression if we have nothing
1164 to do. */
1165
1166 /* ARGSUSED */
1167 void
1168 md_operand (expressionP)
1169 expressionS *expressionP;
1170 {
1171 }
1172
1173 /* We have no need to default values of symbols. */
1174
1175 /* ARGSUSED */
1176 symbolS *
1177 md_undefined_symbol (name)
1178 char *name;
1179 {
1180 return 0;
1181 }
1182
1183 /* Round up a section size to the appropriate boundary. */
1184 long
1185 md_section_align (segment, size)
1186 segT segment;
1187 long size;
1188 {
1189 return size; /* Byte alignment is fine */
1190 }
1191
1192 /* Exactly what point is a PC-relative offset relative TO?
1193 On the i860, they're relative to the address of the offset, plus
1194 its size. (??? Is this right? FIXME-SOON!) */
1195 long
1196 md_pcrel_from (fixP)
1197 fixS *fixP;
1198 {
1199 return fixP->fx_size + fixP->fx_where + fixP->fx_frag->fr_address;
1200 }
1201
1202 void
1203 md_apply_fix(fixP, val)
1204 fixS *fixP;
1205 long val;
1206 {
1207 char *place = fixP->fx_where + fixP->fx_frag->fr_literal;
1208
1209 if (!fixP->fx_bit_fixP) {
1210
1211 switch (fixP->fx_im_disp) {
1212 case 0:
1213 fixP->fx_addnumber = val;
1214 md_number_to_imm(place, val, fixP->fx_size, fixP);
1215 break;
1216 case 1:
1217 md_number_to_disp (place,
1218 fixP->fx_pcrel ? val+fixP->fx_pcrel_adjust:val,
1219 fixP->fx_size);
1220 break;
1221 case 2: /* fix requested for .long .word etc */
1222 md_number_to_chars (place, val, fixP->fx_size);
1223 break;
1224 default:
1225 as_fatal("Internal error in md_apply_fix() in file \"%s\"", __FILE__);
1226 } /* OVE: maybe one ought to put _imm _disp _chars in one md-func */
1227 } else {
1228 md_number_to_field (place, val, fixP->fx_bit_fixP);
1229 }
1230
1231 return;
1232 } /* md_apply_fix() */
1233
1234 /*
1235 * Local Variables:
1236 * fill-column: 131
1237 * comment-column: 0
1238 */
1239
1240 /* end of tc-i860.c */