1 /* tc-v850.c -- Assembler code for the NEC V850
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/v850.h"
28 /* Generic assembler global variables which must be defined by all targets. */
30 /* Characters which always start a comment. */
31 const char comment_chars
[] = "#";
33 /* Characters which start a comment at the beginning of a line. */
34 const char line_comment_chars
[] = "#";
36 /* Characters which may be used to separate multiple commands on a
38 const char line_separator_chars
[] = ";";
40 /* Characters which are used to indicate an exponent in a floating
42 const char EXP_CHARS
[] = "eE";
44 /* Characters which mean that a number is a floating point constant,
46 const char FLT_CHARS
[] = "dD";
49 static unsigned long v850_insert_operand
50 PARAMS ((unsigned long insn
, const struct v850_operand
*operand
,
51 offsetT val
, char *file
, unsigned int line
));
52 static int reg_name_search
PARAMS ((char *name
));
53 static boolean register_name
PARAMS ((expressionS
*expressionP
));
54 static int postfix
PARAMS ((char *p
));
55 static bfd_reloc_code_real_type get_reloc
PARAMS ((struct v850_operand
*op
));
56 static unsigned long build_insn
PARAMS ((struct v850_opcode
*opcode
, expressionS
*opers
));
60 #define MAX_INSN_FIXUPS (5)
65 bfd_reloc_code_real_type reloc
;
67 struct v850_fixup fixups
[MAX_INSN_FIXUPS
];
70 const char *md_shortopts
= "";
71 struct option md_longopts
[] = {
72 {NULL
, no_argument
, NULL
, 0}
74 size_t md_longopts_size
= sizeof(md_longopts
);
76 /* The target specific pseudo-ops which we support. */
77 const pseudo_typeS md_pseudo_table
[] =
80 { "byte", ppc_byte, 0 },
81 { "long", ppc_elf_cons, 4 },
82 { "word", ppc_elf_cons, 2 },
83 { "short", ppc_elf_cons, 2 },
84 { "rdata", ppc_elf_rdata, 0 },
85 { "rodata", ppc_elf_rdata, 0 },
86 { "lcomm", ppc_elf_lcomm, 0 },
91 /* Opcode hash table. */
92 static struct hash_control
*v850_hash
;
94 /* Structure to hold information about predefined registers. */
102 /* an expressionS only has one register type, so we fake it */
103 /* by setting high bits to indicate type */
104 #define REGISTER_MASK 0xFF
106 /* The table is sorted. Suitable for searching by a binary search. */
107 static const struct pd_reg pre_defined_registers
[] =
109 { "ep", 30 }, /* ep - element ptr */
110 { "gp", 4 }, /* gp - global ptr */
111 { "lp", 31 }, /* lp - link ptr */
144 { "sp", 3 }, /* sp - stack ptr */
145 { "tp", 5 }, /* tp - text ptr */
148 #define REG_NAME_CNT (sizeof(pre_defined_registers) / sizeof(struct pd_reg))
150 /* reg_name_search does a binary search of the pre_defined_registers
151 array to see if "name" is a valid regiter name. Returns the register
152 number from the array on success, or -1 on failure. */
155 reg_name_search (name
)
158 int middle
, low
, high
;
162 high
= REG_NAME_CNT
- 1;
166 middle
= (low
+ high
) / 2;
167 cmp
= strcasecmp (name
, pre_defined_registers
[middle
].name
);
173 return pre_defined_registers
[middle
].value
;
180 /* Summary of register_name().
182 * in: Input_line_pointer points to 1st char of operand.
184 * out: A expressionS.
185 * The operand may have been a register: in this case, X_op == O_register,
186 * X_add_number is set to the register number, and truth is returned.
187 * Input_line_pointer->(next non-blank) char after operand, or is in
188 * its original state.
191 register_name (expressionP
)
192 expressionS
*expressionP
;
199 /* Find the spelling of the operand */
200 start
= name
= input_line_pointer
;
202 c
= get_symbol_end ();
203 reg_number
= reg_name_search (name
);
205 /* look to see if it's in the register table */
208 expressionP
->X_op
= O_register
;
209 expressionP
->X_add_number
= reg_number
;
211 /* make the rest nice */
212 expressionP
->X_add_symbol
= NULL
;
213 expressionP
->X_op_symbol
= NULL
;
214 *input_line_pointer
= c
; /* put back the delimiting char */
219 /* reset the line as if we had not done anything */
220 *input_line_pointer
= c
; /* put back the delimiting char */
221 input_line_pointer
= start
; /* reset input_line pointer */
227 md_show_usage (stream
)
230 fprintf(stream
, "V850 options:\n\
235 md_parse_option (c
, arg
)
243 md_undefined_symbol (name
)
250 md_atof (type
, litp
, sizep
)
256 LITTLENUM_TYPE words
[4];
272 return "bad call to md_atof";
275 t
= atof_ieee (input_line_pointer
, type
, words
);
277 input_line_pointer
= t
;
281 for (i
= prec
- 1; i
>= 0; i
--)
283 md_number_to_chars (litp
, (valueT
) words
[i
], 2);
292 md_convert_frag (abfd
, sec
, fragP
)
297 /* printf ("call to md_convert_frag \n"); */
302 md_section_align (seg
, addr
)
306 int align
= bfd_get_section_alignment (stdoutput
, seg
);
307 return ((addr
+ (1 << align
) - 1) & (-1 << align
));
313 char *prev_name
= "";
314 register const struct v850_opcode
*op
;
315 const struct v850_opcode
*op_end
;
317 v850_hash
= hash_new();
319 /* Insert unique names into hash table. The V850 instruction set
320 has many identical opcode names that have different opcodes based
321 on the operands. This hash table then provides a quick index to
322 the first opcode with a particular name in the opcode table. */
325 op_end
= v850_opcodes
+ v850_num_opcodes
;
327 for (; op
< op_end
; op
++)
329 if (strcmp (prev_name
, op
->name
))
331 prev_name
= (char *) op
->name
;
332 hash_insert (v850_hash
, op
->name
, (char *) op
);
338 static bfd_reloc_code_real_type
340 struct v850_operand
*op
;
346 /* get_operands parses a string of operands and returns and array of
352 char *p
= input_line_pointer
;
357 while (*p
== ' ' || *p
== '\t' || *p
== ',')
359 if (*p
==0 || *p
=='\n' || *p
=='\r')
362 input_line_pointer
= p
;
364 if (!register_name(&exp
[numops
]))
365 expression(&exp
[numops
]);
368 p
= input_line_pointer
;
371 exp
[numops
].X_op
= 0;
382 struct v850_opcode
*opcode
;
383 struct v850_opcode
*next_opcode
;
384 const unsigned char *opindex_ptr
;
393 expressionS myops
[5];
395 /* Get the opcode. */
396 for (s
= str
; *s
!= '\0' && ! isspace (*s
); s
++)
401 /* find the first opcode with the proper name */
402 opcode
= (struct v850_opcode
*)hash_find (v850_hash
, str
);
405 as_bad ("Unrecognized opcode: `%s'", str
);
410 while (isspace (*str
))
413 input_line_pointer
= str
;
415 /* get all the operands and save them as expressions */
416 numops
= get_operands (myops
);
418 /* now search the opcode table for one with operands that matches
424 for (i
= 0; opcode
->operands
[i
]; i
++)
426 int flags
= v850_operands
[opcode
->operands
[i
]].flags
;
427 int X_op
= myops
[i
].X_op
;
428 int num
= myops
[i
].X_add_number
;
436 if (flags
& OPERAND_REG
)
438 if (X_op
!= O_register
)
446 /* we're only done if the operands matched so far AND there are
448 if (match
&& myops
[i
].X_op
== 0)
451 next_opcode
= opcode
+ 1;
452 if (next_opcode
->opcode
== 0)
454 if (strcmp (next_opcode
->name
, opcode
->name
))
456 opcode
= next_opcode
;
461 as_bad ("Unrecognized operands");
465 insn
= opcode
->opcode
;
468 while (isspace (*str
))
472 as_bad ("junk at end of line: `%s'", str
);
475 /* Write out the instruction. */
477 md_number_to_chars (f
, insn
, 2);
481 /* if while processing a fixup, a reloc really needs to be created */
482 /* then it is done here */
485 tc_gen_reloc (seg
, fixp
)
490 reloc
= (arelent
*) bfd_alloc_by_size_t (stdoutput
, sizeof (arelent
));
491 reloc
->sym_ptr_ptr
= &fixp
->fx_addsy
->bsym
;
492 reloc
->address
= fixp
->fx_frag
->fr_address
+ fixp
->fx_where
;
493 reloc
->howto
= bfd_reloc_type_lookup (stdoutput
, fixp
->fx_r_type
);
494 if (reloc
->howto
== (reloc_howto_type
*) NULL
)
496 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
497 "reloc %d not supported by object file format", (int)fixp
->fx_r_type
);
500 reloc
->addend
= fixp
->fx_addnumber
;
501 /* printf("tc_gen_reloc: addr=%x addend=%x\n", reloc->address, reloc->addend); */
506 md_estimate_size_before_relax (fragp
, seg
)
515 md_pcrel_from_section (fixp
, sec
)
520 /* return fixp->fx_frag->fr_address + fixp->fx_where; */
524 md_apply_fix3 (fixp
, valuep
, seg
)
536 if (fixp
->fx_addsy
== (symbolS
*) NULL
)
541 else if (fixp
->fx_pcrel
)
545 value
= fixp
->fx_offset
;
546 if (fixp
->fx_subsy
!= (symbolS
*) NULL
)
548 if (S_GET_SEGMENT (fixp
->fx_subsy
) == absolute_section
)
549 value
-= S_GET_VALUE (fixp
->fx_subsy
);
552 /* We don't actually support subtracting a symbol. */
553 as_bad_where (fixp
->fx_file
, fixp
->fx_line
,
554 "expression too complex");
559 /* printf("md_apply_fix: value=0x%x type=%d\n", value, fixp->fx_r_type); */
561 op_type
= fixp
->fx_r_type
;
562 fixp
->fx_r_type
= get_reloc((struct v850_operand
*)&v850_operands
[op_type
]);
564 /* printf("reloc=%d\n",fixp->fx_r_type); */
566 /* Fetch the instruction, insert the fully resolved operand
567 value, and stuff the instruction back again. */
568 where
= fixp
->fx_frag
->fr_literal
+ fixp
->fx_where
;
569 insn
= bfd_getb32 ((unsigned char *) where
);
570 /* printf(" insn=%x value=%x\n",insn,value); */
572 insn
= v850_insert_operand (insn
, op_type
, (offsetT
) value
);
574 /* printf(" new insn=%x\n",insn); */
576 bfd_putb32 ((bfd_vma
) insn
, (unsigned char *) where
);
581 fixp
->fx_addnumber
= value
;
587 /* Insert an operand value into an instruction. */
590 v850_insert_operand (insn
, operand
, val
, file
, line
)
592 const struct v850_operand
*operand
;
597 if (operand
->bits
!= 32)
603 if ((operand
->flags
& PPC_OPERAND_SIGNED
) != 0)
605 if ((operand
->flags
& PPC_OPERAND_SIGNOPT
) != 0
606 && ppc_size
== PPC_OPCODE_32
)
607 max
= (1 << operand
->bits
) - 1;
609 max
= (1 << (operand
->bits
- 1)) - 1;
610 min
= - (1 << (operand
->bits
- 1));
615 max
= (1 << operand
->bits
) - 1;
620 if ((operand
->flags
& PPC_OPERAND_NEGATIVE
) != 0)
627 if (test
< (offsetT
) min
|| test
> (offsetT
) max
)
630 "operand out of range (%s not between %ld and %ld)";
633 sprint_value (buf
, test
);
634 if (file
== (char *) NULL
)
635 as_warn (err
, buf
, min
, max
);
637 as_warn_where (file
, line
, err
, buf
, min
, max
);
641 insn
|= (((long) val
& ((1 << operand
->bits
) - 1)) << operand
->shift
);