diff options
Diffstat (limited to 'binutils-2.24/gas/config/tc-dlx.c')
-rw-r--r-- | binutils-2.24/gas/config/tc-dlx.c | 1243 |
1 files changed, 0 insertions, 1243 deletions
diff --git a/binutils-2.24/gas/config/tc-dlx.c b/binutils-2.24/gas/config/tc-dlx.c deleted file mode 100644 index a629533b..00000000 --- a/binutils-2.24/gas/config/tc-dlx.c +++ /dev/null @@ -1,1243 +0,0 @@ -/* tc-dlx.c -- Assemble for the DLX - Copyright 2002, 2003, 2004, 2005, 2007, 2009, 2010, 2012 - 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. */ - -/* Initially created by Kuang Hwa Lin, 3/20/2002. */ - -#include "as.h" -#include "safe-ctype.h" -#include "tc-dlx.h" -#include "opcode/dlx.h" - -/* Make it easier to clone this machine desc into another one. */ -#define machine_opcode dlx_opcode -#define machine_opcodes dlx_opcodes -#define machine_ip dlx_ip -#define machine_it dlx_it - -#define NO_RELOC BFD_RELOC_NONE -#define RELOC_DLX_REL26 BFD_RELOC_DLX_JMP26 -#define RELOC_DLX_16 BFD_RELOC_16 -#define RELOC_DLX_REL16 BFD_RELOC_16_PCREL_S2 -#define RELOC_DLX_HI16 BFD_RELOC_HI16_S -#define RELOC_DLX_LO16 BFD_RELOC_LO16 -#define RELOC_DLX_VTINHERIT BFD_RELOC_VTABLE_INHERIT -#define RELOC_DLX_VTENTRY BFD_RELOC_VTABLE_ENTRY - -/* handle of the OPCODE hash table */ -static struct hash_control *op_hash = NULL; - -struct machine_it -{ - char *error; - unsigned long opcode; - struct nlist *nlistp; - expressionS exp; - int pcrel; - int size; - int reloc_offset; /* Offset of reloc within insn. */ - int reloc; - int HI; - int LO; -} -the_insn; - -/* This array holds the chars that always start a comment. If the - pre-processor is disabled, these aren't very useful. */ -const char comment_chars[] = ";"; - -/* This array holds the chars that only start a comment at the beginning of - a line. If the line seems to have the form '# 123 filename' - .line and .file directives will appear in the pre-processed output. */ -/* Note that input_file.c hand checks for '#' at the beginning of the - first line of the input file. This is because the compiler outputs - #NO_APP at the beginning of its output. */ -/* Also note that comments like this one will always work. */ -const char line_comment_chars[] = "#"; - -/* We needed an unused char for line separation to work around the - lack of macros, using sed and such. */ -const char line_separator_chars[] = "@"; - -/* Chars that can be used to separate mant from exp in floating point nums. */ -const char EXP_CHARS[] = "eE"; - -/* Chars that mean this number is a floating point constant. - As in 0f12.456 - or 0d1.2345e12. */ -const char FLT_CHARS[] = "rRsSfFdDxXpP"; - -static void -insert_sreg (char *regname, int regnum) -{ - /* Must be large enough to hold the names of the special registers. */ - char buf[80]; - int i; - - symbol_table_insert (symbol_new (regname, reg_section, (valueT) regnum, - &zero_address_frag)); - for (i = 0; regname[i]; i++) - buf[i] = ISLOWER (regname[i]) ? TOUPPER (regname[i]) : regname[i]; - buf[i] = '\0'; - - symbol_table_insert (symbol_new (buf, reg_section, (valueT) regnum, - &zero_address_frag)); -} - -/* Install symbol definitions for assorted special registers. - See MIPS Assembly Language Programmer's Guide page 1-4 */ - -static void -define_some_regs (void) -{ - /* Software representation. */ - insert_sreg ("zero", 0); - insert_sreg ("at", 1); - insert_sreg ("v0", 2); - insert_sreg ("v1", 3); - insert_sreg ("a0", 4); - insert_sreg ("a1", 5); - insert_sreg ("a2", 6); - insert_sreg ("a3", 7); - insert_sreg ("t0", 8); - insert_sreg ("t1", 9); - insert_sreg ("t2", 10); - insert_sreg ("t3", 11); - insert_sreg ("t4", 12); - insert_sreg ("t5", 13); - insert_sreg ("t6", 14); - insert_sreg ("t7", 15); - insert_sreg ("s0", 16); - insert_sreg ("s1", 17); - insert_sreg ("s2", 18); - insert_sreg ("s3", 19); - insert_sreg ("s4", 20); - insert_sreg ("s5", 21); - insert_sreg ("s6", 22); - insert_sreg ("s7", 23); - insert_sreg ("t8", 24); - insert_sreg ("t9", 25); - insert_sreg ("k0", 26); - insert_sreg ("k1", 27); - insert_sreg ("gp", 28); - insert_sreg ("sp", 29); - insert_sreg ("fp", 30); - insert_sreg ("ra", 31); - /* Special registers. */ - insert_sreg ("pc", 0); - insert_sreg ("npc", 1); - insert_sreg ("iad", 2); -} - -/* Subroutine check the string to match an register. */ - -static int -match_sft_register (char *name) -{ -#define MAX_REG_NO 35 -/* Currently we have 35 software registers defined - - we borrowed from MIPS. */ - static char *soft_reg[] = - { - "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", - "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "t9", - "s0", "s1", "s2", "s3", "s4", "s5", "s7", "k0", "k1", - "gp", "sp", "fp", "ra", "pc", "npc", "iad", - "EndofTab" /* End of the Table indicator */ - }; - char low_name[21], *ptr; - int idx; - - for (ptr = name,idx = 0; *ptr != '\0'; ptr++) - low_name[idx++] = TOLOWER (*ptr); - - low_name[idx] = '\0'; - idx = 0; - - while (idx < MAX_REG_NO && strcmp (soft_reg[idx], & low_name [0])) - idx += 1; - - return idx < MAX_REG_NO; -} - -/* Subroutine check the string to match an register. */ - -static int -is_ldst_registers (char *name) -{ - char *ptr = name; - - /* The first character of the register name got to be either %, $, r of R. */ - if ((ptr[0] == '%' || ptr[0] == '$' || ptr[0] == 'r' || ptr[0] == 'R') - && ISDIGIT ((unsigned char) ptr[1])) - return 1; - - /* Now check the software register representation. */ - return match_sft_register (ptr); -} - -/* Subroutine of s_proc so targets can choose a different default prefix. - If DEFAULT_PREFIX is NULL, use the target's "leading char". */ - -static void -s_proc (int end_p) -{ - /* Record the current function so that we can issue an error message for - misplaced .func,.endfunc, and also so that .endfunc needs no - arguments. */ - static char *current_name; - static char *current_label; - - if (end_p) - { - if (current_name == NULL) - { - as_bad (_("missing .proc")); - ignore_rest_of_line (); - return; - } - - current_name = current_label = NULL; - SKIP_WHITESPACE (); - while (!is_end_of_line[(unsigned char) *input_line_pointer]) - input_line_pointer++; - } - else - { - char *name, *label; - char delim1, delim2; - - if (current_name != NULL) - { - as_bad (_(".endfunc missing for previous .proc")); - ignore_rest_of_line (); - return; - } - - name = input_line_pointer; - delim1 = get_symbol_end (); - name = xstrdup (name); - *input_line_pointer = delim1; - SKIP_WHITESPACE (); - - if (*input_line_pointer != ',') - { - char leading_char = 0; - - leading_char = bfd_get_symbol_leading_char (stdoutput); - /* Missing entry point, use function's name with the leading - char prepended. */ - if (leading_char) - { - unsigned len = strlen (name) + 1; - label = xmalloc (len + 1); - label[0] = leading_char; - memcpy (label + 1, name, len); - } - else - label = name; - } - else - { - ++input_line_pointer; - SKIP_WHITESPACE (); - label = input_line_pointer; - delim2 = get_symbol_end (); - label = xstrdup (label); - *input_line_pointer = delim2; - } - - current_name = name; - current_label = label; - } - demand_empty_rest_of_line (); -} - -/* This function is called once, at assembler startup time. It should - set up all the tables, etc., that the MD part of the assembler will - need. */ - -void -md_begin (void) -{ - const char *retval = NULL; - int lose = 0; - unsigned int i; - - /* Create a new hash table. */ - op_hash = hash_new (); - - /* Hash up all the opcodes for fast use later. */ - for (i = 0; i < num_dlx_opcodes; i++) - { - const char *name = machine_opcodes[i].name; - - retval = hash_insert (op_hash, name, (void *) &machine_opcodes[i]); - - if (retval != NULL) - { - fprintf (stderr, _("internal error: can't hash `%s': %s\n"), - machine_opcodes[i].name, retval); - lose = 1; - } - } - - if (lose) - as_fatal (_("Broken assembler. No assembly attempted.")); - - define_some_regs (); -} - -/* This function will check the opcode and return 1 if the opcode is one - of the load/store instruction, and it will fix the operand string to - the standard form so we can use the standard parse_operand routine. */ - -#define READ_OP 0x100 -#define WRITE_OP 0x200 -static char iBuf[81]; - -static char * -dlx_parse_loadop (char * str) -{ - char *ptr = str; - int idx = 0; - - /* The last pair of ()/[] is the register, all other are the - reloc displacement, and if there is a register then it ought - to have a pair of ()/[] - This is not necessarily true, what if the load instruction come - without the register and with %hi/%lo modifier? */ - for (idx = 0; idx < 72 && ptr[idx] != '\0'; idx++) - ; - - if (idx == 72) - { - badoperand_load: - as_bad (_("Bad operand for a load instruction: <%s>"), str); - return NULL; - } - else - { - int i, pb = 0; - int m2 = 0; - char rs1[7], rd[7], endm, match = '0'; - char imm[72]; - - idx -= 1; - switch (str[idx]) - { - case ')': - match = '('; - endm = ')'; - break; - case ']': - match = '['; - endm = ']'; - break; - default: - /* No register indicated, fill in zero. */ - rs1[0] = 'r'; - rs1[1] = '0'; - rs1[2] = '\0'; - match = 0; - endm = 0; - m2 = 1; - } - - if (!m2) - { - /* Searching for (/[ which will match the ]/). */ - for (pb = idx - 1; str[pb] != match; pb -= 1) - /* Match can only be either '[' or '(', if it is - '(' then this can be a normal expression, we'll treat - it as an operand. */ - if (str[pb] == endm || pb < (idx - 5)) - goto load_no_rs1; - pb += 1; - - for (i = 0; (pb + i) < idx; i++) - rs1[i] = str[pb+i]; - - rs1[i] = '\0'; - - if (is_ldst_registers (& rs1[0])) - /* Point to the last character of the imm. */ - pb -= 1; - else - { - load_no_rs1: - if (match == '[') - goto badoperand_load; - /* No register indicated, fill in zero and restore the imm. */ - rs1[0] = 'r'; - rs1[1] = '0'; - rs1[2] = '\0'; - m2 = 1; - } - } - - /* Duplicate the first register. */ - for (i = 0; i < 7 && str[i] != ','; i++) - rd[i] = ptr[i]; - - if (str[i] != ',') - goto badoperand_load; - else - rd[i] = '\0'; - - /* Copy the immd. */ - if (m2) - /* Put the '\0' back in. */ - pb = idx + 1; - - for (i++, m2 = 0; i < pb; m2++,i++) - imm[m2] = ptr[i]; - - imm[m2] = '\0'; - - /* Assemble the instruction to gas internal format. */ - for (i = 0; rd[i] != '\0'; i++) - iBuf[i] = rd[i]; - - iBuf[i++] = ','; - - for (pb = 0 ; rs1[pb] != '\0'; i++, pb++) - iBuf[i] = rs1[pb]; - - iBuf[i++] = ','; - - for (pb = 0; imm[pb] != '\0'; i++, pb++) - iBuf[i] = imm[pb]; - - iBuf[i] = '\0'; - return iBuf; - } -} - -static char * -dlx_parse_storeop (char * str) -{ - char *ptr = str; - int idx = 0; - - /* Search for the ','. */ - for (idx = 0; idx < 72 && ptr[idx] != ','; idx++) - ; - - if (idx == 72) - { - badoperand_store: - as_bad (_("Bad operand for a store instruction: <%s>"), str); - return NULL; - } - else - { - /* idx now points to the ','. */ - int i, pb = 0; - int comma = idx; - int m2 = 0; - char rs1[7], rd[7], endm, match = '0'; - char imm[72]; - - /* Now parse the '(' and ')', and make idx point to ')'. */ - idx -= 1; - switch (str[idx]) - { - case ')': - match = '('; - endm = ')'; - break; - case ']': - match = '['; - endm = ']'; - break; - default: - /* No register indicated, fill in zero. */ - rs1[0] = 'r'; - rs1[1] = '0'; - rs1[2] = '\0'; - match = 0; - endm = 0; - m2 = 1; - } - - if (!m2) - { - /* Searching for (/[ which will match the ]/). */ - for (pb = idx - 1; str[pb] != match; pb -= 1) - if (pb < (idx - 5) || str[pb] == endm) - goto store_no_rs1; - pb += 1; - - for (i = 0; (pb + i) < idx; i++) - rs1[i] = str[pb + i]; - - rs1[i] = '\0'; - - if (is_ldst_registers (& rs1[0])) - /* Point to the last character of the imm. */ - pb -= 1; - else - { - store_no_rs1: - if (match == '[') - goto badoperand_store; - - /* No register indicated, fill in zero and restore the imm. */ - rs1[0] = 'r'; - rs1[1] = '0'; - rs1[2] = '\0'; - pb = comma; - } - } - else - /* No register was specified. */ - pb = comma; - - /* Duplicate the first register. */ - for (i = comma + 1; (str[i] == ' ' || str[i] == '\t'); i++) - ; - - for (m2 = 0; (m2 < 7 && str[i] != '\0'); i++, m2++) - { - if (str[i] != ' ' && str[i] != '\t') - rd[m2] = str[i]; - else - goto badoperand_store; - } - - if (str[i] != '\0') - goto badoperand_store; - else - rd[m2] = '\0'; - - /* Copy the immd. */ - for (i = 0; i < pb; i++) - imm[i] = ptr[i]; - - imm[i] = '\0'; - - /* Assemble the instruction to gas internal format. */ - for (i = 0; rd[i] != '\0'; i++) - iBuf[i] = rd[i]; - iBuf[i++] = ','; - for (pb = 0 ; rs1[pb] != '\0'; i++, pb++) - iBuf[i] = rs1[pb]; - iBuf[i++] = ','; - for (pb = 0; imm[pb] != '\0'; i++, pb++) - iBuf[i] = imm[pb]; - iBuf[i] = '\0'; - return iBuf; - } -} - -static char * -fix_ld_st_operand (unsigned long opcode, char* str) -{ - /* Check the opcode. */ - switch ((int) opcode) - { - case LBOP: - case LBUOP: - case LSBUOP: - case LHOP: - case LHUOP: - case LSHUOP: - case LWOP: - case LSWOP: - return dlx_parse_loadop (str); - case SBOP: - case SHOP: - case SWOP: - return dlx_parse_storeop (str); - default: - return str; - } -} - -static int -hilo_modifier_ok (char *s) -{ - char *ptr = s; - int idx, count = 1; - - if (*ptr != '(') - return 1; - - for (idx = 1; ptr[idx] != '\0' && ptr[idx] != '[' && idx < 73; idx += 1) - { - if (count == 0) - return count; - - if (ptr[idx] == '(') - count += 1; - - if (ptr[idx] == ')') - count -= 1; - } - - return (count == 0) ? 1:0; -} - -static char * -parse_operand (char *s, expressionS *operandp) -{ - char *save = input_line_pointer; - char *new_pos; - - the_insn.HI = the_insn.LO = 0; - - /* Search for %hi and %lo, make a mark and skip it. */ - if (strncmp (s, "%hi", 3) == 0) - { - s += 3; - the_insn.HI = 1; - } - else - { - if (strncmp (s, "%lo", 3) == 0) - { - s += 3; - the_insn.LO = 1; - } - else - the_insn.LO = 0; - } - - if (the_insn.HI || the_insn.LO) - { - if (!hilo_modifier_ok (s)) - as_bad (_("Expression Error for operand modifier %%hi/%%lo\n")); - } - - /* Check for the % and $ register representation */ - if ((s[0] == '%' || s[0] == '$' || s[0] == 'r' || s[0] == 'R') - && ISDIGIT ((unsigned char) s[1])) - { - /* We have a numeric register expression. No biggy. */ - s += 1; - input_line_pointer = s; - (void) expression (operandp); - if (operandp->X_op != O_constant - || operandp->X_add_number > 31) - as_bad (_("Invalid expression after %%%%\n")); - operandp->X_op = O_register; - } - else - { - /* Normal operand parsing. */ - input_line_pointer = s; - (void) expression (operandp); - } - - new_pos = input_line_pointer; - input_line_pointer = save; - return new_pos; -} - -/* Instruction parsing. Takes a string containing the opcode. - Operands are at input_line_pointer. Output is in the_insn. - Warnings or errors are generated. */ - -static void -machine_ip (char *str) -{ - char *s; - const char *args; - struct machine_opcode *insn; - unsigned long opcode; - expressionS the_operand; - expressionS *operand = &the_operand; - unsigned int reg, reg_shift = 0; - - /* Fixup the opcode string to all lower cases, and also - allow numerical digits. */ - s = str; - - if (ISALPHA (*s)) - for (; ISALNUM (*s); ++s) - if (ISUPPER (*s)) - *s = TOLOWER (*s); - - switch (*s) - { - case '\0': - break; - - /* FIXME-SOMEDAY more whitespace. */ - case ' ': - *s++ = '\0'; - break; - - default: - as_bad (_("Unknown opcode: `%s'"), str); - return; - } - - /* Hash the opcode, insn will have the string from opcode table. - also initialized the_insn struct. */ - if ((insn = (struct machine_opcode *) hash_find (op_hash, str)) == NULL) - { - /* Handle the ret and return macro here. */ - if ((strcmp (str, "ret") == 0) || (strcmp (str, "return") == 0)) - { - memset (&the_insn, '\0', sizeof (the_insn)); - the_insn.reloc = NO_RELOC; - the_insn.pcrel = 0; - the_insn.opcode = - (unsigned long)(JROP | 0x03e00000); /* 0x03e00000 = r31 << 21 */ - } - else - as_bad (_("Unknown opcode `%s'."), str); - - return; - } - - opcode = insn->opcode; - memset (&the_insn, '\0', sizeof (the_insn)); - the_insn.reloc = NO_RELOC; - the_insn.pcrel = 0; - - /* Set the sip reloc HI16 flag. */ - if (!set_dlx_skip_hi16_flag (1)) - as_bad (_("Can not set dlx_skip_hi16_flag")); - - /* Fix the operand string if it is one of load store instructions. */ - s = fix_ld_st_operand (opcode, s); - - /* Build the opcode, checking as we go to make sure that the - operands match. - If an operand matches, we modify the_insn or opcode appropriately, - and do a "continue". If an operand fails to match, we "break". */ - if (insn->args[0] != '\0' && insn->args[0] != 'N') - { - /* Prime the pump. */ - if (*s == '\0') - { - as_bad (_("Missing arguments for opcode <%s>."), str); - return; - } - else - s = parse_operand (s, operand); - } - else if (insn->args[0] == 'N') - { - /* Clean up the insn and done! */ - the_insn.opcode = opcode; - return; - } - - /* Parse through the args (this is from opcode table), *s point to - the current character of the instruction stream. */ - for (args = insn->args;; ++args) - { - switch (*args) - { - /* End of Line. */ - case '\0': - /* End of args. */ - if (*s == '\0') - { - /* We are truly done. */ - the_insn.opcode = opcode; - /* Clean up the HI and LO mark. */ - the_insn.HI = 0; - the_insn.LO = 0; - return; - } - - the_insn.HI = 0; - the_insn.LO = 0; - as_bad (_("Too many operands: %s"), s); - break; - - /* ',' Args separator */ - case ',': - /* Must match a comma. */ - if (*s++ == ',') - { - /* Parse next operand. */ - s = parse_operand (s, operand); - continue; - } - break; - - /* It can be a 'a' register or 'i' operand. */ - case 'P': - /* Macro move operand/reg. */ - if (operand->X_op == O_register) - { - /* Its a register. */ - reg_shift = 21; - goto general_reg; - } - - /* The immediate 16 bits literal, bit 0-15. */ - case 'i': - /* offset, unsigned. */ - case 'I': - /* offset, signed. */ - if (operand->X_op == O_constant) - { - if (the_insn.HI) - operand->X_add_number >>= 16; - - opcode |= operand->X_add_number & 0xFFFF; - - if (the_insn.HI && the_insn.LO) - as_bad (_("Both the_insn.HI and the_insn.LO are set : %s"), s); - else - { - the_insn.HI = 0; - the_insn.LO = 0; - } - continue; - } - - the_insn.reloc = (the_insn.HI) ? RELOC_DLX_HI16 - : (the_insn.LO ? RELOC_DLX_LO16 : RELOC_DLX_16); - the_insn.reloc_offset = 2; - the_insn.size = 2; - the_insn.pcrel = 0; - the_insn.exp = * operand; - the_insn.HI = 0; - the_insn.LO = 0; - continue; - - case 'd': - /* offset, signed. */ - if (operand->X_op == O_constant) - { - opcode |= operand->X_add_number & 0xFFFF; - continue; - } - the_insn.reloc = RELOC_DLX_REL16; - the_insn.reloc_offset = 0; /* BIG-ENDIAN Byte 3 of insn. */ - the_insn.size = 4; - the_insn.pcrel = 1; - the_insn.exp = *operand; - continue; - - /* The immediate 26 bits literal, bit 0-25. */ - case 'D': - /* offset, signed. */ - if (operand->X_op == O_constant) - { - opcode |= operand->X_add_number & 0x3FFFFFF; - continue; - } - the_insn.reloc = RELOC_DLX_REL26; - the_insn.reloc_offset = 0; /* BIG-ENDIAN Byte 3 of insn. */ - the_insn.size = 4; - the_insn.pcrel = 1; - the_insn.exp = *operand; - continue; - - /* Type 'a' Register. */ - case 'a': - /* A general register at bits 21-25, rs1. */ - reg_shift = 21; - goto general_reg; - - /* Type 'b' Register. */ - case 'b': - /* A general register at bits 16-20, rs2/rd. */ - reg_shift = 16; - goto general_reg; - - /* Type 'c' Register. */ - case 'c': - /* A general register at bits 11-15, rd. */ - reg_shift = 11; - - general_reg: - know (operand->X_add_symbol == 0); - know (operand->X_op_symbol == 0); - reg = operand->X_add_number; - if (reg & 0xffffffe0) - as_fatal (_("failed regnum sanity check.")); - else - /* Got the register, now figure out where it goes in the opcode. */ - opcode |= reg << reg_shift; - - switch (*args) - { - case 'a': - case 'b': - case 'c': - case 'P': - continue; - } - as_fatal (_("failed general register sanity check.")); - break; - - default: - BAD_CASE (*args); - } - - /* Types or values of args don't match. */ - as_bad (_("Invalid operands")); - return; - } -} - -/* Assemble a single instruction. Its label has already been handled - by the generic front end. We just parse opcode and operands, and - produce the bytes of data and relocation. */ - -void -md_assemble (char *str) -{ - char *toP; - fixS *fixP; - bit_fixS *bitP; - - know (str); - machine_ip (str); - toP = frag_more (4); - dwarf2_emit_insn (4); - - /* Put out the opcode. */ - md_number_to_chars (toP, the_insn.opcode, 4); - - /* Put out the symbol-dependent stuff. */ - if (the_insn.reloc != NO_RELOC) - { - fixP = fix_new_exp (frag_now, - (toP - frag_now->fr_literal + the_insn.reloc_offset), - the_insn.size, & the_insn.exp, the_insn.pcrel, - the_insn.reloc); - - /* Turn off complaints that the addend is - too large for things like foo+100000@ha. */ - switch (the_insn.reloc) - { - case RELOC_DLX_HI16: - case RELOC_DLX_LO16: - fixP->fx_no_overflow = 1; - break; - default: - break; - } - - switch (fixP->fx_r_type) - { - case RELOC_DLX_REL26: - bitP = malloc (sizeof (bit_fixS)); - bitP->fx_bit_size = 26; - bitP->fx_bit_offset = 25; - bitP->fx_bit_base = the_insn.opcode & 0xFC000000; - bitP->fx_bit_base_adj = 0; - bitP->fx_bit_max = 0; - bitP->fx_bit_min = 0; - bitP->fx_bit_add = 0x03FFFFFF; - fixP->fx_bit_fixP = bitP; - break; - case RELOC_DLX_LO16: - case RELOC_DLX_REL16: - bitP = malloc (sizeof (bit_fixS)); - bitP->fx_bit_size = 16; - bitP->fx_bit_offset = 15; - bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000; - bitP->fx_bit_base_adj = 0; - bitP->fx_bit_max = 0; - bitP->fx_bit_min = 0; - bitP->fx_bit_add = 0x0000FFFF; - fixP->fx_bit_fixP = bitP; - break; - case RELOC_DLX_HI16: - bitP = malloc (sizeof (bit_fixS)); - bitP->fx_bit_size = 16; - bitP->fx_bit_offset = 15; - bitP->fx_bit_base = the_insn.opcode & 0xFFFF0000; - bitP->fx_bit_base_adj = 0; - bitP->fx_bit_max = 0; - bitP->fx_bit_min = 0; - bitP->fx_bit_add = 0x0000FFFF; - fixP->fx_bit_fixP = bitP; - break; - default: - fixP->fx_bit_fixP = NULL; - break; - } - } -} - -/* This is identical to the md_atof in m68k.c. I think this is right, - but I'm not sure. Dlx will not use it anyway, so I just leave it - here for now. */ - -char * -md_atof (int type, char *litP, int *sizeP) -{ - return ieee_md_atof (type, litP, sizeP, TRUE); -} - -/* Write out big-endian. */ -void -md_number_to_chars (char *buf, valueT val, int n) -{ - number_to_chars_bigendian (buf, val, n); -} - -bfd_boolean -md_dlx_fix_adjustable (fixS *fixP) -{ - /* We need the symbol name for the VTABLE entries. */ - return (fixP->fx_r_type != BFD_RELOC_VTABLE_INHERIT - && fixP->fx_r_type != BFD_RELOC_VTABLE_ENTRY); -} - -void -md_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED) -{ - long val = *valP; - char *place = fixP->fx_where + fixP->fx_frag->fr_literal; - - switch (fixP->fx_r_type) - { - case RELOC_DLX_LO16: - case RELOC_DLX_REL16: - if (fixP->fx_bit_fixP != NULL) - { - val = (val & 0x0000FFFF) | fixP->fx_bit_fixP->fx_bit_base; - free (fixP->fx_bit_fixP); - fixP->fx_bit_fixP = NULL; - } -#ifdef DEBUG - else - know ((fixP->fx_bit_fixP != NULL)); -#endif - break; - - case RELOC_DLX_HI16: - if (fixP->fx_bit_fixP != NULL) - { - val = (val >> 16) | fixP->fx_bit_fixP->fx_bit_base; - free (fixP->fx_bit_fixP); - fixP->fx_bit_fixP = NULL; - } -#ifdef DEBUG - else - know ((fixP->fx_bit_fixP != NULL)); -#endif - break; - - case RELOC_DLX_REL26: - if (fixP->fx_bit_fixP != NULL) - { - val = (val & 0x03FFFFFF) | fixP->fx_bit_fixP->fx_bit_base; - free (fixP->fx_bit_fixP); - fixP->fx_bit_fixP = NULL; - } -#ifdef DEBUG - else - know ((fixP->fx_bit_fixP != NULL)); -#endif - break; - - case BFD_RELOC_VTABLE_INHERIT: - /* This borrowed from tc-ppc.c on a whim. */ - fixP->fx_done = 0; - if (fixP->fx_addsy - && !S_IS_DEFINED (fixP->fx_addsy) - && !S_IS_WEAK (fixP->fx_addsy)) - S_SET_WEAK (fixP->fx_addsy); - return; - - case BFD_RELOC_VTABLE_ENTRY: - fixP->fx_done = 0; - return; - - default: - break; - } - - number_to_chars_bigendian (place, val, fixP->fx_size); - if (fixP->fx_addsy == NULL) - fixP->fx_done = 1; -} - -const char *md_shortopts = ""; - -struct option md_longopts[] = - { - {NULL, no_argument, NULL, 0} - }; - -size_t md_longopts_size = sizeof (md_longopts); - -int -md_parse_option (int c ATTRIBUTE_UNUSED, - char *arg ATTRIBUTE_UNUSED) -{ - return 0; -} - -void -md_show_usage (FILE *stream ATTRIBUTE_UNUSED) -{ -} - -/* This is called when a line is unrecognized. */ - -int -dlx_unrecognized_line (int c) -{ - int lab; - char *s; - - if (c != '$' || ! ISDIGIT ((unsigned char) input_line_pointer[0])) - return 0; - - s = input_line_pointer; - - lab = 0; - while (ISDIGIT ((unsigned char) *s)) - { - lab = lab * 10 + *s - '0'; - ++s; - } - - if (*s != ':') - /* Not a label definition. */ - return 0; - - if (dollar_label_defined (lab)) - { - as_bad (_("label \"$%d\" redefined"), lab); - return 0; - } - - define_dollar_label (lab); - colon (dollar_label_name (lab, 0)); - input_line_pointer = s + 1; - - return 1; -} - -/* Default the values of symbols known that should be "predefined". We - don't bother to predefine them unless you actually use one, since there - are a lot of them. */ - -symbolS * -md_undefined_symbol (char *name ATTRIBUTE_UNUSED) -{ - return NULL; -} - -/* Parse an operand that is machine-specific, the function was called - in expr.c by operand() function, when everything failed before it - call a quit. */ - -void -md_operand (expressionS* expressionP) -{ - /* Check for the #number representation */ - if (input_line_pointer[0] == '#' && - ISDIGIT ((unsigned char) input_line_pointer[1])) - { - /* We have a numeric number expression. No biggy. */ - input_line_pointer += 1; /* Skip # */ - - (void) expression (expressionP); - - if (expressionP->X_op != O_constant) - as_bad (_("Invalid expression after # number\n")); - } - - return; -} - -/* Round up a section size to the appropriate boundary. */ - -valueT -md_section_align (segT segment ATTRIBUTE_UNUSED, - valueT size) -{ - /* Byte alignment is fine. */ - return size; -} - -/* Exactly what point is a PC-relative offset relative TO? - On the 29000, they're relative to the address of the instruction, - which we have set up as the address of the fixup too. */ - -long -md_pcrel_from (fixS* fixP) -{ - return 4 + fixP->fx_where + fixP->fx_frag->fr_address; -} - -/* Translate internal representation of relocation info to BFD target - format. - FIXME: To what extent can we get all relevant targets to use this? - The above FIXME is from a29k, but I think it is also needed here. */ - -arelent * -tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, - fixS *fixP) -{ - arelent * reloc; - - reloc = xmalloc (sizeof (arelent)); - reloc->howto = bfd_reloc_type_lookup (stdoutput, fixP->fx_r_type); - - if (reloc->howto == NULL) - { - as_bad_where (fixP->fx_file, fixP->fx_line, - _("internal error: can't export reloc type %d (`%s')"), - fixP->fx_r_type, - bfd_get_reloc_code_name (fixP->fx_r_type)); - return NULL; - } - - gas_assert (!fixP->fx_pcrel == !reloc->howto->pc_relative); - - reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *)); - *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy); - reloc->address = fixP->fx_frag->fr_address + fixP->fx_where; - - if (fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY) - reloc->address = fixP->fx_offset; - reloc->addend = 0; - - return reloc; -} - -const pseudo_typeS -dlx_pseudo_table[] = -{ - /* Some additional ops that are used by gcc-dlx. */ - {"asciiz", stringer, 8 + 1}, - {"half", cons, 2}, - {"dword", cons, 8}, - {"word", cons, 4}, - {"proc", s_proc, 0}, - {"endproc", s_proc, 1}, - {NULL, NULL, 0} -}; - -void -dlx_pop_insert (void) -{ - pop_insert (dlx_pseudo_table); - return ; -} |