start-sanitize-d10v
[deliverable/binutils-gdb.git] / gas / config / tc-d10v.c
1 /* tc-d10v.c -- Assembler code for the Mitsubishi D10V
2
3 Copyright (C) 1996 Free Software Foundation.
4
5 This file is part of GAS, the GNU Assembler.
6
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 #include <stdio.h>
23 #include <ctype.h>
24 #include "as.h"
25 #include "subsegs.h"
26 #include "opcode/d10v.h"
27 #include "elf/ppc.h"
28
29 const char comment_chars[] = "#;";
30 const char line_comment_chars[] = "#";
31 const char line_separator_chars[] = "";
32 const char *md_shortopts = "";
33 const char EXP_CHARS[] = "eE";
34 const char FLT_CHARS[] = "dD";
35
36 /* local functions */
37 static int reg_name_search PARAMS ((char *name));
38 static void register_name PARAMS ((expressionS *expressionP));
39 static int postfix PARAMS ((char *p));
40 static bfd_reloc_code_real_type get_reloc PARAMS ((struct d10v_operand *op));
41 static int get_operands PARAMS ((expressionS exp[]));
42 static unsigned long build_insn PARAMS ((struct d10v_opcode *opcode, expressionS *opers));
43 static void write_long PARAMS ((struct d10v_opcode *opcode, unsigned long insn));
44 static void write_1_short PARAMS ((struct d10v_opcode *opcode, unsigned long insn));
45 static int write_2_short PARAMS ((struct d10v_opcode *opcode1, unsigned long insn1,
46 struct d10v_opcode *opcode2, unsigned long insn2, int exec_type));
47 static unsigned long do_assemble PARAMS ((char *str, struct d10v_opcode **opcode));
48
49 /* fixups */
50 #define MAX_INSN_FIXUPS (5)
51 struct d10v_fixup
52 {
53 expressionS exp;
54 int opindex;
55 bfd_reloc_code_real_type reloc;
56 };
57 struct d10v_fixup fixups[MAX_INSN_FIXUPS];
58 static int fc;
59
60 struct option md_longopts[] = {
61 {NULL, no_argument, NULL, 0}
62 };
63 size_t md_longopts_size = sizeof(md_longopts);
64
65 /* The target specific pseudo-ops which we support. */
66 const pseudo_typeS md_pseudo_table[] =
67 {
68 /*
69 { "byte", ppc_byte, 0 },
70 { "long", ppc_elf_cons, 4 },
71 { "word", ppc_elf_cons, 2 },
72 { "short", ppc_elf_cons, 2 },
73 { "rdata", ppc_elf_rdata, 0 },
74 { "rodata", ppc_elf_rdata, 0 },
75 { "lcomm", ppc_elf_lcomm, 0 },
76 */
77 { NULL, NULL, 0 }
78 };
79
80 /* Opcode hash table. */
81 static struct hash_control *d10v_hash;
82
83 /* Structure to hold information about predefined registers. */
84 struct pd_reg
85 {
86 char *name;
87 int value;
88 };
89
90
91 /* an expressionS only has one register type, so we fake it */
92 /* by setting high bits to indicate type */
93 #define REGISTER_MASK 0xFF
94
95 /* The table is sorted. Suitable for searching by a binary search. */
96 static const struct pd_reg pre_defined_registers[] =
97 {
98 { "a0", OPERAND_ACC+0 },
99 { "a1", OPERAND_ACC+1 },
100 { "bpc", OPERAND_CONTROL+3 },
101 { "bpsw", OPERAND_CONTROL+1 },
102 { "c", OPERAND_FLAG+3 },
103 { "f0", OPERAND_FLAG+0 },
104 { "f1", OPERAND_FLAG+1 },
105 { "iba", OPERAND_CONTROL+14 },
106 { "mod_e", OPERAND_CONTROL+11 },
107 { "mod_s", OPERAND_CONTROL+10 },
108 { "pc", OPERAND_CONTROL+2 },
109 { "psw", OPERAND_CONTROL+0 },
110 { "r0", 0 },
111 { "r1", 1 },
112 { "r10", 10 },
113 { "r11", 11 },
114 { "r12", 12 },
115 { "r13", 13 },
116 { "r14", 14 },
117 { "r15", 15 },
118 { "r2", 2 },
119 { "r3", 3 },
120 { "r4", 4 },
121 { "r5", 5 },
122 { "r6", 6 },
123 { "r7", 7 },
124 { "r8", 8 },
125 { "r9", 9 },
126 { "rpt_c", OPERAND_CONTROL+7 },
127 { "rpt_e", OPERAND_CONTROL+9 },
128 { "rpt_s", OPERAND_CONTROL+8 },
129 { "sp", 15 },
130 };
131 #define REG_NAME_CNT (sizeof(pre_defined_registers) / sizeof(struct pd_reg))
132
133 /* reg_name_search does a binary search of the pre_defined_registers
134 array to see if "name" is a valid regiter name. Returns the register
135 number from the array on success, or -1 on failure. */
136
137 static int
138 reg_name_search (name)
139 char *name;
140 {
141 int middle, low, high;
142 int cmp;
143
144 low = 0;
145 high = REG_NAME_CNT - 1;
146
147 do
148 {
149 middle = (low + high) / 2;
150 cmp = strcasecmp (name, pre_defined_registers[middle].name);
151 if (cmp < 0)
152 high = middle - 1;
153 else if (cmp > 0)
154 low = middle + 1;
155 else
156 return pre_defined_registers[middle].value;
157 }
158 while (low <= high);
159 return -1;
160 }
161
162
163 /* register_name check to see if an expression is a valid
164 register name. If it is, it marks the expression type
165 as O_register. */
166
167 static void
168 register_name (expressionP)
169 expressionS *expressionP;
170 {
171 int reg_number;
172 char *name;
173
174 if (expressionP->X_op == O_symbol)
175 {
176 name = (char *)S_GET_NAME (expressionP->X_add_symbol);
177 reg_number = reg_name_search (name);
178
179 /* look to see if it's in the register table */
180 if (reg_number >= 0)
181 {
182 expressionP->X_op = O_register;
183 expressionP->X_add_number = reg_number;
184 }
185 }
186 }
187
188 void
189 md_show_usage (stream)
190 FILE *stream;
191 {
192 fprintf(stream, "D10V options:\n\
193 none yet\n");
194 }
195
196 int
197 md_parse_option (c, arg)
198 int c;
199 char *arg;
200 {
201 return 0;
202 }
203
204 symbolS *
205 md_undefined_symbol (name)
206 char *name;
207 {
208 return 0;
209 }
210
211 char *
212 md_atof (type, litp, sizep)
213 int type;
214 char *litp;
215 int *sizep;
216 {
217 return "";
218 }
219
220 void
221 md_convert_frag (abfd, sec, fragP)
222 bfd *abfd;
223 asection *sec;
224 fragS *fragP;
225 {
226 /* printf ("call to md_convert_frag \n"); */
227 abort ();
228 }
229
230 valueT
231 md_section_align (seg, addr)
232 asection *seg;
233 valueT addr;
234 {
235 int align = bfd_get_section_alignment (stdoutput, seg);
236 return ((addr + (1 << align) - 1) & (-1 << align));
237 }
238
239 void
240 md_begin ()
241 {
242 char *prev_name = "";
243 struct d10v_opcode *opcode;
244 d10v_hash = hash_new();
245
246 /* Insert unique names into hash table. The D10v instruction set
247 has many identical opcode names that have different opcodes based
248 on the operands. This hash table then provides a quick index to
249 the first opcode with a particular name in the opcode table. */
250
251 for (opcode = (struct d10v_opcode *)d10v_opcodes; opcode->name; opcode++)
252 {
253 if (strcmp (prev_name, opcode->name))
254 {
255 prev_name = (char *)opcode->name;
256 hash_insert (d10v_hash, opcode->name, (char *) opcode);
257 }
258 }
259 }
260
261
262 /* this function removes the postincrement or postdecrement
263 operator ( '+' or '-' ) from an expression */
264
265 static int postfix (p)
266 char *p;
267 {
268 while (*p != '-' && *p != '+')
269 {
270 if (*p==0 || *p=='\n' || *p=='\r')
271 break;
272 p++;
273 }
274
275 if (*p == '-')
276 {
277 *p = ' ';
278 return (-1);
279 }
280 if (*p == '+')
281 {
282 *p = ' ';
283 return (1);
284 }
285
286 return (0);
287 }
288
289
290 static bfd_reloc_code_real_type
291 get_reloc (op)
292 struct d10v_operand *op;
293 {
294 int bits = op->bits;
295
296 /* printf("get_reloc: bits=%d address=%d\n",bits,op->flags & OPERAND_ADDR); */
297 if (bits <= 4)
298 return (0);
299
300 if (op->flags & OPERAND_ADDR)
301 {
302 if (bits == 8)
303 return (BFD_RELOC_D10V_10_PCREL_R);
304 else
305 return (BFD_RELOC_D10V_18_PCREL);
306 }
307
308 return (BFD_RELOC_16);
309 }
310
311 /* get_operands parses a string of operands and returns
312 an array of expressions */
313
314 static int
315 get_operands (exp)
316 expressionS exp[];
317 {
318 char *p = input_line_pointer;
319 int numops = 0;
320 int post = 0;
321
322 while (*p)
323 {
324 while (*p == ' ' || *p == '\t' || *p == ',')
325 p++;
326 if (*p==0 || *p=='\n' || *p=='\r')
327 break;
328
329 if (*p == '@')
330 {
331 p++;
332 exp[numops].X_op = O_absent;
333 if (*p == '(')
334 {
335 p++;
336 exp[numops].X_add_number = OPERAND_ATPAR;
337 }
338 else if (*p == '-')
339 {
340 p++;
341 exp[numops].X_add_number = OPERAND_ATMINUS;
342 }
343 else
344 {
345 exp[numops].X_add_number = OPERAND_ATSIGN;
346 post = postfix (p);
347 }
348 numops++;
349 continue;
350 }
351
352 if (*p == ')')
353 {
354 /* just skip the trailing paren */
355 p++;
356 continue;
357 }
358
359 input_line_pointer = p;
360 /* create an expression */
361 expression (&exp[numops]);
362 /* check to see if it might be a register name */
363 register_name (&exp[numops]);
364
365 if (exp[numops].X_op == O_illegal)
366 as_bad ("illegal operand");
367 else if (exp[numops].X_op == O_absent)
368 as_bad ("missing operand");
369
370 numops++;
371 p = input_line_pointer;
372 }
373
374 switch (post)
375 {
376 case -1: /* postdecrement mode */
377 exp[numops].X_op = O_absent;
378 exp[numops++].X_add_number = OPERAND_MINUS;
379 break;
380 case 1: /* postincrement mode */
381 exp[numops].X_op = O_absent;
382 exp[numops++].X_add_number = OPERAND_PLUS;
383 break;
384 }
385
386 exp[numops].X_op = 0;
387 return (numops);
388 }
389
390 static unsigned long
391 d10v_insert_operand (insn, op_type, value)
392 unsigned long insn;
393 int op_type;
394 offsetT value;
395 {
396 int shift, bits;
397
398 shift = d10v_operands[op_type].shift;
399 bits = d10v_operands[op_type].bits;
400 /* truncate to the proper number of bits */
401 /* FIXME: overflow checking here? */
402 value &= 0x7FFFFFFF >> (31 - bits);
403 insn |= (value << shift);
404
405 return insn;
406 }
407
408
409 /* build_insn takes a pointer to the opcode entry in the opcode table
410 and the array of operand expressions and returns the instruction */
411
412 static unsigned long
413 build_insn (opcode, opers)
414 struct d10v_opcode *opcode;
415 expressionS *opers;
416 {
417 int i, bits, shift, flags;
418 unsigned long insn;
419 unsigned int number;
420 insn = opcode->opcode;
421
422 for (i=0;opcode->operands[i];i++)
423 {
424 flags = d10v_operands[opcode->operands[i]].flags;
425 bits = d10v_operands[opcode->operands[i]].bits;
426 shift = d10v_operands[opcode->operands[i]].shift;
427 number = opers[i].X_add_number;
428
429 if (flags & OPERAND_REG)
430 {
431 number &= REGISTER_MASK;
432 if (opcode->format == LONG_L)
433 shift += 15;
434 }
435
436 if (opers[i].X_op != O_register && opers[i].X_op != O_constant)
437 {
438 /* now create a fixup */
439
440 /*
441 printf("need a fixup: ");
442 print_expr_1(stdout,&opers[i]);
443 printf("\n");
444 */
445
446 if (fc >= MAX_INSN_FIXUPS)
447 as_fatal ("too many fixups");
448 fixups[fc].exp = opers[i];
449
450 /* put the operand number here for now. We can look up
451 the reloc type and/or fixup the instruction in md_apply_fix() */
452 fixups[fc].reloc = opcode->operands[i];
453 fc++;
454 }
455
456 /* truncate to the proper number of bits */
457 /* FIXME: overflow checking here? */
458 number &= 0x7FFFFFFF >> (31 - bits);
459 insn = insn | (number << shift);
460 }
461 return insn;
462 }
463
464 /* write out a long form instruction */
465 static void
466 write_long (opcode, insn)
467 struct d10v_opcode *opcode;
468 unsigned long insn;
469 {
470 int i;
471 char *f = frag_more(4);
472
473 insn |= FM11;
474 /* printf("INSN: %08x\n",insn); */
475 number_to_chars_bigendian (f, insn, 4);
476
477 for (i=0; i<fc; i++)
478 {
479 if (get_reloc((struct d10v_operand *)&d10v_operands[fixups[i].reloc]))
480 {
481 /*
482 printf("fix_new_exp: where:%x size:4\n ",f - frag_now->fr_literal);
483 print_expr_1(stdout,&fixups[i].exp);
484 printf("\n");
485 */
486
487 fix_new_exp (frag_now,
488 f - frag_now->fr_literal,
489 4,
490 &fixups[i].exp,
491 1,
492 fixups[i].reloc);
493 }
494 }
495 }
496
497 /* write out a short form instruction by itself */
498 static void
499 write_1_short (opcode, insn)
500 struct d10v_opcode *opcode;
501 unsigned long insn;
502 {
503 char *f = frag_more(4);
504 int i;
505
506 insn |= FM00 | (NOP << 15);
507 /* printf("INSN: %08x\n",insn); */
508 number_to_chars_bigendian (f, insn, 4);
509 for (i=0; i<fc; i++)
510 {
511 if (get_reloc((struct d10v_operand *)&d10v_operands[fixups[i].reloc]))
512 {
513 /*
514 printf("fix_new_exp: where:%x size:4\n ",f - frag_now->fr_literal);
515 print_expr_1(stdout,&fixups[i].exp);
516 printf("\n");
517 */
518
519 fix_new_exp (frag_now,
520 f - frag_now->fr_literal,
521 4,
522 &fixups[i].exp,
523 1,
524 fixups[i].reloc);
525 }
526 }
527 }
528
529 /* write out a short form instruction if possible */
530 /* return number of instructions not written out */
531 static int
532 write_2_short (opcode1, insn1, opcode2, insn2, exec_type)
533 struct d10v_opcode *opcode1, *opcode2;
534 unsigned long insn1, insn2;
535 int exec_type;
536 {
537 unsigned long insn;
538
539 if(opcode1->exec_type == BRANCH_LINK)
540 {
541 /* subroutines must be called from 32-bit boundaries */
542 /* so the return address will be correct */
543 write_1_short (opcode1, insn1);
544 return (1);
545 }
546
547 switch (exec_type)
548 {
549 case 0:
550 if (opcode1->unit == IU)
551 {
552 insn = FM10 | (insn2 << 15) | insn1;
553 }
554 else
555 {
556 insn = FM01 | (insn1 << 15) | insn2;
557 }
558 break;
559 case 1: /* parallel */
560 insn = FM00 | (insn1 << 15) | insn2;
561 break;
562 case 2: /* sequential */
563 insn = FM01 | (insn1 << 15) | insn2;
564 break;
565 case 3: /* reverse sequential */
566 insn = FM10 | (insn1 << 15) | insn2;
567 break;
568 default:
569 as_fatal("unknown execution type passed to write_2_short()");
570 }
571
572 /* printf("INSN: %08x\n",insn); */
573 number_to_chars_bigendian (frag_more(4), insn, 4);
574 return (0);
575 }
576
577
578 /* This is the main entry point for the machine-dependent assembler. str points to a
579 machine-dependent instruction. This function is supposed to emit the frags/bytes
580 it assembles to. For the D10V, it mostly handles the special VLIW parsing and packing
581 and leaves the difficult stuff to do_assemble().
582 */
583
584 static unsigned long prev_insn;
585 static struct d10v_opcode *prev_opcode = 0;
586
587 void
588 md_assemble (str)
589 char *str;
590 {
591 struct d10v_opcode *opcode;
592 unsigned long insn;
593 int t=0;
594 char *str2;
595
596 /* printf("md_assemble: str=%s\n",str); */
597 fc = 0;
598
599 /* look for the special multiple instruction seperators */
600 str2 = strstr (str, "||");
601 if (str2)
602 t = 1;
603 else
604 {
605 str2 = strstr (str, "->");
606 if (str2)
607 t = 2;
608 else
609 {
610 str2 = strstr (str, "<-");
611 if (str2)
612 t = 3;
613 }
614 }
615
616
617 /* str2 points to the seperator, if one */
618 if (str2)
619 {
620 *str2 = 0;
621
622 /* if two instructions are present and we already have one saved
623 then first write it out */
624 if (prev_opcode)
625 write_1_short (prev_opcode, prev_insn);
626
627 /* assemble first instruction and save it */
628 prev_insn = do_assemble (str, &prev_opcode);
629 str = str2 + 2;
630 }
631
632 insn = do_assemble (str, &opcode);
633
634 /* if this is a long instruction, write it and any previous short instruction */
635 if (opcode->format & LONG_OPCODE)
636 {
637 if (t)
638 as_fatal("Unable to mix instructions as specified");
639 if (prev_opcode)
640 {
641 write_1_short (prev_opcode, prev_insn);
642 prev_opcode = NULL;
643 }
644 write_long (opcode, insn);
645 prev_opcode = NULL;
646 return;
647 }
648
649 if (prev_opcode && (write_2_short (prev_opcode, prev_insn, opcode, insn, t) == 0))
650 {
651 /* no instructions saved */
652 prev_opcode = NULL;
653 }
654 else
655 {
656 if (t)
657 as_fatal("Unable to mix instructions as specified");
658 /* save off last instruction so it may be packed on next pass */
659 prev_opcode = opcode;
660 prev_insn = insn;
661 }
662 }
663
664
665 static unsigned long
666 do_assemble (str, opcode)
667 char *str;
668 struct d10v_opcode **opcode;
669 {
670 struct d10v_opcode *next_opcode;
671 unsigned char *op_start, *save;
672 unsigned char *op_end;
673 char name[20];
674 int nlen = 0, i, match, numops;
675 expressionS myops[6];
676 unsigned long insn;
677
678 /* printf("do_assemble: str=%s\n",str);*/
679
680 /* Drop leading whitespace */
681 while (*str == ' ')
682 str++;
683
684 /* find the opcode end */
685 for (op_start = op_end = (unsigned char *) (str);
686 *op_end
687 && nlen < 20
688 && !is_end_of_line[*op_end] && *op_end != ' ';
689 op_end++)
690 {
691 name[nlen] = op_start[nlen];
692 nlen++;
693 }
694 name[nlen] = 0;
695
696 if (nlen == 0)
697 as_bad ("can't find opcode ");
698
699 /* find the first opcode with the proper name */
700 *opcode = (struct d10v_opcode *)hash_find (d10v_hash, name);
701 if (*opcode == NULL)
702 {
703 as_bad ("unknown opcode");
704 return;
705 }
706
707 save = input_line_pointer;
708 input_line_pointer = op_end;
709
710 /* get all the operands and save them as expressions */
711 numops = get_operands (myops);
712
713 /* now search the opcode table table for one with operands */
714 /* that match what we've got */
715 do
716 {
717 match = 1;
718 for (i = 0; (*opcode)->operands[i]; i++)
719 {
720 int flags = d10v_operands[(*opcode)->operands[i]].flags;
721
722 if (myops[i].X_op==0)
723 {
724 match=0;
725 break;
726 }
727
728 if (flags & OPERAND_REG)
729 {
730 if ((myops[i].X_op != O_register) ||
731 ((flags & OPERAND_ACC) != (myops[i].X_add_number & OPERAND_ACC)) ||
732 ((flags & OPERAND_FLAG) != (myops[i].X_add_number & OPERAND_FLAG)) ||
733 ((flags & OPERAND_CONTROL) != (myops[i].X_add_number & OPERAND_CONTROL)))
734 {
735 match=0;
736 break;
737 }
738 }
739
740 if (((flags & OPERAND_MINUS) && ((myops[i].X_op != O_absent) || (myops[i].X_add_number != OPERAND_MINUS))) ||
741 ((flags & OPERAND_PLUS) && ((myops[i].X_op != O_absent) || (myops[i].X_add_number != OPERAND_PLUS))) ||
742 ((flags & OPERAND_ATMINUS) && ((myops[i].X_op != O_absent) || (myops[i].X_add_number != OPERAND_ATMINUS))) ||
743 ((flags & OPERAND_ATPAR) && ((myops[i].X_op != O_absent) || (myops[i].X_add_number != OPERAND_ATPAR))) ||
744 ((flags & OPERAND_ATSIGN) && ((myops[i].X_op != O_absent) || (myops[i].X_add_number != OPERAND_ATSIGN))))
745 {
746 match=0;
747 break;
748 }
749 }
750
751 /* we're only done if the operands matched AND there
752 are no more to check */
753 if (match && myops[i].X_op==0)
754 break;
755
756 next_opcode = (*opcode)+1;
757 if (next_opcode->opcode == 0)
758 break;
759 if (strcmp(next_opcode->name, (*opcode)->name))
760 break;
761 (*opcode) = next_opcode;
762 } while (!match);
763
764 if (!match)
765 {
766 as_bad ("bad opcode or operands");
767 return (0);
768 }
769
770 /* Check that all registers that are required to be even are. */
771 /* Also, if any operands were marked as registers, but were really symbols */
772 /* fix that here. */
773 for (i=0; (*opcode)->operands[i]; i++)
774 {
775 if ((d10v_operands[(*opcode)->operands[i]].flags & OPERAND_EVEN) &&
776 (myops[i].X_add_number & 1))
777 as_fatal("Register number must be EVEN");
778 if (myops[i].X_op == O_register)
779 {
780 if (!(d10v_operands[(*opcode)->operands[i]].flags & OPERAND_REG))
781 {
782 myops[i].X_op = O_symbol;
783 myops[i].X_add_number = 0;
784 /* FIXME create a fixup */
785 }
786 }
787 }
788
789 input_line_pointer = save;
790
791 /* at this point, we have "opcode" pointing to the opcode entry in the
792 d10v opcode table, with myops filled out with the operands. */
793 insn = build_insn ((*opcode), myops);
794 /* printf("sub-insn = %lx\n",insn); */
795
796 return (insn);
797 }
798
799
800 /* if while processing a fixup, a reloc really needs to be created */
801 /* then it is done here */
802
803 arelent *
804 tc_gen_reloc (seg, fixp)
805 asection *seg;
806 fixS *fixp;
807 {
808 arelent *reloc;
809 reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
810 reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
811 reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
812 reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
813 if (reloc->howto == (reloc_howto_type *) NULL)
814 {
815 as_bad_where (fixp->fx_file, fixp->fx_line,
816 "reloc %d not supported by object file format", (int)fixp->fx_r_type);
817 return NULL;
818 }
819 reloc->addend = fixp->fx_addnumber;
820 /* printf("tc_gen_reloc: addr=%x addend=%x\n", reloc->address, reloc->addend); */
821 return reloc;
822 }
823
824 int
825 md_estimate_size_before_relax (fragp, seg)
826 fragS *fragp;
827 asection *seg;
828 {
829 abort ();
830 return 0;
831 }
832
833 long
834 md_pcrel_from_section (fixp, sec)
835 fixS *fixp;
836 segT sec;
837 {
838 return 0;
839 /* return fixp->fx_frag->fr_address + fixp->fx_where; */
840 }
841
842 int
843 md_apply_fix3 (fixp, valuep, seg)
844 fixS *fixp;
845 valueT *valuep;
846 segT seg;
847 {
848 valueT value;
849 char *where;
850 unsigned long insn;
851 int op_type;
852
853 if (fixp->fx_addsy == (symbolS *) NULL)
854 {
855 value = *valuep;
856 fixp->fx_done = 1;
857 }
858 else if (fixp->fx_pcrel)
859 value = *valuep;
860 else
861 {
862 value = fixp->fx_offset;
863 if (fixp->fx_subsy != (symbolS *) NULL)
864 {
865 if (S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
866 value -= S_GET_VALUE (fixp->fx_subsy);
867 else
868 {
869 /* We don't actually support subtracting a symbol. */
870 as_bad_where (fixp->fx_file, fixp->fx_line,
871 "expression too complex");
872 }
873 }
874 }
875
876 /* printf("md_apply_fix: value=0x%x type=%d\n", value, fixp->fx_r_type); */
877
878 op_type = fixp->fx_r_type;
879 fixp->fx_r_type = get_reloc((struct d10v_operand *)&d10v_operands[op_type]);
880
881 /* printf("reloc=%d\n",fixp->fx_r_type); */
882
883 /* Fetch the instruction, insert the fully resolved operand
884 value, and stuff the instruction back again. */
885 where = fixp->fx_frag->fr_literal + fixp->fx_where;
886 insn = bfd_getb32 ((unsigned char *) where);
887 /* printf(" insn=%x value=%x\n",insn,value); */
888
889 insn = d10v_insert_operand (insn, op_type, (offsetT) value);
890
891 /* printf(" new insn=%x\n",insn); */
892
893 bfd_putb32 ((bfd_vma) insn, (unsigned char *) where);
894
895 if (fixp->fx_done)
896 return 1;
897
898 fixp->fx_addnumber = value;
899 return 1;
900 }
901
902 /* This is called after the assembler has finished parsing the input
903 file. Because the D10V assembler sometimes saves short instructions
904 to see if it can package them with the next instruction, there may
905 be a short instruction that still needs written. */
906
907 int md_after_pass()
908 {
909 if (prev_opcode)
910 {
911 write_1_short (prev_opcode, prev_insn);
912 prev_opcode = NULL;
913 }
914 }
915
916
917 /* there is a label to be defined. Any saved instruction must
918 be written out. */
919 int
920 start_label()
921 {
922 if (prev_opcode)
923 {
924 write_1_short (prev_opcode, prev_insn);
925 prev_opcode = NULL;
926 }
927 return 1;
928 }
This page took 0.089019 seconds and 5 git commands to generate.