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