diff options
author | Nick Clifton <nickc@redhat.com> | 2009-04-16 15:39:48 +0000 |
---|---|---|
committer | Nick Clifton <nickc@redhat.com> | 2009-04-16 15:39:48 +0000 |
commit | 20135e4cea8994900955e560910b2e675881fa95 (patch) | |
tree | f3e60cf7a267184a4d9ffef4f6ab0e54ceb599e9 /gas | |
parent | 335d71d67eab3d9e1cfdefc45af81fa65fbd5c8b (diff) | |
download | gdb-20135e4cea8994900955e560910b2e675881fa95.zip gdb-20135e4cea8994900955e560910b2e675881fa95.tar.gz gdb-20135e4cea8994900955e560910b2e675881fa95.tar.bz2 |
Add new binutils target: moxie
Diffstat (limited to 'gas')
-rw-r--r-- | gas/ChangeLog | 7 | ||||
-rw-r--r-- | gas/config/tc-moxie.c | 731 | ||||
-rw-r--r-- | gas/config/tc-moxie.h | 47 | ||||
-rw-r--r-- | gas/configure.tgt | 2 |
4 files changed, 787 insertions, 0 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index b837c17..a3442b3 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,10 @@ +2008-04-15 Anthony Green <green@moxielogic.com> + + * config/tc-moxie.h: New file. + * config/tc-moxie.c: New file. + * configure: Add support for moxie. + * configure.tgt: Add support for moxie. + 2009-04-16 Jan Beulich <jbeulich@novell.com> * expr.c: Include limits.h if available, and #define CHAR_BITS diff --git a/gas/config/tc-moxie.c b/gas/config/tc-moxie.c new file mode 100644 index 0000000..84563ce --- /dev/null +++ b/gas/config/tc-moxie.c @@ -0,0 +1,731 @@ +/* tc-moxie.c -- Assemble code for moxie + Copyright 2009 + Free Software Foundation, Inc. + + This file is part of GAS, the GNU Assembler. + + GAS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GAS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GAS; see the file COPYING. If not, write to + the Free Software Foundation, 51 Franklin Street - Fifth Floor, + Boston, MA 02110-1301, USA. */ + +/* Contributed by Anthony Green <green@moxielogic.com>. */ + +#include "as.h" +#include "safe-ctype.h" +#include "opcode/moxie.h" +#include "elf/moxie.h" + +extern const moxie_opc_info_t moxie_opc_info[128]; + +const char comment_chars[] = "#"; +const char line_separator_chars[] = ";"; +const char line_comment_chars[] = "#"; + +static int pending_reloc; +static struct hash_control *opcode_hash_control; + +const pseudo_typeS md_pseudo_table[] = +{ + {0, 0, 0} +}; + +const char FLT_CHARS[] = "rRsSfFdDxXpP"; +const char EXP_CHARS[] = "eE"; + +void +md_operand (expressionS *op __attribute__((unused))) +{ + /* Empty for now. */ +} + +/* This function is called once, at assembler startup time. It sets + up the hash table with all the opcodes in it, and also initializes + some aliases for compatibility with other assemblers. */ + +void +md_begin (void) +{ + int count; + const moxie_opc_info_t *opcode; + opcode_hash_control = hash_new (); + + /* Insert names into hash table. */ + for (count = 0, opcode = moxie_form1_opc_info; count++ < 64; opcode++) + hash_insert (opcode_hash_control, opcode->name, (char *) opcode); + + for (count = 0, opcode = moxie_form2_opc_info; count++ < 4; opcode++) + hash_insert (opcode_hash_control, opcode->name, (char *) opcode); + + for (count = 0, opcode = moxie_form3_opc_info; count++ < 4; opcode++) + hash_insert (opcode_hash_control, opcode->name, (char *) opcode); + + bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0); +} + +/* Parse an expression and then restore the input line pointer. */ + +static char * +parse_exp_save_ilp (char *s, expressionS *op) +{ + char *save = input_line_pointer; + + input_line_pointer = s; + expression (op); + s = input_line_pointer; + input_line_pointer = save; + return s; +} + +static int +parse_register_operand (char **ptr) +{ + int reg; + char *s = *ptr; + + if (*s != '$') + { + as_bad ("expecting register"); + ignore_rest_of_line (); + return -1; + } + if (s[1] == 'f' && s[2] == 'p') + { + *ptr += 3; + return 0; + } + if (s[1] == 's' && s[2] == 'p') + { + *ptr += 3; + return 1; + } + if (s[1] == 'r') + { + reg = s[2] - '0'; + if ((reg < 0) || (reg > 9)) + { + as_bad ("illegal register number"); + ignore_rest_of_line (); + return -1; + } + if (reg == 1) + { + int r2 = s[3] - '0'; + if ((r2 >= 0) && (r2 <= 3)) + { + reg = 10 + r2; + *ptr += 1; + } + } + } + else + { + as_bad ("illegal register number"); + ignore_rest_of_line (); + return -1; + } + + *ptr += 3; + + return reg + 2; +} + +/* This is the guts of the machine-dependent assembler. STR points to + a machine dependent instruction. This function is supposed to emit + the frags/bytes it assembles to. */ + +void +md_assemble (char *str) +{ + char *op_start; + char *op_end; + + moxie_opc_info_t *opcode; + char *p; + char pend; + + unsigned short iword = 0; + + int nlen = 0; + + /* Drop leading whitespace. */ + while (*str == ' ') + str++; + + /* Find the op code end. */ + op_start = str; + for (op_end = str; + *op_end && !is_end_of_line[*op_end & 0xff] && *op_end != ' '; + op_end++) + nlen++; + + pend = *op_end; + *op_end = 0; + + if (nlen == 0) + as_bad (_("can't find opcode ")); + opcode = (moxie_opc_info_t *) hash_find (opcode_hash_control, op_start); + *op_end = pend; + + if (opcode == NULL) + { + as_bad (_("unknown opcode %s"), op_start); + return; + } + + p = frag_more (2); + + switch (opcode->itype) + { + case MOXIE_F2_A8V: + iword = (1<<15) | (opcode->opcode << 12); + while (ISSPACE (*op_end)) + op_end++; + { + expressionS arg; + int reg; + reg = parse_register_operand (&op_end); + iword += (reg << 8); + if (*op_end != ',') + as_warn ("expecting comma delimeted register operands"); + op_end++; + op_end = parse_exp_save_ilp (op_end, &arg); + fix_new_exp (frag_now, + ((p+1) - frag_now->fr_literal), + 1, + &arg, + 0, + BFD_RELOC_8); + } + break; + case MOXIE_F1_AB: + iword = opcode->opcode << 8; + while (ISSPACE (*op_end)) + op_end++; + { + int dest, src; + dest = parse_register_operand (&op_end); + if (*op_end != ',') + as_warn ("expecting comma delimeted register operands"); + op_end++; + src = parse_register_operand (&op_end); + iword += (dest << 4) + src; + while (ISSPACE (*op_end)) + op_end++; + if (*op_end != 0) + as_warn ("extra stuff on line ignored"); + } + break; + case MOXIE_F1_A4: + iword = opcode->opcode << 8; + while (ISSPACE (*op_end)) + op_end++; + { + expressionS arg; + char *where; + int regnum; + + regnum = parse_register_operand (&op_end); + while (ISSPACE (*op_end)) + op_end++; + + iword += (regnum << 4); + + if (*op_end != ',') + { + as_bad ("expecting comma delimited operands"); + ignore_rest_of_line (); + return; + } + op_end++; + + op_end = parse_exp_save_ilp (op_end, &arg); + where = frag_more (4); + fix_new_exp (frag_now, + (where - frag_now->fr_literal), + 4, + &arg, + 0, + BFD_RELOC_32); + } + break; + case MOXIE_F1_4: + iword = opcode->opcode << 8; + while (ISSPACE (*op_end)) + op_end++; + { + expressionS arg; + char *where; + + op_end = parse_exp_save_ilp (op_end, &arg); + where = frag_more (4); + fix_new_exp (frag_now, + (where - frag_now->fr_literal), + 4, + &arg, + 0, + BFD_RELOC_32); + } + break; + case MOXIE_F1_NARG: + iword = opcode->opcode << 8; + while (ISSPACE (*op_end)) + op_end++; + if (*op_end != 0) + as_warn ("extra stuff on line ignored"); + break; + case MOXIE_F1_A: + iword = opcode->opcode << 8; + while (ISSPACE (*op_end)) + op_end++; + { + int reg; + reg = parse_register_operand (&op_end); + while (ISSPACE (*op_end)) + op_end++; + if (*op_end != 0) + as_warn ("extra stuff on line ignored"); + iword += (reg << 4); + } + break; + case MOXIE_F1_ABi: + iword = opcode->opcode << 8; + while (ISSPACE (*op_end)) + op_end++; + { + int a, b; + a = parse_register_operand (&op_end); + if (*op_end != ',') + as_warn ("expecting comma delimeted register operands"); + op_end++; + if (*op_end != '(') + { + as_bad ("expecting indirect register `($rA)'"); + ignore_rest_of_line (); + return; + } + op_end++; + b = parse_register_operand (&op_end); + if (*op_end != ')') + { + as_bad ("missing closing parenthesis"); + ignore_rest_of_line (); + return; + } + op_end++; + iword += (a << 4) + b; + while (ISSPACE (*op_end)) + op_end++; + if (*op_end != 0) + as_warn ("extra stuff on line ignored"); + } + break; + case MOXIE_F1_AiB: + iword = opcode->opcode << 8; + while (ISSPACE (*op_end)) + op_end++; + { + int a, b; + if (*op_end != '(') + { + as_bad ("expecting indirect register `($rA)'"); + ignore_rest_of_line (); + return; + } + op_end++; + a = parse_register_operand (&op_end); + if (*op_end != ')') + { + as_bad ("missing closing parenthesis"); + ignore_rest_of_line (); + return; + } + op_end++; + if (*op_end != ',') + as_warn ("expecting comma delimeted register operands"); + op_end++; + b = parse_register_operand (&op_end); + iword += (a << 4) + b; + while (ISSPACE (*op_end)) + op_end++; + if (*op_end != 0) + as_warn ("extra stuff on line ignored"); + } + break; + case MOXIE_F1_4A: + iword = opcode->opcode << 8; + while (ISSPACE (*op_end)) + op_end++; + { + expressionS arg; + char *where; + int a; + + op_end = parse_exp_save_ilp (op_end, &arg); + where = frag_more (4); + fix_new_exp (frag_now, + (where - frag_now->fr_literal), + 4, + &arg, + 0, + BFD_RELOC_32); + + if (*op_end != ',') + { + as_bad ("expecting comma delimited operands"); + ignore_rest_of_line (); + return; + } + op_end++; + + a = parse_register_operand (&op_end); + while (ISSPACE (*op_end)) + op_end++; + if (*op_end != 0) + as_warn ("extra stuff on line ignored"); + + iword += (a << 4); + } + break; + case MOXIE_F1_ABi4: + iword = opcode->opcode << 8; + while (ISSPACE (*op_end)) + op_end++; + { + expressionS arg; + char *offset; + int a, b; + + a = parse_register_operand (&op_end); + while (ISSPACE (*op_end)) + op_end++; + + if (*op_end != ',') + { + as_bad ("expecting comma delimited operands"); + ignore_rest_of_line (); + return; + } + op_end++; + + op_end = parse_exp_save_ilp (op_end, &arg); + offset = frag_more (4); + fix_new_exp (frag_now, + (offset - frag_now->fr_literal), + 4, + &arg, + 0, + BFD_RELOC_32); + + if (*op_end != '(') + { + as_bad ("expecting indirect register `($rX)'"); + ignore_rest_of_line (); + return; + } + op_end++; + b = parse_register_operand (&op_end); + if (*op_end != ')') + { + as_bad ("missing closing parenthesis"); + ignore_rest_of_line (); + return; + } + op_end++; + + while (ISSPACE (*op_end)) + op_end++; + if (*op_end != 0) + as_warn ("extra stuff on line ignored"); + + iword += (a << 4) + b; + } + break; + case MOXIE_F1_AiB4: + iword = opcode->opcode << 8; + while (ISSPACE (*op_end)) + op_end++; + { + expressionS arg; + char *offset; + int a, b; + + op_end = parse_exp_save_ilp (op_end, &arg); + offset = frag_more (4); + fix_new_exp (frag_now, + (offset - frag_now->fr_literal), + 4, + &arg, + 0, + BFD_RELOC_32); + + if (*op_end != '(') + { + as_bad ("expecting indirect register `($rX)'"); + ignore_rest_of_line (); + return; + } + op_end++; + a = parse_register_operand (&op_end); + if (*op_end != ')') + { + as_bad ("missing closing parenthesis"); + ignore_rest_of_line (); + return; + } + op_end++; + + if (*op_end != ',') + { + as_bad ("expecting comma delimited operands"); + ignore_rest_of_line (); + return; + } + op_end++; + + b = parse_register_operand (&op_end); + while (ISSPACE (*op_end)) + op_end++; + + while (ISSPACE (*op_end)) + op_end++; + if (*op_end != 0) + as_warn ("extra stuff on line ignored"); + + iword += (a << 4) + b; + } + break; + case MOXIE_F2_NARG: + iword = opcode->opcode << 12; + while (ISSPACE (*op_end)) + op_end++; + if (*op_end != 0) + as_warn ("extra stuff on line ignored"); + break; + default: + abort(); + } + + md_number_to_chars (p, iword, 2); + + while (ISSPACE (*op_end)) + op_end++; + + if (*op_end != 0) + as_warn ("extra stuff on line ignored"); + + if (pending_reloc) + as_bad ("Something forgot to clean up\n"); +} + +/* Turn a string in input_line_pointer into a floating point constant + of type type, and store the appropriate bytes in *LITP. The number + of LITTLENUMS emitted is stored in *SIZEP . An error message is + returned, or NULL on OK. */ + +char * +md_atof (int type, char *litP, int *sizeP) +{ + int prec; + LITTLENUM_TYPE words[4]; + char *t; + int i; + + switch (type) + { + case 'f': + prec = 2; + break; + + case 'd': + prec = 4; + break; + + default: + *sizeP = 0; + return _("bad call to md_atof"); + } + + t = atof_ieee (input_line_pointer, type, words); + if (t) + input_line_pointer = t; + + *sizeP = prec * 2; + + for (i = prec - 1; i >= 0; i--) + { + md_number_to_chars (litP, (valueT) words[i], 2); + litP += 2; + } + + return NULL; +} + +const char *md_shortopts = ""; + +struct option md_longopts[] = +{ + {NULL, no_argument, NULL, 0} +}; +size_t md_longopts_size = sizeof (md_longopts); + +/* We have no target specific options yet, so these next + two functions are empty. */ +int +md_parse_option (int c ATTRIBUTE_UNUSED, char *arg ATTRIBUTE_UNUSED) +{ + return 0; +} + +void +md_show_usage (FILE *stream ATTRIBUTE_UNUSED) +{ +} + +/* Apply a fixup to the object file. */ + +void +md_apply_fix (fixS *fixP ATTRIBUTE_UNUSED, valueT * valP ATTRIBUTE_UNUSED, segT seg ATTRIBUTE_UNUSED) +{ + char *buf = fixP->fx_where + fixP->fx_frag->fr_literal; + long val = *valP; + long max, min; + int shift; + + max = min = 0; + shift = 0; + switch (fixP->fx_r_type) + { + case BFD_RELOC_32: + *buf++ = val >> 24; + *buf++ = val >> 16; + *buf++ = val >> 8; + *buf++ = val >> 0; + break; + + case BFD_RELOC_16: + *buf++ = val >> 8; + *buf++ = val >> 0; + break; + + case BFD_RELOC_8: + *buf++ = val; + break; + + default: + abort (); + } + + if (max != 0 && (val < min || val > max)) + as_bad_where (fixP->fx_file, fixP->fx_line, _("offset out of range")); + + if (fixP->fx_addsy == NULL && fixP->fx_pcrel == 0) + fixP->fx_done = 1; +} + +/* Put number into target byte order (big endian). */ + +void +md_number_to_chars (char *ptr, valueT use, int nbytes) +{ + number_to_chars_bigendian (ptr, use, nbytes); +} + +/* Generate a machine-dependent relocation. */ +arelent * +tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP) +{ + arelent *relP; + bfd_reloc_code_real_type code; + + switch (fixP->fx_r_type) + { + case BFD_RELOC_32: + code = fixP->fx_r_type; + break; + default: + as_bad_where (fixP->fx_file, fixP->fx_line, + _("Semantics error. This type of operand can not be relocated, it must be an assembly-time constant")); + return 0; + } + + relP = xmalloc (sizeof (arelent)); + assert (relP != 0); + relP->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); + *relP->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy); + relP->address = fixP->fx_frag->fr_address + fixP->fx_where; + + relP->addend = fixP->fx_offset; + + /* This is the standard place for KLUDGEs to work around bugs in + bfd_install_relocation (first such note in the documentation + appears with binutils-2.8). + + That function bfd_install_relocation does the wrong thing with + putting stuff into the addend of a reloc (it should stay out) for a + weak symbol. The really bad thing is that it adds the + "segment-relative offset" of the symbol into the reloc. In this + case, the reloc should instead be relative to the symbol with no + other offset than the assembly code shows; and since the symbol is + weak, any local definition should be ignored until link time (or + thereafter). + To wit: weaksym+42 should be weaksym+42 in the reloc, + not weaksym+(offset_from_segment_of_local_weaksym_definition) + + To "work around" this, we subtract the segment-relative offset of + "known" weak symbols. This evens out the extra offset. + + That happens for a.out but not for ELF, since for ELF, + bfd_install_relocation uses the "special function" field of the + howto, and does not execute the code that needs to be undone. */ + + if (OUTPUT_FLAVOR == bfd_target_aout_flavour + && fixP->fx_addsy && S_IS_WEAK (fixP->fx_addsy) + && ! bfd_is_und_section (S_GET_SEGMENT (fixP->fx_addsy))) + { + relP->addend -= S_GET_VALUE (fixP->fx_addsy); + } + + relP->howto = bfd_reloc_type_lookup (stdoutput, code); + if (! relP->howto) + { + const char *name; + + name = S_GET_NAME (fixP->fx_addsy); + if (name == NULL) + name = _("<unknown>"); + as_fatal (_("Cannot generate relocation type for symbol %s, code %s"), + name, bfd_get_reloc_code_name (code)); + } + + return relP; +} + +/* Decide from what point a pc-relative relocation is relative to, + relative to the pc-relative fixup. Er, relatively speaking. */ +long +md_pcrel_from (fixS *fixP) +{ + valueT addr = fixP->fx_where + fixP->fx_frag->fr_address; + + fprintf (stderr, "md_pcrel_from 0x%d\n", fixP->fx_r_type); + + switch (fixP->fx_r_type) + { + case BFD_RELOC_32: + return addr + 4; + default: + abort (); + return addr; + } +} diff --git a/gas/config/tc-moxie.h b/gas/config/tc-moxie.h new file mode 100644 index 0000000..db1d01a --- /dev/null +++ b/gas/config/tc-moxie.h @@ -0,0 +1,47 @@ +/* tc-moxie.h -- Header file for tc-moxie.c. + + Copyright 2009 Free Software Foundation, Inc. + + This file is part of GAS, the GNU Assembler. + + GAS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3, or (at your option) + any later version. + + GAS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with GAS; see the file COPYING. If not, write to the Free Software + Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ + +#define TC_MOXIE 1 +#define TARGET_BYTES_BIG_ENDIAN 1 +#define WORKING_DOT_WORD + +/* This macro is the BFD target name to use when creating the output + file. This will normally depend upon the `OBJ_FMT' macro. */ +#define TARGET_FORMAT "elf32-moxie" + +/* This macro is the BFD architecture to pass to `bfd_set_arch_mach'. */ +#define TARGET_ARCH bfd_arch_moxie + +#define md_undefined_symbol(NAME) 0 + +/* These macros must be defined, but is will be a fatal assembler + error if we ever hit them. */ +#define md_estimate_size_before_relax(A, B) (as_fatal (_("estimate size\n")), 0) +#define md_convert_frag(B, S, F) (as_fatal (_("convert_frag\n")), 0) + +/* If you define this macro, it should return the offset between the + address of a PC relative fixup and the position from which the PC + relative adjustment should be made. On many processors, the base + of a PC relative instruction is the next instruction, so this + macro would return the length of an instruction. */ +#define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from (FIX) +extern long md_pcrel_from (struct fix *); + +#define md_section_align(SEGMENT, SIZE) (SIZE) diff --git a/gas/configure.tgt b/gas/configure.tgt index e3eadac..9d722ed 100644 --- a/gas/configure.tgt +++ b/gas/configure.tgt @@ -148,6 +148,8 @@ case ${generic_target} in frv-*-*linux*) fmt=elf em=linux;; frv-*-*) fmt=elf ;; + moxie-*-*) fmt=elf ;; + hppa-*-linux*) case ${cpu} in hppa*64*) fmt=elf em=hppalinux64 ;; |