summaryrefslogtreecommitdiffstats
path: root/binutils-2.24/gas/config/tc-dlx.c
diff options
context:
space:
mode:
Diffstat (limited to 'binutils-2.24/gas/config/tc-dlx.c')
-rw-r--r--binutils-2.24/gas/config/tc-dlx.c1243
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 ;
-}