1 /* tc-d10v.c -- Assembler code for the Mitsubishi D10V
3 Copyright (C) 1996 Free Software Foundation.
5 This file is part of GAS, the GNU Assembler.
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)
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.
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. */
26 #include "opcode/d10v.h"
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";
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
));
50 #define MAX_INSN_FIXUPS (5)
55 bfd_reloc_code_real_type reloc
;
57 struct d10v_fixup fixups
[MAX_INSN_FIXUPS
];
60 struct option md_longopts
[] = {
61 {NULL
, no_argument
, NULL
, 0}
63 size_t md_longopts_size
= sizeof(md_longopts
);
65 /* The target specific pseudo-ops which we support. */
66 const pseudo_typeS md_pseudo_table
[] =
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 },
80 /* Opcode hash table. */
81 static struct hash_control
*d10v_hash
;
83 /* Structure to hold information about predefined registers. */
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
95 /* The table is sorted. Suitable for searching by a binary search. */
96 static const struct pd_reg pre_defined_registers
[] =
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 },
126 { "rpt_c", OPERAND_CONTROL
+7 },
127 { "rpt_e", OPERAND_CONTROL
+9 },
128 { "rpt_s", OPERAND_CONTROL
+8 },
131 #define REG_NAME_CNT (sizeof(pre_defined_registers) / sizeof(struct pd_reg))
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. */
138 reg_name_search (name
)
141 int middle
, low
, high
;
145 high
= REG_NAME_CNT
- 1;
149 middle
= (low
+ high
) / 2;
150 cmp
= strcasecmp (name
, pre_defined_registers
[middle
].name
);
156 return pre_defined_registers
[middle
].value
;
163 /* register_name check to see if an expression is a valid
164 register name. If it is, it marks the expression type
168 register_name (expressionP
)
169 expressionS
*expressionP
;
174 if (expressionP
->X_op
== O_symbol
)
176 name
= (char *)S_GET_NAME (expressionP
->X_add_symbol
);
177 reg_number
= reg_name_search (name
);
179 /* look to see if it's in the register table */
182 expressionP
->X_op
= O_register
;
183 expressionP
->X_add_number
= reg_number
;
189 md_show_usage (stream
)
192 fprintf(stream
, "D10V options:\n\
197 md_parse_option (c
, arg
)
205 md_undefined_symbol (name
)
212 md_atof (type
, litp
, sizep
)
221 md_convert_frag (abfd
, sec
, fragP
)
226 /* printf ("call to md_convert_frag \n"); */
231 md_section_align (seg
, addr
)
235 int align
= bfd_get_section_alignment (stdoutput
, seg
);
236 return ((addr
+ (1 << align
) - 1) & (-1 << align
));
242 char *prev_name
= "";
243 struct d10v_opcode
*opcode
;
244 d10v_hash
= hash_new();
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. */
251 for (opcode
= (struct d10v_opcode
*)d10v_opcodes
; opcode
->name
; opcode
++)
253 if (strcmp (prev_name
, opcode
->name
))
255 prev_name
= (char *)opcode
->name
;
256 hash_insert (d10v_hash
, opcode
->name
, (char *) opcode
);
262 /* this function removes the postincrement or postdecrement
263 operator ( '+' or '-' ) from an expression */
265 static int postfix (p
)
268 while (*p
!= '-' && *p
!= '+')
270 if (*p
==0 || *p
=='\n' || *p
=='\r')
290 static bfd_reloc_code_real_type
292 struct d10v_operand
*op
;
296 /* printf("get_reloc: bits=%d address=%d\n",bits,op->flags & OPERAND_ADDR); */
300 if (op
->flags
& OPERAND_ADDR
)
303 return (BFD_RELOC_D10V_10_PCREL_R
);
305 return (BFD_RELOC_D10V_18_PCREL
);
308 return (BFD_RELOC_16
);
311 /* get_operands parses a string of operands and returns
312 an array of expressions */
318 char *p
= input_line_pointer
;
324 while (*p
== ' ' || *p
== '\t' || *p
== ',')
326 if (*p
==0 || *p
=='\n' || *p
=='\r')
332 exp
[numops
].X_op
= O_absent
;
336 exp
[numops
].X_add_number
= OPERAND_ATPAR
;
341 exp
[numops
].X_add_number
= OPERAND_ATMINUS
;
345 exp
[numops
].X_add_number
= OPERAND_ATSIGN
;
354 /* just skip the trailing paren */
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
]);
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");
371 p
= input_line_pointer
;
376 case -1: /* postdecrement mode */
377 exp
[numops
].X_op
= O_absent
;
378 exp
[numops
++].X_add_number
= OPERAND_MINUS
;
380 case 1: /* postincrement mode */
381 exp
[numops
].X_op
= O_absent
;
382 exp
[numops
++].X_add_number
= OPERAND_PLUS
;
386 exp
[numops
].X_op
= 0;
391 d10v_insert_operand (insn
, op_type
, value
)
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
);
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 */
413 build_insn (opcode
, opers
)
414 struct d10v_opcode
*opcode
;
417 int i
, bits
, shift
, flags
;
420 insn
= opcode
->opcode
;
422 for (i
=0;opcode
->operands
[i
];i
++)
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
;
429 if (flags
& OPERAND_REG
)
431 number
&= REGISTER_MASK
;
432 if (opcode
->format
== LONG_L
)
436 if (opers
[i
].X_op
!= O_register
&& opers
[i
].X_op
!= O_constant
)
438 /* now create a fixup */
441 printf("need a fixup: ");
442 print_expr_1(stdout,&opers[i]);
446 if (fc
>= MAX_INSN_FIXUPS
)
447 as_fatal ("too many fixups");
448 fixups
[fc
].exp
= opers
[i
];
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
];
456 /* truncate to the proper number of bits */
457 /* FIXME: overflow checking here? */
458 number
&= 0x7FFFFFFF >> (31 - bits
);
459 insn
= insn
| (number
<< shift
);
464 /* write out a long form instruction */
466 write_long (opcode
, insn
)
467 struct d10v_opcode
*opcode
;
471 char *f
= frag_more(4);
474 /* printf("INSN: %08x\n",insn); */
475 number_to_chars_bigendian (f
, insn
, 4);
479 if (get_reloc((struct d10v_operand
*)&d10v_operands
[fixups
[i
].reloc
]))
482 printf("fix_new_exp: where:%x size:4\n ",f - frag_now->fr_literal);
483 print_expr_1(stdout,&fixups[i].exp);
487 fix_new_exp (frag_now
,
488 f
- frag_now
->fr_literal
,
497 /* write out a short form instruction by itself */
499 write_1_short (opcode
, insn
)
500 struct d10v_opcode
*opcode
;
503 char *f
= frag_more(4);
506 insn
|= FM00
| (NOP
<< 15);
507 /* printf("INSN: %08x\n",insn); */
508 number_to_chars_bigendian (f
, insn
, 4);
511 if (get_reloc((struct d10v_operand
*)&d10v_operands
[fixups
[i
].reloc
]))
514 printf("fix_new_exp: where:%x size:4\n ",f - frag_now->fr_literal);
515 print_expr_1(stdout,&fixups[i].exp);
519 fix_new_exp (frag_now
,
520 f
- frag_now
->fr_literal
,
529 /* write out a short form instruction if possible */
530 /* return number of instructions not written out */
532 write_2_short (opcode1
, insn1
, opcode2
, insn2
, exec_type
)
533 struct d10v_opcode
*opcode1
, *opcode2
;
534 unsigned long insn1
, insn2
;
539 if(opcode1
->exec_type
== BRANCH_LINK
)
541 /* subroutines must be called from 32-bit boundaries */
542 /* so the return address will be correct */
543 write_1_short (opcode1
, insn1
);
550 if (opcode1
->unit
== IU
)
552 insn
= FM10
| (insn2
<< 15) | insn1
;
556 insn
= FM01
| (insn1
<< 15) | insn2
;
559 case 1: /* parallel */
560 insn
= FM00
| (insn1
<< 15) | insn2
;
562 case 2: /* sequential */
563 insn
= FM01
| (insn1
<< 15) | insn2
;
565 case 3: /* reverse sequential */
566 insn
= FM10
| (insn1
<< 15) | insn2
;
569 as_fatal("unknown execution type passed to write_2_short()");
572 /* printf("INSN: %08x\n",insn); */
573 number_to_chars_bigendian (frag_more(4), insn
, 4);
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().
584 static unsigned long prev_insn
;
585 static struct d10v_opcode
*prev_opcode
= 0;
591 struct d10v_opcode
*opcode
;
596 /* printf("md_assemble: str=%s\n",str); */
599 /* look for the special multiple instruction seperators */
600 str2
= strstr (str
, "||");
605 str2
= strstr (str
, "->");
610 str2
= strstr (str
, "<-");
617 /* str2 points to the seperator, if one */
622 /* if two instructions are present and we already have one saved
623 then first write it out */
625 write_1_short (prev_opcode
, prev_insn
);
627 /* assemble first instruction and save it */
628 prev_insn
= do_assemble (str
, &prev_opcode
);
632 insn
= do_assemble (str
, &opcode
);
634 /* if this is a long instruction, write it and any previous short instruction */
635 if (opcode
->format
& LONG_OPCODE
)
638 as_fatal("Unable to mix instructions as specified");
641 write_1_short (prev_opcode
, prev_insn
);
644 write_long (opcode
, insn
);
649 if (prev_opcode
&& (write_2_short (prev_opcode
, prev_insn
, opcode
, insn
, t
) == 0))
651 /* no instructions saved */
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
;
666 do_assemble (str
, opcode
)
668 struct d10v_opcode
**opcode
;
670 struct d10v_opcode
*next_opcode
;
671 unsigned char *op_start
, *save
;
672 unsigned char *op_end
;
674 int nlen
= 0, i
, match
, numops
;
675 expressionS myops
[6];
678 /* printf("do_assemble: str=%s\n",str);*/
680 /* Drop leading whitespace */
684 /* find the opcode end */
685 for (op_start
= op_end
= (unsigned char *) (str
);
688 && !is_end_of_line
[*op_end
] && *op_end
!= ' ';
691 name
[nlen
] = op_start
[nlen
];
697 as_bad ("can't find opcode ");
699 /* find the first opcode with the proper name */
700 *opcode
= (struct d10v_opcode
*)hash_find (d10v_hash
, name
);
703 as_bad ("unknown opcode");
707 save
= input_line_pointer
;
708 input_line_pointer
= op_end
;
710 /* get all the operands and save them as expressions */
711 numops
= get_operands (myops
);
713 /* now search the opcode table table for one with operands */
714 /* that match what we've got */
718 for (i
= 0; (*opcode
)->operands
[i
]; i
++)
720 int flags
= d10v_operands
[(*opcode
)->operands
[i
]].flags
;
722 if (myops
[i
].X_op
==0)
728 if (flags
& OPERAND_REG
)
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
)))
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
))))
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)
756 next_opcode
= (*opcode
)+1;
757 if (next_opcode
->opcode
== 0)
759 if (strcmp(next_opcode
->name
, (*opcode
)->name
))
761 (*opcode
) = next_opcode
;
766 as_bad ("bad opcode or operands");
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 */
773 for (i
=0; (*opcode
)->operands
[i
]; i
++)
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
)
780 if (!(d10v_operands
[(*opcode
)->operands
[i
]].flags
& OPERAND_REG
))
782 myops
[i
].X_op
= O_symbol
;
783 myops
[i
].X_add_number
= 0;
784 /* FIXME create a fixup */
789 input_line_pointer
= save
;
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); */
800 /* if while processing a fixup, a reloc really needs to be created */
801 /* then it is done here */
804 tc_gen_reloc (seg
, fixp
)
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
)
815 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
816 "reloc %d not supported by object file format", (int)fixp
->fx_r_type
);
819 reloc
->addend
= fixp
->fx_addnumber
;
820 /* printf("tc_gen_reloc: addr=%x addend=%x\n", reloc->address, reloc->addend); */
825 md_estimate_size_before_relax (fragp
, seg
)
834 md_pcrel_from_section (fixp
, sec
)
839 /* return fixp->fx_frag->fr_address + fixp->fx_where; */
843 md_apply_fix3 (fixp
, valuep
, seg
)
853 if (fixp
->fx_addsy
== (symbolS
*) NULL
)
858 else if (fixp
->fx_pcrel
)
862 value
= fixp
->fx_offset
;
863 if (fixp
->fx_subsy
!= (symbolS
*) NULL
)
865 if (S_GET_SEGMENT (fixp
->fx_subsy
) == absolute_section
)
866 value
-= S_GET_VALUE (fixp
->fx_subsy
);
869 /* We don't actually support subtracting a symbol. */
870 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
871 "expression too complex");
876 /* printf("md_apply_fix: value=0x%x type=%d\n", value, fixp->fx_r_type); */
878 op_type
= fixp
->fx_r_type
;
879 fixp
->fx_r_type
= get_reloc((struct d10v_operand
*)&d10v_operands
[op_type
]);
881 /* printf("reloc=%d\n",fixp->fx_r_type); */
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); */
889 insn
= d10v_insert_operand (insn
, op_type
, (offsetT
) value
);
891 /* printf(" new insn=%x\n",insn); */
893 bfd_putb32 ((bfd_vma
) insn
, (unsigned char *) where
);
898 fixp
->fx_addnumber
= value
;
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. */
911 write_1_short (prev_opcode
, prev_insn
);
917 /* there is a label to be defined. Any saved instruction must
924 write_1_short (prev_opcode
, prev_insn
);