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