OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [binutils-2.18.50/] [gas/] [config/] [tc-score.c] - Diff between revs 156 and 816

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 156 Rev 816
/* tc-score.c -- Assembler for Score
/* tc-score.c -- Assembler for Score
   Copyright 2006, 2007 Free Software Foundation, Inc.
   Copyright 2006, 2007 Free Software Foundation, Inc.
   Contributed by:
   Contributed by:
   Mei Ligang (ligang@sunnorth.com.cn)
   Mei Ligang (ligang@sunnorth.com.cn)
   Pei-Lin Tsai (pltsai@sunplus.com)
   Pei-Lin Tsai (pltsai@sunplus.com)
 
 
   This file is part of GAS, the GNU Assembler.
   This file is part of GAS, the GNU Assembler.
 
 
   GAS is free software; you can redistribute it and/or modify
   GAS is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   the Free Software Foundation; either version 3, or (at your option)
   any later version.
   any later version.
 
 
   GAS is distributed in the hope that it will be useful,
   GAS is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   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
   along with GAS; see the file COPYING.  If not, write to the Free
   Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
   Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
   02110-1301, USA.  */
   02110-1301, USA.  */
 
 
#include "as.h"
#include "as.h"
#include "config.h"
#include "config.h"
#include "subsegs.h"
#include "subsegs.h"
#include "safe-ctype.h"
#include "safe-ctype.h"
#include "opcode/score-inst.h"
#include "opcode/score-inst.h"
#include "opcode/score-datadep.h"
#include "opcode/score-datadep.h"
#include "struc-symbol.h"
#include "struc-symbol.h"
 
 
#ifdef OBJ_ELF
#ifdef OBJ_ELF
#include "elf/score.h"
#include "elf/score.h"
#include "dwarf2dbg.h"
#include "dwarf2dbg.h"
#endif
#endif
 
 
#define GP                     28
#define GP                     28
#define PIC_CALL_REG           29
#define PIC_CALL_REG           29
#define MAX_LITERAL_POOL_SIZE  1024
#define MAX_LITERAL_POOL_SIZE  1024
#define FAIL                   0x80000000
#define FAIL                   0x80000000
#define SUCCESS         0
#define SUCCESS         0
#define INSN_SIZE       4
#define INSN_SIZE       4
#define INSN16_SIZE     2
#define INSN16_SIZE     2
#define RELAX_INST_NUM  3
#define RELAX_INST_NUM  3
 
 
/* For score5u : div/mul will pop warning message, mmu/alw/asw will pop error message.  */
/* For score5u : div/mul will pop warning message, mmu/alw/asw will pop error message.  */
#define BAD_ARGS                  _("bad arguments to instruction")
#define BAD_ARGS                  _("bad arguments to instruction")
#define BAD_PC                    _("r15 not allowed here")
#define BAD_PC                    _("r15 not allowed here")
#define BAD_COND                  _("instruction is not conditional")
#define BAD_COND                  _("instruction is not conditional")
#define ERR_NO_ACCUM              _("acc0 expected")
#define ERR_NO_ACCUM              _("acc0 expected")
#define ERR_FOR_SCORE5U_MUL_DIV   _("div / mul are reserved instructions")
#define ERR_FOR_SCORE5U_MUL_DIV   _("div / mul are reserved instructions")
#define ERR_FOR_SCORE5U_MMU       _("This architecture doesn't support mmu")
#define ERR_FOR_SCORE5U_MMU       _("This architecture doesn't support mmu")
#define ERR_FOR_SCORE5U_ATOMIC    _("This architecture doesn't support atomic instruction")
#define ERR_FOR_SCORE5U_ATOMIC    _("This architecture doesn't support atomic instruction")
#define LONG_LABEL_LEN            _("the label length is longer than 1024");
#define LONG_LABEL_LEN            _("the label length is longer than 1024");
#define BAD_SKIP_COMMA            BAD_ARGS
#define BAD_SKIP_COMMA            BAD_ARGS
#define BAD_GARBAGE               _("garbage following instruction");
#define BAD_GARBAGE               _("garbage following instruction");
 
 
#define skip_whitespace(str)  while (*(str) == ' ') ++(str)
#define skip_whitespace(str)  while (*(str) == ' ') ++(str)
 
 
/* The name of the readonly data section.  */
/* The name of the readonly data section.  */
#define RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \
#define RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \
                            ? ".data" \
                            ? ".data" \
                            : OUTPUT_FLAVOR == bfd_target_ecoff_flavour \
                            : OUTPUT_FLAVOR == bfd_target_ecoff_flavour \
                            ? ".rdata" \
                            ? ".rdata" \
                            : OUTPUT_FLAVOR == bfd_target_coff_flavour \
                            : OUTPUT_FLAVOR == bfd_target_coff_flavour \
                            ? ".rdata" \
                            ? ".rdata" \
                            : OUTPUT_FLAVOR == bfd_target_elf_flavour \
                            : OUTPUT_FLAVOR == bfd_target_elf_flavour \
                            ? ".rodata" \
                            ? ".rodata" \
                            : (abort (), ""))
                            : (abort (), ""))
 
 
#define RELAX_ENCODE(old, new, type, reloc1, reloc2, opt) \
#define RELAX_ENCODE(old, new, type, reloc1, reloc2, opt) \
  ((relax_substateT) \
  ((relax_substateT) \
   (((old) << 23) \
   (((old) << 23) \
    | ((new) << 16) \
    | ((new) << 16) \
    | ((type) << 9) \
    | ((type) << 9) \
    | ((reloc1) << 5) \
    | ((reloc1) << 5) \
    | ((reloc2) << 1) \
    | ((reloc2) << 1) \
    | ((opt) ? 1 : 0)))
    | ((opt) ? 1 : 0)))
 
 
#define RELAX_OLD(i)       (((i) >> 23) & 0x7f)
#define RELAX_OLD(i)       (((i) >> 23) & 0x7f)
#define RELAX_NEW(i)       (((i) >> 16) & 0x7f)
#define RELAX_NEW(i)       (((i) >> 16) & 0x7f)
#define RELAX_TYPE(i)      (((i) >> 9) & 0x7f)
#define RELAX_TYPE(i)      (((i) >> 9) & 0x7f)
#define RELAX_RELOC1(i)    ((valueT) ((i) >> 5) & 0xf)
#define RELAX_RELOC1(i)    ((valueT) ((i) >> 5) & 0xf)
#define RELAX_RELOC2(i)    ((valueT) ((i) >> 1) & 0xf)
#define RELAX_RELOC2(i)    ((valueT) ((i) >> 1) & 0xf)
#define RELAX_OPT(i)       ((i) & 1)
#define RELAX_OPT(i)       ((i) & 1)
#define RELAX_OPT_CLEAR(i) ((i) & ~1)
#define RELAX_OPT_CLEAR(i) ((i) & ~1)
 
 
#define SET_INSN_ERROR(s) (inst.error = (s))
#define SET_INSN_ERROR(s) (inst.error = (s))
#define INSN_IS_PCE_P(s)  (strstr (str, "||") != NULL)
#define INSN_IS_PCE_P(s)  (strstr (str, "||") != NULL)
 
 
#define GET_INSN_CLASS(type) (get_insn_class_from_type (type))
#define GET_INSN_CLASS(type) (get_insn_class_from_type (type))
 
 
#define GET_INSN_SIZE(type) ((GET_INSN_CLASS (type) == INSN_CLASS_16) \
#define GET_INSN_SIZE(type) ((GET_INSN_CLASS (type) == INSN_CLASS_16) \
                             ? INSN16_SIZE : INSN_SIZE)
                             ? INSN16_SIZE : INSN_SIZE)
 
 
/* This array holds the chars that always start a comment.  If the
/* This array holds the chars that always start a comment.  If the
   pre-processor is disabled, these aren't very useful.  */
   pre-processor is disabled, these aren't very useful.  */
const char comment_chars[] = "#";
const char comment_chars[] = "#";
const char line_comment_chars[] = "#";
const char line_comment_chars[] = "#";
const char line_separator_chars[] = ";";
const char line_separator_chars[] = ";";
 
 
/* Chars that can be used to separate mant from exp in floating point numbers.  */
/* Chars that can be used to separate mant from exp in floating point numbers.  */
const char EXP_CHARS[] = "eE";
const char EXP_CHARS[] = "eE";
const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
 
 
/* Used to contain constructed error messages.  */
/* Used to contain constructed error messages.  */
static char err_msg[255];
static char err_msg[255];
 
 
fragS *score_fragp = 0;
fragS *score_fragp = 0;
static int fix_data_dependency = 0;
static int fix_data_dependency = 0;
static int warn_fix_data_dependency = 1;
static int warn_fix_data_dependency = 1;
static int score7 = 1;
static int score7 = 1;
static int university_version = 0;
static int university_version = 0;
 
 
static int in_my_get_expression = 0;
static int in_my_get_expression = 0;
 
 
#define USE_GLOBAL_POINTER_OPT 1
#define USE_GLOBAL_POINTER_OPT 1
#define SCORE_BI_ENDIAN
#define SCORE_BI_ENDIAN
 
 
/* Default, pop warning message when using r1.  */
/* Default, pop warning message when using r1.  */
static int nor1 = 1;
static int nor1 = 1;
 
 
/* Default will do instruction relax, -O0 will set g_opt = 0.  */
/* Default will do instruction relax, -O0 will set g_opt = 0.  */
static unsigned int g_opt = 1;
static unsigned int g_opt = 1;
 
 
/* The size of the small data section.  */
/* The size of the small data section.  */
static unsigned int g_switch_value = 8;
static unsigned int g_switch_value = 8;
 
 
#ifdef OBJ_ELF
#ifdef OBJ_ELF
/* Pre-defined "_GLOBAL_OFFSET_TABLE_"  */
/* Pre-defined "_GLOBAL_OFFSET_TABLE_"  */
symbolS *GOT_symbol;
symbolS *GOT_symbol;
#endif
#endif
static segT pdr_seg;
static segT pdr_seg;
 
 
enum score_pic_level score_pic = NO_PIC;
enum score_pic_level score_pic = NO_PIC;
 
 
#define INSN_NAME_LEN 16
#define INSN_NAME_LEN 16
struct score_it
struct score_it
{
{
  char name[INSN_NAME_LEN];
  char name[INSN_NAME_LEN];
  unsigned long instruction;
  unsigned long instruction;
  unsigned long relax_inst;
  unsigned long relax_inst;
  int size;
  int size;
  int relax_size;
  int relax_size;
  enum score_insn_type type;
  enum score_insn_type type;
  char str[MAX_LITERAL_POOL_SIZE];
  char str[MAX_LITERAL_POOL_SIZE];
  const char *error;
  const char *error;
  int bwarn;
  int bwarn;
  char reg[INSN_NAME_LEN];
  char reg[INSN_NAME_LEN];
  struct
  struct
  {
  {
    bfd_reloc_code_real_type type;
    bfd_reloc_code_real_type type;
    expressionS exp;
    expressionS exp;
    int pc_rel;
    int pc_rel;
  }reloc;
  }reloc;
};
};
struct score_it inst;
struct score_it inst;
 
 
typedef struct proc
typedef struct proc
{
{
  symbolS *isym;
  symbolS *isym;
  unsigned long reg_mask;
  unsigned long reg_mask;
  unsigned long reg_offset;
  unsigned long reg_offset;
  unsigned long fpreg_mask;
  unsigned long fpreg_mask;
  unsigned long leaf;
  unsigned long leaf;
  unsigned long frame_offset;
  unsigned long frame_offset;
  unsigned long frame_reg;
  unsigned long frame_reg;
  unsigned long pc_reg;
  unsigned long pc_reg;
}
}
procS;
procS;
 
 
static procS cur_proc;
static procS cur_proc;
static procS *cur_proc_ptr;
static procS *cur_proc_ptr;
static int numprocs;
static int numprocs;
 
 
#define SCORE7_PIPELINE 7
#define SCORE7_PIPELINE 7
#define SCORE5_PIPELINE 5
#define SCORE5_PIPELINE 5
static int vector_size = SCORE7_PIPELINE;
static int vector_size = SCORE7_PIPELINE;
struct score_it dependency_vector[SCORE7_PIPELINE];
struct score_it dependency_vector[SCORE7_PIPELINE];
 
 
/* Relax will need some padding for alignment.  */
/* Relax will need some padding for alignment.  */
#define RELAX_PAD_BYTE 3
#define RELAX_PAD_BYTE 3
 
 
/* Structure for a hash table entry for a register.  */
/* Structure for a hash table entry for a register.  */
struct reg_entry
struct reg_entry
{
{
  const char *name;
  const char *name;
  int number;
  int number;
};
};
 
 
static const struct reg_entry score_rn_table[] =
static const struct reg_entry score_rn_table[] =
{
{
  {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
  {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
  {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
  {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
  {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
  {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
  {"r12", 12}, {"r13", 13}, {"r14", 14}, {"r15", 15},
  {"r12", 12}, {"r13", 13}, {"r14", 14}, {"r15", 15},
  {"r16", 16}, {"r17", 17}, {"r18", 18}, {"r19", 19},
  {"r16", 16}, {"r17", 17}, {"r18", 18}, {"r19", 19},
  {"r20", 20}, {"r21", 21}, {"r22", 22}, {"r23", 23},
  {"r20", 20}, {"r21", 21}, {"r22", 22}, {"r23", 23},
  {"r24", 24}, {"r25", 25}, {"r26", 26}, {"r27", 27},
  {"r24", 24}, {"r25", 25}, {"r26", 26}, {"r27", 27},
  {"r28", 28}, {"r29", 29}, {"r30", 30}, {"r31", 31},
  {"r28", 28}, {"r29", 29}, {"r30", 30}, {"r31", 31},
  {NULL, 0}
  {NULL, 0}
};
};
 
 
static const struct reg_entry score_srn_table[] =
static const struct reg_entry score_srn_table[] =
{
{
  {"sr0", 0}, {"sr1", 1}, {"sr2", 2},
  {"sr0", 0}, {"sr1", 1}, {"sr2", 2},
  {NULL, 0}
  {NULL, 0}
};
};
 
 
static const struct reg_entry score_crn_table[] =
static const struct reg_entry score_crn_table[] =
{
{
  {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3},
  {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3},
  {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7},
  {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7},
  {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11},
  {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11},
  {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
  {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
  {"cr16", 16}, {"cr17", 17}, {"cr18", 18}, {"cr19", 19},
  {"cr16", 16}, {"cr17", 17}, {"cr18", 18}, {"cr19", 19},
  {"cr20", 20}, {"cr21", 21}, {"cr22", 22}, {"cr23", 23},
  {"cr20", 20}, {"cr21", 21}, {"cr22", 22}, {"cr23", 23},
  {"cr24", 24}, {"cr25", 25}, {"cr26", 26}, {"cr27", 27},
  {"cr24", 24}, {"cr25", 25}, {"cr26", 26}, {"cr27", 27},
  {"cr28", 28}, {"cr29", 29}, {"cr30", 30}, {"cr31", 31},
  {"cr28", 28}, {"cr29", 29}, {"cr30", 30}, {"cr31", 31},
  {NULL, 0}
  {NULL, 0}
};
};
 
 
struct reg_map
struct reg_map
{
{
  const struct reg_entry *names;
  const struct reg_entry *names;
  int max_regno;
  int max_regno;
  struct hash_control *htab;
  struct hash_control *htab;
  const char *expected;
  const char *expected;
};
};
 
 
struct reg_map all_reg_maps[] =
struct reg_map all_reg_maps[] =
{
{
  {score_rn_table, 31, NULL, N_("S+core register expected")},
  {score_rn_table, 31, NULL, N_("S+core register expected")},
  {score_srn_table, 2, NULL, N_("S+core special-register expected")},
  {score_srn_table, 2, NULL, N_("S+core special-register expected")},
  {score_crn_table, 31, NULL, N_("S+core co-processor register expected")},
  {score_crn_table, 31, NULL, N_("S+core co-processor register expected")},
};
};
 
 
static struct hash_control *score_ops_hsh = NULL;
static struct hash_control *score_ops_hsh = NULL;
 
 
static struct hash_control *dependency_insn_hsh = NULL;
static struct hash_control *dependency_insn_hsh = NULL;
 
 
/* Enumeration matching entries in table above.  */
/* Enumeration matching entries in table above.  */
enum score_reg_type
enum score_reg_type
{
{
  REG_TYPE_SCORE = 0,
  REG_TYPE_SCORE = 0,
#define REG_TYPE_FIRST REG_TYPE_SCORE
#define REG_TYPE_FIRST REG_TYPE_SCORE
  REG_TYPE_SCORE_SR = 1,
  REG_TYPE_SCORE_SR = 1,
  REG_TYPE_SCORE_CR = 2,
  REG_TYPE_SCORE_CR = 2,
  REG_TYPE_MAX = 3
  REG_TYPE_MAX = 3
};
};
 
 
typedef struct literalS
typedef struct literalS
{
{
  struct expressionS exp;
  struct expressionS exp;
  struct score_it *inst;
  struct score_it *inst;
}
}
literalT;
literalT;
 
 
literalT literals[MAX_LITERAL_POOL_SIZE];
literalT literals[MAX_LITERAL_POOL_SIZE];
 
 
static void do_ldst_insn (char *);
static void do_ldst_insn (char *);
static void do_crdcrscrsimm5 (char *);
static void do_crdcrscrsimm5 (char *);
static void do_ldst_unalign (char *);
static void do_ldst_unalign (char *);
static void do_ldst_atomic (char *);
static void do_ldst_atomic (char *);
static void do_ldst_cop (char *);
static void do_ldst_cop (char *);
static void do_macro_li_rdi32 (char *);
static void do_macro_li_rdi32 (char *);
static void do_macro_la_rdi32 (char *);
static void do_macro_la_rdi32 (char *);
static void do_macro_rdi32hi (char *);
static void do_macro_rdi32hi (char *);
static void do_macro_rdi32lo (char *);
static void do_macro_rdi32lo (char *);
static void do_macro_mul_rdrsrs (char *);
static void do_macro_mul_rdrsrs (char *);
static void do_macro_ldst_label (char *);
static void do_macro_ldst_label (char *);
static void do_branch (char *);
static void do_branch (char *);
static void do_jump (char *);
static void do_jump (char *);
static void do_empty (char *);
static void do_empty (char *);
static void do_rdrsrs (char *);
static void do_rdrsrs (char *);
static void do_rdsi16 (char *);
static void do_rdsi16 (char *);
static void do_rdrssi14 (char *);
static void do_rdrssi14 (char *);
static void do_sub_rdsi16 (char *);
static void do_sub_rdsi16 (char *);
static void do_sub_rdrssi14 (char *);
static void do_sub_rdrssi14 (char *);
static void do_rdrsi5 (char *);
static void do_rdrsi5 (char *);
static void do_rdrsi14 (char *);
static void do_rdrsi14 (char *);
static void do_rdi16 (char *);
static void do_rdi16 (char *);
static void do_xrsi5 (char *);
static void do_xrsi5 (char *);
static void do_rdrs (char *);
static void do_rdrs (char *);
static void do_rdxrs (char *);
static void do_rdxrs (char *);
static void do_rsrs (char *);
static void do_rsrs (char *);
static void do_rdcrs (char *);
static void do_rdcrs (char *);
static void do_rdsrs (char *);
static void do_rdsrs (char *);
static void do_rd (char *);
static void do_rd (char *);
static void do_rs (char *);
static void do_rs (char *);
static void do_i15 (char *);
static void do_i15 (char *);
static void do_xi5x (char *);
static void do_xi5x (char *);
static void do_ceinst (char *);
static void do_ceinst (char *);
static void do_cache (char *);
static void do_cache (char *);
static void do16_rdrs (char *);
static void do16_rdrs (char *);
static void do16_rs (char *);
static void do16_rs (char *);
static void do16_xrs (char *);
static void do16_xrs (char *);
static void do16_mv_rdrs (char *);
static void do16_mv_rdrs (char *);
static void do16_hrdrs (char *);
static void do16_hrdrs (char *);
static void do16_rdhrs (char *);
static void do16_rdhrs (char *);
static void do16_rdi4 (char *);
static void do16_rdi4 (char *);
static void do16_rdi5 (char *);
static void do16_rdi5 (char *);
static void do16_xi5 (char *);
static void do16_xi5 (char *);
static void do16_ldst_insn (char *);
static void do16_ldst_insn (char *);
static void do16_ldst_imm_insn (char *);
static void do16_ldst_imm_insn (char *);
static void do16_push_pop (char *);
static void do16_push_pop (char *);
static void do16_branch (char *);
static void do16_branch (char *);
static void do16_jump (char *);
static void do16_jump (char *);
static void do_rdi16_pic (char *);
static void do_rdi16_pic (char *);
static void do_addi_s_pic (char *);
static void do_addi_s_pic (char *);
static void do_addi_u_pic (char *);
static void do_addi_u_pic (char *);
static void do_lw_pic (char *);
static void do_lw_pic (char *);
 
 
static const struct asm_opcode score_ldst_insns[] =
static const struct asm_opcode score_ldst_insns[] =
{
{
  {"lw",        0x20000000, 0x3e000000, 0x2008,     Rd_rvalueRs_SI15,     do_ldst_insn},
  {"lw",        0x20000000, 0x3e000000, 0x2008,     Rd_rvalueRs_SI15,     do_ldst_insn},
  {"lw",        0x06000000, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  do_ldst_insn},
  {"lw",        0x06000000, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  do_ldst_insn},
  {"lw",        0x0e000000, 0x3e000007, 0x200a,     Rd_rvalueRs_postSI12, do_ldst_insn},
  {"lw",        0x0e000000, 0x3e000007, 0x200a,     Rd_rvalueRs_postSI12, do_ldst_insn},
  {"lh",        0x22000000, 0x3e000000, 0x2009,     Rd_rvalueRs_SI15,     do_ldst_insn},
  {"lh",        0x22000000, 0x3e000000, 0x2009,     Rd_rvalueRs_SI15,     do_ldst_insn},
  {"lh",        0x06000001, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  do_ldst_insn},
  {"lh",        0x06000001, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  do_ldst_insn},
  {"lh",        0x0e000001, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, do_ldst_insn},
  {"lh",        0x0e000001, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, do_ldst_insn},
  {"lhu",       0x24000000, 0x3e000000, 0x8000,     Rd_rvalueRs_SI15,     do_ldst_insn},
  {"lhu",       0x24000000, 0x3e000000, 0x8000,     Rd_rvalueRs_SI15,     do_ldst_insn},
  {"lhu",       0x06000002, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  do_ldst_insn},
  {"lhu",       0x06000002, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  do_ldst_insn},
  {"lhu",       0x0e000002, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, do_ldst_insn},
  {"lhu",       0x0e000002, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, do_ldst_insn},
  {"lb",        0x26000000, 0x3e000000, 0x8000,     Rd_rvalueRs_SI15,     do_ldst_insn},
  {"lb",        0x26000000, 0x3e000000, 0x8000,     Rd_rvalueRs_SI15,     do_ldst_insn},
  {"lb",        0x06000003, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  do_ldst_insn},
  {"lb",        0x06000003, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  do_ldst_insn},
  {"lb",        0x0e000003, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, do_ldst_insn},
  {"lb",        0x0e000003, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, do_ldst_insn},
  {"sw",        0x28000000, 0x3e000000, 0x200c,     Rd_lvalueRs_SI15,     do_ldst_insn},
  {"sw",        0x28000000, 0x3e000000, 0x200c,     Rd_lvalueRs_SI15,     do_ldst_insn},
  {"sw",        0x06000004, 0x3e000007, 0x200e,     Rd_lvalueRs_preSI12,  do_ldst_insn},
  {"sw",        0x06000004, 0x3e000007, 0x200e,     Rd_lvalueRs_preSI12,  do_ldst_insn},
  {"sw",        0x0e000004, 0x3e000007, 0x8000,     Rd_lvalueRs_postSI12, do_ldst_insn},
  {"sw",        0x0e000004, 0x3e000007, 0x8000,     Rd_lvalueRs_postSI12, do_ldst_insn},
  {"sh",        0x2a000000, 0x3e000000, 0x200d,     Rd_lvalueRs_SI15,     do_ldst_insn},
  {"sh",        0x2a000000, 0x3e000000, 0x200d,     Rd_lvalueRs_SI15,     do_ldst_insn},
  {"sh",        0x06000005, 0x3e000007, 0x8000,     Rd_lvalueRs_preSI12,  do_ldst_insn},
  {"sh",        0x06000005, 0x3e000007, 0x8000,     Rd_lvalueRs_preSI12,  do_ldst_insn},
  {"sh",        0x0e000005, 0x3e000007, 0x8000,     Rd_lvalueRs_postSI12, do_ldst_insn},
  {"sh",        0x0e000005, 0x3e000007, 0x8000,     Rd_lvalueRs_postSI12, do_ldst_insn},
  {"lbu",       0x2c000000, 0x3e000000, 0x200b,     Rd_rvalueRs_SI15,     do_ldst_insn},
  {"lbu",       0x2c000000, 0x3e000000, 0x200b,     Rd_rvalueRs_SI15,     do_ldst_insn},
  {"lbu",       0x06000006, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  do_ldst_insn},
  {"lbu",       0x06000006, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  do_ldst_insn},
  {"lbu",       0x0e000006, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, do_ldst_insn},
  {"lbu",       0x0e000006, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, do_ldst_insn},
  {"sb",        0x2e000000, 0x3e000000, 0x200f,     Rd_lvalueRs_SI15,     do_ldst_insn},
  {"sb",        0x2e000000, 0x3e000000, 0x200f,     Rd_lvalueRs_SI15,     do_ldst_insn},
  {"sb",        0x06000007, 0x3e000007, 0x8000,     Rd_lvalueRs_preSI12,  do_ldst_insn},
  {"sb",        0x06000007, 0x3e000007, 0x8000,     Rd_lvalueRs_preSI12,  do_ldst_insn},
  {"sb",        0x0e000007, 0x3e000007, 0x8000,     Rd_lvalueRs_postSI12, do_ldst_insn},
  {"sb",        0x0e000007, 0x3e000007, 0x8000,     Rd_lvalueRs_postSI12, do_ldst_insn},
};
};
 
 
static const struct asm_opcode score_insns[] =
static const struct asm_opcode score_insns[] =
{
{
  {"abs",       0x3800000a, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"abs",       0x3800000a, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"abs.s",     0x3800004b, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"abs.s",     0x3800004b, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"add",       0x00000010, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"add",       0x00000010, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"add.c",     0x00000011, 0x3e0003ff, 0x2000,     Rd_Rs_Rs,             do_rdrsrs},
  {"add.c",     0x00000011, 0x3e0003ff, 0x2000,     Rd_Rs_Rs,             do_rdrsrs},
  {"add.s",     0x38000048, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"add.s",     0x38000048, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"addc",      0x00000012, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"addc",      0x00000012, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"addc.c",    0x00000013, 0x3e0003ff, 0x0009,     Rd_Rs_Rs,             do_rdrsrs},
  {"addc.c",    0x00000013, 0x3e0003ff, 0x0009,     Rd_Rs_Rs,             do_rdrsrs},
  {"addi",      0x02000000, 0x3e0e0001, 0x8000,     Rd_SI16,              do_rdsi16},
  {"addi",      0x02000000, 0x3e0e0001, 0x8000,     Rd_SI16,              do_rdsi16},
  {"addi.c",    0x02000001, 0x3e0e0001, 0x8000,     Rd_SI16,              do_rdsi16},
  {"addi.c",    0x02000001, 0x3e0e0001, 0x8000,     Rd_SI16,              do_rdsi16},
  {"addis",     0x0a000000, 0x3e0e0001, 0x8000,     Rd_SI16,              do_rdi16},
  {"addis",     0x0a000000, 0x3e0e0001, 0x8000,     Rd_SI16,              do_rdi16},
  {"addis.c",   0x0a000001, 0x3e0e0001, 0x8000,     Rd_SI16,              do_rdi16},
  {"addis.c",   0x0a000001, 0x3e0e0001, 0x8000,     Rd_SI16,              do_rdi16},
  {"addri",     0x10000000, 0x3e000001, 0x8000,     Rd_Rs_SI14,           do_rdrssi14},
  {"addri",     0x10000000, 0x3e000001, 0x8000,     Rd_Rs_SI14,           do_rdrssi14},
  {"addri.c",   0x10000001, 0x3e000001, 0x8000,     Rd_Rs_SI14,           do_rdrssi14},
  {"addri.c",   0x10000001, 0x3e000001, 0x8000,     Rd_Rs_SI14,           do_rdrssi14},
  {"addc!",     0x0009,     0x700f,     0x00000013, Rd_Rs,                do16_rdrs},
  {"addc!",     0x0009,     0x700f,     0x00000013, Rd_Rs,                do16_rdrs},
  {"add!",      0x2000,     0x700f,     0x00000011, Rd_Rs,                do16_rdrs},
  {"add!",      0x2000,     0x700f,     0x00000011, Rd_Rs,                do16_rdrs},
  {"addei!",    0x6000    , 0x7087,     0x02000001, Rd_I4,                do16_rdi4},
  {"addei!",    0x6000    , 0x7087,     0x02000001, Rd_I4,                do16_rdi4},
  {"subi",      0x02000000, 0x3e0e0001, 0x8000,     Rd_SI16,              do_sub_rdsi16},
  {"subi",      0x02000000, 0x3e0e0001, 0x8000,     Rd_SI16,              do_sub_rdsi16},
  {"subi.c",    0x02000001, 0x3e0e0001, 0x8000,     Rd_SI16,              do_sub_rdsi16},
  {"subi.c",    0x02000001, 0x3e0e0001, 0x8000,     Rd_SI16,              do_sub_rdsi16},
  {"subri",     0x10000000, 0x3e000001, 0x8000,     Rd_Rs_SI14,           do_sub_rdrssi14},
  {"subri",     0x10000000, 0x3e000001, 0x8000,     Rd_Rs_SI14,           do_sub_rdrssi14},
  {"subri.c",   0x10000001, 0x3e000001, 0x8000,     Rd_Rs_SI14,           do_sub_rdrssi14},
  {"subri.c",   0x10000001, 0x3e000001, 0x8000,     Rd_Rs_SI14,           do_sub_rdrssi14},
  {"and",       0x00000020, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"and",       0x00000020, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"and.c",     0x00000021, 0x3e0003ff, 0x2004,     Rd_Rs_Rs,             do_rdrsrs},
  {"and.c",     0x00000021, 0x3e0003ff, 0x2004,     Rd_Rs_Rs,             do_rdrsrs},
  {"andi",      0x02080000, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
  {"andi",      0x02080000, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
  {"andi.c",    0x02080001, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
  {"andi.c",    0x02080001, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
  {"andis",     0x0a080000, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
  {"andis",     0x0a080000, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
  {"andis.c",   0x0a080001, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
  {"andis.c",   0x0a080001, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
  {"andri",     0x18000000, 0x3e000001, 0x8000,     Rd_Rs_I14,            do_rdrsi14},
  {"andri",     0x18000000, 0x3e000001, 0x8000,     Rd_Rs_I14,            do_rdrsi14},
  {"andri.c",   0x18000001, 0x3e000001, 0x8000,     Rd_Rs_I14,            do_rdrsi14},
  {"andri.c",   0x18000001, 0x3e000001, 0x8000,     Rd_Rs_I14,            do_rdrsi14},
  {"and!",      0x2004,     0x700f,     0x00000021, Rd_Rs,                do16_rdrs},
  {"and!",      0x2004,     0x700f,     0x00000021, Rd_Rs,                do16_rdrs},
  {"bcs",       0x08000000, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bcs",       0x08000000, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bcc",       0x08000400, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bcc",       0x08000400, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bcnz",      0x08003800, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bcnz",      0x08003800, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bcsl",      0x08000001, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bcsl",      0x08000001, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bccl",      0x08000401, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bccl",      0x08000401, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bcnzl",     0x08003801, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bcnzl",     0x08003801, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bcs!",      0x4000,     0x7f00,     0x08000000, PC_DISP8div2,         do16_branch},
  {"bcs!",      0x4000,     0x7f00,     0x08000000, PC_DISP8div2,         do16_branch},
  {"bcc!",      0x4100,     0x7f00,     0x08000400, PC_DISP8div2,         do16_branch},
  {"bcc!",      0x4100,     0x7f00,     0x08000400, PC_DISP8div2,         do16_branch},
  {"bcnz!",     0x4e00,     0x7f00,     0x08003800, PC_DISP8div2,         do16_branch},
  {"bcnz!",     0x4e00,     0x7f00,     0x08003800, PC_DISP8div2,         do16_branch},
  {"beq",       0x08001000, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"beq",       0x08001000, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"beql",      0x08001001, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"beql",      0x08001001, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"beq!",      0x4400,     0x7f00,     0x08001000, PC_DISP8div2,         do16_branch},
  {"beq!",      0x4400,     0x7f00,     0x08001000, PC_DISP8div2,         do16_branch},
  {"bgtu",      0x08000800, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bgtu",      0x08000800, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bgt",       0x08001800, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bgt",       0x08001800, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bge",       0x08002000, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bge",       0x08002000, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bgtul",     0x08000801, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bgtul",     0x08000801, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bgtl",      0x08001801, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bgtl",      0x08001801, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bgel",      0x08002001, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bgel",      0x08002001, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bgtu!",     0x4200,     0x7f00,     0x08000800, PC_DISP8div2,         do16_branch},
  {"bgtu!",     0x4200,     0x7f00,     0x08000800, PC_DISP8div2,         do16_branch},
  {"bgt!",      0x4600,     0x7f00,     0x08001800, PC_DISP8div2,         do16_branch},
  {"bgt!",      0x4600,     0x7f00,     0x08001800, PC_DISP8div2,         do16_branch},
  {"bge!",      0x4800,     0x7f00,     0x08002000, PC_DISP8div2,         do16_branch},
  {"bge!",      0x4800,     0x7f00,     0x08002000, PC_DISP8div2,         do16_branch},
  {"bitclr.c",  0x00000029, 0x3e0003ff, 0x6004,     Rd_Rs_I5,             do_rdrsi5},
  {"bitclr.c",  0x00000029, 0x3e0003ff, 0x6004,     Rd_Rs_I5,             do_rdrsi5},
  {"bitrev",    0x3800000c, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"bitrev",    0x3800000c, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"bitset.c",  0x0000002b, 0x3e0003ff, 0x6005,     Rd_Rs_I5,             do_rdrsi5},
  {"bitset.c",  0x0000002b, 0x3e0003ff, 0x6005,     Rd_Rs_I5,             do_rdrsi5},
  {"bittst.c",  0x0000002d, 0x3e0003ff, 0x6006,     x_Rs_I5,              do_xrsi5},
  {"bittst.c",  0x0000002d, 0x3e0003ff, 0x6006,     x_Rs_I5,              do_xrsi5},
  {"bittgl.c",  0x0000002f, 0x3e0003ff, 0x6007,     Rd_Rs_I5,             do_rdrsi5},
  {"bittgl.c",  0x0000002f, 0x3e0003ff, 0x6007,     Rd_Rs_I5,             do_rdrsi5},
  {"bitclr!",   0x6004,     0x7007,     0x00000029, Rd_I5,                do16_rdi5},
  {"bitclr!",   0x6004,     0x7007,     0x00000029, Rd_I5,                do16_rdi5},
  {"bitset!",   0x6005,     0x7007,     0x0000002b, Rd_I5,                do16_rdi5},
  {"bitset!",   0x6005,     0x7007,     0x0000002b, Rd_I5,                do16_rdi5},
  {"bittst!",   0x6006,     0x7007,     0x0000002d, Rd_I5,                do16_rdi5},
  {"bittst!",   0x6006,     0x7007,     0x0000002d, Rd_I5,                do16_rdi5},
  {"bittgl!",   0x6007,     0x7007,     0x0000002f, Rd_I5,                do16_rdi5},
  {"bittgl!",   0x6007,     0x7007,     0x0000002f, Rd_I5,                do16_rdi5},
  {"bleu",      0x08000c00, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bleu",      0x08000c00, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"ble",       0x08001c00, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"ble",       0x08001c00, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"blt",       0x08002400, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"blt",       0x08002400, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bleul",     0x08000c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bleul",     0x08000c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"blel",      0x08001c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"blel",      0x08001c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bltl",      0x08002401, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bltl",      0x08002401, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bl",        0x08003c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bl",        0x08003c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bleu!",     0x4300,     0x7f00,     0x08000c00, PC_DISP8div2,         do16_branch},
  {"bleu!",     0x4300,     0x7f00,     0x08000c00, PC_DISP8div2,         do16_branch},
  {"ble!",      0x4700,     0x7f00,     0x08001c00, PC_DISP8div2,         do16_branch},
  {"ble!",      0x4700,     0x7f00,     0x08001c00, PC_DISP8div2,         do16_branch},
  {"blt!",      0x4900,     0x7f00,     0x08002400, PC_DISP8div2,         do16_branch},
  {"blt!",      0x4900,     0x7f00,     0x08002400, PC_DISP8div2,         do16_branch},
  {"bmi",       0x08002800, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bmi",       0x08002800, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bmil",      0x08002801, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bmil",      0x08002801, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bmi!",      0x00004a00, 0x00007f00, 0x08002800, PC_DISP8div2,         do16_branch},
  {"bmi!",      0x00004a00, 0x00007f00, 0x08002800, PC_DISP8div2,         do16_branch},
  {"bne",       0x08001400, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bne",       0x08001400, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bnel",      0x08001401, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bnel",      0x08001401, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bne!",      0x4500,     0x7f00,     0x08001400, PC_DISP8div2,         do16_branch},
  {"bne!",      0x4500,     0x7f00,     0x08001400, PC_DISP8div2,         do16_branch},
  {"bpl",       0x08002c00, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bpl",       0x08002c00, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bpll",      0x08002c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bpll",      0x08002c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bpl!",      0x4b00,     0x7f00,     0x08002c00, PC_DISP8div2,         do16_branch},
  {"bpl!",      0x4b00,     0x7f00,     0x08002c00, PC_DISP8div2,         do16_branch},
  {"brcs",      0x00000008, 0x3e007fff, 0x0004,     x_Rs_x,               do_rs},
  {"brcs",      0x00000008, 0x3e007fff, 0x0004,     x_Rs_x,               do_rs},
  {"brcc",      0x00000408, 0x3e007fff, 0x0104,     x_Rs_x,               do_rs},
  {"brcc",      0x00000408, 0x3e007fff, 0x0104,     x_Rs_x,               do_rs},
  {"brgtu",     0x00000808, 0x3e007fff, 0x0204,     x_Rs_x,               do_rs},
  {"brgtu",     0x00000808, 0x3e007fff, 0x0204,     x_Rs_x,               do_rs},
  {"brleu",     0x00000c08, 0x3e007fff, 0x0304,     x_Rs_x,               do_rs},
  {"brleu",     0x00000c08, 0x3e007fff, 0x0304,     x_Rs_x,               do_rs},
  {"breq",      0x00001008, 0x3e007fff, 0x0404,     x_Rs_x,               do_rs},
  {"breq",      0x00001008, 0x3e007fff, 0x0404,     x_Rs_x,               do_rs},
  {"brne",      0x00001408, 0x3e007fff, 0x0504,     x_Rs_x,               do_rs},
  {"brne",      0x00001408, 0x3e007fff, 0x0504,     x_Rs_x,               do_rs},
  {"brgt",      0x00001808, 0x3e007fff, 0x0604,     x_Rs_x,               do_rs},
  {"brgt",      0x00001808, 0x3e007fff, 0x0604,     x_Rs_x,               do_rs},
  {"brle",      0x00001c08, 0x3e007fff, 0x0704,     x_Rs_x,               do_rs},
  {"brle",      0x00001c08, 0x3e007fff, 0x0704,     x_Rs_x,               do_rs},
  {"brge",      0x00002008, 0x3e007fff, 0x0804,     x_Rs_x,               do_rs},
  {"brge",      0x00002008, 0x3e007fff, 0x0804,     x_Rs_x,               do_rs},
  {"brlt",      0x00002408, 0x3e007fff, 0x0904,     x_Rs_x,               do_rs},
  {"brlt",      0x00002408, 0x3e007fff, 0x0904,     x_Rs_x,               do_rs},
  {"brmi",      0x00002808, 0x3e007fff, 0x0a04,     x_Rs_x,               do_rs},
  {"brmi",      0x00002808, 0x3e007fff, 0x0a04,     x_Rs_x,               do_rs},
  {"brpl",      0x00002c08, 0x3e007fff, 0x0b04,     x_Rs_x,               do_rs},
  {"brpl",      0x00002c08, 0x3e007fff, 0x0b04,     x_Rs_x,               do_rs},
  {"brvs",      0x00003008, 0x3e007fff, 0x0c04,     x_Rs_x,               do_rs},
  {"brvs",      0x00003008, 0x3e007fff, 0x0c04,     x_Rs_x,               do_rs},
  {"brvc",      0x00003408, 0x3e007fff, 0x0d04,     x_Rs_x,               do_rs},
  {"brvc",      0x00003408, 0x3e007fff, 0x0d04,     x_Rs_x,               do_rs},
  {"brcnz",     0x00003808, 0x3e007fff, 0x0e04,     x_Rs_x,               do_rs},
  {"brcnz",     0x00003808, 0x3e007fff, 0x0e04,     x_Rs_x,               do_rs},
  {"br",        0x00003c08, 0x3e007fff, 0x0f04,     x_Rs_x,               do_rs},
  {"br",        0x00003c08, 0x3e007fff, 0x0f04,     x_Rs_x,               do_rs},
  {"brcsl",     0x00000009, 0x3e007fff, 0x000c,     x_Rs_x,               do_rs},
  {"brcsl",     0x00000009, 0x3e007fff, 0x000c,     x_Rs_x,               do_rs},
  {"brccl",     0x00000409, 0x3e007fff, 0x010c,     x_Rs_x,               do_rs},
  {"brccl",     0x00000409, 0x3e007fff, 0x010c,     x_Rs_x,               do_rs},
  {"brgtul",    0x00000809, 0x3e007fff, 0x020c,     x_Rs_x,               do_rs},
  {"brgtul",    0x00000809, 0x3e007fff, 0x020c,     x_Rs_x,               do_rs},
  {"brleul",    0x00000c09, 0x3e007fff, 0x030c,     x_Rs_x,               do_rs},
  {"brleul",    0x00000c09, 0x3e007fff, 0x030c,     x_Rs_x,               do_rs},
  {"breql",     0x00001009, 0x3e007fff, 0x040c,     x_Rs_x,               do_rs},
  {"breql",     0x00001009, 0x3e007fff, 0x040c,     x_Rs_x,               do_rs},
  {"brnel",     0x00001409, 0x3e007fff, 0x050c,     x_Rs_x,               do_rs},
  {"brnel",     0x00001409, 0x3e007fff, 0x050c,     x_Rs_x,               do_rs},
  {"brgtl",     0x00001809, 0x3e007fff, 0x060c,     x_Rs_x,               do_rs},
  {"brgtl",     0x00001809, 0x3e007fff, 0x060c,     x_Rs_x,               do_rs},
  {"brlel",     0x00001c09, 0x3e007fff, 0x070c,     x_Rs_x,               do_rs},
  {"brlel",     0x00001c09, 0x3e007fff, 0x070c,     x_Rs_x,               do_rs},
  {"brgel",     0x00002009, 0x3e007fff, 0x080c,     x_Rs_x,               do_rs},
  {"brgel",     0x00002009, 0x3e007fff, 0x080c,     x_Rs_x,               do_rs},
  {"brltl",     0x00002409, 0x3e007fff, 0x090c,     x_Rs_x,               do_rs},
  {"brltl",     0x00002409, 0x3e007fff, 0x090c,     x_Rs_x,               do_rs},
  {"brmil",     0x00002809, 0x3e007fff, 0x0a0c,     x_Rs_x,               do_rs},
  {"brmil",     0x00002809, 0x3e007fff, 0x0a0c,     x_Rs_x,               do_rs},
  {"brpll",     0x00002c09, 0x3e007fff, 0x0b0c,     x_Rs_x,               do_rs},
  {"brpll",     0x00002c09, 0x3e007fff, 0x0b0c,     x_Rs_x,               do_rs},
  {"brvsl",     0x00003009, 0x3e007fff, 0x0c0c,     x_Rs_x,               do_rs},
  {"brvsl",     0x00003009, 0x3e007fff, 0x0c0c,     x_Rs_x,               do_rs},
  {"brvcl",     0x00003409, 0x3e007fff, 0x0d0c,     x_Rs_x,               do_rs},
  {"brvcl",     0x00003409, 0x3e007fff, 0x0d0c,     x_Rs_x,               do_rs},
  {"brcnzl",    0x00003809, 0x3e007fff, 0x0e0c,     x_Rs_x,               do_rs},
  {"brcnzl",    0x00003809, 0x3e007fff, 0x0e0c,     x_Rs_x,               do_rs},
  {"brl",       0x00003c09, 0x3e007fff, 0x0f0c,     x_Rs_x,               do_rs},
  {"brl",       0x00003c09, 0x3e007fff, 0x0f0c,     x_Rs_x,               do_rs},
  {"brcs!",     0x0004,     0x7f0f,     0x00000008, x_Rs,                 do16_xrs},
  {"brcs!",     0x0004,     0x7f0f,     0x00000008, x_Rs,                 do16_xrs},
  {"brcc!",     0x0104,     0x7f0f,     0x00000408, x_Rs,                 do16_xrs},
  {"brcc!",     0x0104,     0x7f0f,     0x00000408, x_Rs,                 do16_xrs},
  {"brgtu!",    0x0204,     0x7f0f,     0x00000808, x_Rs,                 do16_xrs},
  {"brgtu!",    0x0204,     0x7f0f,     0x00000808, x_Rs,                 do16_xrs},
  {"brleu!",    0x0304,     0x7f0f,     0x00000c08, x_Rs,                 do16_xrs},
  {"brleu!",    0x0304,     0x7f0f,     0x00000c08, x_Rs,                 do16_xrs},
  {"breq!",     0x0404,     0x7f0f,     0x00001008, x_Rs,                 do16_xrs},
  {"breq!",     0x0404,     0x7f0f,     0x00001008, x_Rs,                 do16_xrs},
  {"brne!",     0x0504,     0x7f0f,     0x00001408, x_Rs,                 do16_xrs},
  {"brne!",     0x0504,     0x7f0f,     0x00001408, x_Rs,                 do16_xrs},
  {"brgt!",     0x0604,     0x7f0f,     0x00001808, x_Rs,                 do16_xrs},
  {"brgt!",     0x0604,     0x7f0f,     0x00001808, x_Rs,                 do16_xrs},
  {"brle!",     0x0704,     0x7f0f,     0x00001c08, x_Rs,                 do16_xrs},
  {"brle!",     0x0704,     0x7f0f,     0x00001c08, x_Rs,                 do16_xrs},
  {"brge!",     0x0804,     0x7f0f,     0x00002008, x_Rs,                 do16_xrs},
  {"brge!",     0x0804,     0x7f0f,     0x00002008, x_Rs,                 do16_xrs},
  {"brlt!",     0x0904,     0x7f0f,     0x00002408, x_Rs,                 do16_xrs},
  {"brlt!",     0x0904,     0x7f0f,     0x00002408, x_Rs,                 do16_xrs},
  {"brmi!",     0x0a04,     0x7f0f,     0x00002808, x_Rs,                 do16_xrs},
  {"brmi!",     0x0a04,     0x7f0f,     0x00002808, x_Rs,                 do16_xrs},
  {"brpl!",     0x0b04,     0x7f0f,     0x00002c08, x_Rs,                 do16_xrs},
  {"brpl!",     0x0b04,     0x7f0f,     0x00002c08, x_Rs,                 do16_xrs},
  {"brvs!",     0x0c04,     0x7f0f,     0x00003008, x_Rs,                 do16_xrs},
  {"brvs!",     0x0c04,     0x7f0f,     0x00003008, x_Rs,                 do16_xrs},
  {"brvc!",     0x0d04,     0x7f0f,     0x00003408, x_Rs,                 do16_xrs},
  {"brvc!",     0x0d04,     0x7f0f,     0x00003408, x_Rs,                 do16_xrs},
  {"brcnz!",    0x0e04,     0x7f0f,     0x00003808, x_Rs,                 do16_xrs},
  {"brcnz!",    0x0e04,     0x7f0f,     0x00003808, x_Rs,                 do16_xrs},
  {"br!",       0x0f04,     0x7f0f,     0x00003c08, x_Rs,                 do16_xrs},
  {"br!",       0x0f04,     0x7f0f,     0x00003c08, x_Rs,                 do16_xrs},
  {"brcsl!",    0x000c,     0x7f0f,     0x00000009, x_Rs,                 do16_xrs},
  {"brcsl!",    0x000c,     0x7f0f,     0x00000009, x_Rs,                 do16_xrs},
  {"brccl!",    0x010c,     0x7f0f,     0x00000409, x_Rs,                 do16_xrs},
  {"brccl!",    0x010c,     0x7f0f,     0x00000409, x_Rs,                 do16_xrs},
  {"brgtul!",   0x020c,     0x7f0f,     0x00000809, x_Rs,                 do16_xrs},
  {"brgtul!",   0x020c,     0x7f0f,     0x00000809, x_Rs,                 do16_xrs},
  {"brleul!",   0x030c,     0x7f0f,     0x00000c09, x_Rs,                 do16_xrs},
  {"brleul!",   0x030c,     0x7f0f,     0x00000c09, x_Rs,                 do16_xrs},
  {"breql!",    0x040c,     0x7f0f,     0x00001009, x_Rs,                 do16_xrs},
  {"breql!",    0x040c,     0x7f0f,     0x00001009, x_Rs,                 do16_xrs},
  {"brnel!",    0x050c,     0x7f0f,     0x00001409, x_Rs,                 do16_xrs},
  {"brnel!",    0x050c,     0x7f0f,     0x00001409, x_Rs,                 do16_xrs},
  {"brgtl!",    0x060c,     0x7f0f,     0x00001809, x_Rs,                 do16_xrs},
  {"brgtl!",    0x060c,     0x7f0f,     0x00001809, x_Rs,                 do16_xrs},
  {"brlel!",    0x070c,     0x7f0f,     0x00001c09, x_Rs,                 do16_xrs},
  {"brlel!",    0x070c,     0x7f0f,     0x00001c09, x_Rs,                 do16_xrs},
  {"brgel!",    0x080c,     0x7f0f,     0x00002009, x_Rs,                 do16_xrs},
  {"brgel!",    0x080c,     0x7f0f,     0x00002009, x_Rs,                 do16_xrs},
  {"brltl!",    0x090c,     0x7f0f,     0x00002409, x_Rs,                 do16_xrs},
  {"brltl!",    0x090c,     0x7f0f,     0x00002409, x_Rs,                 do16_xrs},
  {"brmil!",    0x0a0c,     0x7f0f,     0x00002809, x_Rs,                 do16_xrs},
  {"brmil!",    0x0a0c,     0x7f0f,     0x00002809, x_Rs,                 do16_xrs},
  {"brpll!",    0x0b0c,     0x7f0f,     0x00002c09, x_Rs,                 do16_xrs},
  {"brpll!",    0x0b0c,     0x7f0f,     0x00002c09, x_Rs,                 do16_xrs},
  {"brvsl!",    0x0c0c,     0x7f0f,     0x00003009, x_Rs,                 do16_xrs},
  {"brvsl!",    0x0c0c,     0x7f0f,     0x00003009, x_Rs,                 do16_xrs},
  {"brvcl!",    0x0d0c,     0x7f0f,     0x00003409, x_Rs,                 do16_xrs},
  {"brvcl!",    0x0d0c,     0x7f0f,     0x00003409, x_Rs,                 do16_xrs},
  {"brcnzl!",   0x0e0c,     0x7f0f,     0x00003809, x_Rs,                 do16_xrs},
  {"brcnzl!",   0x0e0c,     0x7f0f,     0x00003809, x_Rs,                 do16_xrs},
  {"brl!",      0x0f0c,     0x7f0f,     0x00003c09, x_Rs,                 do16_xrs},
  {"brl!",      0x0f0c,     0x7f0f,     0x00003c09, x_Rs,                 do16_xrs},
  {"bvs",       0x08003000, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bvs",       0x08003000, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bvc",       0x08003400, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bvc",       0x08003400, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"bvsl",      0x08003001, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bvsl",      0x08003001, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bvcl",      0x08003401, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bvcl",      0x08003401, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
  {"bvs!",      0x4c00,     0x7f00,     0x08003000, PC_DISP8div2,         do16_branch},
  {"bvs!",      0x4c00,     0x7f00,     0x08003000, PC_DISP8div2,         do16_branch},
  {"bvc!",      0x4d00,     0x7f00,     0x08003400, PC_DISP8div2,         do16_branch},
  {"bvc!",      0x4d00,     0x7f00,     0x08003400, PC_DISP8div2,         do16_branch},
  {"b!",        0x4f00,     0x7f00,     0x08003c00, PC_DISP8div2,         do16_branch},
  {"b!",        0x4f00,     0x7f00,     0x08003c00, PC_DISP8div2,         do16_branch},
  {"b",         0x08003c00, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"b",         0x08003c00, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
  {"cache",     0x30000000, 0x3ff00000, 0x8000,     OP5_rvalueRs_SI15,    do_cache},
  {"cache",     0x30000000, 0x3ff00000, 0x8000,     OP5_rvalueRs_SI15,    do_cache},
  {"ceinst",    0x38000000, 0x3e000000, 0x8000,     I5_Rs_Rs_I5_OP5,      do_ceinst},
  {"ceinst",    0x38000000, 0x3e000000, 0x8000,     I5_Rs_Rs_I5_OP5,      do_ceinst},
  {"clz",       0x3800000d, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"clz",       0x3800000d, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"cmpteq.c",  0x00000019, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"cmpteq.c",  0x00000019, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"cmptmi.c",  0x00100019, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"cmptmi.c",  0x00100019, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"cmp.c",     0x00300019, 0x3ff003ff, 0x2003,     x_Rs_Rs,              do_rsrs},
  {"cmp.c",     0x00300019, 0x3ff003ff, 0x2003,     x_Rs_Rs,              do_rsrs},
  {"cmpzteq.c", 0x0000001b, 0x3ff07fff, 0x8000,     x_Rs_x,               do_rs},
  {"cmpzteq.c", 0x0000001b, 0x3ff07fff, 0x8000,     x_Rs_x,               do_rs},
  {"cmpztmi.c", 0x0010001b, 0x3ff07fff, 0x8000,     x_Rs_x,               do_rs},
  {"cmpztmi.c", 0x0010001b, 0x3ff07fff, 0x8000,     x_Rs_x,               do_rs},
  {"cmpz.c",    0x0030001b, 0x3ff07fff, 0x8000,     x_Rs_x,               do_rs},
  {"cmpz.c",    0x0030001b, 0x3ff07fff, 0x8000,     x_Rs_x,               do_rs},
  {"cmpi.c",    0x02040001, 0x3e0e0001, 0x8000,     Rd_SI16,              do_rdsi16},
  {"cmpi.c",    0x02040001, 0x3e0e0001, 0x8000,     Rd_SI16,              do_rdsi16},
  {"cmp!",      0x2003,     0x700f,     0x00300019, Rd_Rs,                do16_rdrs},
  {"cmp!",      0x2003,     0x700f,     0x00300019, Rd_Rs,                do16_rdrs},
  {"cop1",      0x0c00000c, 0x3e00001f, 0x8000,     Rd_Rs_Rs_imm,         do_crdcrscrsimm5},
  {"cop1",      0x0c00000c, 0x3e00001f, 0x8000,     Rd_Rs_Rs_imm,         do_crdcrscrsimm5},
  {"cop2",      0x0c000014, 0x3e00001f, 0x8000,     Rd_Rs_Rs_imm,         do_crdcrscrsimm5},
  {"cop2",      0x0c000014, 0x3e00001f, 0x8000,     Rd_Rs_Rs_imm,         do_crdcrscrsimm5},
  {"cop3",      0x0c00001c, 0x3e00001f, 0x8000,     Rd_Rs_Rs_imm,         do_crdcrscrsimm5},
  {"cop3",      0x0c00001c, 0x3e00001f, 0x8000,     Rd_Rs_Rs_imm,         do_crdcrscrsimm5},
  {"drte",      0x0c0000a4, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
  {"drte",      0x0c0000a4, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
  {"extsb",     0x00000058, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"extsb",     0x00000058, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"extsb.c",   0x00000059, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"extsb.c",   0x00000059, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"extsh",     0x0000005a, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"extsh",     0x0000005a, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"extsh.c",   0x0000005b, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"extsh.c",   0x0000005b, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"extzb",     0x0000005c, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"extzb",     0x0000005c, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"extzb.c",   0x0000005d, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"extzb.c",   0x0000005d, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"extzh",     0x0000005e, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"extzh",     0x0000005e, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"extzh.c",   0x0000005f, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"extzh.c",   0x0000005f, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"jl",        0x04000001, 0x3e000001, 0x8000,     PC_DISP24div2,        do_jump},
  {"jl",        0x04000001, 0x3e000001, 0x8000,     PC_DISP24div2,        do_jump},
  {"jl!",       0x3001,     0x7001,     0x04000001, PC_DISP11div2,        do16_jump},
  {"jl!",       0x3001,     0x7001,     0x04000001, PC_DISP11div2,        do16_jump},
  {"j!",        0x3000,     0x7001,     0x04000000, PC_DISP11div2,        do16_jump},
  {"j!",        0x3000,     0x7001,     0x04000000, PC_DISP11div2,        do16_jump},
  {"j",         0x04000000, 0x3e000001, 0x8000,     PC_DISP24div2,        do_jump},
  {"j",         0x04000000, 0x3e000001, 0x8000,     PC_DISP24div2,        do_jump},
  {"lbu!",      0x200b,     0x0000700f, 0x2c000000, Rd_rvalueRs,          do16_ldst_insn},
  {"lbu!",      0x200b,     0x0000700f, 0x2c000000, Rd_rvalueRs,          do16_ldst_insn},
  {"lbup!",     0x7003,     0x7007,     0x2c000000, Rd_rvalueBP_I5,       do16_ldst_imm_insn},
  {"lbup!",     0x7003,     0x7007,     0x2c000000, Rd_rvalueBP_I5,       do16_ldst_imm_insn},
  {"alw",       0x0000000c, 0x3e0003ff, 0x8000,     Rd_rvalue32Rs,        do_ldst_atomic},
  {"alw",       0x0000000c, 0x3e0003ff, 0x8000,     Rd_rvalue32Rs,        do_ldst_atomic},
  {"lcb",       0x00000060, 0x3e0003ff, 0x8000,     x_rvalueRs_post4,     do_ldst_unalign},
  {"lcb",       0x00000060, 0x3e0003ff, 0x8000,     x_rvalueRs_post4,     do_ldst_unalign},
  {"lcw",       0x00000062, 0x3e0003ff, 0x8000,     Rd_rvalueRs_post4,    do_ldst_unalign},
  {"lcw",       0x00000062, 0x3e0003ff, 0x8000,     Rd_rvalueRs_post4,    do_ldst_unalign},
  {"lce",       0x00000066, 0x3e0003ff, 0x8000,     Rd_rvalueRs_post4,    do_ldst_unalign},
  {"lce",       0x00000066, 0x3e0003ff, 0x8000,     Rd_rvalueRs_post4,    do_ldst_unalign},
  {"ldc1",      0x0c00000a, 0x3e00001f, 0x8000,     Rd_rvalueRs_SI10,     do_ldst_cop},
  {"ldc1",      0x0c00000a, 0x3e00001f, 0x8000,     Rd_rvalueRs_SI10,     do_ldst_cop},
  {"ldc2",      0x0c000012, 0x3e00001f, 0x8000,     Rd_rvalueRs_SI10,     do_ldst_cop},
  {"ldc2",      0x0c000012, 0x3e00001f, 0x8000,     Rd_rvalueRs_SI10,     do_ldst_cop},
  {"ldc3",      0x0c00001a, 0x3e00001f, 0x8000,     Rd_rvalueRs_SI10,     do_ldst_cop},
  {"ldc3",      0x0c00001a, 0x3e00001f, 0x8000,     Rd_rvalueRs_SI10,     do_ldst_cop},
  {"lh!",       0x2009,     0x700f,     0x22000000, Rd_rvalueRs,          do16_ldst_insn},
  {"lh!",       0x2009,     0x700f,     0x22000000, Rd_rvalueRs,          do16_ldst_insn},
  {"lhp!",      0x7001,     0x7007,     0x22000000, Rd_rvalueBP_I5,       do16_ldst_imm_insn},
  {"lhp!",      0x7001,     0x7007,     0x22000000, Rd_rvalueBP_I5,       do16_ldst_imm_insn},
  {"ldi",       0x020c0000, 0x3e0e0000, 0x5000,     Rd_SI16,              do_rdsi16},
  {"ldi",       0x020c0000, 0x3e0e0000, 0x5000,     Rd_SI16,              do_rdsi16},
  {"ldis",      0x0a0c0000, 0x3e0e0000, 0x8000,     Rd_I16,               do_rdi16},
  {"ldis",      0x0a0c0000, 0x3e0e0000, 0x8000,     Rd_I16,               do_rdi16},
  {"ldiu!",     0x5000,     0x7000,     0x020c0000, Rd_I8,                do16_ldst_imm_insn},
  {"ldiu!",     0x5000,     0x7000,     0x020c0000, Rd_I8,                do16_ldst_imm_insn},
  {"lw!",       0x2008,     0x700f,     0x20000000, Rd_rvalueRs,          do16_ldst_insn},
  {"lw!",       0x2008,     0x700f,     0x20000000, Rd_rvalueRs,          do16_ldst_insn},
  {"lwp!",      0x7000,     0x7007,     0x20000000, Rd_rvalueBP_I5,       do16_ldst_imm_insn},
  {"lwp!",      0x7000,     0x7007,     0x20000000, Rd_rvalueBP_I5,       do16_ldst_imm_insn},
  {"mfcel",     0x00000448, 0x3e007fff, 0x8000,     Rd_x_x,               do_rd},
  {"mfcel",     0x00000448, 0x3e007fff, 0x8000,     Rd_x_x,               do_rd},
  {"mfcel!",    0x1001,     0x7f0f,     0x00000448, x_Rs,                 do16_rs},
  {"mfcel!",    0x1001,     0x7f0f,     0x00000448, x_Rs,                 do16_rs},
  {"mad",       0x38000000, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"mad",       0x38000000, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"mad.f!",    0x1004,     0x700f,     0x38000080, Rd_Rs,                do16_rdrs},
  {"mad.f!",    0x1004,     0x700f,     0x38000080, Rd_Rs,                do16_rdrs},
  {"madh",      0x38000203, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"madh",      0x38000203, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"madh.fs",   0x380002c3, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"madh.fs",   0x380002c3, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"madh.fs!",  0x100b,     0x700f,     0x380002c3, Rd_Rs,                do16_rdrs},
  {"madh.fs!",  0x100b,     0x700f,     0x380002c3, Rd_Rs,                do16_rdrs},
  {"madl",      0x38000002, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"madl",      0x38000002, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"madl.fs",   0x380000c2, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"madl.fs",   0x380000c2, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"madl.fs!",  0x100a,     0x700f,     0x380000c2, Rd_Rs,                do16_rdrs},
  {"madl.fs!",  0x100a,     0x700f,     0x380000c2, Rd_Rs,                do16_rdrs},
  {"madu",      0x38000020, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"madu",      0x38000020, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"madu!",     0x1005,     0x700f,     0x38000020, Rd_Rs,                do16_rdrs},
  {"madu!",     0x1005,     0x700f,     0x38000020, Rd_Rs,                do16_rdrs},
  {"mad.f",     0x38000080, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"mad.f",     0x38000080, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"max",       0x38000007, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"max",       0x38000007, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"mazh",      0x38000303, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"mazh",      0x38000303, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"mazh.f",    0x38000383, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"mazh.f",    0x38000383, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"mazh.f!",   0x1009,     0x700f,     0x3800038c, Rd_Rs,                do16_rdrs},
  {"mazh.f!",   0x1009,     0x700f,     0x3800038c, Rd_Rs,                do16_rdrs},
  {"mazl",      0x38000102, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"mazl",      0x38000102, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"mazl.f",    0x38000182, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"mazl.f",    0x38000182, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"mazl.f!",   0x1008,     0x700f,     0x38000182, Rd_Rs,                do16_rdrs},
  {"mazl.f!",   0x1008,     0x700f,     0x38000182, Rd_Rs,                do16_rdrs},
  {"mfceh",     0x00000848, 0x3e007fff, 0x8000,     Rd_x_x,               do_rd},
  {"mfceh",     0x00000848, 0x3e007fff, 0x8000,     Rd_x_x,               do_rd},
  {"mfceh!",    0x1101,     0x7f0f,     0x00000848, x_Rs,                 do16_rs},
  {"mfceh!",    0x1101,     0x7f0f,     0x00000848, x_Rs,                 do16_rs},
  {"mfcehl",    0x00000c48, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mfcehl",    0x00000c48, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mfsr",      0x00000050, 0x3e0003ff, 0x8000,     Rd_x_I5,              do_rdsrs},
  {"mfsr",      0x00000050, 0x3e0003ff, 0x8000,     Rd_x_I5,              do_rdsrs},
  {"mfcr",      0x0c000001, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mfcr",      0x0c000001, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mfc1",      0x0c000009, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mfc1",      0x0c000009, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mfc2",      0x0c000011, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mfc2",      0x0c000011, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mfc3",      0x0c000019, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mfc3",      0x0c000019, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mfcc1",     0x0c00000f, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mfcc1",     0x0c00000f, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mfcc2",     0x0c000017, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mfcc2",     0x0c000017, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mfcc3",     0x0c00001f, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mfcc3",     0x0c00001f, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mhfl!",     0x0002,     0x700f,     0x00003c56, Rd_LowRs,             do16_hrdrs},
  {"mhfl!",     0x0002,     0x700f,     0x00003c56, Rd_LowRs,             do16_hrdrs},
  {"min",       0x38000006, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"min",       0x38000006, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"mlfh!",     0x0001,     0x700f,     0x00003c56, Rd_HighRs,            do16_rdhrs},
  {"mlfh!",     0x0001,     0x700f,     0x00003c56, Rd_HighRs,            do16_rdhrs},
  {"msb",       0x38000001, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"msb",       0x38000001, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"msb.f!",    0x1006,     0x700f,     0x38000081, Rd_Rs,                do16_rdrs},
  {"msb.f!",    0x1006,     0x700f,     0x38000081, Rd_Rs,                do16_rdrs},
  {"msbh",      0x38000205, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"msbh",      0x38000205, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"msbh.fs",   0x380002c5, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"msbh.fs",   0x380002c5, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"msbh.fs!",  0x100f,     0x700f,     0x380002c5, Rd_Rs,                do16_rdrs},
  {"msbh.fs!",  0x100f,     0x700f,     0x380002c5, Rd_Rs,                do16_rdrs},
  {"msbl",      0x38000004, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"msbl",      0x38000004, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"msbl.fs",   0x380000c4, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"msbl.fs",   0x380000c4, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"msbl.fs!",  0x100e,     0x700f,     0x380000c4, Rd_Rs,                do16_rdrs},
  {"msbl.fs!",  0x100e,     0x700f,     0x380000c4, Rd_Rs,                do16_rdrs},
  {"msbu",      0x38000021, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"msbu",      0x38000021, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"msbu!",     0x1007,     0x700f,     0x38000021, Rd_Rs,                do16_rdrs},
  {"msbu!",     0x1007,     0x700f,     0x38000021, Rd_Rs,                do16_rdrs},
  {"msb.f",     0x38000081, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"msb.f",     0x38000081, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"mszh",      0x38000305, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"mszh",      0x38000305, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"mszh.f",    0x38000385, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"mszh.f",    0x38000385, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"mszh.f!",   0x100d,     0x700f,     0x38000385, Rd_Rs,                do16_rdrs},
  {"mszh.f!",   0x100d,     0x700f,     0x38000385, Rd_Rs,                do16_rdrs},
  {"mszl",      0x38000104, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"mszl",      0x38000104, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"mszl.f",    0x38000184, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"mszl.f",    0x38000184, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
  {"mszl.f!",   0x100c,     0x700f,     0x38000184, Rd_Rs,                do16_rdrs},
  {"mszl.f!",   0x100c,     0x700f,     0x38000184, Rd_Rs,                do16_rdrs},
  {"mtcel!",    0x1000,     0x7f0f,     0x0000044a, x_Rs,                 do16_rs},
  {"mtcel!",    0x1000,     0x7f0f,     0x0000044a, x_Rs,                 do16_rs},
  {"mtcel",     0x0000044a, 0x3e007fff, 0x8000,     Rd_x_x,               do_rd},
  {"mtcel",     0x0000044a, 0x3e007fff, 0x8000,     Rd_x_x,               do_rd},
  {"mtceh",     0x0000084a, 0x3e007fff, 0x8000,     Rd_x_x,               do_rd},
  {"mtceh",     0x0000084a, 0x3e007fff, 0x8000,     Rd_x_x,               do_rd},
  {"mtceh!",    0x1100,     0x7f0f,     0x0000084a, x_Rs,                 do16_rs},
  {"mtceh!",    0x1100,     0x7f0f,     0x0000084a, x_Rs,                 do16_rs},
  {"mtcehl",    0x00000c4a, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mtcehl",    0x00000c4a, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mtsr",      0x00000052, 0x3e0003ff, 0x8000,     x_Rs_I5,              do_rdsrs},
  {"mtsr",      0x00000052, 0x3e0003ff, 0x8000,     x_Rs_I5,              do_rdsrs},
  {"mtcr",      0x0c000000, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mtcr",      0x0c000000, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mtc1",      0x0c000008, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mtc1",      0x0c000008, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mtc2",      0x0c000010, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mtc2",      0x0c000010, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mtc3",      0x0c000018, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mtc3",      0x0c000018, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mtcc1",     0x0c00000e, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mtcc1",     0x0c00000e, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mtcc2",     0x0c000016, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mtcc2",     0x0c000016, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mtcc3",     0x0c00001e, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mtcc3",     0x0c00001e, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
  {"mul.f!",    0x1002,     0x700f,     0x00000041, Rd_Rs,                do16_rdrs},
  {"mul.f!",    0x1002,     0x700f,     0x00000041, Rd_Rs,                do16_rdrs},
  {"mulu!",     0x1003,     0x700f,     0x00000042, Rd_Rs,                do16_rdrs},
  {"mulu!",     0x1003,     0x700f,     0x00000042, Rd_Rs,                do16_rdrs},
  {"mvcs",      0x00000056, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvcs",      0x00000056, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvcc",      0x00000456, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvcc",      0x00000456, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvgtu",     0x00000856, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvgtu",     0x00000856, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvleu",     0x00000c56, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvleu",     0x00000c56, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mveq",      0x00001056, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mveq",      0x00001056, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvne",      0x00001456, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvne",      0x00001456, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvgt",      0x00001856, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvgt",      0x00001856, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvle",      0x00001c56, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvle",      0x00001c56, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvge",      0x00002056, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvge",      0x00002056, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvlt",      0x00002456, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvlt",      0x00002456, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvmi",      0x00002856, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvmi",      0x00002856, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvpl",      0x00002c56, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvpl",      0x00002c56, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvvs",      0x00003056, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvvs",      0x00003056, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvvc",      0x00003456, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mvvc",      0x00003456, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"mv",        0x00003c56, 0x3e007fff, 0x0003,     Rd_Rs_x,              do_rdrs},
  {"mv",        0x00003c56, 0x3e007fff, 0x0003,     Rd_Rs_x,              do_rdrs},
  {"mv!",       0x0003,     0x700f,     0x00003c56, Rd_Rs,                do16_mv_rdrs},
  {"mv!",       0x0003,     0x700f,     0x00003c56, Rd_Rs,                do16_mv_rdrs},
  {"neg",       0x0000001e, 0x3e0003ff, 0x8000,     Rd_x_Rs,              do_rdxrs},
  {"neg",       0x0000001e, 0x3e0003ff, 0x8000,     Rd_x_Rs,              do_rdxrs},
  {"neg.c",     0x0000001f, 0x3e0003ff, 0x2002,     Rd_x_Rs,              do_rdxrs},
  {"neg.c",     0x0000001f, 0x3e0003ff, 0x2002,     Rd_x_Rs,              do_rdxrs},
  {"neg!",      0x2002,     0x700f,     0x0000001f, Rd_Rs,                do16_rdrs},
  {"neg!",      0x2002,     0x700f,     0x0000001f, Rd_Rs,                do16_rdrs},
  {"nop",       0x00000000, 0x3e0003ff, 0x0000,     NO_OPD,               do_empty},
  {"nop",       0x00000000, 0x3e0003ff, 0x0000,     NO_OPD,               do_empty},
  {"not",       0x00000024, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"not",       0x00000024, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
  {"not.c",     0x00000025, 0x3e0003ff, 0x2006,     Rd_Rs_x,              do_rdrs},
  {"not.c",     0x00000025, 0x3e0003ff, 0x2006,     Rd_Rs_x,              do_rdrs},
  {"nop!",      0x0000,     0x700f,     0x00000000, NO16_OPD,               do_empty},
  {"nop!",      0x0000,     0x700f,     0x00000000, NO16_OPD,               do_empty},
  {"not!",      0x2006,     0x700f,     0x00000025, Rd_Rs,                do16_rdrs},
  {"not!",      0x2006,     0x700f,     0x00000025, Rd_Rs,                do16_rdrs},
  {"or",        0x00000022, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"or",        0x00000022, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"or.c",      0x00000023, 0x3e0003ff, 0x2005,     Rd_Rs_Rs,             do_rdrsrs},
  {"or.c",      0x00000023, 0x3e0003ff, 0x2005,     Rd_Rs_Rs,             do_rdrsrs},
  {"ori",       0x020a0000, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
  {"ori",       0x020a0000, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
  {"ori.c",     0x020a0001, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
  {"ori.c",     0x020a0001, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
  {"oris",      0x0a0a0000, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
  {"oris",      0x0a0a0000, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
  {"oris.c",    0x0a0a0001, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
  {"oris.c",    0x0a0a0001, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
  {"orri",      0x1a000000, 0x3e000001, 0x8000,     Rd_Rs_I14,            do_rdrsi14},
  {"orri",      0x1a000000, 0x3e000001, 0x8000,     Rd_Rs_I14,            do_rdrsi14},
  {"orri.c",    0x1a000001, 0x3e000001, 0x8000,     Rd_Rs_I14,            do_rdrsi14},
  {"orri.c",    0x1a000001, 0x3e000001, 0x8000,     Rd_Rs_I14,            do_rdrsi14},
  {"or!",       0x2005,     0x700f,     0x00000023, Rd_Rs,                do16_rdrs},
  {"or!",       0x2005,     0x700f,     0x00000023, Rd_Rs,                do16_rdrs},
  {"pflush",    0x0000000a, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
  {"pflush",    0x0000000a, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
  {"pop!",      0x200a,     0x700f,     0x0e000000, Rd_rvalueRs,          do16_push_pop},
  {"pop!",      0x200a,     0x700f,     0x0e000000, Rd_rvalueRs,          do16_push_pop},
  {"push!",     0x200e,     0x700f,     0x06000004, Rd_lvalueRs,          do16_push_pop},
  {"push!",     0x200e,     0x700f,     0x06000004, Rd_lvalueRs,          do16_push_pop},
  {"ror",       0x00000038, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"ror",       0x00000038, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"ror.c",     0x00000039, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"ror.c",     0x00000039, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"rorc.c",    0x0000003b, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"rorc.c",    0x0000003b, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"rol",       0x0000003c, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"rol",       0x0000003c, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"rol.c",     0x0000003d, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"rol.c",     0x0000003d, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"rolc.c",    0x0000003f, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"rolc.c",    0x0000003f, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"rori",      0x00000078, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
  {"rori",      0x00000078, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
  {"rori.c",    0x00000079, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
  {"rori.c",    0x00000079, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
  {"roric.c",   0x0000007b, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
  {"roric.c",   0x0000007b, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
  {"roli",      0x0000007c, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
  {"roli",      0x0000007c, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
  {"roli.c",    0x0000007d, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
  {"roli.c",    0x0000007d, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
  {"rolic.c",   0x0000007f, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
  {"rolic.c",   0x0000007f, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
  {"rte",       0x0c000084, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
  {"rte",       0x0c000084, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
  {"sb!",       0x200f,     0x700f,     0x2e000000, Rd_lvalueRs,          do16_ldst_insn},
  {"sb!",       0x200f,     0x700f,     0x2e000000, Rd_lvalueRs,          do16_ldst_insn},
  {"sbp!",      0x7007,     0x7007,     0x2e000000, Rd_lvalueBP_I5,       do16_ldst_imm_insn},
  {"sbp!",      0x7007,     0x7007,     0x2e000000, Rd_lvalueBP_I5,       do16_ldst_imm_insn},
  {"asw",       0x0000000e, 0x3e0003ff, 0x8000,     Rd_lvalue32Rs,        do_ldst_atomic},
  {"asw",       0x0000000e, 0x3e0003ff, 0x8000,     Rd_lvalue32Rs,        do_ldst_atomic},
  {"scb",       0x00000068, 0x3e0003ff, 0x8000,     Rd_lvalueRs_post4,    do_ldst_unalign},
  {"scb",       0x00000068, 0x3e0003ff, 0x8000,     Rd_lvalueRs_post4,    do_ldst_unalign},
  {"scw",       0x0000006a, 0x3e0003ff, 0x8000,     Rd_lvalueRs_post4,    do_ldst_unalign},
  {"scw",       0x0000006a, 0x3e0003ff, 0x8000,     Rd_lvalueRs_post4,    do_ldst_unalign},
  {"sce",       0x0000006e, 0x3e0003ff, 0x8000,     x_lvalueRs_post4,     do_ldst_unalign},
  {"sce",       0x0000006e, 0x3e0003ff, 0x8000,     x_lvalueRs_post4,     do_ldst_unalign},
  {"sdbbp",     0x00000006, 0x3e0003ff, 0x6002,     x_I5_x,               do_xi5x},
  {"sdbbp",     0x00000006, 0x3e0003ff, 0x6002,     x_I5_x,               do_xi5x},
  {"sdbbp!",    0x6002,     0x7007,     0x00000006, Rd_I5,                do16_xi5},
  {"sdbbp!",    0x6002,     0x7007,     0x00000006, Rd_I5,                do16_xi5},
  {"sh!",       0x200d,     0x700f,     0x2a000000, Rd_lvalueRs,          do16_ldst_insn},
  {"sh!",       0x200d,     0x700f,     0x2a000000, Rd_lvalueRs,          do16_ldst_insn},
  {"shp!",      0x7005,     0x7007,     0x2a000000, Rd_lvalueBP_I5,       do16_ldst_imm_insn},
  {"shp!",      0x7005,     0x7007,     0x2a000000, Rd_lvalueBP_I5,       do16_ldst_imm_insn},
  {"sleep",     0x0c0000c4, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
  {"sleep",     0x0c0000c4, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
  {"sll",       0x00000030, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"sll",       0x00000030, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"sll.c",     0x00000031, 0x3e0003ff, 0x0008,     Rd_Rs_Rs,             do_rdrsrs},
  {"sll.c",     0x00000031, 0x3e0003ff, 0x0008,     Rd_Rs_Rs,             do_rdrsrs},
  {"sll.s",     0x3800004e, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"sll.s",     0x3800004e, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"slli",      0x00000070, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
  {"slli",      0x00000070, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
  {"slli.c",    0x00000071, 0x3e0003ff, 0x6001,     Rd_Rs_I5,             do_rdrsi5},
  {"slli.c",    0x00000071, 0x3e0003ff, 0x6001,     Rd_Rs_I5,             do_rdrsi5},
  {"sll!",      0x0008,     0x700f,     0x00000031, Rd_Rs,                do16_rdrs},
  {"sll!",      0x0008,     0x700f,     0x00000031, Rd_Rs,                do16_rdrs},
  {"slli!",     0x6001,     0x7007,     0x00000071, Rd_I5,                do16_rdi5},
  {"slli!",     0x6001,     0x7007,     0x00000071, Rd_I5,                do16_rdi5},
  {"srl",       0x00000034, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"srl",       0x00000034, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"srl.c",     0x00000035, 0x3e0003ff, 0x000a,     Rd_Rs_Rs,             do_rdrsrs},
  {"srl.c",     0x00000035, 0x3e0003ff, 0x000a,     Rd_Rs_Rs,             do_rdrsrs},
  {"sra",       0x00000036, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"sra",       0x00000036, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"sra.c",     0x00000037, 0x3e0003ff, 0x000b,     Rd_Rs_Rs,             do_rdrsrs},
  {"sra.c",     0x00000037, 0x3e0003ff, 0x000b,     Rd_Rs_Rs,             do_rdrsrs},
  {"srli",      0x00000074, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
  {"srli",      0x00000074, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
  {"srli.c",    0x00000075, 0x3e0003ff, 0x6003,     Rd_Rs_I5,             do_rdrsi5},
  {"srli.c",    0x00000075, 0x3e0003ff, 0x6003,     Rd_Rs_I5,             do_rdrsi5},
  {"srai",      0x00000076, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
  {"srai",      0x00000076, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
  {"srai.c",    0x00000077, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
  {"srai.c",    0x00000077, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
  {"srl!",      0x000a,     0x700f,     0x00000035, Rd_Rs,                do16_rdrs},
  {"srl!",      0x000a,     0x700f,     0x00000035, Rd_Rs,                do16_rdrs},
  {"sra!",      0x000b,     0x700f,     0x00000037, Rd_Rs,                do16_rdrs},
  {"sra!",      0x000b,     0x700f,     0x00000037, Rd_Rs,                do16_rdrs},
  {"srli!",     0x6003,     0x7007,     0x00000075, Rd_Rs,                do16_rdi5},
  {"srli!",     0x6003,     0x7007,     0x00000075, Rd_Rs,                do16_rdi5},
  {"stc1",      0x0c00000b, 0x3e00001f, 0x8000,     Rd_lvalueRs_SI10,     do_ldst_cop},
  {"stc1",      0x0c00000b, 0x3e00001f, 0x8000,     Rd_lvalueRs_SI10,     do_ldst_cop},
  {"stc2",      0x0c000013, 0x3e00001f, 0x8000,     Rd_lvalueRs_SI10,     do_ldst_cop},
  {"stc2",      0x0c000013, 0x3e00001f, 0x8000,     Rd_lvalueRs_SI10,     do_ldst_cop},
  {"stc3",      0x0c00001b, 0x3e00001f, 0x8000,     Rd_lvalueRs_SI10,     do_ldst_cop},
  {"stc3",      0x0c00001b, 0x3e00001f, 0x8000,     Rd_lvalueRs_SI10,     do_ldst_cop},
  {"sub",       0x00000014, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"sub",       0x00000014, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"sub.c",     0x00000015, 0x3e0003ff, 0x2001,     Rd_Rs_Rs,             do_rdrsrs},
  {"sub.c",     0x00000015, 0x3e0003ff, 0x2001,     Rd_Rs_Rs,             do_rdrsrs},
  {"sub.s",     0x38000049, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"sub.s",     0x38000049, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"subc",      0x00000016, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"subc",      0x00000016, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"subc.c",    0x00000017, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"subc.c",    0x00000017, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"sub!",      0x2001,     0x700f,     0x00000015, Rd_Rs,                do16_rdrs},
  {"sub!",      0x2001,     0x700f,     0x00000015, Rd_Rs,                do16_rdrs},
  {"subei!",    0x6080,     0x7087,     0x02000001, Rd_I4,                do16_rdi4},
  {"subei!",    0x6080,     0x7087,     0x02000001, Rd_I4,                do16_rdi4},
  {"sw!",       0x200c,     0x700f,     0x28000000, Rd_lvalueRs,          do16_ldst_insn},
  {"sw!",       0x200c,     0x700f,     0x28000000, Rd_lvalueRs,          do16_ldst_insn},
  {"swp!",      0x7004,     0x7007,     0x28000000, Rd_lvalueBP_I5,       do16_ldst_imm_insn},
  {"swp!",      0x7004,     0x7007,     0x28000000, Rd_lvalueBP_I5,       do16_ldst_imm_insn},
  {"syscall",   0x00000002, 0x3e0003ff, 0x8000,     I15,                  do_i15},
  {"syscall",   0x00000002, 0x3e0003ff, 0x8000,     I15,                  do_i15},
  {"tcs",       0x00000054, 0x3e007fff, 0x0005,     NO_OPD,               do_empty},
  {"tcs",       0x00000054, 0x3e007fff, 0x0005,     NO_OPD,               do_empty},
  {"tcc",       0x00000454, 0x3e007fff, 0x0105,     NO_OPD,               do_empty},
  {"tcc",       0x00000454, 0x3e007fff, 0x0105,     NO_OPD,               do_empty},
  {"tcnz",      0x00003854, 0x3e007fff, 0x0e05,     NO_OPD,               do_empty},
  {"tcnz",      0x00003854, 0x3e007fff, 0x0e05,     NO_OPD,               do_empty},
  {"tcs!",      0x0005,     0x7f0f,     0x00000054, NO16_OPD,             do_empty},
  {"tcs!",      0x0005,     0x7f0f,     0x00000054, NO16_OPD,             do_empty},
  {"tcc!",      0x0105,     0x7f0f,     0x00000454, NO16_OPD,             do_empty},
  {"tcc!",      0x0105,     0x7f0f,     0x00000454, NO16_OPD,             do_empty},
  {"tcnz!",     0x0e05,     0x7f0f,     0x00003854, NO16_OPD,             do_empty},
  {"tcnz!",     0x0e05,     0x7f0f,     0x00003854, NO16_OPD,             do_empty},
  {"teq",       0x00001054, 0x3e007fff, 0x0405,     NO_OPD,               do_empty},
  {"teq",       0x00001054, 0x3e007fff, 0x0405,     NO_OPD,               do_empty},
  {"teq!",      0x0405,     0x7f0f,     0x00001054, NO16_OPD,             do_empty},
  {"teq!",      0x0405,     0x7f0f,     0x00001054, NO16_OPD,             do_empty},
  {"tgtu",      0x00000854, 0x3e007fff, 0x0205,     NO_OPD,               do_empty},
  {"tgtu",      0x00000854, 0x3e007fff, 0x0205,     NO_OPD,               do_empty},
  {"tgt",       0x00001854, 0x3e007fff, 0x0605,     NO_OPD,               do_empty},
  {"tgt",       0x00001854, 0x3e007fff, 0x0605,     NO_OPD,               do_empty},
  {"tge",       0x00002054, 0x3e007fff, 0x0805,     NO_OPD,               do_empty},
  {"tge",       0x00002054, 0x3e007fff, 0x0805,     NO_OPD,               do_empty},
  {"tgtu!",     0x0205,     0x7f0f,     0x00000854, NO16_OPD,             do_empty},
  {"tgtu!",     0x0205,     0x7f0f,     0x00000854, NO16_OPD,             do_empty},
  {"tgt!",      0x0605,     0x7f0f,     0x00001854, NO16_OPD,             do_empty},
  {"tgt!",      0x0605,     0x7f0f,     0x00001854, NO16_OPD,             do_empty},
  {"tge!",      0x0805,     0x7f0f,     0x00002054, NO16_OPD,             do_empty},
  {"tge!",      0x0805,     0x7f0f,     0x00002054, NO16_OPD,             do_empty},
  {"tleu",      0x00000c54, 0x3e007fff, 0x0305,     NO_OPD,               do_empty},
  {"tleu",      0x00000c54, 0x3e007fff, 0x0305,     NO_OPD,               do_empty},
  {"tle",       0x00001c54, 0x3e007fff, 0x0705,     NO_OPD,               do_empty},
  {"tle",       0x00001c54, 0x3e007fff, 0x0705,     NO_OPD,               do_empty},
  {"tlt",       0x00002454, 0x3e007fff, 0x0905,     NO_OPD,               do_empty},
  {"tlt",       0x00002454, 0x3e007fff, 0x0905,     NO_OPD,               do_empty},
  {"stlb",      0x0c000004, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
  {"stlb",      0x0c000004, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
  {"mftlb",     0x0c000024, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
  {"mftlb",     0x0c000024, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
  {"mtptlb",    0x0c000044, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
  {"mtptlb",    0x0c000044, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
  {"mtrtlb",    0x0c000064, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
  {"mtrtlb",    0x0c000064, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
  {"tleu!",     0x0305,     0x7f0f,     0x00000c54, NO16_OPD,             do_empty},
  {"tleu!",     0x0305,     0x7f0f,     0x00000c54, NO16_OPD,             do_empty},
  {"tle!",      0x0705,     0x7f0f,     0x00001c54, NO16_OPD,             do_empty},
  {"tle!",      0x0705,     0x7f0f,     0x00001c54, NO16_OPD,             do_empty},
  {"tlt!",      0x0905,     0x7f0f,     0x00002454, NO16_OPD,             do_empty},
  {"tlt!",      0x0905,     0x7f0f,     0x00002454, NO16_OPD,             do_empty},
  {"tmi",       0x00002854, 0x3e007fff, 0x0a05,     NO_OPD,               do_empty},
  {"tmi",       0x00002854, 0x3e007fff, 0x0a05,     NO_OPD,               do_empty},
  {"tmi!",      0x0a05,     0x7f0f,     0x00002854, NO16_OPD,             do_empty},
  {"tmi!",      0x0a05,     0x7f0f,     0x00002854, NO16_OPD,             do_empty},
  {"tne",       0x00001454, 0x3e007fff, 0x0505,     NO_OPD,               do_empty},
  {"tne",       0x00001454, 0x3e007fff, 0x0505,     NO_OPD,               do_empty},
  {"tne!",      0x0505,     0x7f0f,     0x00001454, NO16_OPD,             do_empty},
  {"tne!",      0x0505,     0x7f0f,     0x00001454, NO16_OPD,             do_empty},
  {"tpl",       0x00002c54, 0x3e007fff, 0x0b05,     NO_OPD,               do_empty},
  {"tpl",       0x00002c54, 0x3e007fff, 0x0b05,     NO_OPD,               do_empty},
  {"tpl!",      0x0b05,     0x7f0f,     0x00002c54, NO16_OPD,             do_empty},
  {"tpl!",      0x0b05,     0x7f0f,     0x00002c54, NO16_OPD,             do_empty},
  {"trapcs",    0x00000004, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trapcs",    0x00000004, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trapcc",    0x00000404, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trapcc",    0x00000404, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trapgtu",   0x00000804, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trapgtu",   0x00000804, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trapleu",   0x00000c04, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trapleu",   0x00000c04, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trapeq",    0x00001004, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trapeq",    0x00001004, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trapne",    0x00001404, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trapne",    0x00001404, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trapgt",    0x00001804, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trapgt",    0x00001804, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"traple",    0x00001c04, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"traple",    0x00001c04, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trapge",    0x00002004, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trapge",    0x00002004, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"traplt",    0x00002404, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"traplt",    0x00002404, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trapmi",    0x00002804, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trapmi",    0x00002804, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trappl",    0x00002c04, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trappl",    0x00002c04, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trapvs",    0x00003004, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trapvs",    0x00003004, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trapvc",    0x00003404, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trapvc",    0x00003404, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trap",      0x00003c04, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"trap",      0x00003c04, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
  {"tset",      0x00003c54, 0x3e007fff, 0x0f05,     NO_OPD,               do_empty},
  {"tset",      0x00003c54, 0x3e007fff, 0x0f05,     NO_OPD,               do_empty},
  {"tset!",     0x0f05,     0x00007f0f, 0x00003c54, NO16_OPD,             do_empty},
  {"tset!",     0x0f05,     0x00007f0f, 0x00003c54, NO16_OPD,             do_empty},
  {"tvs",       0x00003054, 0x3e007fff, 0x0c05,     NO_OPD,               do_empty},
  {"tvs",       0x00003054, 0x3e007fff, 0x0c05,     NO_OPD,               do_empty},
  {"tvc",       0x00003454, 0x3e007fff, 0x0d05,     NO_OPD,               do_empty},
  {"tvc",       0x00003454, 0x3e007fff, 0x0d05,     NO_OPD,               do_empty},
  {"tvs!",      0x0c05,     0x7f0f,     0x00003054, NO16_OPD,             do_empty},
  {"tvs!",      0x0c05,     0x7f0f,     0x00003054, NO16_OPD,             do_empty},
  {"tvc!",      0x0d05,     0x7f0f,     0x00003454, NO16_OPD,             do_empty},
  {"tvc!",      0x0d05,     0x7f0f,     0x00003454, NO16_OPD,             do_empty},
  {"xor",       0x00000026, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"xor",       0x00000026, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
  {"xor.c",     0x00000027, 0x3e0003ff, 0x2007,     Rd_Rs_Rs,             do_rdrsrs},
  {"xor.c",     0x00000027, 0x3e0003ff, 0x2007,     Rd_Rs_Rs,             do_rdrsrs},
  {"xor!",      0x2007,     0x700f,     0x00000027, Rd_Rs,                do16_rdrs},
  {"xor!",      0x2007,     0x700f,     0x00000027, Rd_Rs,                do16_rdrs},
  /* Macro instruction.  */
  /* Macro instruction.  */
  {"li",        0x020c0000, 0x3e0e0000, 0x8000,     Insn_Type_SYN,        do_macro_li_rdi32},
  {"li",        0x020c0000, 0x3e0e0000, 0x8000,     Insn_Type_SYN,        do_macro_li_rdi32},
  /* la reg, imm32        -->(1)  ldi  reg, simm16
  /* la reg, imm32        -->(1)  ldi  reg, simm16
                             (2)  ldis reg, %HI(imm32)
                             (2)  ldis reg, %HI(imm32)
                                  ori  reg, %LO(imm32)
                                  ori  reg, %LO(imm32)
 
 
     la reg, symbol       -->(1)  lis  reg, %HI(imm32)
     la reg, symbol       -->(1)  lis  reg, %HI(imm32)
                                  ori  reg, %LO(imm32)  */
                                  ori  reg, %LO(imm32)  */
  {"la",        0x020c0000, 0x3e0e0000, 0x8000,     Insn_Type_SYN,        do_macro_la_rdi32},
  {"la",        0x020c0000, 0x3e0e0000, 0x8000,     Insn_Type_SYN,        do_macro_la_rdi32},
  {"div",       0x00000044, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
  {"div",       0x00000044, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
  {"divu",      0x00000046, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
  {"divu",      0x00000046, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
  {"rem",       0x00000044, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
  {"rem",       0x00000044, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
  {"remu",      0x00000046, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
  {"remu",      0x00000046, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
  {"mul",       0x00000040, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
  {"mul",       0x00000040, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
  {"mulu",      0x00000042, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
  {"mulu",      0x00000042, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
  {"maz",       0x00000040, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
  {"maz",       0x00000040, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
  {"mazu",      0x00000042, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
  {"mazu",      0x00000042, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
  {"mul.f",     0x00000041, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
  {"mul.f",     0x00000041, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
  {"maz.f",     0x00000041, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
  {"maz.f",     0x00000041, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
  {"lb",        INSN_LB,    0x00000000, 0x8000,     Insn_Type_SYN,        do_macro_ldst_label},
  {"lb",        INSN_LB,    0x00000000, 0x8000,     Insn_Type_SYN,        do_macro_ldst_label},
  {"lbu",       INSN_LBU,   0x00000000, 0x200b,     Insn_Type_SYN,        do_macro_ldst_label},
  {"lbu",       INSN_LBU,   0x00000000, 0x200b,     Insn_Type_SYN,        do_macro_ldst_label},
  {"lh",        INSN_LH,    0x00000000, 0x2009,     Insn_Type_SYN,        do_macro_ldst_label},
  {"lh",        INSN_LH,    0x00000000, 0x2009,     Insn_Type_SYN,        do_macro_ldst_label},
  {"lhu",       INSN_LHU,   0x00000000, 0x8000,     Insn_Type_SYN,        do_macro_ldst_label},
  {"lhu",       INSN_LHU,   0x00000000, 0x8000,     Insn_Type_SYN,        do_macro_ldst_label},
  {"lw",        INSN_LW,    0x00000000, 0x2008,     Insn_Type_SYN,        do_macro_ldst_label},
  {"lw",        INSN_LW,    0x00000000, 0x2008,     Insn_Type_SYN,        do_macro_ldst_label},
  {"sb",        INSN_SB,    0x00000000, 0x200f,     Insn_Type_SYN,        do_macro_ldst_label},
  {"sb",        INSN_SB,    0x00000000, 0x200f,     Insn_Type_SYN,        do_macro_ldst_label},
  {"sh",        INSN_SH,    0x00000000, 0x200d,     Insn_Type_SYN,        do_macro_ldst_label},
  {"sh",        INSN_SH,    0x00000000, 0x200d,     Insn_Type_SYN,        do_macro_ldst_label},
  {"sw",        INSN_SW,    0x00000000, 0x200c,     Insn_Type_SYN,        do_macro_ldst_label},
  {"sw",        INSN_SW,    0x00000000, 0x200c,     Insn_Type_SYN,        do_macro_ldst_label},
  /* Assembler use internal.  */
  /* Assembler use internal.  */
  {"ld_i32hi",  0x0a0c0000, 0x3e0e0000, 0x8000,     Insn_internal, do_macro_rdi32hi},
  {"ld_i32hi",  0x0a0c0000, 0x3e0e0000, 0x8000,     Insn_internal, do_macro_rdi32hi},
  {"ld_i32lo",  0x020a0000, 0x3e0e0001, 0x8000,     Insn_internal, do_macro_rdi32lo},
  {"ld_i32lo",  0x020a0000, 0x3e0e0001, 0x8000,     Insn_internal, do_macro_rdi32lo},
  {"ldis_pic",  0x0a0c0000, 0x3e0e0000, 0x5000,     Insn_internal, do_rdi16_pic},
  {"ldis_pic",  0x0a0c0000, 0x3e0e0000, 0x5000,     Insn_internal, do_rdi16_pic},
  {"addi_s_pic",0x02000000, 0x3e0e0001, 0x8000,     Insn_internal, do_addi_s_pic},
  {"addi_s_pic",0x02000000, 0x3e0e0001, 0x8000,     Insn_internal, do_addi_s_pic},
  {"addi_u_pic",0x02000000, 0x3e0e0001, 0x8000,     Insn_internal, do_addi_u_pic},
  {"addi_u_pic",0x02000000, 0x3e0e0001, 0x8000,     Insn_internal, do_addi_u_pic},
  {"lw_pic",    0x20000000, 0x3e000000, 0x8000,     Insn_internal, do_lw_pic},
  {"lw_pic",    0x20000000, 0x3e000000, 0x8000,     Insn_internal, do_lw_pic},
};
};
 
 
/* Next free entry in the pool.  */
/* Next free entry in the pool.  */
int next_literal_pool_place = 0;
int next_literal_pool_place = 0;
 
 
/* Next literal pool number.  */
/* Next literal pool number.  */
int lit_pool_num = 1;
int lit_pool_num = 1;
symbolS *current_poolP = NULL;
symbolS *current_poolP = NULL;
 
 
 
 
static int
static int
end_of_line (char *str)
end_of_line (char *str)
{
{
  int retval = SUCCESS;
  int retval = SUCCESS;
 
 
  skip_whitespace (str);
  skip_whitespace (str);
  if (*str != '\0')
  if (*str != '\0')
    {
    {
      retval = (int) FAIL;
      retval = (int) FAIL;
 
 
      if (!inst.error)
      if (!inst.error)
        inst.error = BAD_GARBAGE;
        inst.error = BAD_GARBAGE;
    }
    }
 
 
  return retval;
  return retval;
}
}
 
 
static int
static int
score_reg_parse (char **ccp, struct hash_control *htab)
score_reg_parse (char **ccp, struct hash_control *htab)
{
{
  char *start = *ccp;
  char *start = *ccp;
  char c;
  char c;
  char *p;
  char *p;
  struct reg_entry *reg;
  struct reg_entry *reg;
 
 
  p = start;
  p = start;
  if (!ISALPHA (*p) || !is_name_beginner (*p))
  if (!ISALPHA (*p) || !is_name_beginner (*p))
    return (int) FAIL;
    return (int) FAIL;
 
 
  c = *p++;
  c = *p++;
 
 
  while (ISALPHA (c) || ISDIGIT (c) || c == '_')
  while (ISALPHA (c) || ISDIGIT (c) || c == '_')
    c = *p++;
    c = *p++;
 
 
  *--p = 0;
  *--p = 0;
  reg = (struct reg_entry *) hash_find (htab, start);
  reg = (struct reg_entry *) hash_find (htab, start);
  *p = c;
  *p = c;
 
 
  if (reg)
  if (reg)
    {
    {
      *ccp = p;
      *ccp = p;
      return reg->number;
      return reg->number;
    }
    }
  return (int) FAIL;
  return (int) FAIL;
}
}
 
 
/* If shift <= 0, only return reg.  */
/* If shift <= 0, only return reg.  */
 
 
static int
static int
reg_required_here (char **str, int shift, enum score_reg_type reg_type)
reg_required_here (char **str, int shift, enum score_reg_type reg_type)
{
{
  static char buff[MAX_LITERAL_POOL_SIZE];
  static char buff[MAX_LITERAL_POOL_SIZE];
  int reg = (int) FAIL;
  int reg = (int) FAIL;
  char *start = *str;
  char *start = *str;
 
 
  if ((reg = score_reg_parse (str, all_reg_maps[reg_type].htab)) != (int) FAIL)
  if ((reg = score_reg_parse (str, all_reg_maps[reg_type].htab)) != (int) FAIL)
    {
    {
      if (reg_type == REG_TYPE_SCORE)
      if (reg_type == REG_TYPE_SCORE)
        {
        {
          if ((reg == 1) && (nor1 == 1) && (inst.bwarn == 0))
          if ((reg == 1) && (nor1 == 1) && (inst.bwarn == 0))
            {
            {
              as_warn (_("Using temp register(r1)"));
              as_warn (_("Using temp register(r1)"));
              inst.bwarn = 1;
              inst.bwarn = 1;
            }
            }
        }
        }
      if (shift >= 0)
      if (shift >= 0)
        {
        {
          if (reg_type == REG_TYPE_SCORE_CR)
          if (reg_type == REG_TYPE_SCORE_CR)
            strcpy (inst.reg, score_crn_table[reg].name);
            strcpy (inst.reg, score_crn_table[reg].name);
          else if (reg_type == REG_TYPE_SCORE_SR)
          else if (reg_type == REG_TYPE_SCORE_SR)
            strcpy (inst.reg, score_srn_table[reg].name);
            strcpy (inst.reg, score_srn_table[reg].name);
          else
          else
            strcpy (inst.reg, "");
            strcpy (inst.reg, "");
 
 
          inst.instruction |= reg << shift;
          inst.instruction |= reg << shift;
        }
        }
    }
    }
  else
  else
    {
    {
      *str = start;
      *str = start;
      sprintf (buff, _("register expected, not '%.100s'"), start);
      sprintf (buff, _("register expected, not '%.100s'"), start);
      inst.error = buff;
      inst.error = buff;
    }
    }
 
 
  return reg;
  return reg;
}
}
 
 
static int
static int
skip_past_comma (char **str)
skip_past_comma (char **str)
{
{
  char *p = *str;
  char *p = *str;
  char c;
  char c;
  int comma = 0;
  int comma = 0;
 
 
  while ((c = *p) == ' ' || c == ',')
  while ((c = *p) == ' ' || c == ',')
    {
    {
      p++;
      p++;
      if (c == ',' && comma++)
      if (c == ',' && comma++)
        {
        {
          inst.error = BAD_SKIP_COMMA;
          inst.error = BAD_SKIP_COMMA;
          return (int) FAIL;
          return (int) FAIL;
        }
        }
    }
    }
 
 
  if ((c == '\0') || (comma == 0))
  if ((c == '\0') || (comma == 0))
    {
    {
      inst.error = BAD_SKIP_COMMA;
      inst.error = BAD_SKIP_COMMA;
      return (int) FAIL;
      return (int) FAIL;
    }
    }
 
 
  *str = p;
  *str = p;
  return comma ? SUCCESS : (int) FAIL;
  return comma ? SUCCESS : (int) FAIL;
}
}
 
 
static void
static void
do_rdrsrs (char *str)
do_rdrsrs (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
      || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
      || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
      || end_of_line (str) == (int) FAIL)
      || end_of_line (str) == (int) FAIL)
    {
    {
      return;
      return;
    }
    }
  else
  else
    {
    {
      if ((((inst.instruction >> 15) & 0x10) == 0)
      if ((((inst.instruction >> 15) & 0x10) == 0)
          && (((inst.instruction >> 10) & 0x10) == 0)
          && (((inst.instruction >> 10) & 0x10) == 0)
          && (((inst.instruction >> 20) & 0x10) == 0)
          && (((inst.instruction >> 20) & 0x10) == 0)
          && (inst.relax_inst != 0x8000)
          && (inst.relax_inst != 0x8000)
          && (((inst.instruction >> 20) & 0xf) == ((inst.instruction >> 15) & 0xf)))
          && (((inst.instruction >> 20) & 0xf) == ((inst.instruction >> 15) & 0xf)))
        {
        {
          inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4)
          inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4)
            | (((inst.instruction >> 15) & 0xf) << 8);
            | (((inst.instruction >> 15) & 0xf) << 8);
          inst.relax_size = 2;
          inst.relax_size = 2;
        }
        }
      else
      else
        {
        {
          inst.relax_inst = 0x8000;
          inst.relax_inst = 0x8000;
        }
        }
    }
    }
}
}
 
 
static int
static int
walk_no_bignums (symbolS * sp)
walk_no_bignums (symbolS * sp)
{
{
  if (symbol_get_value_expression (sp)->X_op == O_big)
  if (symbol_get_value_expression (sp)->X_op == O_big)
    return 1;
    return 1;
 
 
  if (symbol_get_value_expression (sp)->X_add_symbol)
  if (symbol_get_value_expression (sp)->X_add_symbol)
    return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
    return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
            || (symbol_get_value_expression (sp)->X_op_symbol
            || (symbol_get_value_expression (sp)->X_op_symbol
                && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
                && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
 
 
  return 0;
  return 0;
}
}
 
 
static int
static int
my_get_expression (expressionS * ep, char **str)
my_get_expression (expressionS * ep, char **str)
{
{
  char *save_in;
  char *save_in;
  segT seg;
  segT seg;
 
 
  save_in = input_line_pointer;
  save_in = input_line_pointer;
  input_line_pointer = *str;
  input_line_pointer = *str;
  in_my_get_expression = 1;
  in_my_get_expression = 1;
  seg = expression (ep);
  seg = expression (ep);
  in_my_get_expression = 0;
  in_my_get_expression = 0;
 
 
  if (ep->X_op == O_illegal)
  if (ep->X_op == O_illegal)
    {
    {
      *str = input_line_pointer;
      *str = input_line_pointer;
      input_line_pointer = save_in;
      input_line_pointer = save_in;
      inst.error = _("illegal expression");
      inst.error = _("illegal expression");
      return (int) FAIL;
      return (int) FAIL;
    }
    }
  /* Get rid of any bignums now, so that we don't generate an error for which
  /* Get rid of any bignums now, so that we don't generate an error for which
     we can't establish a line number later on.  Big numbers are never valid
     we can't establish a line number later on.  Big numbers are never valid
     in instructions, which is where this routine is always called.  */
     in instructions, which is where this routine is always called.  */
  if (ep->X_op == O_big
  if (ep->X_op == O_big
      || (ep->X_add_symbol
      || (ep->X_add_symbol
          && (walk_no_bignums (ep->X_add_symbol)
          && (walk_no_bignums (ep->X_add_symbol)
              || (ep->X_op_symbol && walk_no_bignums (ep->X_op_symbol)))))
              || (ep->X_op_symbol && walk_no_bignums (ep->X_op_symbol)))))
    {
    {
      inst.error = _("invalid constant");
      inst.error = _("invalid constant");
      *str = input_line_pointer;
      *str = input_line_pointer;
      input_line_pointer = save_in;
      input_line_pointer = save_in;
      return (int) FAIL;
      return (int) FAIL;
    }
    }
 
 
  if ((ep->X_add_symbol != NULL)
  if ((ep->X_add_symbol != NULL)
      && (inst.type != PC_DISP19div2)
      && (inst.type != PC_DISP19div2)
      && (inst.type != PC_DISP8div2)
      && (inst.type != PC_DISP8div2)
      && (inst.type != PC_DISP24div2)
      && (inst.type != PC_DISP24div2)
      && (inst.type != PC_DISP11div2)
      && (inst.type != PC_DISP11div2)
      && (inst.type != Insn_Type_SYN)
      && (inst.type != Insn_Type_SYN)
      && (inst.type != Rd_rvalueRs_SI15)
      && (inst.type != Rd_rvalueRs_SI15)
      && (inst.type != Rd_lvalueRs_SI15)
      && (inst.type != Rd_lvalueRs_SI15)
      && (inst.type != Insn_internal))
      && (inst.type != Insn_internal))
    {
    {
      inst.error = BAD_ARGS;
      inst.error = BAD_ARGS;
      *str = input_line_pointer;
      *str = input_line_pointer;
      input_line_pointer = save_in;
      input_line_pointer = save_in;
      return (int) FAIL;
      return (int) FAIL;
    }
    }
 
 
  *str = input_line_pointer;
  *str = input_line_pointer;
  input_line_pointer = save_in;
  input_line_pointer = save_in;
  return SUCCESS;
  return SUCCESS;
}
}
 
 
/* Check if an immediate is valid.  If so, convert it to the right format.  */
/* Check if an immediate is valid.  If so, convert it to the right format.  */
 
 
static int
static int
validate_immediate (int val, unsigned int data_type, int hex_p)
validate_immediate (int val, unsigned int data_type, int hex_p)
{
{
  switch (data_type)
  switch (data_type)
    {
    {
    case _VALUE_HI16:
    case _VALUE_HI16:
      {
      {
        int val_hi = ((val & 0xffff0000) >> 16);
        int val_hi = ((val & 0xffff0000) >> 16);
 
 
        if (score_df_range[data_type].range[0] <= val_hi
        if (score_df_range[data_type].range[0] <= val_hi
            && val_hi <= score_df_range[data_type].range[1])
            && val_hi <= score_df_range[data_type].range[1])
          return val_hi;
          return val_hi;
      }
      }
      break;
      break;
 
 
    case _VALUE_LO16:
    case _VALUE_LO16:
      {
      {
        int val_lo = (val & 0xffff);
        int val_lo = (val & 0xffff);
 
 
        if (score_df_range[data_type].range[0] <= val_lo
        if (score_df_range[data_type].range[0] <= val_lo
            && val_lo <= score_df_range[data_type].range[1])
            && val_lo <= score_df_range[data_type].range[1])
          return val_lo;
          return val_lo;
      }
      }
      break;
      break;
 
 
    case _VALUE:
    case _VALUE:
      return val;
      return val;
      break;
      break;
 
 
    case _SIMM14:
    case _SIMM14:
      if (hex_p == 1)
      if (hex_p == 1)
        {
        {
          if (!(val >= -0x2000 && val <= 0x3fff))
          if (!(val >= -0x2000 && val <= 0x3fff))
            {
            {
              return (int) FAIL;
              return (int) FAIL;
            }
            }
        }
        }
      else
      else
        {
        {
          if (!(val >= -8192 && val <= 8191))
          if (!(val >= -8192 && val <= 8191))
            {
            {
              return (int) FAIL;
              return (int) FAIL;
            }
            }
        }
        }
 
 
      return val;
      return val;
      break;
      break;
 
 
    case _SIMM16_NEG:
    case _SIMM16_NEG:
      if (hex_p == 1)
      if (hex_p == 1)
        {
        {
          if (!(val >= -0x7fff && val <= 0xffff && val != 0x8000))
          if (!(val >= -0x7fff && val <= 0xffff && val != 0x8000))
            {
            {
              return (int) FAIL;
              return (int) FAIL;
            }
            }
        }
        }
      else
      else
        {
        {
          if (!(val >= -32767 && val <= 32768))
          if (!(val >= -32767 && val <= 32768))
            {
            {
              return (int) FAIL;
              return (int) FAIL;
            }
            }
        }
        }
 
 
      val = -val;
      val = -val;
      return val;
      return val;
      break;
      break;
 
 
    default:
    default:
      if (data_type == _SIMM14_NEG || data_type == _IMM16_NEG)
      if (data_type == _SIMM14_NEG || data_type == _IMM16_NEG)
        val = -val;
        val = -val;
 
 
      if (score_df_range[data_type].range[0] <= val
      if (score_df_range[data_type].range[0] <= val
          && val <= score_df_range[data_type].range[1])
          && val <= score_df_range[data_type].range[1])
        return val;
        return val;
 
 
      break;
      break;
    }
    }
 
 
  return (int) FAIL;
  return (int) FAIL;
}
}
 
 
static int
static int
data_op2 (char **str, int shift, enum score_data_type data_type)
data_op2 (char **str, int shift, enum score_data_type data_type)
{
{
  int value;
  int value;
  char data_exp[MAX_LITERAL_POOL_SIZE];
  char data_exp[MAX_LITERAL_POOL_SIZE];
  char *dataptr;
  char *dataptr;
  int cnt = 0;
  int cnt = 0;
  char *pp = NULL;
  char *pp = NULL;
 
 
  skip_whitespace (*str);
  skip_whitespace (*str);
  inst.error = NULL;
  inst.error = NULL;
  dataptr = * str;
  dataptr = * str;
 
 
  /* Set hex_p to zero.  */
  /* Set hex_p to zero.  */
  int hex_p = 0;
  int hex_p = 0;
 
 
  while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= MAX_LITERAL_POOL_SIZE))     /* 0x7c = ='|' */
  while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= MAX_LITERAL_POOL_SIZE))     /* 0x7c = ='|' */
    {
    {
      data_exp[cnt] = *dataptr;
      data_exp[cnt] = *dataptr;
      dataptr++;
      dataptr++;
      cnt++;
      cnt++;
    }
    }
 
 
  data_exp[cnt] = '\0';
  data_exp[cnt] = '\0';
  pp = (char *)&data_exp;
  pp = (char *)&data_exp;
 
 
  if (*dataptr == '|')          /* process PCE */
  if (*dataptr == '|')          /* process PCE */
    {
    {
      if (my_get_expression (&inst.reloc.exp, &pp) == (int) FAIL)
      if (my_get_expression (&inst.reloc.exp, &pp) == (int) FAIL)
        return (int) FAIL;
        return (int) FAIL;
      end_of_line (pp);
      end_of_line (pp);
      if (inst.error != 0)
      if (inst.error != 0)
        return (int) FAIL;       /* to ouptut_inst to printf out the error */
        return (int) FAIL;       /* to ouptut_inst to printf out the error */
      *str = dataptr;
      *str = dataptr;
    }
    }
  else                          /* process  16 bit */
  else                          /* process  16 bit */
    {
    {
      if (my_get_expression (&inst.reloc.exp, str) == (int) FAIL)
      if (my_get_expression (&inst.reloc.exp, str) == (int) FAIL)
        {
        {
          return (int) FAIL;
          return (int) FAIL;
        }
        }
 
 
      dataptr = (char *)data_exp;
      dataptr = (char *)data_exp;
      for (; *dataptr != '\0'; dataptr++)
      for (; *dataptr != '\0'; dataptr++)
        {
        {
          *dataptr = TOLOWER (*dataptr);
          *dataptr = TOLOWER (*dataptr);
          if (*dataptr == '!' || *dataptr == ' ')
          if (*dataptr == '!' || *dataptr == ' ')
            break;
            break;
        }
        }
      dataptr = (char *)data_exp;
      dataptr = (char *)data_exp;
 
 
      if ((dataptr != NULL)
      if ((dataptr != NULL)
          && (((strstr (dataptr, "0x")) != NULL)
          && (((strstr (dataptr, "0x")) != NULL)
              || ((strstr (dataptr, "0X")) != NULL)))
              || ((strstr (dataptr, "0X")) != NULL)))
        {
        {
          hex_p = 1;
          hex_p = 1;
          if ((data_type != _SIMM16_LA)
          if ((data_type != _SIMM16_LA)
              && (data_type != _VALUE_HI16)
              && (data_type != _VALUE_HI16)
              && (data_type != _VALUE_LO16)
              && (data_type != _VALUE_LO16)
              && (data_type != _IMM16)
              && (data_type != _IMM16)
              && (data_type != _IMM15)
              && (data_type != _IMM15)
              && (data_type != _IMM14)
              && (data_type != _IMM14)
              && (data_type != _IMM4)
              && (data_type != _IMM4)
              && (data_type != _IMM5)
              && (data_type != _IMM5)
              && (data_type != _IMM8)
              && (data_type != _IMM8)
              && (data_type != _IMM5_RSHIFT_1)
              && (data_type != _IMM5_RSHIFT_1)
              && (data_type != _IMM5_RSHIFT_2)
              && (data_type != _IMM5_RSHIFT_2)
              && (data_type != _SIMM14)
              && (data_type != _SIMM14)
              && (data_type != _SIMM14_NEG)
              && (data_type != _SIMM14_NEG)
              && (data_type != _SIMM16_NEG)
              && (data_type != _SIMM16_NEG)
              && (data_type != _IMM10_RSHIFT_2)
              && (data_type != _IMM10_RSHIFT_2)
              && (data_type != _GP_IMM15))
              && (data_type != _GP_IMM15))
            {
            {
              data_type += 24;
              data_type += 24;
            }
            }
        }
        }
 
 
      if ((inst.reloc.exp.X_add_number == 0)
      if ((inst.reloc.exp.X_add_number == 0)
          && (inst.type != Insn_Type_SYN)
          && (inst.type != Insn_Type_SYN)
          && (inst.type != Rd_rvalueRs_SI15)
          && (inst.type != Rd_rvalueRs_SI15)
          && (inst.type != Rd_lvalueRs_SI15)
          && (inst.type != Rd_lvalueRs_SI15)
          && (inst.type != Insn_internal)
          && (inst.type != Insn_internal)
          && (((*dataptr >= 'a') && (*dataptr <= 'z'))
          && (((*dataptr >= 'a') && (*dataptr <= 'z'))
             || ((*dataptr == '0') && (*(dataptr + 1) == 'x') && (*(dataptr + 2) != '0'))
             || ((*dataptr == '0') && (*(dataptr + 1) == 'x') && (*(dataptr + 2) != '0'))
             || ((*dataptr == '+') && (*(dataptr + 1) != '0'))
             || ((*dataptr == '+') && (*(dataptr + 1) != '0'))
             || ((*dataptr == '-') && (*(dataptr + 1) != '0'))))
             || ((*dataptr == '-') && (*(dataptr + 1) != '0'))))
        {
        {
          inst.error = BAD_ARGS;
          inst.error = BAD_ARGS;
          return (int) FAIL;
          return (int) FAIL;
        }
        }
    }
    }
 
 
  if ((inst.reloc.exp.X_add_symbol)
  if ((inst.reloc.exp.X_add_symbol)
      && ((data_type == _SIMM16)
      && ((data_type == _SIMM16)
          || (data_type == _SIMM16_NEG)
          || (data_type == _SIMM16_NEG)
          || (data_type == _IMM16_NEG)
          || (data_type == _IMM16_NEG)
          || (data_type == _SIMM14)
          || (data_type == _SIMM14)
          || (data_type == _SIMM14_NEG)
          || (data_type == _SIMM14_NEG)
          || (data_type == _IMM5)
          || (data_type == _IMM5)
          || (data_type == _IMM14)
          || (data_type == _IMM14)
          || (data_type == _IMM20)
          || (data_type == _IMM20)
          || (data_type == _IMM16)
          || (data_type == _IMM16)
          || (data_type == _IMM15)
          || (data_type == _IMM15)
          || (data_type == _IMM4)))
          || (data_type == _IMM4)))
    {
    {
      inst.error = BAD_ARGS;
      inst.error = BAD_ARGS;
      return (int) FAIL;
      return (int) FAIL;
    }
    }
 
 
  if (inst.reloc.exp.X_add_symbol)
  if (inst.reloc.exp.X_add_symbol)
    {
    {
      switch (data_type)
      switch (data_type)
        {
        {
        case _SIMM16_LA:
        case _SIMM16_LA:
          return (int) FAIL;
          return (int) FAIL;
        case _VALUE_HI16:
        case _VALUE_HI16:
          inst.reloc.type = BFD_RELOC_HI16_S;
          inst.reloc.type = BFD_RELOC_HI16_S;
          inst.reloc.pc_rel = 0;
          inst.reloc.pc_rel = 0;
          break;
          break;
        case _VALUE_LO16:
        case _VALUE_LO16:
          inst.reloc.type = BFD_RELOC_LO16;
          inst.reloc.type = BFD_RELOC_LO16;
          inst.reloc.pc_rel = 0;
          inst.reloc.pc_rel = 0;
          break;
          break;
        case _GP_IMM15:
        case _GP_IMM15:
          inst.reloc.type = BFD_RELOC_SCORE_GPREL15;
          inst.reloc.type = BFD_RELOC_SCORE_GPREL15;
          inst.reloc.pc_rel = 0;
          inst.reloc.pc_rel = 0;
          break;
          break;
        case _SIMM16_pic:
        case _SIMM16_pic:
        case _IMM16_LO16_pic:
        case _IMM16_LO16_pic:
          inst.reloc.type = BFD_RELOC_SCORE_GOT_LO16;
          inst.reloc.type = BFD_RELOC_SCORE_GOT_LO16;
          inst.reloc.pc_rel = 0;
          inst.reloc.pc_rel = 0;
          break;
          break;
        default:
        default:
          inst.reloc.type = BFD_RELOC_32;
          inst.reloc.type = BFD_RELOC_32;
          inst.reloc.pc_rel = 0;
          inst.reloc.pc_rel = 0;
          break;
          break;
        }
        }
    }
    }
  else
  else
    {
    {
      if (data_type == _IMM16_pic)
      if (data_type == _IMM16_pic)
        {
        {
          inst.reloc.type = BFD_RELOC_SCORE_DUMMY_HI16;
          inst.reloc.type = BFD_RELOC_SCORE_DUMMY_HI16;
          inst.reloc.pc_rel = 0;
          inst.reloc.pc_rel = 0;
        }
        }
 
 
      if (data_type == _SIMM16_LA && inst.reloc.exp.X_unsigned == 1)
      if (data_type == _SIMM16_LA && inst.reloc.exp.X_unsigned == 1)
        {
        {
          value = validate_immediate (inst.reloc.exp.X_add_number, _SIMM16_LA_POS, hex_p);
          value = validate_immediate (inst.reloc.exp.X_add_number, _SIMM16_LA_POS, hex_p);
          if (value == (int) FAIL)       /* for advance to check if this is ldis */
          if (value == (int) FAIL)       /* for advance to check if this is ldis */
            if ((inst.reloc.exp.X_add_number & 0xffff) == 0)
            if ((inst.reloc.exp.X_add_number & 0xffff) == 0)
              {
              {
                inst.instruction |= 0x8000000;
                inst.instruction |= 0x8000000;
                inst.instruction |= ((inst.reloc.exp.X_add_number >> 16) << 1) & 0x1fffe;
                inst.instruction |= ((inst.reloc.exp.X_add_number >> 16) << 1) & 0x1fffe;
                return SUCCESS;
                return SUCCESS;
              }
              }
        }
        }
      else
      else
        {
        {
          value = validate_immediate (inst.reloc.exp.X_add_number, data_type, hex_p);
          value = validate_immediate (inst.reloc.exp.X_add_number, data_type, hex_p);
        }
        }
 
 
      if (value == (int) FAIL)
      if (value == (int) FAIL)
        {
        {
          if ((data_type != _SIMM14_NEG) && (data_type != _SIMM16_NEG) && (data_type != _IMM16_NEG))
          if ((data_type != _SIMM14_NEG) && (data_type != _SIMM16_NEG) && (data_type != _IMM16_NEG))
            {
            {
              sprintf (err_msg,
              sprintf (err_msg,
                       _("invalid constant: %d bit expression not in range %d..%d"),
                       _("invalid constant: %d bit expression not in range %d..%d"),
                       score_df_range[data_type].bits,
                       score_df_range[data_type].bits,
                       score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
                       score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
            }
            }
          else
          else
            {
            {
              sprintf (err_msg,
              sprintf (err_msg,
                       _("invalid constant: %d bit expression not in range %d..%d"),
                       _("invalid constant: %d bit expression not in range %d..%d"),
                       score_df_range[data_type].bits,
                       score_df_range[data_type].bits,
                       -score_df_range[data_type].range[1], -score_df_range[data_type].range[0]);
                       -score_df_range[data_type].range[1], -score_df_range[data_type].range[0]);
            }
            }
 
 
          inst.error = err_msg;
          inst.error = err_msg;
          return (int) FAIL;
          return (int) FAIL;
        }
        }
 
 
      if ((score_df_range[data_type].range[0] != 0) || (data_type == _IMM5_RANGE_8_31))
      if ((score_df_range[data_type].range[0] != 0) || (data_type == _IMM5_RANGE_8_31))
        {
        {
          value &= (1 << score_df_range[data_type].bits) - 1;
          value &= (1 << score_df_range[data_type].bits) - 1;
        }
        }
 
 
      inst.instruction |= value << shift;
      inst.instruction |= value << shift;
    }
    }
 
 
  if ((inst.instruction & 0xf0000000) == 0x30000000)
  if ((inst.instruction & 0xf0000000) == 0x30000000)
    {
    {
      if ((((inst.instruction >> 20) & 0x1F) != 0)
      if ((((inst.instruction >> 20) & 0x1F) != 0)
          && (((inst.instruction >> 20) & 0x1F) != 1)
          && (((inst.instruction >> 20) & 0x1F) != 1)
          && (((inst.instruction >> 20) & 0x1F) != 2)
          && (((inst.instruction >> 20) & 0x1F) != 2)
          && (((inst.instruction >> 20) & 0x1F) != 3)
          && (((inst.instruction >> 20) & 0x1F) != 3)
          && (((inst.instruction >> 20) & 0x1F) != 4)
          && (((inst.instruction >> 20) & 0x1F) != 4)
          && (((inst.instruction >> 20) & 0x1F) != 8)
          && (((inst.instruction >> 20) & 0x1F) != 8)
          && (((inst.instruction >> 20) & 0x1F) != 9)
          && (((inst.instruction >> 20) & 0x1F) != 9)
          && (((inst.instruction >> 20) & 0x1F) != 0xa)
          && (((inst.instruction >> 20) & 0x1F) != 0xa)
          && (((inst.instruction >> 20) & 0x1F) != 0xb)
          && (((inst.instruction >> 20) & 0x1F) != 0xb)
          && (((inst.instruction >> 20) & 0x1F) != 0xc)
          && (((inst.instruction >> 20) & 0x1F) != 0xc)
          && (((inst.instruction >> 20) & 0x1F) != 0xd)
          && (((inst.instruction >> 20) & 0x1F) != 0xd)
          && (((inst.instruction >> 20) & 0x1F) != 0xe)
          && (((inst.instruction >> 20) & 0x1F) != 0xe)
          && (((inst.instruction >> 20) & 0x1F) != 0x10)
          && (((inst.instruction >> 20) & 0x1F) != 0x10)
          && (((inst.instruction >> 20) & 0x1F) != 0x11)
          && (((inst.instruction >> 20) & 0x1F) != 0x11)
          && (((inst.instruction >> 20) & 0x1F) != 0x18)
          && (((inst.instruction >> 20) & 0x1F) != 0x18)
          && (((inst.instruction >> 20) & 0x1F) != 0x1A)
          && (((inst.instruction >> 20) & 0x1F) != 0x1A)
          && (((inst.instruction >> 20) & 0x1F) != 0x1B)
          && (((inst.instruction >> 20) & 0x1F) != 0x1B)
          && (((inst.instruction >> 20) & 0x1F) != 0x1d)
          && (((inst.instruction >> 20) & 0x1F) != 0x1d)
          && (((inst.instruction >> 20) & 0x1F) != 0x1e)
          && (((inst.instruction >> 20) & 0x1F) != 0x1e)
          && (((inst.instruction >> 20) & 0x1F) != 0x1f))
          && (((inst.instruction >> 20) & 0x1F) != 0x1f))
        {
        {
          inst.error = _("invalid constant: bit expression not defined");
          inst.error = _("invalid constant: bit expression not defined");
          return (int) FAIL;
          return (int) FAIL;
        }
        }
    }
    }
 
 
  return SUCCESS;
  return SUCCESS;
}
}
 
 
/* Handle addi/addi.c/addis.c/cmpi.c/addis.c/ldi.  */
/* Handle addi/addi.c/addis.c/cmpi.c/addis.c/ldi.  */
 
 
static void
static void
do_rdsi16 (char *str)
do_rdsi16 (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || data_op2 (&str, 1, _SIMM16) == (int) FAIL
      || data_op2 (&str, 1, _SIMM16) == (int) FAIL
      || end_of_line (str) == (int) FAIL)
      || end_of_line (str) == (int) FAIL)
    return;
    return;
 
 
  /* ldi.  */
  /* ldi.  */
  if ((inst.instruction & 0x20c0000) == 0x20c0000)
  if ((inst.instruction & 0x20c0000) == 0x20c0000)
    {
    {
      if ((((inst.instruction >> 20) & 0x10) == 0x10) || ((inst.instruction & 0x1fe00) != 0))
      if ((((inst.instruction >> 20) & 0x10) == 0x10) || ((inst.instruction & 0x1fe00) != 0))
        {
        {
          inst.relax_inst = 0x8000;
          inst.relax_inst = 0x8000;
        }
        }
      else
      else
        {
        {
          inst.relax_inst |= (inst.instruction >> 1) & 0xff;
          inst.relax_inst |= (inst.instruction >> 1) & 0xff;
          inst.relax_inst |= (((inst.instruction >> 20) & 0xf) << 8);
          inst.relax_inst |= (((inst.instruction >> 20) & 0xf) << 8);
          inst.relax_size = 2;
          inst.relax_size = 2;
        }
        }
    }
    }
  else if (((inst.instruction >> 20) & 0x10) == 0x10)
  else if (((inst.instruction >> 20) & 0x10) == 0x10)
    {
    {
      inst.relax_inst = 0x8000;
      inst.relax_inst = 0x8000;
    }
    }
}
}
 
 
/* Handle subi/subi.c.  */
/* Handle subi/subi.c.  */
 
 
static void
static void
do_sub_rdsi16 (char *str)
do_sub_rdsi16 (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && data_op2 (&str, 1, _SIMM16_NEG) != (int) FAIL)
      && data_op2 (&str, 1, _SIMM16_NEG) != (int) FAIL)
    end_of_line (str);
    end_of_line (str);
}
}
 
 
/* Handle addri/addri.c.  */
/* Handle addri/addri.c.  */
 
 
static void
static void
do_rdrssi14 (char *str)         /* -(2^13)~((2^13)-1) */
do_rdrssi14 (char *str)         /* -(2^13)~((2^13)-1) */
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
      && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL)
      && skip_past_comma (&str) != (int) FAIL)
    data_op2 (&str, 1, _SIMM14);
    data_op2 (&str, 1, _SIMM14);
}
}
 
 
/* Handle subri.c/subri.  */
/* Handle subri.c/subri.  */
static void
static void
do_sub_rdrssi14 (char *str)     /* -(2^13)~((2^13)-1) */
do_sub_rdrssi14 (char *str)     /* -(2^13)~((2^13)-1) */
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
      && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && data_op2 (&str, 1, _SIMM14_NEG) != (int) FAIL)
      && data_op2 (&str, 1, _SIMM14_NEG) != (int) FAIL)
    end_of_line (str);
    end_of_line (str);
}
}
 
 
/* Handle bitclr.c/bitset.c/bittgl.c/slli.c/srai.c/srli.c/roli.c/rori.c/rolic.c.  */
/* Handle bitclr.c/bitset.c/bittgl.c/slli.c/srai.c/srli.c/roli.c/rori.c/rolic.c.  */
static void
static void
do_rdrsi5 (char *str)           /* 0~((2^14)-1) */
do_rdrsi5 (char *str)           /* 0~((2^14)-1) */
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
      || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || data_op2 (&str, 10, _IMM5) == (int) FAIL
      || data_op2 (&str, 10, _IMM5) == (int) FAIL
      || end_of_line (str) == (int) FAIL)
      || end_of_line (str) == (int) FAIL)
    return;
    return;
 
 
  if ((((inst.instruction >> 20) & 0x1f) == ((inst.instruction >> 15) & 0x1f))
  if ((((inst.instruction >> 20) & 0x1f) == ((inst.instruction >> 15) & 0x1f))
      && (inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
      && (inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
    {
    {
      inst.relax_inst |= (((inst.instruction >> 10) & 0x1f) << 3) | (((inst.instruction >> 15) & 0xf) << 8);
      inst.relax_inst |= (((inst.instruction >> 10) & 0x1f) << 3) | (((inst.instruction >> 15) & 0xf) << 8);
      inst.relax_size = 2;
      inst.relax_size = 2;
    }
    }
  else
  else
    inst.relax_inst = 0x8000;
    inst.relax_inst = 0x8000;
}
}
 
 
/* Handle andri/orri/andri.c/orri.c.  */
/* Handle andri/orri/andri.c/orri.c.  */
 
 
static void
static void
do_rdrsi14 (char *str)          /* 0 ~ ((2^14)-1)  */
do_rdrsi14 (char *str)          /* 0 ~ ((2^14)-1)  */
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
      && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && data_op2 (&str, 1, _IMM14) != (int) FAIL)
      && data_op2 (&str, 1, _IMM14) != (int) FAIL)
    end_of_line (str);
    end_of_line (str);
}
}
 
 
/* Handle bittst.c.  */
/* Handle bittst.c.  */
static void
static void
do_xrsi5 (char *str)
do_xrsi5 (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
  if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || data_op2 (&str, 10, _IMM5) == (int) FAIL
      || data_op2 (&str, 10, _IMM5) == (int) FAIL
      || end_of_line (str) == (int) FAIL)
      || end_of_line (str) == (int) FAIL)
    return;
    return;
 
 
  if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
  if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
    {
    {
      inst.relax_inst |= (((inst.instruction >> 10) & 0x1f) << 3) | (((inst.instruction >> 15) & 0xf) << 8);
      inst.relax_inst |= (((inst.instruction >> 10) & 0x1f) << 3) | (((inst.instruction >> 15) & 0xf) << 8);
      inst.relax_size = 2;
      inst.relax_size = 2;
    }
    }
  else
  else
    inst.relax_inst = 0x8000;
    inst.relax_inst = 0x8000;
}
}
 
 
/* Handle addis/andi/ori/andis/oris/ldis.  */
/* Handle addis/andi/ori/andis/oris/ldis.  */
static void
static void
do_rdi16 (char *str)
do_rdi16 (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || data_op2 (&str, 1, _IMM16) == (int) FAIL
      || data_op2 (&str, 1, _IMM16) == (int) FAIL
      || end_of_line (str) == (int) FAIL)
      || end_of_line (str) == (int) FAIL)
    return;
    return;
  /*
  /*
  if (((inst.instruction & 0xa0dfffe) != 0xa0c0000) || ((((inst.instruction >> 20) & 0x1f) & 0x10) == 0x10))
  if (((inst.instruction & 0xa0dfffe) != 0xa0c0000) || ((((inst.instruction >> 20) & 0x1f) & 0x10) == 0x10))
    inst.relax_inst = 0x8000;
    inst.relax_inst = 0x8000;
  else
  else
    inst.relax_size = 2;
    inst.relax_size = 2;
  */
  */
}
}
 
 
static void
static void
do_macro_rdi32hi (char *str)
do_macro_rdi32hi (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  /* Do not handle end_of_line().  */
  /* Do not handle end_of_line().  */
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL)
      && skip_past_comma (&str) != (int) FAIL)
    data_op2 (&str, 1, _VALUE_HI16);
    data_op2 (&str, 1, _VALUE_HI16);
}
}
 
 
static void
static void
do_macro_rdi32lo (char *str)
do_macro_rdi32lo (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  /* Do not handle end_of_line().  */
  /* Do not handle end_of_line().  */
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL)
      && skip_past_comma (&str) != (int) FAIL)
    data_op2 (&str, 1, _VALUE_LO16);
    data_op2 (&str, 1, _VALUE_LO16);
}
}
 
 
/* Handle ldis_pic.  */
/* Handle ldis_pic.  */
 
 
static void
static void
do_rdi16_pic (char *str)
do_rdi16_pic (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && data_op2 (&str, 1, _IMM16_pic) != (int) FAIL)
      && data_op2 (&str, 1, _IMM16_pic) != (int) FAIL)
    end_of_line (str);
    end_of_line (str);
}
}
 
 
/* Handle addi_s_pic to generate R_SCORE_GOT_LO16 .  */
/* Handle addi_s_pic to generate R_SCORE_GOT_LO16 .  */
 
 
static void
static void
do_addi_s_pic (char *str)
do_addi_s_pic (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && data_op2 (&str, 1, _SIMM16_pic) != (int) FAIL)
      && data_op2 (&str, 1, _SIMM16_pic) != (int) FAIL)
    end_of_line (str);
    end_of_line (str);
}
}
 
 
/* Handle addi_u_pic to generate R_SCORE_GOT_LO16 .  */
/* Handle addi_u_pic to generate R_SCORE_GOT_LO16 .  */
 
 
static void
static void
do_addi_u_pic (char *str)
do_addi_u_pic (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && data_op2 (&str, 1, _IMM16_LO16_pic) != (int) FAIL)
      && data_op2 (&str, 1, _IMM16_LO16_pic) != (int) FAIL)
    end_of_line (str);
    end_of_line (str);
}
}
 
 
/* Handle mfceh/mfcel/mtceh/mtchl.  */
/* Handle mfceh/mfcel/mtceh/mtchl.  */
 
 
static void
static void
do_rd (char *str)
do_rd (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL)
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL)
    end_of_line (str);
    end_of_line (str);
}
}
 
 
static void
static void
do_rs (char *str)
do_rs (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
  if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
      || end_of_line (str) == (int) FAIL)
      || end_of_line (str) == (int) FAIL)
    return;
    return;
 
 
  if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
  if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
    {
    {
      inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 8) | (((inst.instruction >> 15) & 0xf) << 4);
      inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 8) | (((inst.instruction >> 15) & 0xf) << 4);
      inst.relax_size = 2;
      inst.relax_size = 2;
    }
    }
  else
  else
    inst.relax_inst = 0x8000;
    inst.relax_inst = 0x8000;
}
}
 
 
static void
static void
do_i15 (char *str)
do_i15 (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (data_op2 (&str, 10, _IMM15) != (int) FAIL)
  if (data_op2 (&str, 10, _IMM15) != (int) FAIL)
    end_of_line (str);
    end_of_line (str);
}
}
 
 
static void
static void
do_xi5x (char *str)
do_xi5x (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (data_op2 (&str, 15, _IMM5) == (int) FAIL || end_of_line (str) == (int) FAIL)
  if (data_op2 (&str, 15, _IMM5) == (int) FAIL || end_of_line (str) == (int) FAIL)
    return;
    return;
 
 
  if (inst.relax_inst != 0x8000)
  if (inst.relax_inst != 0x8000)
    {
    {
      inst.relax_inst |= (((inst.instruction >> 15) & 0x1f) << 3);
      inst.relax_inst |= (((inst.instruction >> 15) & 0x1f) << 3);
      inst.relax_size = 2;
      inst.relax_size = 2;
    }
    }
}
}
 
 
static void
static void
do_rdrs (char *str)
do_rdrs (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
      || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
      || end_of_line (str) == (int) FAIL)
      || end_of_line (str) == (int) FAIL)
    return;
    return;
 
 
  if (inst.relax_inst != 0x8000)
  if (inst.relax_inst != 0x8000)
    {
    {
      if (((inst.instruction & 0x7f) == 0x56))  /* adjust mv -> mv! / mlfh! / mhfl! */
      if (((inst.instruction & 0x7f) == 0x56))  /* adjust mv -> mv! / mlfh! / mhfl! */
        {
        {
          /* mlfh */
          /* mlfh */
          if ((((inst.instruction >> 15) & 0x10) != 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
          if ((((inst.instruction >> 15) & 0x10) != 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
            {
            {
              inst.relax_inst = 0x00000001 | (((inst.instruction >> 15) & 0xf) << 4)
              inst.relax_inst = 0x00000001 | (((inst.instruction >> 15) & 0xf) << 4)
                | (((inst.instruction >> 20) & 0xf) << 8);
                | (((inst.instruction >> 20) & 0xf) << 8);
              inst.relax_size = 2;
              inst.relax_size = 2;
            }
            }
          /* mhfl */
          /* mhfl */
          else if ((((inst.instruction >> 15) & 0x10) == 0x0) && ((inst.instruction >> 20) & 0x10) != 0)
          else if ((((inst.instruction >> 15) & 0x10) == 0x0) && ((inst.instruction >> 20) & 0x10) != 0)
            {
            {
              inst.relax_inst = 0x00000002 | (((inst.instruction >> 15) & 0xf) << 4)
              inst.relax_inst = 0x00000002 | (((inst.instruction >> 15) & 0xf) << 4)
                | (((inst.instruction >> 20) & 0xf) << 8);
                | (((inst.instruction >> 20) & 0xf) << 8);
              inst.relax_size = 2;
              inst.relax_size = 2;
            }
            }
          else if ((((inst.instruction >> 15) & 0x10) == 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
          else if ((((inst.instruction >> 15) & 0x10) == 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
            {
            {
              inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
              inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
                | (((inst.instruction >> 20) & 0xf) << 8);
                | (((inst.instruction >> 20) & 0xf) << 8);
              inst.relax_size = 2;
              inst.relax_size = 2;
            }
            }
          else
          else
            {
            {
              inst.relax_inst = 0x8000;
              inst.relax_inst = 0x8000;
            }
            }
        }
        }
      else if ((((inst.instruction >> 15) & 0x10) == 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
      else if ((((inst.instruction >> 15) & 0x10) == 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
        {
        {
          inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
          inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
            | (((inst.instruction >> 20) & 0xf) << 8);
            | (((inst.instruction >> 20) & 0xf) << 8);
          inst.relax_size = 2;
          inst.relax_size = 2;
        }
        }
      else
      else
        {
        {
          inst.relax_inst = 0x8000;
          inst.relax_inst = 0x8000;
        }
        }
    }
    }
}
}
 
 
/* Handle mfcr/mtcr.  */
/* Handle mfcr/mtcr.  */
static void
static void
do_rdcrs (char *str)
do_rdcrs (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && reg_required_here (&str, 15, REG_TYPE_SCORE_CR) != (int) FAIL)
      && reg_required_here (&str, 15, REG_TYPE_SCORE_CR) != (int) FAIL)
    end_of_line (str);
    end_of_line (str);
}
}
 
 
/* Handle mfsr/mtsr.  */
/* Handle mfsr/mtsr.  */
 
 
static void
static void
do_rdsrs (char *str)
do_rdsrs (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  /* mfsr */
  /* mfsr */
  if ((inst.instruction & 0xff) == 0x50)
  if ((inst.instruction & 0xff) == 0x50)
    {
    {
      if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
      if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
          && skip_past_comma (&str) != (int) FAIL
          && skip_past_comma (&str) != (int) FAIL
          && reg_required_here (&str, 10, REG_TYPE_SCORE_SR) != (int) FAIL)
          && reg_required_here (&str, 10, REG_TYPE_SCORE_SR) != (int) FAIL)
        end_of_line (str);
        end_of_line (str);
    }
    }
  else
  else
    {
    {
      if (reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
      if (reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
          && skip_past_comma (&str) != (int) FAIL)
          && skip_past_comma (&str) != (int) FAIL)
        reg_required_here (&str, 10, REG_TYPE_SCORE_SR);
        reg_required_here (&str, 10, REG_TYPE_SCORE_SR);
    }
    }
}
}
 
 
/* Handle neg.  */
/* Handle neg.  */
 
 
static void
static void
do_rdxrs (char *str)
do_rdxrs (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
  if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
      || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
      || end_of_line (str) == (int) FAIL)
      || end_of_line (str) == (int) FAIL)
    return;
    return;
 
 
  if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 10) & 0x10) == 0)
  if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 10) & 0x10) == 0)
      && (((inst.instruction >> 20) & 0x10) == 0))
      && (((inst.instruction >> 20) & 0x10) == 0))
    {
    {
      inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) | (((inst.instruction >> 20) & 0xf) << 8);
      inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) | (((inst.instruction >> 20) & 0xf) << 8);
      inst.relax_size = 2;
      inst.relax_size = 2;
    }
    }
  else
  else
    inst.relax_inst = 0x8000;
    inst.relax_inst = 0x8000;
}
}
 
 
/* Handle cmp.c/cmp<cond>.  */
/* Handle cmp.c/cmp<cond>.  */
static void
static void
do_rsrs (char *str)
do_rsrs (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
  if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
      || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
      || end_of_line (str) == (int) FAIL)
      || end_of_line (str) == (int) FAIL)
    return;
    return;
 
 
  if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 20) & 0x1f) == 3)
  if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 20) & 0x1f) == 3)
      && (((inst.instruction >> 10) & 0x10) == 0) && (((inst.instruction >> 15) & 0x10) == 0))
      && (((inst.instruction >> 10) & 0x10) == 0) && (((inst.instruction >> 15) & 0x10) == 0))
    {
    {
      inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) | (((inst.instruction >> 15) & 0xf) << 8);
      inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) | (((inst.instruction >> 15) & 0xf) << 8);
      inst.relax_size = 2;
      inst.relax_size = 2;
    }
    }
  else
  else
    inst.relax_inst = 0x8000;
    inst.relax_inst = 0x8000;
}
}
 
 
static void
static void
do_ceinst (char *str)
do_ceinst (char *str)
{
{
  char *strbak;
  char *strbak;
 
 
  strbak = str;
  strbak = str;
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (data_op2 (&str, 20, _IMM5) == (int) FAIL
  if (data_op2 (&str, 20, _IMM5) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
      || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
      || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || data_op2 (&str, 5, _IMM5) == (int) FAIL
      || data_op2 (&str, 5, _IMM5) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || data_op2 (&str, 0, _IMM5) == (int) FAIL
      || data_op2 (&str, 0, _IMM5) == (int) FAIL
      || end_of_line (str) == (int) FAIL)
      || end_of_line (str) == (int) FAIL)
    {
    {
      return;
      return;
    }
    }
  else
  else
    {
    {
      str = strbak;
      str = strbak;
      if (data_op2 (&str, 0, _IMM25) == (int) FAIL)
      if (data_op2 (&str, 0, _IMM25) == (int) FAIL)
        return;
        return;
    }
    }
}
}
 
 
static int
static int
reglow_required_here (char **str, int shift)
reglow_required_here (char **str, int shift)
{
{
  static char buff[MAX_LITERAL_POOL_SIZE];
  static char buff[MAX_LITERAL_POOL_SIZE];
  int reg;
  int reg;
  char *start = *str;
  char *start = *str;
 
 
  if ((reg = score_reg_parse (str, all_reg_maps[REG_TYPE_SCORE].htab)) != (int) FAIL)
  if ((reg = score_reg_parse (str, all_reg_maps[REG_TYPE_SCORE].htab)) != (int) FAIL)
    {
    {
      if ((reg == 1) && (nor1 == 1) && (inst.bwarn == 0))
      if ((reg == 1) && (nor1 == 1) && (inst.bwarn == 0))
        {
        {
          as_warn (_("Using temp register(r1)"));
          as_warn (_("Using temp register(r1)"));
          inst.bwarn = 1;
          inst.bwarn = 1;
        }
        }
      if (reg < 16)
      if (reg < 16)
        {
        {
          if (shift >= 0)
          if (shift >= 0)
            inst.instruction |= reg << shift;
            inst.instruction |= reg << shift;
 
 
          return reg;
          return reg;
        }
        }
    }
    }
 
 
  /* Restore the start point, we may have got a reg of the wrong class.  */
  /* Restore the start point, we may have got a reg of the wrong class.  */
  *str = start;
  *str = start;
  sprintf (buff, _("low register(r0-r15)expected, not '%.100s'"), start);
  sprintf (buff, _("low register(r0-r15)expected, not '%.100s'"), start);
  inst.error = buff;
  inst.error = buff;
  return (int) FAIL;
  return (int) FAIL;
}
}
 
 
/* Handle addc!/add!/and!/cmp!/neg!/not!/or!/sll!/srl!/sra!/xor!/sub!.  */
/* Handle addc!/add!/and!/cmp!/neg!/not!/or!/sll!/srl!/sra!/xor!/sub!.  */
static void
static void
do16_rdrs (char *str)
do16_rdrs (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reglow_required_here (&str, 8) == (int) FAIL
  if (reglow_required_here (&str, 8) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || reglow_required_here (&str, 4) == (int) FAIL
      || reglow_required_here (&str, 4) == (int) FAIL
      || end_of_line (str) == (int) FAIL)
      || end_of_line (str) == (int) FAIL)
    {
    {
      return;
      return;
    }
    }
  else
  else
    {
    {
      if ((inst.instruction & 0x700f) == 0x2003)        /* cmp!  */
      if ((inst.instruction & 0x700f) == 0x2003)        /* cmp!  */
        {
        {
          inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 15)
          inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 15)
            | (((inst.instruction >> 4) & 0xf) << 10);
            | (((inst.instruction >> 4) & 0xf) << 10);
        }
        }
      else if ((inst.instruction & 0x700f) == 0x2006)   /* not!  */
      else if ((inst.instruction & 0x700f) == 0x2006)   /* not!  */
        {
        {
          inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
          inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
            | (((inst.instruction >> 4) & 0xf) << 15);
            | (((inst.instruction >> 4) & 0xf) << 15);
        }
        }
      else
      else
        {
        {
          inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
          inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
            | (((inst.instruction >> 8) & 0xf) << 15) | (((inst.instruction >> 4) & 0xf) << 10);
            | (((inst.instruction >> 8) & 0xf) << 15) | (((inst.instruction >> 4) & 0xf) << 10);
        }
        }
      inst.relax_size = 4;
      inst.relax_size = 4;
    }
    }
}
}
 
 
static void
static void
do16_rs (char *str)
do16_rs (char *str)
{
{
  int rd = 0;
  int rd = 0;
 
 
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if ((rd = reglow_required_here (&str, 4)) == (int) FAIL
  if ((rd = reglow_required_here (&str, 4)) == (int) FAIL
      || end_of_line (str) == (int) FAIL)
      || end_of_line (str) == (int) FAIL)
    {
    {
      return;
      return;
    }
    }
  else
  else
    {
    {
      inst.relax_inst |= rd << 20;
      inst.relax_inst |= rd << 20;
      inst.relax_size = 4;
      inst.relax_size = 4;
    }
    }
}
}
 
 
/* Handle br!/brl!.  */
/* Handle br!/brl!.  */
static void
static void
do16_xrs (char *str)
do16_xrs (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reglow_required_here (&str, 4) == (int) FAIL || end_of_line (str) == (int) FAIL)
  if (reglow_required_here (&str, 4) == (int) FAIL || end_of_line (str) == (int) FAIL)
    {
    {
      return;
      return;
    }
    }
  else
  else
    {
    {
      inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 10)
      inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 10)
                      | (((inst.instruction >> 4) & 0xf) << 15);
                      | (((inst.instruction >> 4) & 0xf) << 15);
      inst.relax_size = 4;
      inst.relax_size = 4;
    }
    }
}
}
 
 
static int
static int
reghigh_required_here (char **str, int shift)
reghigh_required_here (char **str, int shift)
{
{
  static char buff[MAX_LITERAL_POOL_SIZE];
  static char buff[MAX_LITERAL_POOL_SIZE];
  int reg;
  int reg;
  char *start = *str;
  char *start = *str;
 
 
  if ((reg = score_reg_parse (str, all_reg_maps[REG_TYPE_SCORE].htab)) != (int) FAIL)
  if ((reg = score_reg_parse (str, all_reg_maps[REG_TYPE_SCORE].htab)) != (int) FAIL)
    {
    {
      if (15 < reg && reg < 32)
      if (15 < reg && reg < 32)
        {
        {
          if (shift >= 0)
          if (shift >= 0)
            inst.instruction |= (reg & 0xf) << shift;
            inst.instruction |= (reg & 0xf) << shift;
 
 
          return reg;
          return reg;
        }
        }
    }
    }
 
 
  *str = start;
  *str = start;
  sprintf (buff, _("high register(r16-r31)expected, not '%.100s'"), start);
  sprintf (buff, _("high register(r16-r31)expected, not '%.100s'"), start);
  inst.error = buff;
  inst.error = buff;
  return (int) FAIL;
  return (int) FAIL;
}
}
 
 
/* Handle mhfl!.  */
/* Handle mhfl!.  */
static void
static void
do16_hrdrs (char *str)
do16_hrdrs (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reghigh_required_here (&str, 8) != (int) FAIL
  if (reghigh_required_here (&str, 8) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && reglow_required_here (&str, 4) != (int) FAIL
      && reglow_required_here (&str, 4) != (int) FAIL
      && end_of_line (str) != (int) FAIL)
      && end_of_line (str) != (int) FAIL)
    {
    {
      inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
      inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
        | (((inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
        | (((inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
      inst.relax_size = 4;
      inst.relax_size = 4;
    }
    }
}
}
 
 
/* Handle mlfh!.  */
/* Handle mlfh!.  */
static void
static void
do16_rdhrs (char *str)
do16_rdhrs (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reglow_required_here (&str, 8) != (int) FAIL
  if (reglow_required_here (&str, 8) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && skip_past_comma (&str) != (int) FAIL
      && reghigh_required_here (&str, 4) != (int) FAIL
      && reghigh_required_here (&str, 4) != (int) FAIL
      && end_of_line (str) != (int) FAIL)
      && end_of_line (str) != (int) FAIL)
    {
    {
      inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
      inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
        | ((((inst.instruction >> 4) & 0xf) | 0x10) << 15) | (0xf << 10);
        | ((((inst.instruction >> 4) & 0xf) | 0x10) << 15) | (0xf << 10);
      inst.relax_size = 4;
      inst.relax_size = 4;
    }
    }
}
}
 
 
/* We need to be able to fix up arbitrary expressions in some statements.
/* We need to be able to fix up arbitrary expressions in some statements.
   This is so that we can handle symbols that are an arbitrary distance from
   This is so that we can handle symbols that are an arbitrary distance from
   the pc.  The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
   the pc.  The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
   which returns part of an address in a form which will be valid for
   which returns part of an address in a form which will be valid for
   a data instruction.  We do this by pushing the expression into a symbol
   a data instruction.  We do this by pushing the expression into a symbol
   in the expr_section, and creating a fix for that.  */
   in the expr_section, and creating a fix for that.  */
static fixS *
static fixS *
fix_new_score (fragS * frag, int where, short int size, expressionS * exp, int pc_rel, int reloc)
fix_new_score (fragS * frag, int where, short int size, expressionS * exp, int pc_rel, int reloc)
{
{
  fixS *new_fix;
  fixS *new_fix;
 
 
  switch (exp->X_op)
  switch (exp->X_op)
    {
    {
    case O_constant:
    case O_constant:
    case O_symbol:
    case O_symbol:
    case O_add:
    case O_add:
    case O_subtract:
    case O_subtract:
      new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
      new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
      break;
      break;
    default:
    default:
      new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0, pc_rel, reloc);
      new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0, pc_rel, reloc);
      break;
      break;
    }
    }
  return new_fix;
  return new_fix;
}
}
 
 
static void
static void
init_dependency_vector (void)
init_dependency_vector (void)
{
{
  int i;
  int i;
 
 
  for (i = 0; i < vector_size; i++)
  for (i = 0; i < vector_size; i++)
    memset (&dependency_vector[i], '\0', sizeof (dependency_vector[i]));
    memset (&dependency_vector[i], '\0', sizeof (dependency_vector[i]));
 
 
  return;
  return;
}
}
 
 
static enum insn_type_for_dependency
static enum insn_type_for_dependency
dependency_type_from_insn (char *insn_name)
dependency_type_from_insn (char *insn_name)
{
{
  char name[INSN_NAME_LEN];
  char name[INSN_NAME_LEN];
  const struct insn_to_dependency *tmp;
  const struct insn_to_dependency *tmp;
 
 
  strcpy (name, insn_name);
  strcpy (name, insn_name);
  tmp = (const struct insn_to_dependency *) hash_find (dependency_insn_hsh, name);
  tmp = (const struct insn_to_dependency *) hash_find (dependency_insn_hsh, name);
 
 
  if (tmp)
  if (tmp)
    return tmp->type;
    return tmp->type;
 
 
  return D_all_insn;
  return D_all_insn;
}
}
 
 
static int
static int
check_dependency (char *pre_insn, char *pre_reg,
check_dependency (char *pre_insn, char *pre_reg,
                  char *cur_insn, char *cur_reg, int *warn_or_error)
                  char *cur_insn, char *cur_reg, int *warn_or_error)
{
{
  int bubbles = 0;
  int bubbles = 0;
  unsigned int i;
  unsigned int i;
  enum insn_type_for_dependency pre_insn_type;
  enum insn_type_for_dependency pre_insn_type;
  enum insn_type_for_dependency cur_insn_type;
  enum insn_type_for_dependency cur_insn_type;
 
 
  pre_insn_type = dependency_type_from_insn (pre_insn);
  pre_insn_type = dependency_type_from_insn (pre_insn);
  cur_insn_type = dependency_type_from_insn (cur_insn);
  cur_insn_type = dependency_type_from_insn (cur_insn);
 
 
  for (i = 0; i < sizeof (data_dependency_table) / sizeof (data_dependency_table[0]); i++)
  for (i = 0; i < sizeof (data_dependency_table) / sizeof (data_dependency_table[0]); i++)
    {
    {
      if ((pre_insn_type == data_dependency_table[i].pre_insn_type)
      if ((pre_insn_type == data_dependency_table[i].pre_insn_type)
          && (D_all_insn == data_dependency_table[i].cur_insn_type
          && (D_all_insn == data_dependency_table[i].cur_insn_type
              || cur_insn_type == data_dependency_table[i].cur_insn_type)
              || cur_insn_type == data_dependency_table[i].cur_insn_type)
          && (strcmp (data_dependency_table[i].pre_reg, "") == 0
          && (strcmp (data_dependency_table[i].pre_reg, "") == 0
              || strcmp (data_dependency_table[i].pre_reg, pre_reg) == 0)
              || strcmp (data_dependency_table[i].pre_reg, pre_reg) == 0)
          && (strcmp (data_dependency_table[i].cur_reg, "") == 0
          && (strcmp (data_dependency_table[i].cur_reg, "") == 0
              || strcmp (data_dependency_table[i].cur_reg, cur_reg) == 0))
              || strcmp (data_dependency_table[i].cur_reg, cur_reg) == 0))
        {
        {
          bubbles = (score7) ? data_dependency_table[i].bubblenum_7 : data_dependency_table[i].bubblenum_5;
          bubbles = (score7) ? data_dependency_table[i].bubblenum_7 : data_dependency_table[i].bubblenum_5;
          *warn_or_error = data_dependency_table[i].warn_or_error;
          *warn_or_error = data_dependency_table[i].warn_or_error;
          break;
          break;
        }
        }
    }
    }
 
 
  return bubbles;
  return bubbles;
}
}
 
 
static void
static void
build_one_frag (struct score_it one_inst)
build_one_frag (struct score_it one_inst)
{
{
  char *p;
  char *p;
  int relaxable_p = g_opt;
  int relaxable_p = g_opt;
  int relax_size = 0;
  int relax_size = 0;
 
 
  /* Start a new frag if frag_now is not empty.  */
  /* Start a new frag if frag_now is not empty.  */
  if (frag_now_fix () != 0)
  if (frag_now_fix () != 0)
    {
    {
      if (!frag_now->tc_frag_data.is_insn)
      if (!frag_now->tc_frag_data.is_insn)
        frag_wane (frag_now);
        frag_wane (frag_now);
 
 
      frag_new (0);
      frag_new (0);
    }
    }
  frag_grow (20);
  frag_grow (20);
 
 
  p = frag_more (one_inst.size);
  p = frag_more (one_inst.size);
  md_number_to_chars (p, one_inst.instruction, one_inst.size);
  md_number_to_chars (p, one_inst.instruction, one_inst.size);
 
 
#ifdef OBJ_ELF
#ifdef OBJ_ELF
  dwarf2_emit_insn (one_inst.size);
  dwarf2_emit_insn (one_inst.size);
#endif
#endif
 
 
  relaxable_p &= (one_inst.relax_size != 0);
  relaxable_p &= (one_inst.relax_size != 0);
  relax_size = relaxable_p ? one_inst.relax_size : 0;
  relax_size = relaxable_p ? one_inst.relax_size : 0;
 
 
  p = frag_var (rs_machine_dependent, relax_size + RELAX_PAD_BYTE, 0,
  p = frag_var (rs_machine_dependent, relax_size + RELAX_PAD_BYTE, 0,
                RELAX_ENCODE (one_inst.size, one_inst.relax_size,
                RELAX_ENCODE (one_inst.size, one_inst.relax_size,
                              one_inst.type, 0, 0, relaxable_p),
                              one_inst.type, 0, 0, relaxable_p),
                NULL, 0, NULL);
                NULL, 0, NULL);
 
 
  if (relaxable_p)
  if (relaxable_p)
    md_number_to_chars (p, one_inst.relax_inst, relax_size);
    md_number_to_chars (p, one_inst.relax_inst, relax_size);
}
}
 
 
static void
static void
handle_dependency (struct score_it *theinst)
handle_dependency (struct score_it *theinst)
{
{
  int i;
  int i;
  int warn_or_error = 0;   /* warn - 0; error - 1  */
  int warn_or_error = 0;   /* warn - 0; error - 1  */
  int bubbles = 0;
  int bubbles = 0;
  int remainder_bubbles = 0;
  int remainder_bubbles = 0;
  char cur_insn[INSN_NAME_LEN];
  char cur_insn[INSN_NAME_LEN];
  char pre_insn[INSN_NAME_LEN];
  char pre_insn[INSN_NAME_LEN];
  struct score_it nop_inst;
  struct score_it nop_inst;
  struct score_it pflush_inst;
  struct score_it pflush_inst;
 
 
  nop_inst.instruction = 0x0000;
  nop_inst.instruction = 0x0000;
  nop_inst.size = 2;
  nop_inst.size = 2;
  nop_inst.relax_inst = 0x80008000;
  nop_inst.relax_inst = 0x80008000;
  nop_inst.relax_size = 4;
  nop_inst.relax_size = 4;
  nop_inst.type = NO16_OPD;
  nop_inst.type = NO16_OPD;
 
 
  pflush_inst.instruction = 0x8000800a;
  pflush_inst.instruction = 0x8000800a;
  pflush_inst.size = 4;
  pflush_inst.size = 4;
  pflush_inst.relax_inst = 0x8000;
  pflush_inst.relax_inst = 0x8000;
  pflush_inst.relax_size = 0;
  pflush_inst.relax_size = 0;
  pflush_inst.type = NO_OPD;
  pflush_inst.type = NO_OPD;
 
 
  /* pflush will clear all data dependency.  */
  /* pflush will clear all data dependency.  */
  if (strcmp (theinst->name, "pflush") == 0)
  if (strcmp (theinst->name, "pflush") == 0)
    {
    {
      init_dependency_vector ();
      init_dependency_vector ();
      return;
      return;
    }
    }
 
 
  /* Push current instruction to dependency_vector[0].  */
  /* Push current instruction to dependency_vector[0].  */
  for (i = vector_size - 1; i > 0; i--)
  for (i = vector_size - 1; i > 0; i--)
    memcpy (&dependency_vector[i], &dependency_vector[i - 1], sizeof (dependency_vector[i]));
    memcpy (&dependency_vector[i], &dependency_vector[i - 1], sizeof (dependency_vector[i]));
 
 
  memcpy (&dependency_vector[0], theinst, sizeof (dependency_vector[i]));
  memcpy (&dependency_vector[0], theinst, sizeof (dependency_vector[i]));
 
 
  /* There is no dependency between nop and any instruction.  */
  /* There is no dependency between nop and any instruction.  */
  if (strcmp (dependency_vector[0].name, "nop") == 0
  if (strcmp (dependency_vector[0].name, "nop") == 0
      || strcmp (dependency_vector[0].name, "nop!") == 0)
      || strcmp (dependency_vector[0].name, "nop!") == 0)
    return;
    return;
 
 
  /* "pce" is defined in insn_to_dependency_table.  */
  /* "pce" is defined in insn_to_dependency_table.  */
#define PCE_NAME "pce"
#define PCE_NAME "pce"
 
 
  if (dependency_vector[0].type == Insn_Type_PCE)
  if (dependency_vector[0].type == Insn_Type_PCE)
    strcpy (cur_insn, PCE_NAME);
    strcpy (cur_insn, PCE_NAME);
  else
  else
    strcpy (cur_insn, dependency_vector[0].name);
    strcpy (cur_insn, dependency_vector[0].name);
 
 
  for (i = 1; i < vector_size; i++)
  for (i = 1; i < vector_size; i++)
    {
    {
      /* The element of dependency_vector is NULL.  */
      /* The element of dependency_vector is NULL.  */
      if (dependency_vector[i].name[0] == '\0')
      if (dependency_vector[i].name[0] == '\0')
        continue;
        continue;
 
 
      if (dependency_vector[i].type == Insn_Type_PCE)
      if (dependency_vector[i].type == Insn_Type_PCE)
        strcpy (pre_insn, PCE_NAME);
        strcpy (pre_insn, PCE_NAME);
      else
      else
        strcpy (pre_insn, dependency_vector[i].name);
        strcpy (pre_insn, dependency_vector[i].name);
 
 
      bubbles = check_dependency (pre_insn, dependency_vector[i].reg,
      bubbles = check_dependency (pre_insn, dependency_vector[i].reg,
                                  cur_insn, dependency_vector[0].reg, &warn_or_error);
                                  cur_insn, dependency_vector[0].reg, &warn_or_error);
      remainder_bubbles = bubbles - i + 1;
      remainder_bubbles = bubbles - i + 1;
 
 
      if (remainder_bubbles > 0)
      if (remainder_bubbles > 0)
        {
        {
          int j;
          int j;
 
 
          if (fix_data_dependency == 1)
          if (fix_data_dependency == 1)
            {
            {
              if (remainder_bubbles <= 2)
              if (remainder_bubbles <= 2)
                {
                {
                  if (warn_fix_data_dependency)
                  if (warn_fix_data_dependency)
                    as_warn (_("Fix data dependency: %s %s -- %s %s  (insert %d nop!/%d)"),
                    as_warn (_("Fix data dependency: %s %s -- %s %s  (insert %d nop!/%d)"),
                             dependency_vector[i].name, dependency_vector[i].reg,
                             dependency_vector[i].name, dependency_vector[i].reg,
                             dependency_vector[0].name, dependency_vector[0].reg,
                             dependency_vector[0].name, dependency_vector[0].reg,
                             remainder_bubbles, bubbles);
                             remainder_bubbles, bubbles);
 
 
                  for (j = (vector_size - 1); (j - remainder_bubbles) > 0; j--)
                  for (j = (vector_size - 1); (j - remainder_bubbles) > 0; j--)
                    memcpy (&dependency_vector[j], &dependency_vector[j - remainder_bubbles],
                    memcpy (&dependency_vector[j], &dependency_vector[j - remainder_bubbles],
                            sizeof (dependency_vector[j]));
                            sizeof (dependency_vector[j]));
 
 
                  for (j = 1; j <= remainder_bubbles; j++)
                  for (j = 1; j <= remainder_bubbles; j++)
                    {
                    {
                      memset (&dependency_vector[j], '\0', sizeof (dependency_vector[j]));
                      memset (&dependency_vector[j], '\0', sizeof (dependency_vector[j]));
                      /* Insert nop!.  */
                      /* Insert nop!.  */
                      build_one_frag (nop_inst);
                      build_one_frag (nop_inst);
                    }
                    }
                }
                }
              else
              else
                {
                {
                  if (warn_fix_data_dependency)
                  if (warn_fix_data_dependency)
                    as_warn (_("Fix data dependency: %s %s -- %s %s  (insert 1 pflush/%d)"),
                    as_warn (_("Fix data dependency: %s %s -- %s %s  (insert 1 pflush/%d)"),
                             dependency_vector[i].name, dependency_vector[i].reg,
                             dependency_vector[i].name, dependency_vector[i].reg,
                             dependency_vector[0].name, dependency_vector[0].reg,
                             dependency_vector[0].name, dependency_vector[0].reg,
                             bubbles);
                             bubbles);
 
 
                  for (j = 1; j < vector_size; j++)
                  for (j = 1; j < vector_size; j++)
                    memset (&dependency_vector[j], '\0', sizeof (dependency_vector[j]));
                    memset (&dependency_vector[j], '\0', sizeof (dependency_vector[j]));
 
 
                  /* Insert pflush.  */
                  /* Insert pflush.  */
                  build_one_frag (pflush_inst);
                  build_one_frag (pflush_inst);
                }
                }
            }
            }
          else
          else
            {
            {
              if (warn_or_error)
              if (warn_or_error)
                {
                {
                  as_bad (_("data dependency: %s %s -- %s %s  (%d/%d bubble)"),
                  as_bad (_("data dependency: %s %s -- %s %s  (%d/%d bubble)"),
                           dependency_vector[i].name, dependency_vector[i].reg,
                           dependency_vector[i].name, dependency_vector[i].reg,
                           dependency_vector[0].name, dependency_vector[0].reg,
                           dependency_vector[0].name, dependency_vector[0].reg,
                           remainder_bubbles, bubbles);
                           remainder_bubbles, bubbles);
                }
                }
              else
              else
                {
                {
                  as_warn (_("data dependency: %s %s -- %s %s  (%d/%d bubble)"),
                  as_warn (_("data dependency: %s %s -- %s %s  (%d/%d bubble)"),
                           dependency_vector[i].name, dependency_vector[i].reg,
                           dependency_vector[i].name, dependency_vector[i].reg,
                           dependency_vector[0].name, dependency_vector[0].reg,
                           dependency_vector[0].name, dependency_vector[0].reg,
                           remainder_bubbles, bubbles);
                           remainder_bubbles, bubbles);
                }
                }
            }
            }
        }
        }
    }
    }
}
}
 
 
static enum insn_class
static enum insn_class
get_insn_class_from_type (enum score_insn_type type)
get_insn_class_from_type (enum score_insn_type type)
{
{
  enum insn_class retval = (int) FAIL;
  enum insn_class retval = (int) FAIL;
 
 
  switch (type)
  switch (type)
    {
    {
    case Rd_I4:
    case Rd_I4:
    case Rd_I5:
    case Rd_I5:
    case Rd_rvalueBP_I5:
    case Rd_rvalueBP_I5:
    case Rd_lvalueBP_I5:
    case Rd_lvalueBP_I5:
    case Rd_I8:
    case Rd_I8:
    case PC_DISP8div2:
    case PC_DISP8div2:
    case PC_DISP11div2:
    case PC_DISP11div2:
    case Rd_Rs:
    case Rd_Rs:
    case Rd_HighRs:
    case Rd_HighRs:
    case Rd_lvalueRs:
    case Rd_lvalueRs:
    case Rd_rvalueRs:
    case Rd_rvalueRs:
    case x_Rs:
    case x_Rs:
    case Rd_LowRs:
    case Rd_LowRs:
    case NO16_OPD:
    case NO16_OPD:
      retval = INSN_CLASS_16;
      retval = INSN_CLASS_16;
      break;
      break;
    case Rd_Rs_I5:
    case Rd_Rs_I5:
    case x_Rs_I5:
    case x_Rs_I5:
    case x_I5_x:
    case x_I5_x:
    case Rd_Rs_I14:
    case Rd_Rs_I14:
    case I15:
    case I15:
    case Rd_I16:
    case Rd_I16:
    case Rd_SI16:
    case Rd_SI16:
    case Rd_rvalueRs_SI10:
    case Rd_rvalueRs_SI10:
    case Rd_lvalueRs_SI10:
    case Rd_lvalueRs_SI10:
    case Rd_rvalueRs_preSI12:
    case Rd_rvalueRs_preSI12:
    case Rd_rvalueRs_postSI12:
    case Rd_rvalueRs_postSI12:
    case Rd_lvalueRs_preSI12:
    case Rd_lvalueRs_preSI12:
    case Rd_lvalueRs_postSI12:
    case Rd_lvalueRs_postSI12:
    case Rd_Rs_SI14:
    case Rd_Rs_SI14:
    case Rd_rvalueRs_SI15:
    case Rd_rvalueRs_SI15:
    case Rd_lvalueRs_SI15:
    case Rd_lvalueRs_SI15:
    case PC_DISP19div2:
    case PC_DISP19div2:
    case PC_DISP24div2:
    case PC_DISP24div2:
    case Rd_Rs_Rs:
    case Rd_Rs_Rs:
    case x_Rs_x:
    case x_Rs_x:
    case x_Rs_Rs:
    case x_Rs_Rs:
    case Rd_Rs_x:
    case Rd_Rs_x:
    case Rd_x_Rs:
    case Rd_x_Rs:
    case Rd_x_x:
    case Rd_x_x:
    case OP5_rvalueRs_SI15:
    case OP5_rvalueRs_SI15:
    case I5_Rs_Rs_I5_OP5:
    case I5_Rs_Rs_I5_OP5:
    case x_rvalueRs_post4:
    case x_rvalueRs_post4:
    case Rd_rvalueRs_post4:
    case Rd_rvalueRs_post4:
    case Rd_x_I5:
    case Rd_x_I5:
    case Rd_lvalueRs_post4:
    case Rd_lvalueRs_post4:
    case x_lvalueRs_post4:
    case x_lvalueRs_post4:
    case Rd_Rs_Rs_imm:
    case Rd_Rs_Rs_imm:
    case NO_OPD:
    case NO_OPD:
    case Rd_lvalue32Rs:
    case Rd_lvalue32Rs:
    case Rd_rvalue32Rs:
    case Rd_rvalue32Rs:
    case Insn_GP:
    case Insn_GP:
    case Insn_PIC:
    case Insn_PIC:
    case Insn_internal:
    case Insn_internal:
      retval = INSN_CLASS_32;
      retval = INSN_CLASS_32;
      break;
      break;
    case Insn_Type_PCE:
    case Insn_Type_PCE:
      retval = INSN_CLASS_PCE;
      retval = INSN_CLASS_PCE;
      break;
      break;
    case Insn_Type_SYN:
    case Insn_Type_SYN:
      retval = INSN_CLASS_SYN;
      retval = INSN_CLASS_SYN;
      break;
      break;
    default:
    default:
      abort ();
      abort ();
      break;
      break;
    }
    }
  return retval;
  return retval;
}
}
 
 
static unsigned long
static unsigned long
adjust_paritybit (unsigned long m_code, enum insn_class class)
adjust_paritybit (unsigned long m_code, enum insn_class class)
{
{
  unsigned long result = 0;
  unsigned long result = 0;
  unsigned long m_code_high = 0;
  unsigned long m_code_high = 0;
  unsigned long m_code_low = 0;
  unsigned long m_code_low = 0;
  unsigned long pb_high = 0;
  unsigned long pb_high = 0;
  unsigned long pb_low = 0;
  unsigned long pb_low = 0;
 
 
  if (class == INSN_CLASS_32)
  if (class == INSN_CLASS_32)
    {
    {
      pb_high = 0x80000000;
      pb_high = 0x80000000;
      pb_low = 0x00008000;
      pb_low = 0x00008000;
    }
    }
  else if (class == INSN_CLASS_16)
  else if (class == INSN_CLASS_16)
    {
    {
      pb_high = 0;
      pb_high = 0;
      pb_low = 0;
      pb_low = 0;
    }
    }
  else if (class == INSN_CLASS_PCE)
  else if (class == INSN_CLASS_PCE)
    {
    {
      pb_high = 0;
      pb_high = 0;
      pb_low = 0x00008000;
      pb_low = 0x00008000;
    }
    }
  else if (class == INSN_CLASS_SYN)
  else if (class == INSN_CLASS_SYN)
    {
    {
      /* FIXME.  at this time, INSN_CLASS_SYN must be 32 bit, but, instruction type should
      /* FIXME.  at this time, INSN_CLASS_SYN must be 32 bit, but, instruction type should
         be changed if macro instruction has been expanded.  */
         be changed if macro instruction has been expanded.  */
      pb_high = 0x80000000;
      pb_high = 0x80000000;
      pb_low = 0x00008000;
      pb_low = 0x00008000;
    }
    }
  else
  else
    {
    {
      abort ();
      abort ();
    }
    }
 
 
  m_code_high = m_code & 0x3fff8000;
  m_code_high = m_code & 0x3fff8000;
  m_code_low = m_code & 0x00007fff;
  m_code_low = m_code & 0x00007fff;
  result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
  result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
  return result;
  return result;
 
 
}
}
 
 
static void
static void
gen_insn_frag (struct score_it *part_1, struct score_it *part_2)
gen_insn_frag (struct score_it *part_1, struct score_it *part_2)
{
{
  char *p;
  char *p;
  bfd_boolean pce_p = FALSE;
  bfd_boolean pce_p = FALSE;
  int relaxable_p = g_opt;
  int relaxable_p = g_opt;
  int relax_size = 0;
  int relax_size = 0;
  struct score_it *inst1 = part_1;
  struct score_it *inst1 = part_1;
  struct score_it *inst2 = part_2;
  struct score_it *inst2 = part_2;
  struct score_it backup_inst1;
  struct score_it backup_inst1;
 
 
  pce_p = (inst2) ? TRUE : FALSE;
  pce_p = (inst2) ? TRUE : FALSE;
  memcpy (&backup_inst1, inst1, sizeof (struct score_it));
  memcpy (&backup_inst1, inst1, sizeof (struct score_it));
 
 
  /* Adjust instruction opcode and to be relaxed instruction opcode.  */
  /* Adjust instruction opcode and to be relaxed instruction opcode.  */
  if (pce_p)
  if (pce_p)
    {
    {
      backup_inst1.instruction = ((backup_inst1.instruction & 0x7FFF) << 15)
      backup_inst1.instruction = ((backup_inst1.instruction & 0x7FFF) << 15)
                                  | (inst2->instruction & 0x7FFF);
                                  | (inst2->instruction & 0x7FFF);
      backup_inst1.instruction = adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE);
      backup_inst1.instruction = adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE);
      backup_inst1.relax_inst = 0x8000;
      backup_inst1.relax_inst = 0x8000;
      backup_inst1.size = INSN_SIZE;
      backup_inst1.size = INSN_SIZE;
      backup_inst1.relax_size = 0;
      backup_inst1.relax_size = 0;
      backup_inst1.type = Insn_Type_PCE;
      backup_inst1.type = Insn_Type_PCE;
    }
    }
  else
  else
    {
    {
      backup_inst1.instruction = adjust_paritybit (backup_inst1.instruction,
      backup_inst1.instruction = adjust_paritybit (backup_inst1.instruction,
                                                   GET_INSN_CLASS (backup_inst1.type));
                                                   GET_INSN_CLASS (backup_inst1.type));
    }
    }
 
 
  if (backup_inst1.relax_size != 0)
  if (backup_inst1.relax_size != 0)
    {
    {
      enum insn_class tmp;
      enum insn_class tmp;
 
 
      tmp = (backup_inst1.size == INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32;
      tmp = (backup_inst1.size == INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32;
      backup_inst1.relax_inst = adjust_paritybit (backup_inst1.relax_inst, tmp);
      backup_inst1.relax_inst = adjust_paritybit (backup_inst1.relax_inst, tmp);
    }
    }
 
 
  /* Check data dependency.  */
  /* Check data dependency.  */
  handle_dependency (&backup_inst1);
  handle_dependency (&backup_inst1);
 
 
  /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains
  /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains
     data produced by .ascii etc.  Doing this is to make one instruction per frag.  */
     data produced by .ascii etc.  Doing this is to make one instruction per frag.  */
  if (frag_now_fix () != 0)
  if (frag_now_fix () != 0)
    {
    {
      if (!frag_now->tc_frag_data.is_insn)
      if (!frag_now->tc_frag_data.is_insn)
        frag_wane (frag_now);
        frag_wane (frag_now);
 
 
      frag_new (0);
      frag_new (0);
    }
    }
 
 
  /* Here, we must call frag_grow in order to keep the instruction frag type is
  /* Here, we must call frag_grow in order to keep the instruction frag type is
     rs_machine_dependent.
     rs_machine_dependent.
     For, frag_var may change frag_now->fr_type to rs_fill by calling frag_grow which
     For, frag_var may change frag_now->fr_type to rs_fill by calling frag_grow which
     acturally will call frag_wane.
     acturally will call frag_wane.
     Calling frag_grow first will create a new frag_now which free size is 20 that is enough
     Calling frag_grow first will create a new frag_now which free size is 20 that is enough
     for frag_var.  */
     for frag_var.  */
  frag_grow (20);
  frag_grow (20);
 
 
  p = frag_more (backup_inst1.size);
  p = frag_more (backup_inst1.size);
  md_number_to_chars (p, backup_inst1.instruction, backup_inst1.size);
  md_number_to_chars (p, backup_inst1.instruction, backup_inst1.size);
 
 
#ifdef OBJ_ELF
#ifdef OBJ_ELF
  dwarf2_emit_insn (backup_inst1.size);
  dwarf2_emit_insn (backup_inst1.size);
#endif
#endif
 
 
  /* Generate fixup structure.  */
  /* Generate fixup structure.  */
  if (pce_p)
  if (pce_p)
    {
    {
      if (inst1->reloc.type != BFD_RELOC_NONE)
      if (inst1->reloc.type != BFD_RELOC_NONE)
        fix_new_score (frag_now, p - frag_now->fr_literal,
        fix_new_score (frag_now, p - frag_now->fr_literal,
                       inst1->size, &inst1->reloc.exp,
                       inst1->size, &inst1->reloc.exp,
                       inst1->reloc.pc_rel, inst1->reloc.type);
                       inst1->reloc.pc_rel, inst1->reloc.type);
 
 
      if (inst2->reloc.type != BFD_RELOC_NONE)
      if (inst2->reloc.type != BFD_RELOC_NONE)
        fix_new_score (frag_now, p - frag_now->fr_literal + 2,
        fix_new_score (frag_now, p - frag_now->fr_literal + 2,
                       inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type);
                       inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type);
    }
    }
  else
  else
    {
    {
      if (backup_inst1.reloc.type != BFD_RELOC_NONE)
      if (backup_inst1.reloc.type != BFD_RELOC_NONE)
        fix_new_score (frag_now, p - frag_now->fr_literal,
        fix_new_score (frag_now, p - frag_now->fr_literal,
                       backup_inst1.size, &backup_inst1.reloc.exp,
                       backup_inst1.size, &backup_inst1.reloc.exp,
                       backup_inst1.reloc.pc_rel, backup_inst1.reloc.type);
                       backup_inst1.reloc.pc_rel, backup_inst1.reloc.type);
    }
    }
 
 
  /* relax_size may be 2, 4, 12 or 0, 0 indicates no relaxation.  */
  /* relax_size may be 2, 4, 12 or 0, 0 indicates no relaxation.  */
  relaxable_p &= (backup_inst1.relax_size != 0);
  relaxable_p &= (backup_inst1.relax_size != 0);
  relax_size = relaxable_p ? backup_inst1.relax_size : 0;
  relax_size = relaxable_p ? backup_inst1.relax_size : 0;
 
 
  p = frag_var (rs_machine_dependent, relax_size + RELAX_PAD_BYTE, 0,
  p = frag_var (rs_machine_dependent, relax_size + RELAX_PAD_BYTE, 0,
                RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size,
                RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size,
                              backup_inst1.type, 0, 0, relaxable_p),
                              backup_inst1.type, 0, 0, relaxable_p),
                backup_inst1.reloc.exp.X_add_symbol, 0, NULL);
                backup_inst1.reloc.exp.X_add_symbol, 0, NULL);
 
 
  if (relaxable_p)
  if (relaxable_p)
    md_number_to_chars (p, backup_inst1.relax_inst, relax_size);
    md_number_to_chars (p, backup_inst1.relax_inst, relax_size);
 
 
  memcpy (inst1, &backup_inst1, sizeof (struct score_it));
  memcpy (inst1, &backup_inst1, sizeof (struct score_it));
}
}
 
 
static void
static void
parse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p)
parse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p)
{
{
  char c;
  char c;
  char *p;
  char *p;
  char *operator = insnstr;
  char *operator = insnstr;
  const struct asm_opcode *opcode;
  const struct asm_opcode *opcode;
 
 
  /* Parse operator and operands.  */
  /* Parse operator and operands.  */
  skip_whitespace (operator);
  skip_whitespace (operator);
 
 
  for (p = operator; *p != '\0'; p++)
  for (p = operator; *p != '\0'; p++)
    if ((*p == ' ') || (*p == '!'))
    if ((*p == ' ') || (*p == '!'))
      break;
      break;
 
 
  if (*p == '!')
  if (*p == '!')
    p++;
    p++;
 
 
  c = *p;
  c = *p;
  *p = '\0';
  *p = '\0';
 
 
  opcode = (const struct asm_opcode *) hash_find (score_ops_hsh, operator);
  opcode = (const struct asm_opcode *) hash_find (score_ops_hsh, operator);
  *p = c;
  *p = c;
 
 
  memset (&inst, '\0', sizeof (inst));
  memset (&inst, '\0', sizeof (inst));
  sprintf (inst.str, "%s", insnstr);
  sprintf (inst.str, "%s", insnstr);
  if (opcode)
  if (opcode)
    {
    {
      inst.instruction = opcode->value;
      inst.instruction = opcode->value;
      inst.relax_inst = opcode->relax_value;
      inst.relax_inst = opcode->relax_value;
      inst.type = opcode->type;
      inst.type = opcode->type;
      inst.size = GET_INSN_SIZE (inst.type);
      inst.size = GET_INSN_SIZE (inst.type);
      inst.relax_size = 0;
      inst.relax_size = 0;
      inst.bwarn = 0;
      inst.bwarn = 0;
      sprintf (inst.name, "%s", opcode->template);
      sprintf (inst.name, "%s", opcode->template);
      strcpy (inst.reg, "");
      strcpy (inst.reg, "");
      inst.error = NULL;
      inst.error = NULL;
      inst.reloc.type = BFD_RELOC_NONE;
      inst.reloc.type = BFD_RELOC_NONE;
 
 
      (*opcode->parms) (p);
      (*opcode->parms) (p);
 
 
      /* It indicates current instruction is a macro instruction if inst.bwarn equals -1.  */
      /* It indicates current instruction is a macro instruction if inst.bwarn equals -1.  */
      if ((inst.bwarn != -1) && (!inst.error) && (gen_frag_p))
      if ((inst.bwarn != -1) && (!inst.error) && (gen_frag_p))
        gen_insn_frag (&inst, NULL);
        gen_insn_frag (&inst, NULL);
    }
    }
  else
  else
    inst.error = _("unrecognized opcode");
    inst.error = _("unrecognized opcode");
}
}
 
 
static int
static int
append_insn (char *str, bfd_boolean gen_frag_p)
append_insn (char *str, bfd_boolean gen_frag_p)
{
{
  int retval = SUCCESS;
  int retval = SUCCESS;
 
 
  parse_16_32_inst (str, gen_frag_p);
  parse_16_32_inst (str, gen_frag_p);
 
 
  if (inst.error)
  if (inst.error)
    {
    {
      retval = (int) FAIL;
      retval = (int) FAIL;
      as_bad (_("%s -- `%s'"), inst.error, inst.str);
      as_bad (_("%s -- `%s'"), inst.error, inst.str);
      inst.error = NULL;
      inst.error = NULL;
    }
    }
 
 
  return retval;
  return retval;
}
}
 
 
/* Handle mv! reg_high, reg_low;
/* Handle mv! reg_high, reg_low;
          mv! reg_low, reg_high;
          mv! reg_low, reg_high;
          mv! reg_low, reg_low;  */
          mv! reg_low, reg_low;  */
static void
static void
do16_mv_rdrs (char *str)
do16_mv_rdrs (char *str)
{
{
  int reg_rd;
  int reg_rd;
  int reg_rs;
  int reg_rs;
  char *backupstr = NULL;
  char *backupstr = NULL;
 
 
  backupstr = str;
  backupstr = str;
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if ((reg_rd = reg_required_here (&str, 8, REG_TYPE_SCORE)) == (int) FAIL
  if ((reg_rd = reg_required_here (&str, 8, REG_TYPE_SCORE)) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || (reg_rs = reg_required_here (&str, 4, REG_TYPE_SCORE)) == (int) FAIL
      || (reg_rs = reg_required_here (&str, 4, REG_TYPE_SCORE)) == (int) FAIL
      || end_of_line (str) == (int) FAIL)
      || end_of_line (str) == (int) FAIL)
    {
    {
      return;
      return;
    }
    }
  else
  else
    {
    {
      /* Case 1 : mv! or mlfh!.  */
      /* Case 1 : mv! or mlfh!.  */
      if (reg_rd < 16)
      if (reg_rd < 16)
        {
        {
          if (reg_rs < 16)
          if (reg_rs < 16)
            {
            {
              inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
              inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
                | (((inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
                | (((inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
              inst.relax_size = 4;
              inst.relax_size = 4;
            }
            }
          else
          else
            {
            {
              char append_str[MAX_LITERAL_POOL_SIZE];
              char append_str[MAX_LITERAL_POOL_SIZE];
 
 
              sprintf (append_str, "mlfh! %s", backupstr);
              sprintf (append_str, "mlfh! %s", backupstr);
              if (append_insn (append_str, TRUE) == (int) FAIL)
              if (append_insn (append_str, TRUE) == (int) FAIL)
                return;
                return;
              /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
              /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
              inst.bwarn = -1;
              inst.bwarn = -1;
            }
            }
        }
        }
      /* Case 2 : mhfl!.  */
      /* Case 2 : mhfl!.  */
      else
      else
        {
        {
          if (reg_rs > 16)
          if (reg_rs > 16)
            {
            {
              SET_INSN_ERROR (BAD_ARGS);
              SET_INSN_ERROR (BAD_ARGS);
              return;
              return;
            }
            }
          else
          else
            {
            {
              char append_str[MAX_LITERAL_POOL_SIZE];
              char append_str[MAX_LITERAL_POOL_SIZE];
 
 
              sprintf (append_str, "mhfl! %s", backupstr);
              sprintf (append_str, "mhfl! %s", backupstr);
              if (append_insn (append_str, TRUE) == (int) FAIL)
              if (append_insn (append_str, TRUE) == (int) FAIL)
                return;
                return;
 
 
              /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
              /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
              inst.bwarn = -1;
              inst.bwarn = -1;
            }
            }
        }
        }
    }
    }
}
}
 
 
static void
static void
do16_rdi4 (char *str)
do16_rdi4 (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reglow_required_here (&str, 8) == (int) FAIL
  if (reglow_required_here (&str, 8) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || data_op2 (&str, 3, _IMM4) == (int) FAIL
      || data_op2 (&str, 3, _IMM4) == (int) FAIL
      || end_of_line (str) == (int) FAIL)
      || end_of_line (str) == (int) FAIL)
    {
    {
      return;
      return;
    }
    }
  else
  else
    {
    {
      if (((inst.instruction >> 3) & 0x10) == 0)        /* for judge is addei or subei : bit 5 =0 : addei */
      if (((inst.instruction >> 3) & 0x10) == 0)        /* for judge is addei or subei : bit 5 =0 : addei */
        {
        {
          if (((inst.instruction >> 3) & 0xf) != 0xf)
          if (((inst.instruction >> 3) & 0xf) != 0xf)
            {
            {
              inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
              inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
                | ((1 << ((inst.instruction >> 3) & 0xf)) << 1);
                | ((1 << ((inst.instruction >> 3) & 0xf)) << 1);
              inst.relax_size = 4;
              inst.relax_size = 4;
            }
            }
          else
          else
            {
            {
              inst.relax_inst = 0x8000;
              inst.relax_inst = 0x8000;
            }
            }
        }
        }
      else
      else
        {
        {
          if (((inst.instruction >> 3) & 0xf) != 0xf)
          if (((inst.instruction >> 3) & 0xf) != 0xf)
            {
            {
              inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
              inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
                | (((-(1 << ((inst.instruction >> 3) & 0xf))) & 0xffff) << 1);
                | (((-(1 << ((inst.instruction >> 3) & 0xf))) & 0xffff) << 1);
              inst.relax_size = 4;
              inst.relax_size = 4;
            }
            }
          else
          else
            {
            {
              inst.relax_inst = 0x8000;
              inst.relax_inst = 0x8000;
            }
            }
        }
        }
    }
    }
}
}
 
 
static void
static void
do16_rdi5 (char *str)
do16_rdi5 (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reglow_required_here (&str, 8) == (int) FAIL
  if (reglow_required_here (&str, 8) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || data_op2 (&str, 3, _IMM5) == (int) FAIL
      || data_op2 (&str, 3, _IMM5) == (int) FAIL
      || end_of_line (str) == (int) FAIL)
      || end_of_line (str) == (int) FAIL)
    return;
    return;
  else
  else
    {
    {
      inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
      inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
        | (((inst.instruction >> 8) & 0xf) << 15) | (((inst.instruction >> 3) & 0x1f) << 10);
        | (((inst.instruction >> 8) & 0xf) << 15) | (((inst.instruction >> 3) & 0x1f) << 10);
      inst.relax_size = 4;
      inst.relax_size = 4;
    }
    }
}
}
 
 
/* Handle sdbbp.  */
/* Handle sdbbp.  */
static void
static void
do16_xi5 (char *str)
do16_xi5 (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (data_op2 (&str, 3, _IMM5) == (int) FAIL || end_of_line (str) == (int) FAIL)
  if (data_op2 (&str, 3, _IMM5) == (int) FAIL || end_of_line (str) == (int) FAIL)
    return;
    return;
  else
  else
    {
    {
      inst.relax_inst |= (((inst.instruction >> 3) & 0x1f) << 15);
      inst.relax_inst |= (((inst.instruction >> 3) & 0x1f) << 15);
      inst.relax_size = 4;
      inst.relax_size = 4;
    }
    }
}
}
 
 
/* Check that an immediate is word alignment or half word alignment.
/* Check that an immediate is word alignment or half word alignment.
   If so, convert it to the right format.  */
   If so, convert it to the right format.  */
static int
static int
validate_immediate_align (int val, unsigned int data_type)
validate_immediate_align (int val, unsigned int data_type)
{
{
  if (data_type == _IMM5_RSHIFT_1)
  if (data_type == _IMM5_RSHIFT_1)
    {
    {
      if (val % 2)
      if (val % 2)
        {
        {
          inst.error = _("address offset must be half word alignment");
          inst.error = _("address offset must be half word alignment");
          return (int) FAIL;
          return (int) FAIL;
        }
        }
    }
    }
  else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
  else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
    {
    {
      if (val % 4)
      if (val % 4)
        {
        {
          inst.error = _("address offset must be word alignment");
          inst.error = _("address offset must be word alignment");
          return (int) FAIL;
          return (int) FAIL;
        }
        }
    }
    }
 
 
  return SUCCESS;
  return SUCCESS;
}
}
 
 
static int
static int
exp_ldst_offset (char **str, int shift, unsigned int data_type)
exp_ldst_offset (char **str, int shift, unsigned int data_type)
{
{
  char *dataptr;
  char *dataptr;
 
 
  dataptr = * str;
  dataptr = * str;
 
 
  if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
  if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
      && (data_type != _SIMM16_LA)
      && (data_type != _SIMM16_LA)
      && (data_type != _VALUE_HI16)
      && (data_type != _VALUE_HI16)
      && (data_type != _VALUE_LO16)
      && (data_type != _VALUE_LO16)
      && (data_type != _IMM16)
      && (data_type != _IMM16)
      && (data_type != _IMM15)
      && (data_type != _IMM15)
      && (data_type != _IMM14)
      && (data_type != _IMM14)
      && (data_type != _IMM4)
      && (data_type != _IMM4)
      && (data_type != _IMM5)
      && (data_type != _IMM5)
      && (data_type != _IMM8)
      && (data_type != _IMM8)
      && (data_type != _IMM5_RSHIFT_1)
      && (data_type != _IMM5_RSHIFT_1)
      && (data_type != _IMM5_RSHIFT_2)
      && (data_type != _IMM5_RSHIFT_2)
      && (data_type != _SIMM14_NEG)
      && (data_type != _SIMM14_NEG)
      && (data_type != _IMM10_RSHIFT_2))
      && (data_type != _IMM10_RSHIFT_2))
    {
    {
      data_type += 24;
      data_type += 24;
    }
    }
 
 
  if (my_get_expression (&inst.reloc.exp, str) == (int) FAIL)
  if (my_get_expression (&inst.reloc.exp, str) == (int) FAIL)
    return (int) FAIL;
    return (int) FAIL;
 
 
  if (inst.reloc.exp.X_op == O_constant)
  if (inst.reloc.exp.X_op == O_constant)
    {
    {
      /* Need to check the immediate align.  */
      /* Need to check the immediate align.  */
      int value = validate_immediate_align (inst.reloc.exp.X_add_number, data_type);
      int value = validate_immediate_align (inst.reloc.exp.X_add_number, data_type);
 
 
      if (value == (int) FAIL)
      if (value == (int) FAIL)
        return (int) FAIL;
        return (int) FAIL;
 
 
      value = validate_immediate (inst.reloc.exp.X_add_number, data_type, 0);
      value = validate_immediate (inst.reloc.exp.X_add_number, data_type, 0);
      if (value == (int) FAIL)
      if (value == (int) FAIL)
        {
        {
          if (data_type < 30)
          if (data_type < 30)
            sprintf (err_msg,
            sprintf (err_msg,
                     _("invalid constant: %d bit expression not in range %d..%d"),
                     _("invalid constant: %d bit expression not in range %d..%d"),
                     score_df_range[data_type].bits,
                     score_df_range[data_type].bits,
                     score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
                     score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
          else
          else
            sprintf (err_msg,
            sprintf (err_msg,
                     _("invalid constant: %d bit expression not in range %d..%d"),
                     _("invalid constant: %d bit expression not in range %d..%d"),
                     score_df_range[data_type - 24].bits,
                     score_df_range[data_type - 24].bits,
                     score_df_range[data_type - 24].range[0], score_df_range[data_type - 24].range[1]);
                     score_df_range[data_type - 24].range[0], score_df_range[data_type - 24].range[1]);
          inst.error = err_msg;
          inst.error = err_msg;
          return (int) FAIL;
          return (int) FAIL;
        }
        }
 
 
      if (data_type == _IMM5_RSHIFT_1)
      if (data_type == _IMM5_RSHIFT_1)
        {
        {
          value >>= 1;
          value >>= 1;
        }
        }
      else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
      else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
        {
        {
          value >>= 2;
          value >>= 2;
        }
        }
 
 
      if (score_df_range[data_type].range[0] != 0)
      if (score_df_range[data_type].range[0] != 0)
        {
        {
          value &= (1 << score_df_range[data_type].bits) - 1;
          value &= (1 << score_df_range[data_type].bits) - 1;
        }
        }
 
 
      inst.instruction |= value << shift;
      inst.instruction |= value << shift;
    }
    }
  else
  else
    {
    {
      inst.reloc.pc_rel = 0;
      inst.reloc.pc_rel = 0;
    }
    }
 
 
  return SUCCESS;
  return SUCCESS;
}
}
 
 
static void
static void
do_ldst_insn (char *str)
do_ldst_insn (char *str)
{
{
  int pre_inc = 0;
  int pre_inc = 0;
  int conflict_reg;
  int conflict_reg;
  int value;
  int value;
  char * temp;
  char * temp;
  char *strbak;
  char *strbak;
  char *dataptr;
  char *dataptr;
  int reg;
  int reg;
  int ldst_idx = 0;
  int ldst_idx = 0;
 
 
  strbak = str;
  strbak = str;
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (((conflict_reg = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
  if (((conflict_reg = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
      || (skip_past_comma (&str) == (int) FAIL))
      || (skip_past_comma (&str) == (int) FAIL))
    return;
    return;
 
 
  /* ld/sw rD, [rA, simm15]    ld/sw rD, [rA]+, simm12     ld/sw rD, [rA, simm12]+.  */
  /* ld/sw rD, [rA, simm15]    ld/sw rD, [rA]+, simm12     ld/sw rD, [rA, simm12]+.  */
  if (*str == '[')
  if (*str == '[')
    {
    {
      str++;
      str++;
      skip_whitespace (str);
      skip_whitespace (str);
 
 
      if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
      if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
        return;
        return;
 
 
      /* Conflicts can occur on stores as well as loads.  */
      /* Conflicts can occur on stores as well as loads.  */
      conflict_reg = (conflict_reg == reg);
      conflict_reg = (conflict_reg == reg);
      skip_whitespace (str);
      skip_whitespace (str);
      temp = str + 1;    /* The latter will process decimal/hex expression.  */
      temp = str + 1;    /* The latter will process decimal/hex expression.  */
 
 
      /* ld/sw rD, [rA]+, simm12    ld/sw rD, [rA]+.  */
      /* ld/sw rD, [rA]+, simm12    ld/sw rD, [rA]+.  */
      if (*str == ']')
      if (*str == ']')
        {
        {
          str++;
          str++;
          if (*str == '+')
          if (*str == '+')
            {
            {
              str++;
              str++;
              /* ld/sw rD, [rA]+, simm12.  */
              /* ld/sw rD, [rA]+, simm12.  */
              if (skip_past_comma (&str) == SUCCESS)
              if (skip_past_comma (&str) == SUCCESS)
                {
                {
                  if ((exp_ldst_offset (&str, 3, _SIMM12) == (int) FAIL)
                  if ((exp_ldst_offset (&str, 3, _SIMM12) == (int) FAIL)
                      || (end_of_line (str) == (int) FAIL))
                      || (end_of_line (str) == (int) FAIL))
                    return;
                    return;
 
 
                  if (conflict_reg)
                  if (conflict_reg)
                    {
                    {
                      unsigned int ldst_func = inst.instruction & OPC_PSEUDOLDST_MASK;
                      unsigned int ldst_func = inst.instruction & OPC_PSEUDOLDST_MASK;
 
 
                      if ((ldst_func == INSN_LH)
                      if ((ldst_func == INSN_LH)
                          || (ldst_func == INSN_LHU)
                          || (ldst_func == INSN_LHU)
                          || (ldst_func == INSN_LW)
                          || (ldst_func == INSN_LW)
                          || (ldst_func == INSN_LB)
                          || (ldst_func == INSN_LB)
                          || (ldst_func == INSN_LBU))
                          || (ldst_func == INSN_LBU))
                        {
                        {
                          inst.error = _("register same as write-back base");
                          inst.error = _("register same as write-back base");
                          return;
                          return;
                        }
                        }
                    }
                    }
 
 
                  ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
                  ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
                  inst.instruction &= ~OPC_PSEUDOLDST_MASK;
                  inst.instruction &= ~OPC_PSEUDOLDST_MASK;
                  inst.instruction |= score_ldst_insns[ldst_idx * 3 + LDST_POST].value;
                  inst.instruction |= score_ldst_insns[ldst_idx * 3 + LDST_POST].value;
 
 
                  /* lw rD, [rA]+, 4 convert to pop rD, [rA].  */
                  /* lw rD, [rA]+, 4 convert to pop rD, [rA].  */
                  if ((inst.instruction & 0x3e000007) == 0x0e000000)
                  if ((inst.instruction & 0x3e000007) == 0x0e000000)
                    {
                    {
                      /* rs =  r0-r7, offset = 4 */
                      /* rs =  r0-r7, offset = 4 */
                      if ((((inst.instruction >> 15) & 0x18) == 0)
                      if ((((inst.instruction >> 15) & 0x18) == 0)
                          && (((inst.instruction >> 3) & 0xfff) == 4))
                          && (((inst.instruction >> 3) & 0xfff) == 4))
                        {
                        {
                          /* Relax to pophi.  */
                          /* Relax to pophi.  */
                          if ((((inst.instruction >> 20) & 0x10) == 0x10))
                          if ((((inst.instruction >> 20) & 0x10) == 0x10))
                            {
                            {
                              inst.relax_inst = 0x0000200a | (((inst.instruction >> 20) & 0xf)
                              inst.relax_inst = 0x0000200a | (((inst.instruction >> 20) & 0xf)
                                                              << 8) | 1 << 7 |
                                                              << 8) | 1 << 7 |
                                (((inst.instruction >> 15) & 0x7) << 4);
                                (((inst.instruction >> 15) & 0x7) << 4);
                            }
                            }
                          /* Relax to pop.  */
                          /* Relax to pop.  */
                          else
                          else
                            {
                            {
                              inst.relax_inst = 0x0000200a | (((inst.instruction >> 20) & 0xf)
                              inst.relax_inst = 0x0000200a | (((inst.instruction >> 20) & 0xf)
                                                              << 8) | 0 << 7 |
                                                              << 8) | 0 << 7 |
                                (((inst.instruction >> 15) & 0x7) << 4);
                                (((inst.instruction >> 15) & 0x7) << 4);
                            }
                            }
                          inst.relax_size = 2;
                          inst.relax_size = 2;
                        }
                        }
                    }
                    }
                  return;
                  return;
                }
                }
              /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+.  */
              /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+.  */
              else
              else
                {
                {
                  SET_INSN_ERROR (NULL);
                  SET_INSN_ERROR (NULL);
                  if (end_of_line (str) == (int) FAIL)
                  if (end_of_line (str) == (int) FAIL)
                    {
                    {
                      return;
                      return;
                    }
                    }
 
 
                  pre_inc = 1;
                  pre_inc = 1;
                  value = validate_immediate (inst.reloc.exp.X_add_number, _SIMM12, 0);
                  value = validate_immediate (inst.reloc.exp.X_add_number, _SIMM12, 0);
                  value &= (1 << score_df_range[_SIMM12].bits) - 1;
                  value &= (1 << score_df_range[_SIMM12].bits) - 1;
                  ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
                  ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
                  inst.instruction &= ~OPC_PSEUDOLDST_MASK;
                  inst.instruction &= ~OPC_PSEUDOLDST_MASK;
                  inst.instruction |= score_ldst_insns[ldst_idx * 3 + pre_inc].value;
                  inst.instruction |= score_ldst_insns[ldst_idx * 3 + pre_inc].value;
                  inst.instruction |= value << 3;
                  inst.instruction |= value << 3;
                  inst.relax_inst = 0x8000;
                  inst.relax_inst = 0x8000;
                  return;
                  return;
                }
                }
            }
            }
          /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15].  */
          /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15].  */
          else
          else
            {
            {
              if (end_of_line (str) == (int) FAIL)
              if (end_of_line (str) == (int) FAIL)
                return;
                return;
 
 
              ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
              ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
              inst.instruction &= ~OPC_PSEUDOLDST_MASK;
              inst.instruction &= ~OPC_PSEUDOLDST_MASK;
              inst.instruction |= score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value;
              inst.instruction |= score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value;
 
 
              /* lbu rd, [rs] -> lbu! rd, [rs]  */
              /* lbu rd, [rs] -> lbu! rd, [rs]  */
              if (ldst_idx == INSN_LBU)
              if (ldst_idx == INSN_LBU)
                {
                {
                  inst.relax_inst = INSN16_LBU;
                  inst.relax_inst = INSN16_LBU;
                }
                }
              else if (ldst_idx == INSN_LH)
              else if (ldst_idx == INSN_LH)
                {
                {
                  inst.relax_inst = INSN16_LH;
                  inst.relax_inst = INSN16_LH;
                }
                }
              else if (ldst_idx == INSN_LW)
              else if (ldst_idx == INSN_LW)
                {
                {
                  inst.relax_inst = INSN16_LW;
                  inst.relax_inst = INSN16_LW;
                }
                }
              else if (ldst_idx == INSN_SB)
              else if (ldst_idx == INSN_SB)
                {
                {
                  inst.relax_inst = INSN16_SB;
                  inst.relax_inst = INSN16_SB;
                }
                }
              else if (ldst_idx == INSN_SH)
              else if (ldst_idx == INSN_SH)
                {
                {
                  inst.relax_inst = INSN16_SH;
                  inst.relax_inst = INSN16_SH;
                }
                }
              else if (ldst_idx == INSN_SW)
              else if (ldst_idx == INSN_SW)
                {
                {
                  inst.relax_inst = INSN16_SW;
                  inst.relax_inst = INSN16_SW;
                }
                }
              else
              else
                {
                {
                  inst.relax_inst = 0x8000;
                  inst.relax_inst = 0x8000;
                }
                }
 
 
              /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction.  */
              /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction.  */
              if ((ldst_idx == INSN_LBU)
              if ((ldst_idx == INSN_LBU)
                  || (ldst_idx == INSN_LH)
                  || (ldst_idx == INSN_LH)
                  || (ldst_idx == INSN_LW)
                  || (ldst_idx == INSN_LW)
                  || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))
                  || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))
                {
                {
                  if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
                  if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
                    {
                    {
                      inst.relax_inst |= (2 << 12) | (((inst.instruction >> 20) & 0xf) << 8) |
                      inst.relax_inst |= (2 << 12) | (((inst.instruction >> 20) & 0xf) << 8) |
                        (((inst.instruction >> 15) & 0xf) << 4);
                        (((inst.instruction >> 15) & 0xf) << 4);
                      inst.relax_size = 2;
                      inst.relax_size = 2;
                    }
                    }
                }
                }
 
 
              return;
              return;
            }
            }
        }
        }
      /* ld/sw rD, [rA, simm15]    ld/sw rD, [rA, simm12]+.  */
      /* ld/sw rD, [rA, simm15]    ld/sw rD, [rA, simm12]+.  */
      else
      else
        {
        {
          if (skip_past_comma (&str) == (int) FAIL)
          if (skip_past_comma (&str) == (int) FAIL)
            {
            {
              inst.error = _("pre-indexed expression expected");
              inst.error = _("pre-indexed expression expected");
              return;
              return;
            }
            }
 
 
          if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL)
          if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL)
            return;
            return;
 
 
          skip_whitespace (str);
          skip_whitespace (str);
          if (*str++ != ']')
          if (*str++ != ']')
            {
            {
              inst.error = _("missing ]");
              inst.error = _("missing ]");
              return;
              return;
            }
            }
 
 
          skip_whitespace (str);
          skip_whitespace (str);
          /* ld/sw rD, [rA, simm12]+.  */
          /* ld/sw rD, [rA, simm12]+.  */
          if (*str == '+')
          if (*str == '+')
            {
            {
              str++;
              str++;
              pre_inc = 1;
              pre_inc = 1;
              if (conflict_reg)
              if (conflict_reg)
                {
                {
                  unsigned int ldst_func = inst.instruction & OPC_PSEUDOLDST_MASK;
                  unsigned int ldst_func = inst.instruction & OPC_PSEUDOLDST_MASK;
 
 
                  if ((ldst_func == INSN_LH)
                  if ((ldst_func == INSN_LH)
                      || (ldst_func == INSN_LHU)
                      || (ldst_func == INSN_LHU)
                      || (ldst_func == INSN_LW)
                      || (ldst_func == INSN_LW)
                      || (ldst_func == INSN_LB)
                      || (ldst_func == INSN_LB)
                      || (ldst_func == INSN_LBU))
                      || (ldst_func == INSN_LBU))
                    {
                    {
                      inst.error = _("register same as write-back base");
                      inst.error = _("register same as write-back base");
                      return;
                      return;
                    }
                    }
                }
                }
            }
            }
 
 
          if (end_of_line (str) == (int) FAIL)
          if (end_of_line (str) == (int) FAIL)
            return;
            return;
 
 
          if (inst.reloc.exp.X_op == O_constant)
          if (inst.reloc.exp.X_op == O_constant)
            {
            {
              int value;
              int value;
              unsigned int data_type;
              unsigned int data_type;
 
 
              if (pre_inc == 1)
              if (pre_inc == 1)
                data_type = _SIMM12;
                data_type = _SIMM12;
              else
              else
                data_type = _SIMM15;
                data_type = _SIMM15;
              dataptr = temp;
              dataptr = temp;
 
 
              if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
              if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
                  && (data_type != _SIMM16_LA)
                  && (data_type != _SIMM16_LA)
                  && (data_type != _VALUE_HI16)
                  && (data_type != _VALUE_HI16)
                  && (data_type != _VALUE_LO16)
                  && (data_type != _VALUE_LO16)
                  && (data_type != _IMM16)
                  && (data_type != _IMM16)
                  && (data_type != _IMM15)
                  && (data_type != _IMM15)
                  && (data_type != _IMM14)
                  && (data_type != _IMM14)
                  && (data_type != _IMM4)
                  && (data_type != _IMM4)
                  && (data_type != _IMM5)
                  && (data_type != _IMM5)
                  && (data_type != _IMM8)
                  && (data_type != _IMM8)
                  && (data_type != _IMM5_RSHIFT_1)
                  && (data_type != _IMM5_RSHIFT_1)
                  && (data_type != _IMM5_RSHIFT_2)
                  && (data_type != _IMM5_RSHIFT_2)
                  && (data_type != _SIMM14_NEG)
                  && (data_type != _SIMM14_NEG)
                  && (data_type != _IMM10_RSHIFT_2))
                  && (data_type != _IMM10_RSHIFT_2))
                {
                {
                  data_type += 24;
                  data_type += 24;
                }
                }
 
 
              value = validate_immediate (inst.reloc.exp.X_add_number, data_type, 0);
              value = validate_immediate (inst.reloc.exp.X_add_number, data_type, 0);
              if (value == (int) FAIL)
              if (value == (int) FAIL)
                {
                {
                  if (data_type < 30)
                  if (data_type < 30)
                    sprintf (err_msg,
                    sprintf (err_msg,
                             _("invalid constant: %d bit expression not in range %d..%d"),
                             _("invalid constant: %d bit expression not in range %d..%d"),
                             score_df_range[data_type].bits,
                             score_df_range[data_type].bits,
                             score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
                             score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
                  else
                  else
                    sprintf (err_msg,
                    sprintf (err_msg,
                             _("invalid constant: %d bit expression not in range %d..%d"),
                             _("invalid constant: %d bit expression not in range %d..%d"),
                             score_df_range[data_type - 24].bits,
                             score_df_range[data_type - 24].bits,
                             score_df_range[data_type - 24].range[0],
                             score_df_range[data_type - 24].range[0],
                             score_df_range[data_type - 24].range[1]);
                             score_df_range[data_type - 24].range[1]);
                  inst.error = err_msg;
                  inst.error = err_msg;
                  return;
                  return;
                }
                }
 
 
              value &= (1 << score_df_range[data_type].bits) - 1;
              value &= (1 << score_df_range[data_type].bits) - 1;
              ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
              ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
              inst.instruction &= ~OPC_PSEUDOLDST_MASK;
              inst.instruction &= ~OPC_PSEUDOLDST_MASK;
              inst.instruction |= score_ldst_insns[ldst_idx * 3 + pre_inc].value;
              inst.instruction |= score_ldst_insns[ldst_idx * 3 + pre_inc].value;
              if (pre_inc == 1)
              if (pre_inc == 1)
                inst.instruction |= value << 3;
                inst.instruction |= value << 3;
              else
              else
                inst.instruction |= value;
                inst.instruction |= value;
 
 
              /* lw rD, [rA, simm15]  */
              /* lw rD, [rA, simm15]  */
              if ((inst.instruction & 0x3e000000) == 0x20000000)
              if ((inst.instruction & 0x3e000000) == 0x20000000)
                {
                {
                  /* Both rD and rA are in [r0 - r15].  */
                  /* Both rD and rA are in [r0 - r15].  */
                  if ((((inst.instruction >> 15) & 0x10) == 0)
                  if ((((inst.instruction >> 15) & 0x10) == 0)
                      && (((inst.instruction >> 20) & 0x10) == 0))
                      && (((inst.instruction >> 20) & 0x10) == 0))
                    {
                    {
                      /* simm15 = 0, lw -> lw!.  */
                      /* simm15 = 0, lw -> lw!.  */
                      if ((inst.instruction & 0x7fff) == 0)
                      if ((inst.instruction & 0x7fff) == 0)
                        {
                        {
                          inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
                          inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
                            | (((inst.instruction >> 20) & 0xf) << 8);
                            | (((inst.instruction >> 20) & 0xf) << 8);
                          inst.relax_size = 2;
                          inst.relax_size = 2;
                        }
                        }
                      /* rA = r2, lw -> lwp!.  */
                      /* rA = r2, lw -> lwp!.  */
                      else if ((((inst.instruction >> 15) & 0xf) == 2)
                      else if ((((inst.instruction >> 15) & 0xf) == 2)
                               && ((inst.instruction & 0x3) == 0)
                               && ((inst.instruction & 0x3) == 0)
                               && ((inst.instruction & 0x7fff) < 128))
                               && ((inst.instruction & 0x7fff) < 128))
                        {
                        {
                          inst.relax_inst = 0x7000 | (((inst.instruction >> 20) & 0xf) << 8)
                          inst.relax_inst = 0x7000 | (((inst.instruction >> 20) & 0xf) << 8)
                            | (((inst.instruction & 0x7fff) >> 2) << 3);
                            | (((inst.instruction & 0x7fff) >> 2) << 3);
                          inst.relax_size = 2;
                          inst.relax_size = 2;
                        }
                        }
                      else
                      else
                        {
                        {
                          inst.relax_inst = 0x8000;
                          inst.relax_inst = 0x8000;
                        }
                        }
                    }
                    }
                  else
                  else
                    {
                    {
                      inst.relax_inst = 0x8000;
                      inst.relax_inst = 0x8000;
                    }
                    }
                }
                }
              /* sw rD, [rA, simm15]  */
              /* sw rD, [rA, simm15]  */
              else if ((inst.instruction & 0x3e000000) == 0x28000000)
              else if ((inst.instruction & 0x3e000000) == 0x28000000)
                {
                {
                  /* Both rD and rA are in [r0 - r15].  */
                  /* Both rD and rA are in [r0 - r15].  */
                  if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
                  if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
                    {
                    {
                      /* simm15 = 0, sw -> sw!.  */
                      /* simm15 = 0, sw -> sw!.  */
                      if ((inst.instruction & 0x7fff) == 0)
                      if ((inst.instruction & 0x7fff) == 0)
                        {
                        {
                          inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
                          inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
                            | (((inst.instruction >> 20) & 0xf) << 8);
                            | (((inst.instruction >> 20) & 0xf) << 8);
                          inst.relax_size = 2;
                          inst.relax_size = 2;
                        }
                        }
                      /* rA = r2, sw -> swp!.  */
                      /* rA = r2, sw -> swp!.  */
                      else if ((((inst.instruction >> 15) & 0xf) == 2)
                      else if ((((inst.instruction >> 15) & 0xf) == 2)
                               && ((inst.instruction & 0x3) == 0)
                               && ((inst.instruction & 0x3) == 0)
                               && ((inst.instruction & 0x7fff) < 128))
                               && ((inst.instruction & 0x7fff) < 128))
                        {
                        {
                          inst.relax_inst = 0x7004 | (((inst.instruction >> 20) & 0xf) << 8)
                          inst.relax_inst = 0x7004 | (((inst.instruction >> 20) & 0xf) << 8)
                            | (((inst.instruction & 0x7fff) >> 2) << 3);
                            | (((inst.instruction & 0x7fff) >> 2) << 3);
                          inst.relax_size = 2;
                          inst.relax_size = 2;
                        }
                        }
                      else
                      else
                        {
                        {
                          inst.relax_inst = 0x8000;
                          inst.relax_inst = 0x8000;
                        }
                        }
                    }
                    }
                  else
                  else
                    {
                    {
                      inst.relax_inst = 0x8000;
                      inst.relax_inst = 0x8000;
                    }
                    }
                }
                }
              /* sw rD, [rA, simm15]+    sw pre.  */
              /* sw rD, [rA, simm15]+    sw pre.  */
              else if ((inst.instruction & 0x3e000007) == 0x06000004)
              else if ((inst.instruction & 0x3e000007) == 0x06000004)
                {
                {
                  /* rA is in [r0 - r7], and simm15 = -4.  */
                  /* rA is in [r0 - r7], and simm15 = -4.  */
                  if ((((inst.instruction >> 15) & 0x18) == 0)
                  if ((((inst.instruction >> 15) & 0x18) == 0)
                      && (((inst.instruction >> 3) & 0xfff) == 0xffc))
                      && (((inst.instruction >> 3) & 0xfff) == 0xffc))
                    {
                    {
                      /* sw -> pushhi!.  */
                      /* sw -> pushhi!.  */
                      if ((((inst.instruction >> 20) & 0x10) == 0x10))
                      if ((((inst.instruction >> 20) & 0x10) == 0x10))
                        {
                        {
                          inst.relax_inst = 0x0000200e | (((inst.instruction >> 20) & 0xf) << 8)
                          inst.relax_inst = 0x0000200e | (((inst.instruction >> 20) & 0xf) << 8)
                            | 1 << 7 | (((inst.instruction >> 15) & 0x7) << 4);
                            | 1 << 7 | (((inst.instruction >> 15) & 0x7) << 4);
                          inst.relax_size = 2;
                          inst.relax_size = 2;
                        }
                        }
                      /* sw -> push!.  */
                      /* sw -> push!.  */
                      else
                      else
                        {
                        {
                          inst.relax_inst = 0x0000200e | (((inst.instruction >> 20) & 0xf) << 8)
                          inst.relax_inst = 0x0000200e | (((inst.instruction >> 20) & 0xf) << 8)
                            | 0 << 7 | (((inst.instruction >> 15) & 0x7) << 4);
                            | 0 << 7 | (((inst.instruction >> 15) & 0x7) << 4);
                          inst.relax_size = 2;
                          inst.relax_size = 2;
                        }
                        }
                    }
                    }
                  else
                  else
                    {
                    {
                      inst.relax_inst = 0x8000;
                      inst.relax_inst = 0x8000;
                    }
                    }
                }
                }
              /* lh rD, [rA, simm15]  */
              /* lh rD, [rA, simm15]  */
              else if ((inst.instruction & 0x3e000000) == 0x22000000)
              else if ((inst.instruction & 0x3e000000) == 0x22000000)
                {
                {
                  /* Both rD and rA are in [r0 - r15].  */
                  /* Both rD and rA are in [r0 - r15].  */
                  if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
                  if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
                    {
                    {
                      /* simm15 = 0, lh -> lh!.  */
                      /* simm15 = 0, lh -> lh!.  */
                      if ((inst.instruction & 0x7fff) == 0)
                      if ((inst.instruction & 0x7fff) == 0)
                        {
                        {
                          inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
                          inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
                            | (((inst.instruction >> 20) & 0xf) << 8);
                            | (((inst.instruction >> 20) & 0xf) << 8);
                          inst.relax_size = 2;
                          inst.relax_size = 2;
                        }
                        }
                      /* rA = r2, lh -> lhp!.  */
                      /* rA = r2, lh -> lhp!.  */
                      else if ((((inst.instruction >> 15) & 0xf) == 2)
                      else if ((((inst.instruction >> 15) & 0xf) == 2)
                               && ((inst.instruction & 0x1) == 0)
                               && ((inst.instruction & 0x1) == 0)
                               && ((inst.instruction & 0x7fff) < 64))
                               && ((inst.instruction & 0x7fff) < 64))
                        {
                        {
                          inst.relax_inst = 0x7001 | (((inst.instruction >> 20) & 0xf) << 8)
                          inst.relax_inst = 0x7001 | (((inst.instruction >> 20) & 0xf) << 8)
                            | (((inst.instruction & 0x7fff) >> 1) << 3);
                            | (((inst.instruction & 0x7fff) >> 1) << 3);
                          inst.relax_size = 2;
                          inst.relax_size = 2;
                        }
                        }
                      else
                      else
                        {
                        {
                          inst.relax_inst = 0x8000;
                          inst.relax_inst = 0x8000;
                        }
                        }
                    }
                    }
                  else
                  else
                    {
                    {
                      inst.relax_inst = 0x8000;
                      inst.relax_inst = 0x8000;
                    }
                    }
                }
                }
              /* sh rD, [rA, simm15]  */
              /* sh rD, [rA, simm15]  */
              else if ((inst.instruction & 0x3e000000) == 0x2a000000)
              else if ((inst.instruction & 0x3e000000) == 0x2a000000)
                {
                {
                  /* Both rD and rA are in [r0 - r15].  */
                  /* Both rD and rA are in [r0 - r15].  */
                  if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
                  if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
                    {
                    {
                      /* simm15 = 0, sh -> sh!.  */
                      /* simm15 = 0, sh -> sh!.  */
                      if ((inst.instruction & 0x7fff) == 0)
                      if ((inst.instruction & 0x7fff) == 0)
                        {
                        {
                          inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
                          inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
                            | (((inst.instruction >> 20) & 0xf) << 8);
                            | (((inst.instruction >> 20) & 0xf) << 8);
                          inst.relax_size = 2;
                          inst.relax_size = 2;
                        }
                        }
                      /* rA = r2, sh -> shp!.  */
                      /* rA = r2, sh -> shp!.  */
                      else if ((((inst.instruction >> 15) & 0xf) == 2)
                      else if ((((inst.instruction >> 15) & 0xf) == 2)
                               && ((inst.instruction & 0x1) == 0)
                               && ((inst.instruction & 0x1) == 0)
                               && ((inst.instruction & 0x7fff) < 64))
                               && ((inst.instruction & 0x7fff) < 64))
                        {
                        {
                          inst.relax_inst = 0x7005 | (((inst.instruction >> 20) & 0xf) << 8)
                          inst.relax_inst = 0x7005 | (((inst.instruction >> 20) & 0xf) << 8)
                            | (((inst.instruction & 0x7fff) >> 1) << 3);
                            | (((inst.instruction & 0x7fff) >> 1) << 3);
                          inst.relax_size = 2;
                          inst.relax_size = 2;
                        }
                        }
                      else
                      else
                        {
                        {
                          inst.relax_inst = 0x8000;
                          inst.relax_inst = 0x8000;
                        }
                        }
                    }
                    }
                  else
                  else
                    {
                    {
                      inst.relax_inst = 0x8000;
                      inst.relax_inst = 0x8000;
                    }
                    }
                }
                }
              /* lbu rD, [rA, simm15]  */
              /* lbu rD, [rA, simm15]  */
              else if ((inst.instruction & 0x3e000000) == 0x2c000000)
              else if ((inst.instruction & 0x3e000000) == 0x2c000000)
                {
                {
                  /* Both rD and rA are in [r0 - r15].  */
                  /* Both rD and rA are in [r0 - r15].  */
                  if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
                  if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
                    {
                    {
                      /* simm15 = 0, lbu -> lbu!.  */
                      /* simm15 = 0, lbu -> lbu!.  */
                      if ((inst.instruction & 0x7fff) == 0)
                      if ((inst.instruction & 0x7fff) == 0)
                        {
                        {
                          inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
                          inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
                            | (((inst.instruction >> 20) & 0xf) << 8);
                            | (((inst.instruction >> 20) & 0xf) << 8);
                          inst.relax_size = 2;
                          inst.relax_size = 2;
                        }
                        }
                      /* rA = r2, lbu -> lbup!.  */
                      /* rA = r2, lbu -> lbup!.  */
                      else if ((((inst.instruction >> 15) & 0xf) == 2)
                      else if ((((inst.instruction >> 15) & 0xf) == 2)
                               && ((inst.instruction & 0x7fff) < 32))
                               && ((inst.instruction & 0x7fff) < 32))
                        {
                        {
                          inst.relax_inst = 0x7003 | (((inst.instruction >> 20) & 0xf) << 8)
                          inst.relax_inst = 0x7003 | (((inst.instruction >> 20) & 0xf) << 8)
                            | ((inst.instruction & 0x7fff) << 3);
                            | ((inst.instruction & 0x7fff) << 3);
                          inst.relax_size = 2;
                          inst.relax_size = 2;
                        }
                        }
                      else
                      else
                        {
                        {
                          inst.relax_inst = 0x8000;
                          inst.relax_inst = 0x8000;
                        }
                        }
                    }
                    }
                  else
                  else
                    {
                    {
                      inst.relax_inst = 0x8000;
                      inst.relax_inst = 0x8000;
                    }
                    }
                }
                }
              /* sb rD, [rA, simm15]  */
              /* sb rD, [rA, simm15]  */
              else if ((inst.instruction & 0x3e000000) == 0x2e000000)
              else if ((inst.instruction & 0x3e000000) == 0x2e000000)
                {
                {
                  /* Both rD and rA are in [r0 - r15].  */
                  /* Both rD and rA are in [r0 - r15].  */
                  if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
                  if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
                    {
                    {
                      /* simm15 = 0, sb -> sb!.  */
                      /* simm15 = 0, sb -> sb!.  */
                      if ((inst.instruction & 0x7fff) == 0)
                      if ((inst.instruction & 0x7fff) == 0)
                        {
                        {
                          inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
                          inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
                            | (((inst.instruction >> 20) & 0xf) << 8);
                            | (((inst.instruction >> 20) & 0xf) << 8);
                          inst.relax_size = 2;
                          inst.relax_size = 2;
                        }
                        }
                      /* rA = r2, sb -> sb!.  */
                      /* rA = r2, sb -> sb!.  */
                      else if ((((inst.instruction >> 15) & 0xf) == 2)
                      else if ((((inst.instruction >> 15) & 0xf) == 2)
                               && ((inst.instruction & 0x7fff) < 32))
                               && ((inst.instruction & 0x7fff) < 32))
                        {
                        {
                          inst.relax_inst = 0x7007 | (((inst.instruction >> 20) & 0xf) << 8)
                          inst.relax_inst = 0x7007 | (((inst.instruction >> 20) & 0xf) << 8)
                            | ((inst.instruction & 0x7fff) << 3);
                            | ((inst.instruction & 0x7fff) << 3);
                          inst.relax_size = 2;
                          inst.relax_size = 2;
                        }
                        }
                      else
                      else
                        {
                        {
                          inst.relax_inst = 0x8000;
                          inst.relax_inst = 0x8000;
                        }
                        }
                    }
                    }
                  else
                  else
                    {
                    {
                      inst.relax_inst = 0x8000;
                      inst.relax_inst = 0x8000;
                    }
                    }
                }
                }
              else
              else
                {
                {
                  inst.relax_inst = 0x8000;
                  inst.relax_inst = 0x8000;
                }
                }
 
 
              return;
              return;
            }
            }
          else
          else
            {
            {
              /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
              /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
              inst.reloc.pc_rel = 0;
              inst.reloc.pc_rel = 0;
            }
            }
        }
        }
    }
    }
  else
  else
    {
    {
      inst.error = BAD_ARGS;
      inst.error = BAD_ARGS;
    }
    }
}
}
 
 
/* Handle cache.  */
/* Handle cache.  */
 
 
static void
static void
do_cache (char *str)
do_cache (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if ((data_op2 (&str, 20, _IMM5) == (int) FAIL) || (skip_past_comma (&str) == (int) FAIL))
  if ((data_op2 (&str, 20, _IMM5) == (int) FAIL) || (skip_past_comma (&str) == (int) FAIL))
    {
    {
      return;
      return;
    }
    }
  else
  else
    {
    {
      int cache_op;
      int cache_op;
 
 
      cache_op = (inst.instruction >> 20) & 0x1F;
      cache_op = (inst.instruction >> 20) & 0x1F;
      sprintf (inst.name, "cache %d", cache_op);
      sprintf (inst.name, "cache %d", cache_op);
    }
    }
 
 
  if (*str == '[')
  if (*str == '[')
    {
    {
      str++;
      str++;
      skip_whitespace (str);
      skip_whitespace (str);
 
 
      if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL)
      if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL)
        return;
        return;
 
 
      skip_whitespace (str);
      skip_whitespace (str);
 
 
      /* cache op, [rA]  */
      /* cache op, [rA]  */
      if (skip_past_comma (&str) == (int) FAIL)
      if (skip_past_comma (&str) == (int) FAIL)
        {
        {
          SET_INSN_ERROR (NULL);
          SET_INSN_ERROR (NULL);
          if (*str != ']')
          if (*str != ']')
            {
            {
              inst.error = _("missing ]");
              inst.error = _("missing ]");
              return;
              return;
            }
            }
          str++;
          str++;
        }
        }
      /* cache op, [rA, simm15]  */
      /* cache op, [rA, simm15]  */
      else
      else
        {
        {
          if (exp_ldst_offset (&str, 0, _SIMM15) == (int) FAIL)
          if (exp_ldst_offset (&str, 0, _SIMM15) == (int) FAIL)
            {
            {
              return;
              return;
            }
            }
 
 
          skip_whitespace (str);
          skip_whitespace (str);
          if (*str++ != ']')
          if (*str++ != ']')
            {
            {
              inst.error = _("missing ]");
              inst.error = _("missing ]");
              return;
              return;
            }
            }
        }
        }
 
 
      if (end_of_line (str) == (int) FAIL)
      if (end_of_line (str) == (int) FAIL)
        return;
        return;
    }
    }
  else
  else
    {
    {
      inst.error = BAD_ARGS;
      inst.error = BAD_ARGS;
    }
    }
}
}
 
 
static void
static void
do_crdcrscrsimm5 (char *str)
do_crdcrscrsimm5 (char *str)
{
{
  char *strbak;
  char *strbak;
 
 
  strbak = str;
  strbak = str;
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (reg_required_here (&str, 20, REG_TYPE_SCORE_CR) == (int) FAIL
  if (reg_required_here (&str, 20, REG_TYPE_SCORE_CR) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || reg_required_here (&str, 15, REG_TYPE_SCORE_CR) == (int) FAIL
      || reg_required_here (&str, 15, REG_TYPE_SCORE_CR) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL
      || reg_required_here (&str, 10, REG_TYPE_SCORE_CR) == (int) FAIL
      || reg_required_here (&str, 10, REG_TYPE_SCORE_CR) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL)
      || skip_past_comma (&str) == (int) FAIL)
    {
    {
      str = strbak;
      str = strbak;
      /* cop1 cop_code20.  */
      /* cop1 cop_code20.  */
      if (data_op2 (&str, 5, _IMM20) == (int) FAIL)
      if (data_op2 (&str, 5, _IMM20) == (int) FAIL)
        return;
        return;
    }
    }
  else
  else
    {
    {
      if (data_op2 (&str, 5, _IMM5) == (int) FAIL)
      if (data_op2 (&str, 5, _IMM5) == (int) FAIL)
        return;
        return;
    }
    }
 
 
  end_of_line (str);
  end_of_line (str);
}
}
 
 
/* Handle ldc/stc.  */
/* Handle ldc/stc.  */
static void
static void
do_ldst_cop (char *str)
do_ldst_cop (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if ((reg_required_here (&str, 15, REG_TYPE_SCORE_CR) == (int) FAIL)
  if ((reg_required_here (&str, 15, REG_TYPE_SCORE_CR) == (int) FAIL)
      || (skip_past_comma (&str) == (int) FAIL))
      || (skip_past_comma (&str) == (int) FAIL))
    return;
    return;
 
 
  if (*str == '[')
  if (*str == '[')
    {
    {
      str++;
      str++;
      skip_whitespace (str);
      skip_whitespace (str);
 
 
      if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL)
      if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL)
        return;
        return;
 
 
      skip_whitespace (str);
      skip_whitespace (str);
 
 
      if (*str++ != ']')
      if (*str++ != ']')
        {
        {
          if (exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) FAIL)
          if (exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) FAIL)
            return;
            return;
 
 
          skip_whitespace (str);
          skip_whitespace (str);
          if (*str++ != ']')
          if (*str++ != ']')
            {
            {
              inst.error = _("missing ]");
              inst.error = _("missing ]");
              return;
              return;
            }
            }
        }
        }
 
 
      end_of_line (str);
      end_of_line (str);
    }
    }
  else
  else
    inst.error = BAD_ARGS;
    inst.error = BAD_ARGS;
}
}
 
 
static void
static void
do16_ldst_insn (char *str)
do16_ldst_insn (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if ((reglow_required_here (&str, 8) == (int) FAIL) || (skip_past_comma (&str) == (int) FAIL))
  if ((reglow_required_here (&str, 8) == (int) FAIL) || (skip_past_comma (&str) == (int) FAIL))
    return;
    return;
 
 
  if (*str == '[')
  if (*str == '[')
    {
    {
      int reg;
      int reg;
 
 
      str++;
      str++;
      skip_whitespace (str);
      skip_whitespace (str);
 
 
      if ((reg = reglow_required_here (&str, 4)) == (int) FAIL)
      if ((reg = reglow_required_here (&str, 4)) == (int) FAIL)
        return;
        return;
 
 
      skip_whitespace (str);
      skip_whitespace (str);
      if (*str++ == ']')
      if (*str++ == ']')
        {
        {
          if (end_of_line (str) == (int) FAIL)
          if (end_of_line (str) == (int) FAIL)
            return;
            return;
          else
          else
            {
            {
              inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
              inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
                              | (((inst.instruction >> 4) & 0xf) << 15);
                              | (((inst.instruction >> 4) & 0xf) << 15);
              inst.relax_size = 4;
              inst.relax_size = 4;
            }
            }
        }
        }
      else
      else
        {
        {
          inst.error = _("missing ]");
          inst.error = _("missing ]");
        }
        }
    }
    }
  else
  else
    {
    {
      inst.error = BAD_ARGS;
      inst.error = BAD_ARGS;
    }
    }
}
}
 
 
/* Handle lbup!/lhp!/ldiu!/lwp!/sbp!/shp!/swp!.  */
/* Handle lbup!/lhp!/ldiu!/lwp!/sbp!/shp!/swp!.  */
static void
static void
do16_ldst_imm_insn (char *str)
do16_ldst_imm_insn (char *str)
{
{
  char data_exp[MAX_LITERAL_POOL_SIZE];
  char data_exp[MAX_LITERAL_POOL_SIZE];
  int reg_rd;
  int reg_rd;
  char *dataptr = NULL, *pp = NULL;
  char *dataptr = NULL, *pp = NULL;
  int cnt = 0;
  int cnt = 0;
  int assign_data = (int) FAIL;
  int assign_data = (int) FAIL;
  unsigned int ldst_func;
  unsigned int ldst_func;
 
 
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if (((reg_rd = reglow_required_here (&str, 8)) == (int) FAIL)
  if (((reg_rd = reglow_required_here (&str, 8)) == (int) FAIL)
      || (skip_past_comma (&str) == (int) FAIL))
      || (skip_past_comma (&str) == (int) FAIL))
    return;
    return;
 
 
  skip_whitespace (str);
  skip_whitespace (str);
  dataptr = str;
  dataptr = str;
 
 
  while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= MAX_LITERAL_POOL_SIZE))
  while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= MAX_LITERAL_POOL_SIZE))
    {
    {
      data_exp[cnt] = *dataptr;
      data_exp[cnt] = *dataptr;
      dataptr++;
      dataptr++;
      cnt++;
      cnt++;
    }
    }
 
 
  data_exp[cnt] = '\0';
  data_exp[cnt] = '\0';
  pp = &data_exp[0];
  pp = &data_exp[0];
 
 
  str = dataptr;
  str = dataptr;
 
 
  ldst_func = inst.instruction & LDST16_RI_MASK;
  ldst_func = inst.instruction & LDST16_RI_MASK;
  if (ldst_func == N16_LIU)
  if (ldst_func == N16_LIU)
    assign_data = exp_ldst_offset (&pp, 0, _IMM8);
    assign_data = exp_ldst_offset (&pp, 0, _IMM8);
  else if (ldst_func == N16_LHP || ldst_func == N16_SHP)
  else if (ldst_func == N16_LHP || ldst_func == N16_SHP)
    assign_data = exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_1);
    assign_data = exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_1);
  else if (ldst_func == N16_LWP || ldst_func == N16_SWP)
  else if (ldst_func == N16_LWP || ldst_func == N16_SWP)
    assign_data = exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_2);
    assign_data = exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_2);
  else
  else
    assign_data = exp_ldst_offset (&pp, 3, _IMM5);
    assign_data = exp_ldst_offset (&pp, 3, _IMM5);
 
 
  if ((assign_data == (int) FAIL) || (end_of_line (pp) == (int) FAIL))
  if ((assign_data == (int) FAIL) || (end_of_line (pp) == (int) FAIL))
    return;
    return;
  else
  else
    {
    {
      if ((inst.instruction & 0x7000) == N16_LIU)
      if ((inst.instruction & 0x7000) == N16_LIU)
        {
        {
          inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20
          inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20
                          | ((inst.instruction & 0xff) << 1);
                          | ((inst.instruction & 0xff) << 1);
        }
        }
      else if (((inst.instruction & 0x7007) == N16_LHP)
      else if (((inst.instruction & 0x7007) == N16_LHP)
               || ((inst.instruction & 0x7007) == N16_SHP))
               || ((inst.instruction & 0x7007) == N16_SHP))
        {
        {
          inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
          inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
                          | (((inst.instruction >> 3) & 0x1f) << 1);
                          | (((inst.instruction >> 3) & 0x1f) << 1);
        }
        }
      else if (((inst.instruction & 0x7007) == N16_LWP)
      else if (((inst.instruction & 0x7007) == N16_LWP)
               || ((inst.instruction & 0x7007) == N16_SWP))
               || ((inst.instruction & 0x7007) == N16_SWP))
        {
        {
          inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
          inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
                          | (((inst.instruction >> 3) & 0x1f) << 2);
                          | (((inst.instruction >> 3) & 0x1f) << 2);
        }
        }
      else if (((inst.instruction & 0x7007) == N16_LBUP)
      else if (((inst.instruction & 0x7007) == N16_LBUP)
               || ((inst.instruction & 0x7007) == N16_SBP))
               || ((inst.instruction & 0x7007) == N16_SBP))
        {
        {
          inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
          inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
                          | (((inst.instruction >> 3) & 0x1f));
                          | (((inst.instruction >> 3) & 0x1f));
        }
        }
 
 
      inst.relax_size = 4;
      inst.relax_size = 4;
    }
    }
}
}
 
 
static void
static void
do16_push_pop (char *str)
do16_push_pop (char *str)
{
{
  int reg_rd;
  int reg_rd;
  int H_bit_mask = 0;
  int H_bit_mask = 0;
 
 
  skip_whitespace (str);
  skip_whitespace (str);
  if (((reg_rd = reg_required_here (&str, 8, REG_TYPE_SCORE)) == (int) FAIL)
  if (((reg_rd = reg_required_here (&str, 8, REG_TYPE_SCORE)) == (int) FAIL)
      || (skip_past_comma (&str) == (int) FAIL))
      || (skip_past_comma (&str) == (int) FAIL))
    return;
    return;
 
 
  if (reg_rd >= 16)
  if (reg_rd >= 16)
    H_bit_mask = 1;
    H_bit_mask = 1;
 
 
  /* reg_required_here will change bit 12 of opcode, so we must restore bit 12.  */
  /* reg_required_here will change bit 12 of opcode, so we must restore bit 12.  */
  inst.instruction &= ~(1 << 12);
  inst.instruction &= ~(1 << 12);
 
 
  inst.instruction |= H_bit_mask << 7;
  inst.instruction |= H_bit_mask << 7;
 
 
  if (*str == '[')
  if (*str == '[')
    {
    {
      int reg;
      int reg;
 
 
      str++;
      str++;
      skip_whitespace (str);
      skip_whitespace (str);
      if ((reg = reg_required_here (&str, 4, REG_TYPE_SCORE)) == (int) FAIL)
      if ((reg = reg_required_here (&str, 4, REG_TYPE_SCORE)) == (int) FAIL)
        return;
        return;
      else if (reg > 7)
      else if (reg > 7)
        {
        {
          if (!inst.error)
          if (!inst.error)
            inst.error = _("base register nums are over 3 bit");
            inst.error = _("base register nums are over 3 bit");
 
 
          return;
          return;
        }
        }
 
 
      skip_whitespace (str);
      skip_whitespace (str);
      if ((*str++ != ']') || (end_of_line (str) == (int) FAIL))
      if ((*str++ != ']') || (end_of_line (str) == (int) FAIL))
        {
        {
          if (!inst.error)
          if (!inst.error)
            inst.error = _("missing ]");
            inst.error = _("missing ]");
 
 
          return;
          return;
        }
        }
 
 
      /* pop! */
      /* pop! */
      if ((inst.instruction & 0xf) == 0xa)
      if ((inst.instruction & 0xf) == 0xa)
        {
        {
          if (H_bit_mask)
          if (H_bit_mask)
            {
            {
              inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
              inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
                                  | (((inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
                                  | (((inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
            }
            }
          else
          else
            {
            {
              inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
              inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
                                  | (((inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
                                  | (((inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
            }
            }
        }
        }
      /* push! */
      /* push! */
      else
      else
        {
        {
          if (H_bit_mask)
          if (H_bit_mask)
            {
            {
              inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
              inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
                                  | (((inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
                                  | (((inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
            }
            }
          else
          else
            {
            {
              inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
              inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
                                  | (((inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
                                  | (((inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
            }
            }
        }
        }
      inst.relax_size = 4;
      inst.relax_size = 4;
    }
    }
  else
  else
    {
    {
      inst.error = BAD_ARGS;
      inst.error = BAD_ARGS;
    }
    }
}
}
 
 
/* Handle lcb/lcw/lce/scb/scw/sce.  */
/* Handle lcb/lcw/lce/scb/scw/sce.  */
static void
static void
do_ldst_unalign (char *str)
do_ldst_unalign (char *str)
{
{
  int conflict_reg;
  int conflict_reg;
 
 
  if (university_version == 1)
  if (university_version == 1)
    {
    {
      inst.error = ERR_FOR_SCORE5U_ATOMIC;
      inst.error = ERR_FOR_SCORE5U_ATOMIC;
      return;
      return;
    }
    }
 
 
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  /* lcb/scb [rA]+.  */
  /* lcb/scb [rA]+.  */
  if (*str == '[')
  if (*str == '[')
    {
    {
      str++;
      str++;
      skip_whitespace (str);
      skip_whitespace (str);
 
 
      if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL)
      if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL)
        return;
        return;
 
 
      if (*str++ == ']')
      if (*str++ == ']')
        {
        {
          if (*str++ != '+')
          if (*str++ != '+')
            {
            {
              inst.error = _("missing +");
              inst.error = _("missing +");
              return;
              return;
            }
            }
        }
        }
      else
      else
        {
        {
          inst.error = _("missing ]");
          inst.error = _("missing ]");
          return;
          return;
        }
        }
 
 
      if (end_of_line (str) == (int) FAIL)
      if (end_of_line (str) == (int) FAIL)
        return;
        return;
    }
    }
  /* lcw/lce/scb/sce rD, [rA]+.  */
  /* lcw/lce/scb/sce rD, [rA]+.  */
  else
  else
    {
    {
      if (((conflict_reg = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
      if (((conflict_reg = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
          || (skip_past_comma (&str) == (int) FAIL))
          || (skip_past_comma (&str) == (int) FAIL))
        {
        {
          return;
          return;
        }
        }
 
 
      skip_whitespace (str);
      skip_whitespace (str);
      if (*str++ == '[')
      if (*str++ == '[')
        {
        {
          int reg;
          int reg;
 
 
          skip_whitespace (str);
          skip_whitespace (str);
          if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
          if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
            {
            {
              return;
              return;
            }
            }
 
 
          /* Conflicts can occur on stores as well as loads.  */
          /* Conflicts can occur on stores as well as loads.  */
          conflict_reg = (conflict_reg == reg);
          conflict_reg = (conflict_reg == reg);
          skip_whitespace (str);
          skip_whitespace (str);
          if (*str++ == ']')
          if (*str++ == ']')
            {
            {
              unsigned int ldst_func = inst.instruction & LDST_UNALIGN_MASK;
              unsigned int ldst_func = inst.instruction & LDST_UNALIGN_MASK;
 
 
              if (*str++ == '+')
              if (*str++ == '+')
                {
                {
                  if (conflict_reg)
                  if (conflict_reg)
                    {
                    {
                      as_warn (_("%s register same as write-back base"),
                      as_warn (_("%s register same as write-back base"),
                               ((ldst_func & UA_LCE) || (ldst_func & UA_LCW)
                               ((ldst_func & UA_LCE) || (ldst_func & UA_LCW)
                                ? _("destination") : _("source")));
                                ? _("destination") : _("source")));
                    }
                    }
                }
                }
              else
              else
                {
                {
                  inst.error = _("missing +");
                  inst.error = _("missing +");
                  return;
                  return;
                }
                }
 
 
              if (end_of_line (str) == (int) FAIL)
              if (end_of_line (str) == (int) FAIL)
                return;
                return;
            }
            }
          else
          else
            {
            {
              inst.error = _("missing ]");
              inst.error = _("missing ]");
              return;
              return;
            }
            }
        }
        }
      else
      else
        {
        {
          inst.error = BAD_ARGS;
          inst.error = BAD_ARGS;
          return;
          return;
        }
        }
    }
    }
}
}
 
 
/* Handle alw/asw.  */
/* Handle alw/asw.  */
static void
static void
do_ldst_atomic (char *str)
do_ldst_atomic (char *str)
{
{
  if (university_version == 1)
  if (university_version == 1)
    {
    {
      inst.error = ERR_FOR_SCORE5U_ATOMIC;
      inst.error = ERR_FOR_SCORE5U_ATOMIC;
      return;
      return;
    }
    }
 
 
  skip_whitespace (str);
  skip_whitespace (str);
 
 
  if ((reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL)
  if ((reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL)
      || (skip_past_comma (&str) == (int) FAIL))
      || (skip_past_comma (&str) == (int) FAIL))
    {
    {
      return;
      return;
    }
    }
  else
  else
    {
    {
 
 
      skip_whitespace (str);
      skip_whitespace (str);
      if (*str++ == '[')
      if (*str++ == '[')
        {
        {
          int reg;
          int reg;
 
 
          skip_whitespace (str);
          skip_whitespace (str);
          if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
          if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
            {
            {
              return;
              return;
            }
            }
 
 
          skip_whitespace (str);
          skip_whitespace (str);
          if (*str++ != ']')
          if (*str++ != ']')
            {
            {
              inst.error = _("missing ]");
              inst.error = _("missing ]");
              return;
              return;
            }
            }
 
 
          end_of_line (str);
          end_of_line (str);
        }
        }
      else
      else
        inst.error = BAD_ARGS;
        inst.error = BAD_ARGS;
    }
    }
}
}
 
 
static void
static void
build_relax_frag (struct score_it fix_insts[RELAX_INST_NUM], int fix_num ATTRIBUTE_UNUSED,
build_relax_frag (struct score_it fix_insts[RELAX_INST_NUM], int fix_num ATTRIBUTE_UNUSED,
                  struct score_it var_insts[RELAX_INST_NUM], int var_num,
                  struct score_it var_insts[RELAX_INST_NUM], int var_num,
                  symbolS *add_symbol)
                  symbolS *add_symbol)
{
{
  int i;
  int i;
  char *p;
  char *p;
  fixS *fixp = NULL;
  fixS *fixp = NULL;
  fixS *cur_fixp = NULL;
  fixS *cur_fixp = NULL;
  long where;
  long where;
  struct score_it inst_main;
  struct score_it inst_main;
 
 
  memcpy (&inst_main, &fix_insts[0], sizeof (struct score_it));
  memcpy (&inst_main, &fix_insts[0], sizeof (struct score_it));
 
 
  /* Adjust instruction opcode and to be relaxed instruction opcode.  */
  /* Adjust instruction opcode and to be relaxed instruction opcode.  */
  inst_main.instruction = adjust_paritybit (inst_main.instruction, GET_INSN_CLASS (inst_main.type));
  inst_main.instruction = adjust_paritybit (inst_main.instruction, GET_INSN_CLASS (inst_main.type));
  inst_main.type = Insn_PIC;
  inst_main.type = Insn_PIC;
 
 
  for (i = 0; i < var_num; i++)
  for (i = 0; i < var_num; i++)
    {
    {
      inst_main.relax_size += var_insts[i].size;
      inst_main.relax_size += var_insts[i].size;
      var_insts[i].instruction = adjust_paritybit (var_insts[i].instruction,
      var_insts[i].instruction = adjust_paritybit (var_insts[i].instruction,
                                                   GET_INSN_CLASS (var_insts[i].type));
                                                   GET_INSN_CLASS (var_insts[i].type));
    }
    }
 
 
  /* Check data dependency.  */
  /* Check data dependency.  */
  handle_dependency (&inst_main);
  handle_dependency (&inst_main);
 
 
  /* Start a new frag if frag_now is not empty.  */
  /* Start a new frag if frag_now is not empty.  */
  if (frag_now_fix () != 0)
  if (frag_now_fix () != 0)
    {
    {
      if (!frag_now->tc_frag_data.is_insn)
      if (!frag_now->tc_frag_data.is_insn)
        {
        {
          frag_wane (frag_now);
          frag_wane (frag_now);
        }
        }
      frag_new (0);
      frag_new (0);
    }
    }
  frag_grow (20);
  frag_grow (20);
 
 
  /* Write fr_fix part.  */
  /* Write fr_fix part.  */
  p = frag_more (inst_main.size);
  p = frag_more (inst_main.size);
  md_number_to_chars (p, inst_main.instruction, inst_main.size);
  md_number_to_chars (p, inst_main.instruction, inst_main.size);
 
 
  if (inst_main.reloc.type != BFD_RELOC_NONE)
  if (inst_main.reloc.type != BFD_RELOC_NONE)
    fixp = fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
    fixp = fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
                          &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
                          &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
 
 
  frag_now->tc_frag_data.fixp = fixp;
  frag_now->tc_frag_data.fixp = fixp;
  cur_fixp = frag_now->tc_frag_data.fixp;
  cur_fixp = frag_now->tc_frag_data.fixp;
 
 
#ifdef OBJ_ELF
#ifdef OBJ_ELF
  dwarf2_emit_insn (inst_main.size);
  dwarf2_emit_insn (inst_main.size);
#endif
#endif
 
 
  where = p - frag_now->fr_literal + inst_main.size;
  where = p - frag_now->fr_literal + inst_main.size;
  for (i = 0; i < var_num; i++)
  for (i = 0; i < var_num; i++)
    {
    {
      if (i > 0)
      if (i > 0)
        where += var_insts[i - 1].size;
        where += var_insts[i - 1].size;
 
 
      if (var_insts[i].reloc.type != BFD_RELOC_NONE)
      if (var_insts[i].reloc.type != BFD_RELOC_NONE)
        {
        {
          fixp = fix_new_score (frag_now, where, var_insts[i].size,
          fixp = fix_new_score (frag_now, where, var_insts[i].size,
                                &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel,
                                &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel,
                                var_insts[i].reloc.type);
                                var_insts[i].reloc.type);
          if (fixp)
          if (fixp)
            {
            {
              if (cur_fixp)
              if (cur_fixp)
                {
                {
                  cur_fixp->fx_next = fixp;
                  cur_fixp->fx_next = fixp;
                  cur_fixp = cur_fixp->fx_next;
                  cur_fixp = cur_fixp->fx_next;
                }
                }
              else
              else
                {
                {
                  frag_now->tc_frag_data.fixp = fixp;
                  frag_now->tc_frag_data.fixp = fixp;
                  cur_fixp = frag_now->tc_frag_data.fixp;
                  cur_fixp = frag_now->tc_frag_data.fixp;
                }
                }
            }
            }
        }
        }
    }
    }
 
 
  p = frag_var (rs_machine_dependent, inst_main.relax_size + RELAX_PAD_BYTE, 0,
  p = frag_var (rs_machine_dependent, inst_main.relax_size + RELAX_PAD_BYTE, 0,
                RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type,
                RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type,
                0, inst_main.size, 0), add_symbol, 0, NULL);
                0, inst_main.size, 0), add_symbol, 0, NULL);
 
 
  /* Write fr_var part.
  /* Write fr_var part.
     no calling gen_insn_frag, no fixS will be generated.  */
     no calling gen_insn_frag, no fixS will be generated.  */
  for (i = 0; i < var_num; i++)
  for (i = 0; i < var_num; i++)
    {
    {
      md_number_to_chars (p, var_insts[i].instruction, var_insts[i].size);
      md_number_to_chars (p, var_insts[i].instruction, var_insts[i].size);
      p += var_insts[i].size;
      p += var_insts[i].size;
    }
    }
  /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
  /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
  inst.bwarn = -1;
  inst.bwarn = -1;
}
}
 
 
/* Build a relax frag for la instruction when generating PIC,
/* Build a relax frag for la instruction when generating PIC,
   external symbol first and local symbol second.  */
   external symbol first and local symbol second.  */
 
 
static void
static void
build_la_pic (int reg_rd, expressionS exp)
build_la_pic (int reg_rd, expressionS exp)
{
{
  symbolS *add_symbol = exp.X_add_symbol;
  symbolS *add_symbol = exp.X_add_symbol;
  offsetT add_number = exp.X_add_number;
  offsetT add_number = exp.X_add_number;
  struct score_it fix_insts[RELAX_INST_NUM];
  struct score_it fix_insts[RELAX_INST_NUM];
  struct score_it var_insts[RELAX_INST_NUM];
  struct score_it var_insts[RELAX_INST_NUM];
  int fix_num = 0;
  int fix_num = 0;
  int var_num = 0;
  int var_num = 0;
  char tmp[MAX_LITERAL_POOL_SIZE];
  char tmp[MAX_LITERAL_POOL_SIZE];
  int r1_bak;
  int r1_bak;
 
 
  r1_bak = nor1;
  r1_bak = nor1;
  nor1 = 0;
  nor1 = 0;
 
 
  if (add_number == 0)
  if (add_number == 0)
    {
    {
      fix_num = 1;
      fix_num = 1;
      var_num = 2;
      var_num = 2;
 
 
      /* For an external symbol, only one insn is generated;
      /* For an external symbol, only one insn is generated;
         For a local symbol, two insns are generated.  */
         For a local symbol, two insns are generated.  */
      /* Fix part
      /* Fix part
         For an external symbol: lw rD, <sym>($gp)
         For an external symbol: lw rD, <sym>($gp)
                                 (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15)  */
                                 (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15)  */
      sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
      sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
      if (append_insn (tmp, FALSE) == (int) FAIL)
      if (append_insn (tmp, FALSE) == (int) FAIL)
        return;
        return;
 
 
      if (reg_rd == PIC_CALL_REG)
      if (reg_rd == PIC_CALL_REG)
        inst.reloc.type = BFD_RELOC_SCORE_CALL15;
        inst.reloc.type = BFD_RELOC_SCORE_CALL15;
      memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
      memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
 
 
      /* Var part
      /* Var part
         For a local symbol :
         For a local symbol :
         lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)
         lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)
         addi rD, <sym>       (BFD_RELOC_GOT_LO16) */
         addi rD, <sym>       (BFD_RELOC_GOT_LO16) */
      inst.reloc.type = BFD_RELOC_SCORE_GOT15;
      inst.reloc.type = BFD_RELOC_SCORE_GOT15;
      memcpy (&var_insts[0], &inst, sizeof (struct score_it));
      memcpy (&var_insts[0], &inst, sizeof (struct score_it));
      sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, add_symbol->bsym->name);
      sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, add_symbol->bsym->name);
      if (append_insn (tmp, FALSE) == (int) FAIL)
      if (append_insn (tmp, FALSE) == (int) FAIL)
        return;
        return;
 
 
      memcpy (&var_insts[1], &inst, sizeof (struct score_it));
      memcpy (&var_insts[1], &inst, sizeof (struct score_it));
      build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
      build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
    }
    }
  else if (add_number >= -0x8000 && add_number <= 0x7fff)
  else if (add_number >= -0x8000 && add_number <= 0x7fff)
    {
    {
      /* Insn 1: lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)  */
      /* Insn 1: lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)  */
      sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
      sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
      if (append_insn (tmp, TRUE) == (int) FAIL)
      if (append_insn (tmp, TRUE) == (int) FAIL)
        return;
        return;
 
 
      /* Insn 2  */
      /* Insn 2  */
      fix_num = 1;
      fix_num = 1;
      var_num = 1;
      var_num = 1;
      /* Fix part
      /* Fix part
         For an external symbol: addi rD, <constant> */
         For an external symbol: addi rD, <constant> */
      sprintf (tmp, "addi r%d, %d", reg_rd, (int)add_number);
      sprintf (tmp, "addi r%d, %d", reg_rd, (int)add_number);
      if (append_insn (tmp, FALSE) == (int) FAIL)
      if (append_insn (tmp, FALSE) == (int) FAIL)
        return;
        return;
 
 
      memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
      memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
 
 
      /* Var part
      /* Var part
         For a local symbol: addi rD, <sym>+<constant>    (BFD_RELOC_GOT_LO16)  */
         For a local symbol: addi rD, <sym>+<constant>    (BFD_RELOC_GOT_LO16)  */
      sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd, add_symbol->bsym->name, (int)add_number);
      sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd, add_symbol->bsym->name, (int)add_number);
      if (append_insn (tmp, FALSE) == (int) FAIL)
      if (append_insn (tmp, FALSE) == (int) FAIL)
        return;
        return;
 
 
      memcpy (&var_insts[0], &inst, sizeof (struct score_it));
      memcpy (&var_insts[0], &inst, sizeof (struct score_it));
      build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
      build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
    }
    }
  else
  else
    {
    {
      int hi = (add_number >> 16) & 0x0000FFFF;
      int hi = (add_number >> 16) & 0x0000FFFF;
      int lo = add_number & 0x0000FFFF;
      int lo = add_number & 0x0000FFFF;
 
 
      /* Insn 1: lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)  */
      /* Insn 1: lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)  */
      sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
      sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
      if (append_insn (tmp, TRUE) == (int) FAIL)
      if (append_insn (tmp, TRUE) == (int) FAIL)
        return;
        return;
 
 
      /* Insn 2  */
      /* Insn 2  */
      fix_num = 1;
      fix_num = 1;
      var_num = 1;
      var_num = 1;
      /* Fix part
      /* Fix part
         For an external symbol: ldis r1, HI%<constant>  */
         For an external symbol: ldis r1, HI%<constant>  */
      sprintf (tmp, "ldis r1, %d", hi);
      sprintf (tmp, "ldis r1, %d", hi);
      if (append_insn (tmp, FALSE) == (int) FAIL)
      if (append_insn (tmp, FALSE) == (int) FAIL)
        return;
        return;
 
 
      memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
      memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
 
 
      /* Var part
      /* Var part
         For a local symbol: ldis r1, HI%<constant>
         For a local symbol: ldis r1, HI%<constant>
         but, if lo is outof 16 bit, make hi plus 1  */
         but, if lo is outof 16 bit, make hi plus 1  */
      if ((lo < -0x8000) || (lo > 0x7fff))
      if ((lo < -0x8000) || (lo > 0x7fff))
        {
        {
          hi += 1;
          hi += 1;
        }
        }
      sprintf (tmp, "ldis_pic r1, %d", hi);
      sprintf (tmp, "ldis_pic r1, %d", hi);
      if (append_insn (tmp, FALSE) == (int) FAIL)
      if (append_insn (tmp, FALSE) == (int) FAIL)
        return;
        return;
 
 
      memcpy (&var_insts[0], &inst, sizeof (struct score_it));
      memcpy (&var_insts[0], &inst, sizeof (struct score_it));
      build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
      build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
 
 
      /* Insn 3  */
      /* Insn 3  */
      fix_num = 1;
      fix_num = 1;
      var_num = 1;
      var_num = 1;
      /* Fix part
      /* Fix part
         For an external symbol: ori r1, LO%<constant>  */
         For an external symbol: ori r1, LO%<constant>  */
      sprintf (tmp, "ori r1, %d", lo);
      sprintf (tmp, "ori r1, %d", lo);
      if (append_insn (tmp, FALSE) == (int) FAIL)
      if (append_insn (tmp, FALSE) == (int) FAIL)
        return;
        return;
 
 
      memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
      memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
 
 
      /* Var part
      /* Var part
         For a local symbol: addi r1, <sym>+LO%<constant>    (BFD_RELOC_GOT_LO16)  */
         For a local symbol: addi r1, <sym>+LO%<constant>    (BFD_RELOC_GOT_LO16)  */
      sprintf (tmp, "addi_u_pic r1, %s + %d", add_symbol->bsym->name, lo);
      sprintf (tmp, "addi_u_pic r1, %s + %d", add_symbol->bsym->name, lo);
      if (append_insn (tmp, FALSE) == (int) FAIL)
      if (append_insn (tmp, FALSE) == (int) FAIL)
        return;
        return;
 
 
      memcpy (&var_insts[0], &inst, sizeof (struct score_it));
      memcpy (&var_insts[0], &inst, sizeof (struct score_it));
      build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
      build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
 
 
      /* Insn 4: add rD, rD, r1  */
      /* Insn 4: add rD, rD, r1  */
      sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd);
      sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd);
      if (append_insn (tmp, TRUE) == (int) FAIL)
      if (append_insn (tmp, TRUE) == (int) FAIL)
        return;
        return;
 
 
     /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
     /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
     inst.bwarn = -1;
     inst.bwarn = -1;
    }
    }
 
 
  nor1 = r1_bak;
  nor1 = r1_bak;
}
}
 
 
/* Handle la.  */
/* Handle la.  */
static void
static void
do_macro_la_rdi32 (char *str)
do_macro_la_rdi32 (char *str)
{
{
  int reg_rd;
  int reg_rd;
 
 
  skip_whitespace (str);
  skip_whitespace (str);
  if ((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL
  if ((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL)
      || skip_past_comma (&str) == (int) FAIL)
    {
    {
      return;
      return;
    }
    }
  else
  else
    {
    {
      char append_str[MAX_LITERAL_POOL_SIZE];
      char append_str[MAX_LITERAL_POOL_SIZE];
      char *keep_data = str;
      char *keep_data = str;
 
 
      /* la rd, simm16.  */
      /* la rd, simm16.  */
      if (data_op2 (&str, 1, _SIMM16_LA) != (int) FAIL)
      if (data_op2 (&str, 1, _SIMM16_LA) != (int) FAIL)
        {
        {
          end_of_line (str);
          end_of_line (str);
          return;
          return;
        }
        }
      /* la rd, imm32 or la rd, label.  */
      /* la rd, imm32 or la rd, label.  */
      else
      else
        {
        {
          SET_INSN_ERROR (NULL);
          SET_INSN_ERROR (NULL);
          str = keep_data;
          str = keep_data;
          if ((data_op2 (&str, 1, _VALUE_HI16) == (int) FAIL)
          if ((data_op2 (&str, 1, _VALUE_HI16) == (int) FAIL)
              || (end_of_line (str) == (int) FAIL))
              || (end_of_line (str) == (int) FAIL))
            {
            {
              return;
              return;
            }
            }
          else
          else
            {
            {
              if ((score_pic == NO_PIC) || (!inst.reloc.exp.X_add_symbol))
              if ((score_pic == NO_PIC) || (!inst.reloc.exp.X_add_symbol))
                {
                {
                  sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
                  sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
                  if (append_insn (append_str, TRUE) == (int) FAIL)
                  if (append_insn (append_str, TRUE) == (int) FAIL)
                    return;
                    return;
 
 
                  sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
                  sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
                  if (append_insn (append_str, TRUE) == (int) FAIL)
                  if (append_insn (append_str, TRUE) == (int) FAIL)
                    return;
                    return;
                }
                }
              else
              else
                {
                {
                  assert (inst.reloc.exp.X_add_symbol);
                  assert (inst.reloc.exp.X_add_symbol);
                  build_la_pic (reg_rd, inst.reloc.exp);
                  build_la_pic (reg_rd, inst.reloc.exp);
                }
                }
 
 
              /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
              /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
              inst.bwarn = -1;
              inst.bwarn = -1;
            }
            }
        }
        }
    }
    }
}
}
 
 
/* Handle li.  */
/* Handle li.  */
static void
static void
do_macro_li_rdi32 (char *str){
do_macro_li_rdi32 (char *str){
 
 
  int reg_rd;
  int reg_rd;
 
 
  skip_whitespace (str);
  skip_whitespace (str);
  if ((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL
  if ((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL
      || skip_past_comma (&str) == (int) FAIL)
      || skip_past_comma (&str) == (int) FAIL)
    {
    {
      return;
      return;
    }
    }
  else
  else
    {
    {
      char *keep_data = str;
      char *keep_data = str;
 
 
      /* li rd, simm16.  */
      /* li rd, simm16.  */
      if (data_op2 (&str, 1, _SIMM16_LA) != (int) FAIL)
      if (data_op2 (&str, 1, _SIMM16_LA) != (int) FAIL)
        {
        {
          end_of_line (str);
          end_of_line (str);
          return;
          return;
        }
        }
      /* li rd, imm32.  */
      /* li rd, imm32.  */
      else
      else
        {
        {
          char append_str[MAX_LITERAL_POOL_SIZE];
          char append_str[MAX_LITERAL_POOL_SIZE];
 
 
          str = keep_data;
          str = keep_data;
 
 
          if ((data_op2 (&str, 1, _VALUE_HI16) == (int) FAIL)
          if ((data_op2 (&str, 1, _VALUE_HI16) == (int) FAIL)
              || (end_of_line (str) == (int) FAIL))
              || (end_of_line (str) == (int) FAIL))
            {
            {
              return;
              return;
            }
            }
          else if (inst.reloc.exp.X_add_symbol)
          else if (inst.reloc.exp.X_add_symbol)
            {
            {
              inst.error = _("li rd label isn't correct instruction form");
              inst.error = _("li rd label isn't correct instruction form");
              return;
              return;
            }
            }
          else
          else
            {
            {
              sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
              sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
 
 
              if (append_insn (append_str, TRUE) == (int) FAIL)
              if (append_insn (append_str, TRUE) == (int) FAIL)
                return;
                return;
              else
              else
                {
                {
                  sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
                  sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
                  if (append_insn (append_str, TRUE) == (int) FAIL)
                  if (append_insn (append_str, TRUE) == (int) FAIL)
                    return;
                    return;
 
 
                  /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
                  /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
                  inst.bwarn = -1;
                  inst.bwarn = -1;
                }
                }
            }
            }
        }
        }
    }
    }
}
}
 
 
/* Handle mul/mulu/div/divu/rem/remu.  */
/* Handle mul/mulu/div/divu/rem/remu.  */
static void
static void
do_macro_mul_rdrsrs (char *str)
do_macro_mul_rdrsrs (char *str)
{
{
  int reg_rd;
  int reg_rd;
  int reg_rs1;
  int reg_rs1;
  int reg_rs2;
  int reg_rs2;
  char *backupstr;
  char *backupstr;
  char append_str[MAX_LITERAL_POOL_SIZE];
  char append_str[MAX_LITERAL_POOL_SIZE];
 
 
  if (university_version == 1)
  if (university_version == 1)
    as_warn ("%s", ERR_FOR_SCORE5U_MUL_DIV);
    as_warn ("%s", ERR_FOR_SCORE5U_MUL_DIV);
 
 
  strcpy (append_str, str);
  strcpy (append_str, str);
  backupstr = append_str;
  backupstr = append_str;
  skip_whitespace (backupstr);
  skip_whitespace (backupstr);
  if (((reg_rd = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
  if (((reg_rd = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
      || (skip_past_comma (&backupstr) == (int) FAIL)
      || (skip_past_comma (&backupstr) == (int) FAIL)
      || ((reg_rs1 = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL))
      || ((reg_rs1 = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL))
    {
    {
      inst.error = BAD_ARGS;
      inst.error = BAD_ARGS;
      return;
      return;
    }
    }
 
 
  if (skip_past_comma (&backupstr) == (int) FAIL)
  if (skip_past_comma (&backupstr) == (int) FAIL)
    {
    {
      /* rem/remu rA, rB is error format.  */
      /* rem/remu rA, rB is error format.  */
      if (strcmp (inst.name, "rem") == 0 || strcmp (inst.name, "remu") == 0)
      if (strcmp (inst.name, "rem") == 0 || strcmp (inst.name, "remu") == 0)
        {
        {
          SET_INSN_ERROR (BAD_ARGS);
          SET_INSN_ERROR (BAD_ARGS);
        }
        }
      else
      else
        {
        {
          SET_INSN_ERROR (NULL);
          SET_INSN_ERROR (NULL);
          do_rsrs (str);
          do_rsrs (str);
        }
        }
      return;
      return;
    }
    }
  else
  else
    {
    {
      SET_INSN_ERROR (NULL);
      SET_INSN_ERROR (NULL);
      if (((reg_rs2 = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
      if (((reg_rs2 = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
          || (end_of_line (backupstr) == (int) FAIL))
          || (end_of_line (backupstr) == (int) FAIL))
        {
        {
          return;
          return;
        }
        }
      else
      else
        {
        {
          char append_str1[MAX_LITERAL_POOL_SIZE];
          char append_str1[MAX_LITERAL_POOL_SIZE];
 
 
          if (strcmp (inst.name, "rem") == 0)
          if (strcmp (inst.name, "rem") == 0)
            {
            {
              sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2);
              sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2);
              sprintf (append_str1, "mfceh  r%d", reg_rd);
              sprintf (append_str1, "mfceh  r%d", reg_rd);
            }
            }
          else if (strcmp (inst.name, "remu") == 0)
          else if (strcmp (inst.name, "remu") == 0)
            {
            {
              sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2);
              sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2);
              sprintf (append_str1, "mfceh  r%d", reg_rd);
              sprintf (append_str1, "mfceh  r%d", reg_rd);
            }
            }
          else
          else
            {
            {
              sprintf (append_str, "%s r%d, r%d", inst.name, reg_rs1, reg_rs2);
              sprintf (append_str, "%s r%d, r%d", inst.name, reg_rs1, reg_rs2);
              sprintf (append_str1, "mfcel  r%d", reg_rd);
              sprintf (append_str1, "mfcel  r%d", reg_rd);
            }
            }
 
 
          /* Output mul/mulu or div/divu or rem/remu.  */
          /* Output mul/mulu or div/divu or rem/remu.  */
          if (append_insn (append_str, TRUE) == (int) FAIL)
          if (append_insn (append_str, TRUE) == (int) FAIL)
            return;
            return;
 
 
          /* Output mfcel or mfceh.  */
          /* Output mfcel or mfceh.  */
          if (append_insn (append_str1, TRUE) == (int) FAIL)
          if (append_insn (append_str1, TRUE) == (int) FAIL)
            return;
            return;
 
 
          /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
          /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
          inst.bwarn = -1;
          inst.bwarn = -1;
        }
        }
    }
    }
}
}
 
 
static void
static void
exp_macro_ldst_abs (char *str)
exp_macro_ldst_abs (char *str)
{
{
  int reg_rd;
  int reg_rd;
  char *backupstr, *tmp;
  char *backupstr, *tmp;
  char append_str[MAX_LITERAL_POOL_SIZE];
  char append_str[MAX_LITERAL_POOL_SIZE];
  char verifystr[MAX_LITERAL_POOL_SIZE];
  char verifystr[MAX_LITERAL_POOL_SIZE];
  struct score_it inst_backup;
  struct score_it inst_backup;
  int r1_bak = 0;
  int r1_bak = 0;
 
 
  r1_bak = nor1;
  r1_bak = nor1;
  nor1 = 0;
  nor1 = 0;
  memcpy (&inst_backup, &inst, sizeof (struct score_it));
  memcpy (&inst_backup, &inst, sizeof (struct score_it));
 
 
  strcpy (verifystr, str);
  strcpy (verifystr, str);
  backupstr = verifystr;
  backupstr = verifystr;
  skip_whitespace (backupstr);
  skip_whitespace (backupstr);
  if ((reg_rd = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
  if ((reg_rd = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
    return;
    return;
 
 
  tmp = backupstr;
  tmp = backupstr;
  if (skip_past_comma (&backupstr) == (int) FAIL)
  if (skip_past_comma (&backupstr) == (int) FAIL)
    return;
    return;
 
 
  backupstr = tmp;
  backupstr = tmp;
  sprintf (append_str, "li r1  %s", backupstr);
  sprintf (append_str, "li r1  %s", backupstr);
  append_insn (append_str, TRUE);
  append_insn (append_str, TRUE);
 
 
  memcpy (&inst, &inst_backup, sizeof (struct score_it));
  memcpy (&inst, &inst_backup, sizeof (struct score_it));
  sprintf (append_str, " r%d, [r1,0]", reg_rd);
  sprintf (append_str, " r%d, [r1,0]", reg_rd);
  do_ldst_insn (append_str);
  do_ldst_insn (append_str);
 
 
  nor1 = r1_bak;
  nor1 = r1_bak;
}
}
 
 
static int
static int
nopic_need_relax (symbolS * sym, int before_relaxing)
nopic_need_relax (symbolS * sym, int before_relaxing)
{
{
  if (sym == NULL)
  if (sym == NULL)
    return 0;
    return 0;
  else if (USE_GLOBAL_POINTER_OPT && g_switch_value > 0)
  else if (USE_GLOBAL_POINTER_OPT && g_switch_value > 0)
    {
    {
      const char *symname;
      const char *symname;
      const char *segname;
      const char *segname;
 
 
      /* Find out whether this symbol can be referenced off the $gp
      /* Find out whether this symbol can be referenced off the $gp
         register.  It can be if it is smaller than the -G size or if
         register.  It can be if it is smaller than the -G size or if
         it is in the .sdata or .sbss section.  Certain symbols can
         it is in the .sdata or .sbss section.  Certain symbols can
         not be referenced off the $gp, although it appears as though
         not be referenced off the $gp, although it appears as though
         they can.  */
         they can.  */
      symname = S_GET_NAME (sym);
      symname = S_GET_NAME (sym);
      if (symname != (const char *)NULL
      if (symname != (const char *)NULL
          && (strcmp (symname, "eprol") == 0
          && (strcmp (symname, "eprol") == 0
              || strcmp (symname, "etext") == 0
              || strcmp (symname, "etext") == 0
              || strcmp (symname, "_gp") == 0
              || strcmp (symname, "_gp") == 0
              || strcmp (symname, "edata") == 0
              || strcmp (symname, "edata") == 0
              || strcmp (symname, "_fbss") == 0
              || strcmp (symname, "_fbss") == 0
              || strcmp (symname, "_fdata") == 0
              || strcmp (symname, "_fdata") == 0
              || strcmp (symname, "_ftext") == 0
              || strcmp (symname, "_ftext") == 0
              || strcmp (symname, "end") == 0
              || strcmp (symname, "end") == 0
              || strcmp (symname, GP_DISP_LABEL) == 0))
              || strcmp (symname, GP_DISP_LABEL) == 0))
        {
        {
          return 1;
          return 1;
        }
        }
      else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0
      else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0
      /* We must defer this decision until after the whole file has been read,
      /* We must defer this decision until after the whole file has been read,
         since there might be a .extern after the first use of this symbol.  */
         since there might be a .extern after the first use of this symbol.  */
               || (before_relaxing
               || (before_relaxing
                   && S_GET_VALUE (sym) == 0)
                   && S_GET_VALUE (sym) == 0)
               || (S_GET_VALUE (sym) != 0
               || (S_GET_VALUE (sym) != 0
                   && S_GET_VALUE (sym) <= g_switch_value)))
                   && S_GET_VALUE (sym) <= g_switch_value)))
        {
        {
          return 0;
          return 0;
        }
        }
 
 
      segname = segment_name (S_GET_SEGMENT (sym));
      segname = segment_name (S_GET_SEGMENT (sym));
      return (strcmp (segname, ".sdata") != 0
      return (strcmp (segname, ".sdata") != 0
              && strcmp (segname, ".sbss") != 0
              && strcmp (segname, ".sbss") != 0
              && strncmp (segname, ".sdata.", 7) != 0
              && strncmp (segname, ".sdata.", 7) != 0
              && strncmp (segname, ".gnu.linkonce.s.", 16) != 0);
              && strncmp (segname, ".gnu.linkonce.s.", 16) != 0);
    }
    }
  /* We are not optimizing for the $gp register.  */
  /* We are not optimizing for the $gp register.  */
  else
  else
    return 1;
    return 1;
}
}
 
 
/* Build a relax frag for lw/st instruction when generating PIC,
/* Build a relax frag for lw/st instruction when generating PIC,
   external symbol first and local symbol second.  */
   external symbol first and local symbol second.  */
 
 
static void
static void
build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name)
build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name)
{
{
  symbolS *add_symbol = exp.X_add_symbol;
  symbolS *add_symbol = exp.X_add_symbol;
  int add_number = exp.X_add_number;
  int add_number = exp.X_add_number;
  struct score_it fix_insts[RELAX_INST_NUM];
  struct score_it fix_insts[RELAX_INST_NUM];
  struct score_it var_insts[RELAX_INST_NUM];
  struct score_it var_insts[RELAX_INST_NUM];
  int fix_num = 0;
  int fix_num = 0;
  int var_num = 0;
  int var_num = 0;
  char tmp[MAX_LITERAL_POOL_SIZE];
  char tmp[MAX_LITERAL_POOL_SIZE];
  int r1_bak;
  int r1_bak;
 
 
  r1_bak = nor1;
  r1_bak = nor1;
  nor1 = 0;
  nor1 = 0;
 
 
  if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff))
  if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff))
    {
    {
      fix_num = 1;
      fix_num = 1;
      var_num = 2;
      var_num = 2;
 
 
      /* For an external symbol, two insns are generated;
      /* For an external symbol, two insns are generated;
         For a local symbol, three insns are generated.  */
         For a local symbol, three insns are generated.  */
      /* Fix part
      /* Fix part
         For an external symbol: lw rD, <sym>($gp)
         For an external symbol: lw rD, <sym>($gp)
                                 (BFD_RELOC_SCORE_GOT15)  */
                                 (BFD_RELOC_SCORE_GOT15)  */
      sprintf (tmp, "lw_pic r1, %s", add_symbol->bsym->name);
      sprintf (tmp, "lw_pic r1, %s", add_symbol->bsym->name);
      if (append_insn (tmp, FALSE) == (int) FAIL)
      if (append_insn (tmp, FALSE) == (int) FAIL)
        return;
        return;
 
 
      memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
      memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
 
 
      /* Var part
      /* Var part
         For a local symbol :
         For a local symbol :
         lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)
         lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)
         addi rD, <sym>       (BFD_RELOC_GOT_LO16) */
         addi rD, <sym>       (BFD_RELOC_GOT_LO16) */
      inst.reloc.type = BFD_RELOC_SCORE_GOT15;
      inst.reloc.type = BFD_RELOC_SCORE_GOT15;
      memcpy (&var_insts[0], &inst, sizeof (struct score_it));
      memcpy (&var_insts[0], &inst, sizeof (struct score_it));
      sprintf (tmp, "addi_s_pic r1, %s", add_symbol->bsym->name);
      sprintf (tmp, "addi_s_pic r1, %s", add_symbol->bsym->name);
      if (append_insn (tmp, FALSE) == (int) FAIL)
      if (append_insn (tmp, FALSE) == (int) FAIL)
        return;
        return;
 
 
      memcpy (&var_insts[1], &inst, sizeof (struct score_it));
      memcpy (&var_insts[1], &inst, sizeof (struct score_it));
      build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
      build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
 
 
      /* Insn 2 or Insn 3: lw/st rD, [r1, constant]  */
      /* Insn 2 or Insn 3: lw/st rD, [r1, constant]  */
      sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number);
      sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number);
      if (append_insn (tmp, TRUE) == (int) FAIL)
      if (append_insn (tmp, TRUE) == (int) FAIL)
        return;
        return;
 
 
      /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
      /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
      inst.bwarn = -1;
      inst.bwarn = -1;
    }
    }
  else
  else
    {
    {
      inst.error = _("PIC code offset overflow (max 16 signed bits)");
      inst.error = _("PIC code offset overflow (max 16 signed bits)");
      return;
      return;
    }
    }
 
 
  nor1 = r1_bak;
  nor1 = r1_bak;
}
}
 
 
static void
static void
do_macro_ldst_label (char *str)
do_macro_ldst_label (char *str)
{
{
  int i;
  int i;
  int ldst_gp_p = 0;
  int ldst_gp_p = 0;
  int reg_rd;
  int reg_rd;
  int r1_bak;
  int r1_bak;
  char *backup_str;
  char *backup_str;
  char *label_str;
  char *label_str;
  char *absolute_value;
  char *absolute_value;
  char append_str[3][MAX_LITERAL_POOL_SIZE];
  char append_str[3][MAX_LITERAL_POOL_SIZE];
  char verifystr[MAX_LITERAL_POOL_SIZE];
  char verifystr[MAX_LITERAL_POOL_SIZE];
  struct score_it inst_backup;
  struct score_it inst_backup;
  struct score_it inst_expand[3];
  struct score_it inst_expand[3];
  struct score_it inst_main;
  struct score_it inst_main;
 
 
  memcpy (&inst_backup, &inst, sizeof (struct score_it));
  memcpy (&inst_backup, &inst, sizeof (struct score_it));
  strcpy (verifystr, str);
  strcpy (verifystr, str);
  backup_str = verifystr;
  backup_str = verifystr;
 
 
  skip_whitespace (backup_str);
  skip_whitespace (backup_str);
  if ((reg_rd = reg_required_here (&backup_str, -1, REG_TYPE_SCORE)) == (int) FAIL)
  if ((reg_rd = reg_required_here (&backup_str, -1, REG_TYPE_SCORE)) == (int) FAIL)
    return;
    return;
 
 
  if (skip_past_comma (&backup_str) == (int) FAIL)
  if (skip_past_comma (&backup_str) == (int) FAIL)
    return;
    return;
 
 
  label_str = backup_str;
  label_str = backup_str;
 
 
  /* Ld/st rD, [rA, imm]      ld/st rD, [rA]+, imm      ld/st rD, [rA, imm]+.  */
  /* Ld/st rD, [rA, imm]      ld/st rD, [rA]+, imm      ld/st rD, [rA, imm]+.  */
  if (*backup_str == '[')
  if (*backup_str == '[')
    {
    {
      inst.type = Rd_rvalueRs_preSI12;
      inst.type = Rd_rvalueRs_preSI12;
      do_ldst_insn (str);
      do_ldst_insn (str);
      return;
      return;
    }
    }
 
 
  /* Ld/st rD, imm.  */
  /* Ld/st rD, imm.  */
  absolute_value = backup_str;
  absolute_value = backup_str;
  inst.type = Rd_rvalueRs_SI15;
  inst.type = Rd_rvalueRs_SI15;
  if ((my_get_expression (&inst.reloc.exp, &backup_str) == (int) FAIL)
  if ((my_get_expression (&inst.reloc.exp, &backup_str) == (int) FAIL)
      || (validate_immediate (inst.reloc.exp.X_add_number, _VALUE, 0) == (int) FAIL)
      || (validate_immediate (inst.reloc.exp.X_add_number, _VALUE, 0) == (int) FAIL)
      || (end_of_line (backup_str) == (int) FAIL))
      || (end_of_line (backup_str) == (int) FAIL))
    {
    {
      return;
      return;
    }
    }
  else
  else
    {
    {
      if (inst.reloc.exp.X_add_symbol == 0)
      if (inst.reloc.exp.X_add_symbol == 0)
        {
        {
          memcpy (&inst, &inst_backup, sizeof (struct score_it));
          memcpy (&inst, &inst_backup, sizeof (struct score_it));
          exp_macro_ldst_abs (str);
          exp_macro_ldst_abs (str);
          return;
          return;
        }
        }
    }
    }
 
 
  /* Ld/st rD, label.  */
  /* Ld/st rD, label.  */
  inst.type = Rd_rvalueRs_SI15;
  inst.type = Rd_rvalueRs_SI15;
  backup_str = absolute_value;
  backup_str = absolute_value;
  if ((data_op2 (&backup_str, 1, _GP_IMM15) == (int) FAIL)
  if ((data_op2 (&backup_str, 1, _GP_IMM15) == (int) FAIL)
      || (end_of_line (backup_str) == (int) FAIL))
      || (end_of_line (backup_str) == (int) FAIL))
    {
    {
      return;
      return;
    }
    }
  else
  else
    {
    {
      if (inst.reloc.exp.X_add_symbol == 0)
      if (inst.reloc.exp.X_add_symbol == 0)
        {
        {
          if (!inst.error)
          if (!inst.error)
            inst.error = BAD_ARGS;
            inst.error = BAD_ARGS;
 
 
          return;
          return;
        }
        }
 
 
      if (score_pic == PIC)
      if (score_pic == PIC)
        {
        {
          int ldst_idx = 0;
          int ldst_idx = 0;
          ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
          ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
          build_lwst_pic (reg_rd, inst.reloc.exp, score_ldst_insns[ldst_idx * 3 + 0].template);
          build_lwst_pic (reg_rd, inst.reloc.exp, score_ldst_insns[ldst_idx * 3 + 0].template);
          return;
          return;
        }
        }
      else
      else
        {
        {
          if ((inst.reloc.exp.X_add_number <= 0x3fff)
          if ((inst.reloc.exp.X_add_number <= 0x3fff)
               && (inst.reloc.exp.X_add_number >= -0x4000)
               && (inst.reloc.exp.X_add_number >= -0x4000)
               && (!nopic_need_relax (inst.reloc.exp.X_add_symbol, 1)))
               && (!nopic_need_relax (inst.reloc.exp.X_add_symbol, 1)))
            {
            {
              int ldst_idx = 0;
              int ldst_idx = 0;
 
 
              /* Assign the real opcode.  */
              /* Assign the real opcode.  */
              ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
              ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
              inst.instruction &= ~OPC_PSEUDOLDST_MASK;
              inst.instruction &= ~OPC_PSEUDOLDST_MASK;
              inst.instruction |= score_ldst_insns[ldst_idx * 3 + 0].value;
              inst.instruction |= score_ldst_insns[ldst_idx * 3 + 0].value;
              inst.instruction |= reg_rd << 20;
              inst.instruction |= reg_rd << 20;
              inst.instruction |= GP << 15;
              inst.instruction |= GP << 15;
              inst.relax_inst = 0x8000;
              inst.relax_inst = 0x8000;
              inst.relax_size = 0;
              inst.relax_size = 0;
              ldst_gp_p = 1;
              ldst_gp_p = 1;
            }
            }
        }
        }
    }
    }
 
 
  /* Backup inst.  */
  /* Backup inst.  */
  memcpy (&inst_main, &inst, sizeof (struct score_it));
  memcpy (&inst_main, &inst, sizeof (struct score_it));
  r1_bak = nor1;
  r1_bak = nor1;
  nor1 = 0;
  nor1 = 0;
 
 
  /* Determine which instructions should be output.  */
  /* Determine which instructions should be output.  */
  sprintf (append_str[0], "ld_i32hi r1, %s", label_str);
  sprintf (append_str[0], "ld_i32hi r1, %s", label_str);
  sprintf (append_str[1], "ld_i32lo r1, %s", label_str);
  sprintf (append_str[1], "ld_i32lo r1, %s", label_str);
  sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd);
  sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd);
 
 
  /* Generate three instructions.
  /* Generate three instructions.
     la r1, label
     la r1, label
     ld/st rd, [r1, 0]  */
     ld/st rd, [r1, 0]  */
  for (i = 0; i < 3; i++)
  for (i = 0; i < 3; i++)
    {
    {
      if (append_insn (append_str[i], FALSE) == (int) FAIL)
      if (append_insn (append_str[i], FALSE) == (int) FAIL)
        return;
        return;
 
 
      memcpy (&inst_expand[i], &inst, sizeof (struct score_it));
      memcpy (&inst_expand[i], &inst, sizeof (struct score_it));
    }
    }
 
 
  if (ldst_gp_p)
  if (ldst_gp_p)
    {
    {
      char *p;
      char *p;
 
 
      /* Adjust instruction opcode and to be relaxed instruction opcode.  */
      /* Adjust instruction opcode and to be relaxed instruction opcode.  */
      inst_main.instruction = adjust_paritybit (inst_main.instruction, GET_INSN_CLASS (inst_main.type));
      inst_main.instruction = adjust_paritybit (inst_main.instruction, GET_INSN_CLASS (inst_main.type));
      inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size;
      inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size;
      inst_main.type = Insn_GP;
      inst_main.type = Insn_GP;
 
 
      for (i = 0; i < 3; i++)
      for (i = 0; i < 3; i++)
        inst_expand[i].instruction = adjust_paritybit (inst_expand[i].instruction
        inst_expand[i].instruction = adjust_paritybit (inst_expand[i].instruction
                                                       , GET_INSN_CLASS (inst_expand[i].type));
                                                       , GET_INSN_CLASS (inst_expand[i].type));
 
 
      /* Check data dependency.  */
      /* Check data dependency.  */
      handle_dependency (&inst_main);
      handle_dependency (&inst_main);
 
 
      /* Start a new frag if frag_now is not empty.  */
      /* Start a new frag if frag_now is not empty.  */
      if (frag_now_fix () != 0)
      if (frag_now_fix () != 0)
        {
        {
          if (!frag_now->tc_frag_data.is_insn)
          if (!frag_now->tc_frag_data.is_insn)
            frag_wane (frag_now);
            frag_wane (frag_now);
 
 
          frag_new (0);
          frag_new (0);
        }
        }
      frag_grow (20);
      frag_grow (20);
 
 
      /* Write fr_fix part.  */
      /* Write fr_fix part.  */
      p = frag_more (inst_main.size);
      p = frag_more (inst_main.size);
      md_number_to_chars (p, inst_main.instruction, inst_main.size);
      md_number_to_chars (p, inst_main.instruction, inst_main.size);
 
 
      if (inst_main.reloc.type != BFD_RELOC_NONE)
      if (inst_main.reloc.type != BFD_RELOC_NONE)
        {
        {
          fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
          fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
                         &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
                         &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
        }
        }
 
 
#ifdef OBJ_ELF
#ifdef OBJ_ELF
      dwarf2_emit_insn (inst_main.size);
      dwarf2_emit_insn (inst_main.size);
#endif
#endif
 
 
      /* GP instruction can not do optimization, only can do relax between
      /* GP instruction can not do optimization, only can do relax between
         1 instruction and 3 instructions.  */
         1 instruction and 3 instructions.  */
      p = frag_var (rs_machine_dependent, inst_main.relax_size + RELAX_PAD_BYTE, 0,
      p = frag_var (rs_machine_dependent, inst_main.relax_size + RELAX_PAD_BYTE, 0,
                    RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0),
                    RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0),
                    inst_main.reloc.exp.X_add_symbol, 0, NULL);
                    inst_main.reloc.exp.X_add_symbol, 0, NULL);
 
 
      /* Write fr_var part.
      /* Write fr_var part.
         no calling gen_insn_frag, no fixS will be generated.  */
         no calling gen_insn_frag, no fixS will be generated.  */
      md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
      md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
      p += inst_expand[0].size;
      p += inst_expand[0].size;
      md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
      md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
      p += inst_expand[1].size;
      p += inst_expand[1].size;
      md_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size);
      md_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size);
    }
    }
  else
  else
    {
    {
      gen_insn_frag (&inst_expand[0], NULL);
      gen_insn_frag (&inst_expand[0], NULL);
      gen_insn_frag (&inst_expand[1], NULL);
      gen_insn_frag (&inst_expand[1], NULL);
      gen_insn_frag (&inst_expand[2], NULL);
      gen_insn_frag (&inst_expand[2], NULL);
    }
    }
  nor1 = r1_bak;
  nor1 = r1_bak;
 
 
  /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
  /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
  inst.bwarn = -1;
  inst.bwarn = -1;
}
}
 
 
static void
static void
do_lw_pic (char *str)
do_lw_pic (char *str)
{
{
  int reg_rd;
  int reg_rd;
 
 
  skip_whitespace (str);
  skip_whitespace (str);
  if (((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
  if (((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
      || (skip_past_comma (&str) == (int) FAIL)
      || (skip_past_comma (&str) == (int) FAIL)
      || (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL)
      || (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL)
      || (end_of_line (str) == (int) FAIL))
      || (end_of_line (str) == (int) FAIL))
    {
    {
      return;
      return;
    }
    }
  else
  else
    {
    {
      if (inst.reloc.exp.X_add_symbol == 0)
      if (inst.reloc.exp.X_add_symbol == 0)
        {
        {
          if (!inst.error)
          if (!inst.error)
            inst.error = BAD_ARGS;
            inst.error = BAD_ARGS;
 
 
          return;
          return;
        }
        }
 
 
      inst.instruction |= GP << 15;
      inst.instruction |= GP << 15;
      inst.reloc.type = BFD_RELOC_SCORE_GOT15;
      inst.reloc.type = BFD_RELOC_SCORE_GOT15;
    }
    }
}
}
 
 
static void
static void
do_empty (char *str)
do_empty (char *str)
{
{
  str = str;
  str = str;
  if (university_version == 1)
  if (university_version == 1)
    {
    {
      if (((inst.instruction & 0x3e0003ff) == 0x0c000004)
      if (((inst.instruction & 0x3e0003ff) == 0x0c000004)
          || ((inst.instruction & 0x3e0003ff) == 0x0c000024)
          || ((inst.instruction & 0x3e0003ff) == 0x0c000024)
          || ((inst.instruction & 0x3e0003ff) == 0x0c000044)
          || ((inst.instruction & 0x3e0003ff) == 0x0c000044)
          || ((inst.instruction & 0x3e0003ff) == 0x0c000064))
          || ((inst.instruction & 0x3e0003ff) == 0x0c000064))
        {
        {
          inst.error = ERR_FOR_SCORE5U_MMU;
          inst.error = ERR_FOR_SCORE5U_MMU;
          return;
          return;
        }
        }
    }
    }
  if (end_of_line (str) == (int) FAIL)
  if (end_of_line (str) == (int) FAIL)
    return;
    return;
 
 
  if (inst.relax_inst != 0x8000)
  if (inst.relax_inst != 0x8000)
    {
    {
      if (inst.type == NO_OPD)
      if (inst.type == NO_OPD)
        {
        {
          inst.relax_size = 2;
          inst.relax_size = 2;
        }
        }
      else
      else
        {
        {
          inst.relax_size = 4;
          inst.relax_size = 4;
        }
        }
    }
    }
}
}
 
 
static void
static void
do_jump (char *str)
do_jump (char *str)
{
{
  char *save_in;
  char *save_in;
 
 
  skip_whitespace (str);
  skip_whitespace (str);
  if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
  if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
      || end_of_line (str) == (int) FAIL)
      || end_of_line (str) == (int) FAIL)
    return;
    return;
 
 
  if (inst.reloc.exp.X_add_symbol == 0)
  if (inst.reloc.exp.X_add_symbol == 0)
    {
    {
      inst.error = _("lacking label  ");
      inst.error = _("lacking label  ");
      return;
      return;
    }
    }
 
 
  if (((inst.reloc.exp.X_add_number & 0xff000000) != 0)
  if (((inst.reloc.exp.X_add_number & 0xff000000) != 0)
      && ((inst.reloc.exp.X_add_number & 0xff000000) != 0xff000000))
      && ((inst.reloc.exp.X_add_number & 0xff000000) != 0xff000000))
    {
    {
      inst.error = _("invalid constant: 25 bit expression not in range -2^24..2^24");
      inst.error = _("invalid constant: 25 bit expression not in range -2^24..2^24");
      return;
      return;
    }
    }
 
 
  save_in = input_line_pointer;
  save_in = input_line_pointer;
  input_line_pointer = str;
  input_line_pointer = str;
  inst.reloc.type = BFD_RELOC_SCORE_JMP;
  inst.reloc.type = BFD_RELOC_SCORE_JMP;
  inst.reloc.pc_rel = 1;
  inst.reloc.pc_rel = 1;
  input_line_pointer = save_in;
  input_line_pointer = save_in;
}
}
 
 
static void
static void
do16_jump (char *str)
do16_jump (char *str)
{
{
  skip_whitespace (str);
  skip_whitespace (str);
  if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
  if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
      || end_of_line (str) == (int) FAIL)
      || end_of_line (str) == (int) FAIL)
    {
    {
      return;
      return;
    }
    }
  else if (inst.reloc.exp.X_add_symbol == 0)
  else if (inst.reloc.exp.X_add_symbol == 0)
    {
    {
      inst.error = _("lacking label  ");
      inst.error = _("lacking label  ");
      return;
      return;
    }
    }
  else if (((inst.reloc.exp.X_add_number & 0xfffff800) != 0)
  else if (((inst.reloc.exp.X_add_number & 0xfffff800) != 0)
           && ((inst.reloc.exp.X_add_number & 0xfffff800) != 0xfffff800))
           && ((inst.reloc.exp.X_add_number & 0xfffff800) != 0xfffff800))
    {
    {
      inst.error = _("invalid constant: 12 bit expression not in range -2^11..2^11");
      inst.error = _("invalid constant: 12 bit expression not in range -2^11..2^11");
      return;
      return;
    }
    }
 
 
  inst.reloc.type = BFD_RELOC_SCORE16_JMP;
  inst.reloc.type = BFD_RELOC_SCORE16_JMP;
  inst.reloc.pc_rel = 1;
  inst.reloc.pc_rel = 1;
}
}
 
 
static void
static void
do_branch (char *str)
do_branch (char *str)
{
{
  unsigned long abs_value = 0;
  unsigned long abs_value = 0;
 
 
  if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
  if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
      || end_of_line (str) == (int) FAIL)
      || end_of_line (str) == (int) FAIL)
    {
    {
      return;
      return;
    }
    }
  else if (inst.reloc.exp.X_add_symbol == 0)
  else if (inst.reloc.exp.X_add_symbol == 0)
    {
    {
      inst.error = _("lacking label  ");
      inst.error = _("lacking label  ");
      return;
      return;
    }
    }
  else if (((inst.reloc.exp.X_add_number & 0xff000000) != 0)
  else if (((inst.reloc.exp.X_add_number & 0xff000000) != 0)
           && ((inst.reloc.exp.X_add_number & 0xff000000) != 0xff000000))
           && ((inst.reloc.exp.X_add_number & 0xff000000) != 0xff000000))
    {
    {
      inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19");
      inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19");
      return;
      return;
    }
    }
 
 
  inst.reloc.type = BFD_RELOC_SCORE_BRANCH;
  inst.reloc.type = BFD_RELOC_SCORE_BRANCH;
  inst.reloc.pc_rel = 1;
  inst.reloc.pc_rel = 1;
 
 
  /* Branch 32  offset field : 20 bit, 16 bit branch offset field : 8 bit.  */
  /* Branch 32  offset field : 20 bit, 16 bit branch offset field : 8 bit.  */
  inst.instruction |= (inst.reloc.exp.X_add_number & 0x3fe) | ((inst.reloc.exp.X_add_number & 0xffc00) << 5);
  inst.instruction |= (inst.reloc.exp.X_add_number & 0x3fe) | ((inst.reloc.exp.X_add_number & 0xffc00) << 5);
 
 
  /* Compute 16 bit branch instruction.  */
  /* Compute 16 bit branch instruction.  */
  if ((inst.relax_inst != 0x8000) && (abs_value & 0xfffffe00) == 0)
  if ((inst.relax_inst != 0x8000) && (abs_value & 0xfffffe00) == 0)
    {
    {
      inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 8);
      inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 8);
      inst.relax_inst |= ((inst.reloc.exp.X_add_number >> 1) & 0xff);
      inst.relax_inst |= ((inst.reloc.exp.X_add_number >> 1) & 0xff);
      inst.relax_size = 2;
      inst.relax_size = 2;
    }
    }
  else
  else
    {
    {
      inst.relax_inst = 0x8000;
      inst.relax_inst = 0x8000;
    }
    }
}
}
 
 
static void
static void
do16_branch (char *str)
do16_branch (char *str)
{
{
  if ((my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
  if ((my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
      || end_of_line (str) == (int) FAIL))
      || end_of_line (str) == (int) FAIL))
    {
    {
      ;
      ;
    }
    }
  else if (inst.reloc.exp.X_add_symbol == 0)
  else if (inst.reloc.exp.X_add_symbol == 0)
    {
    {
      inst.error = _("lacking label");
      inst.error = _("lacking label");
    }
    }
  else if (((inst.reloc.exp.X_add_number & 0xffffff00) != 0)
  else if (((inst.reloc.exp.X_add_number & 0xffffff00) != 0)
           && ((inst.reloc.exp.X_add_number & 0xffffff00) != 0xffffff00))
           && ((inst.reloc.exp.X_add_number & 0xffffff00) != 0xffffff00))
    {
    {
      inst.error = _("invalid constant: 9 bit expression not in range -2^8..2^8");
      inst.error = _("invalid constant: 9 bit expression not in range -2^8..2^8");
    }
    }
  else
  else
    {
    {
      inst.reloc.type = BFD_RELOC_SCORE16_BRANCH;
      inst.reloc.type = BFD_RELOC_SCORE16_BRANCH;
      inst.reloc.pc_rel = 1;
      inst.reloc.pc_rel = 1;
      inst.instruction |= ((inst.reloc.exp.X_add_number >> 1) & 0xff);
      inst.instruction |= ((inst.reloc.exp.X_add_number >> 1) & 0xff);
    }
    }
}
}
 
 
/* Iterate over the base tables to create the instruction patterns.  */
/* Iterate over the base tables to create the instruction patterns.  */
static void
static void
build_score_ops_hsh (void)
build_score_ops_hsh (void)
{
{
  unsigned int i;
  unsigned int i;
  static struct obstack insn_obstack;
  static struct obstack insn_obstack;
 
 
  obstack_begin (&insn_obstack, 4000);
  obstack_begin (&insn_obstack, 4000);
  for (i = 0; i < sizeof (score_insns) / sizeof (struct asm_opcode); i++)
  for (i = 0; i < sizeof (score_insns) / sizeof (struct asm_opcode); i++)
    {
    {
      const struct asm_opcode *insn = score_insns + i;
      const struct asm_opcode *insn = score_insns + i;
      unsigned len = strlen (insn->template);
      unsigned len = strlen (insn->template);
      struct asm_opcode *new;
      struct asm_opcode *new;
      char *template;
      char *template;
      new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
      new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
      template = obstack_alloc (&insn_obstack, len + 1);
      template = obstack_alloc (&insn_obstack, len + 1);
 
 
      strcpy (template, insn->template);
      strcpy (template, insn->template);
      new->template = template;
      new->template = template;
      new->parms = insn->parms;
      new->parms = insn->parms;
      new->value = insn->value;
      new->value = insn->value;
      new->relax_value = insn->relax_value;
      new->relax_value = insn->relax_value;
      new->type = insn->type;
      new->type = insn->type;
      new->bitmask = insn->bitmask;
      new->bitmask = insn->bitmask;
      hash_insert (score_ops_hsh, new->template, (void *) new);
      hash_insert (score_ops_hsh, new->template, (void *) new);
    }
    }
}
}
 
 
static void
static void
build_dependency_insn_hsh (void)
build_dependency_insn_hsh (void)
{
{
  unsigned int i;
  unsigned int i;
  static struct obstack dependency_obstack;
  static struct obstack dependency_obstack;
 
 
  obstack_begin (&dependency_obstack, 4000);
  obstack_begin (&dependency_obstack, 4000);
  for (i = 0; i < sizeof (insn_to_dependency_table) / sizeof (insn_to_dependency_table[0]); i++)
  for (i = 0; i < sizeof (insn_to_dependency_table) / sizeof (insn_to_dependency_table[0]); i++)
    {
    {
      const struct insn_to_dependency *tmp = insn_to_dependency_table + i;
      const struct insn_to_dependency *tmp = insn_to_dependency_table + i;
      unsigned len = strlen (tmp->insn_name);
      unsigned len = strlen (tmp->insn_name);
      struct insn_to_dependency *new;
      struct insn_to_dependency *new;
 
 
      new = obstack_alloc (&dependency_obstack, sizeof (struct insn_to_dependency));
      new = obstack_alloc (&dependency_obstack, sizeof (struct insn_to_dependency));
      new->insn_name = obstack_alloc (&dependency_obstack, len + 1);
      new->insn_name = obstack_alloc (&dependency_obstack, len + 1);
 
 
      strcpy (new->insn_name, tmp->insn_name);
      strcpy (new->insn_name, tmp->insn_name);
      new->type = tmp->type;
      new->type = tmp->type;
      hash_insert (dependency_insn_hsh, new->insn_name, (void *) new);
      hash_insert (dependency_insn_hsh, new->insn_name, (void *) new);
    }
    }
}
}
 
 
/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
/* Turn an integer of n bytes (in val) into a stream of bytes appropriate
   for use in the a.out file, and stores them in the array pointed to by buf.
   for use in the a.out file, and stores them in the array pointed to by buf.
   This knows about the endian-ness of the target machine and does
   This knows about the endian-ness of the target machine and does
   THE RIGHT THING, whatever it is.  Possible values for n are 1 (byte)
   THE RIGHT THING, whatever it is.  Possible values for n are 1 (byte)
   2 (short) and 4 (long)  Floating numbers are put out as a series of
   2 (short) and 4 (long)  Floating numbers are put out as a series of
   LITTLENUMS (shorts, here at least).  */
   LITTLENUMS (shorts, here at least).  */
 
 
void
void
md_number_to_chars (char *buf, valueT val, int n)
md_number_to_chars (char *buf, valueT val, int n)
{
{
  if (target_big_endian)
  if (target_big_endian)
    number_to_chars_bigendian (buf, val, n);
    number_to_chars_bigendian (buf, val, n);
  else
  else
    number_to_chars_littleendian (buf, val, n);
    number_to_chars_littleendian (buf, val, n);
}
}
 
 
static valueT
static valueT
md_chars_to_number (char *buf, int n)
md_chars_to_number (char *buf, int n)
{
{
  valueT result = 0;
  valueT result = 0;
  unsigned char *where = (unsigned char *)buf;
  unsigned char *where = (unsigned char *)buf;
 
 
  if (target_big_endian)
  if (target_big_endian)
    {
    {
      while (n--)
      while (n--)
        {
        {
          result <<= 8;
          result <<= 8;
          result |= (*where++ & 255);
          result |= (*where++ & 255);
        }
        }
    }
    }
  else
  else
    {
    {
      while (n--)
      while (n--)
        {
        {
          result <<= 8;
          result <<= 8;
          result |= (where[n] & 255);
          result |= (where[n] & 255);
        }
        }
    }
    }
 
 
  return result;
  return result;
}
}
 
 
char *
char *
md_atof (int type, char *litP, int *sizeP)
md_atof (int type, char *litP, int *sizeP)
{
{
  return ieee_md_atof (type, litP, sizeP, target_big_endian);
  return ieee_md_atof (type, litP, sizeP, target_big_endian);
}
}
 
 
/* Return true if the given symbol should be considered local for PIC.  */
/* Return true if the given symbol should be considered local for PIC.  */
 
 
static bfd_boolean
static bfd_boolean
pic_need_relax (symbolS *sym, asection *segtype)
pic_need_relax (symbolS *sym, asection *segtype)
{
{
  asection *symsec;
  asection *symsec;
  bfd_boolean linkonce;
  bfd_boolean linkonce;
 
 
  /* Handle the case of a symbol equated to another symbol.  */
  /* Handle the case of a symbol equated to another symbol.  */
  while (symbol_equated_reloc_p (sym))
  while (symbol_equated_reloc_p (sym))
    {
    {
      symbolS *n;
      symbolS *n;
 
 
      /* It's possible to get a loop here in a badly written
      /* It's possible to get a loop here in a badly written
         program.  */
         program.  */
      n = symbol_get_value_expression (sym)->X_add_symbol;
      n = symbol_get_value_expression (sym)->X_add_symbol;
      if (n == sym)
      if (n == sym)
        break;
        break;
      sym = n;
      sym = n;
    }
    }
 
 
  symsec = S_GET_SEGMENT (sym);
  symsec = S_GET_SEGMENT (sym);
 
 
  /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
  /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
  linkonce = FALSE;
  linkonce = FALSE;
  if (symsec != segtype && ! S_IS_LOCAL (sym))
  if (symsec != segtype && ! S_IS_LOCAL (sym))
    {
    {
      if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE) != 0)
      if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE) != 0)
        linkonce = TRUE;
        linkonce = TRUE;
 
 
      /* The GNU toolchain uses an extension for ELF: a section
      /* The GNU toolchain uses an extension for ELF: a section
          beginning with the magic string .gnu.linkonce is a linkonce
          beginning with the magic string .gnu.linkonce is a linkonce
          section.  */
          section.  */
      if (strncmp (segment_name (symsec), ".gnu.linkonce",
      if (strncmp (segment_name (symsec), ".gnu.linkonce",
                   sizeof ".gnu.linkonce" - 1) == 0)
                   sizeof ".gnu.linkonce" - 1) == 0)
        linkonce = TRUE;
        linkonce = TRUE;
    }
    }
 
 
  /* This must duplicate the test in adjust_reloc_syms.  */
  /* This must duplicate the test in adjust_reloc_syms.  */
  return (symsec != &bfd_und_section
  return (symsec != &bfd_und_section
            && symsec != &bfd_abs_section
            && symsec != &bfd_abs_section
          && ! bfd_is_com_section (symsec)
          && ! bfd_is_com_section (symsec)
            && !linkonce
            && !linkonce
#ifdef OBJ_ELF
#ifdef OBJ_ELF
          /* A global or weak symbol is treated as external.  */
          /* A global or weak symbol is treated as external.  */
          && (OUTPUT_FLAVOR != bfd_target_elf_flavour
          && (OUTPUT_FLAVOR != bfd_target_elf_flavour
              || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
              || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
#endif
#endif
          );
          );
}
}
 
 
static int
static int
judge_size_before_relax (fragS * fragp, asection *sec)
judge_size_before_relax (fragS * fragp, asection *sec)
{
{
  int change = 0;
  int change = 0;
 
 
  if (score_pic == NO_PIC)
  if (score_pic == NO_PIC)
    change = nopic_need_relax (fragp->fr_symbol, 0);
    change = nopic_need_relax (fragp->fr_symbol, 0);
  else
  else
    change = pic_need_relax (fragp->fr_symbol, sec);
    change = pic_need_relax (fragp->fr_symbol, sec);
 
 
  if (change == 1)
  if (change == 1)
    {
    {
      /* Only at the first time determining whether GP instruction relax should be done,
      /* Only at the first time determining whether GP instruction relax should be done,
         return the difference between insntruction size and instruction relax size.  */
         return the difference between insntruction size and instruction relax size.  */
      if (fragp->fr_opcode == NULL)
      if (fragp->fr_opcode == NULL)
        {
        {
          fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
          fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
          fragp->fr_opcode = fragp->fr_literal + RELAX_RELOC1 (fragp->fr_subtype);
          fragp->fr_opcode = fragp->fr_literal + RELAX_RELOC1 (fragp->fr_subtype);
          return RELAX_NEW (fragp->fr_subtype) - RELAX_OLD (fragp->fr_subtype);
          return RELAX_NEW (fragp->fr_subtype) - RELAX_OLD (fragp->fr_subtype);
        }
        }
    }
    }
 
 
  return 0;
  return 0;
}
}
 
 
/* In this function, we determine whether GP instruction should do relaxation,
/* In this function, we determine whether GP instruction should do relaxation,
   for the label being against was known now.
   for the label being against was known now.
   Doing this here but not in md_relax_frag() can induce iteration times
   Doing this here but not in md_relax_frag() can induce iteration times
   in stage of doing relax.  */
   in stage of doing relax.  */
int
int
md_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED)
md_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED)
{
{
  if ((RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
  if ((RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
      || (RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
      || (RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
    return judge_size_before_relax (fragp, sec);
    return judge_size_before_relax (fragp, sec);
 
 
  return 0;
  return 0;
}
}
 
 
static int
static int
b32_relax_to_b16 (fragS * fragp)
b32_relax_to_b16 (fragS * fragp)
{
{
  int grows = 0;
  int grows = 0;
  int relaxable_p = 0;
  int relaxable_p = 0;
  int old;
  int old;
  int new;
  int new;
  int frag_addr = fragp->fr_address + fragp->insn_addr;
  int frag_addr = fragp->fr_address + fragp->insn_addr;
 
 
  addressT symbol_address = 0;
  addressT symbol_address = 0;
  symbolS *s;
  symbolS *s;
  offsetT offset;
  offsetT offset;
  unsigned long value;
  unsigned long value;
  unsigned long abs_value;
  unsigned long abs_value;
 
 
  /* FIXME : here may be able to modify better .
  /* FIXME : here may be able to modify better .
     I don't know how to get the fragp's section ,
     I don't know how to get the fragp's section ,
     so in relax stage , it may be wrong to calculate the symbol's offset when the frag's section
     so in relax stage , it may be wrong to calculate the symbol's offset when the frag's section
     is different from the symbol's.  */
     is different from the symbol's.  */
 
 
  old = RELAX_OLD (fragp->fr_subtype);
  old = RELAX_OLD (fragp->fr_subtype);
  new = RELAX_NEW (fragp->fr_subtype);
  new = RELAX_NEW (fragp->fr_subtype);
  relaxable_p = RELAX_OPT (fragp->fr_subtype);
  relaxable_p = RELAX_OPT (fragp->fr_subtype);
 
 
  s = fragp->fr_symbol;
  s = fragp->fr_symbol;
  /* b/bl immediate  */
  /* b/bl immediate  */
  if (s == NULL)
  if (s == NULL)
    frag_addr = 0;
    frag_addr = 0;
  else
  else
    {
    {
      if (s->bsym != 0)
      if (s->bsym != 0)
        symbol_address = (addressT) s->sy_frag->fr_address;
        symbol_address = (addressT) s->sy_frag->fr_address;
    }
    }
 
 
  value = md_chars_to_number (fragp->fr_literal, INSN_SIZE);
  value = md_chars_to_number (fragp->fr_literal, INSN_SIZE);
 
 
  /* b 32's offset : 20 bit, b 16's tolerate field : 0xff.  */
  /* b 32's offset : 20 bit, b 16's tolerate field : 0xff.  */
  offset = ((value & 0x3ff0000) >> 6) | (value & 0x3fe);
  offset = ((value & 0x3ff0000) >> 6) | (value & 0x3fe);
  if ((offset & 0x80000) == 0x80000)
  if ((offset & 0x80000) == 0x80000)
    offset |= 0xfff00000;
    offset |= 0xfff00000;
 
 
  abs_value = offset + symbol_address - frag_addr;
  abs_value = offset + symbol_address - frag_addr;
  if ((abs_value & 0x80000000) == 0x80000000)
  if ((abs_value & 0x80000000) == 0x80000000)
    abs_value = 0xffffffff - abs_value + 1;
    abs_value = 0xffffffff - abs_value + 1;
 
 
  /* Relax branch 32 to branch 16.  */
  /* Relax branch 32 to branch 16.  */
  if (relaxable_p && (s->bsym != NULL) && ((abs_value & 0xffffff00) == 0)
  if (relaxable_p && (s->bsym != NULL) && ((abs_value & 0xffffff00) == 0)
      && (S_IS_DEFINED (s) && !S_IS_COMMON (s) && !S_IS_EXTERNAL (s)))
      && (S_IS_DEFINED (s) && !S_IS_COMMON (s) && !S_IS_EXTERNAL (s)))
    {
    {
      /* do nothing.  */
      /* do nothing.  */
    }
    }
  else
  else
    {
    {
      /* Branch 32 can not be relaxed to b 16, so clear OPT bit.  */
      /* Branch 32 can not be relaxed to b 16, so clear OPT bit.  */
      fragp->fr_opcode = NULL;
      fragp->fr_opcode = NULL;
      fragp->fr_subtype = RELAX_OPT_CLEAR (fragp->fr_subtype);
      fragp->fr_subtype = RELAX_OPT_CLEAR (fragp->fr_subtype);
    }
    }
 
 
  return grows;
  return grows;
}
}
 
 
/* Main purpose is to determine whether one frag should do relax.
/* Main purpose is to determine whether one frag should do relax.
   frag->fr_opcode indicates this point.  */
   frag->fr_opcode indicates this point.  */
 
 
int
int
score_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED)
score_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED)
{
{
  int grows = 0;
  int grows = 0;
  int insn_size;
  int insn_size;
  int insn_relax_size;
  int insn_relax_size;
  int do_relax_p = 0;           /* Indicate doing relaxation for this frag.  */
  int do_relax_p = 0;           /* Indicate doing relaxation for this frag.  */
  int relaxable_p = 0;
  int relaxable_p = 0;
  bfd_boolean word_align_p = FALSE;
  bfd_boolean word_align_p = FALSE;
  fragS *next_fragp;
  fragS *next_fragp;
 
 
  /* If the instruction address is odd, make it half word align first.  */
  /* If the instruction address is odd, make it half word align first.  */
  if ((fragp->fr_address) % 2 != 0)
  if ((fragp->fr_address) % 2 != 0)
    {
    {
      if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
      if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
        {
        {
          fragp->insn_addr = 1;
          fragp->insn_addr = 1;
          grows += 1;
          grows += 1;
        }
        }
    }
    }
 
 
  word_align_p = ((fragp->fr_address + fragp->insn_addr) % 4 == 0) ? TRUE : FALSE;
  word_align_p = ((fragp->fr_address + fragp->insn_addr) % 4 == 0) ? TRUE : FALSE;
 
 
  /* Get instruction size and relax size after the last relaxation.  */
  /* Get instruction size and relax size after the last relaxation.  */
  if (fragp->fr_opcode)
  if (fragp->fr_opcode)
    {
    {
      insn_size = RELAX_NEW (fragp->fr_subtype);
      insn_size = RELAX_NEW (fragp->fr_subtype);
      insn_relax_size = RELAX_OLD (fragp->fr_subtype);
      insn_relax_size = RELAX_OLD (fragp->fr_subtype);
    }
    }
  else
  else
    {
    {
      insn_size = RELAX_OLD (fragp->fr_subtype);
      insn_size = RELAX_OLD (fragp->fr_subtype);
      insn_relax_size = RELAX_NEW (fragp->fr_subtype);
      insn_relax_size = RELAX_NEW (fragp->fr_subtype);
    }
    }
 
 
  /* Handle specially for GP instruction.  for, judge_size_before_relax() has already determine
  /* Handle specially for GP instruction.  for, judge_size_before_relax() has already determine
     whether the GP instruction should do relax.  */
     whether the GP instruction should do relax.  */
  if ((RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
  if ((RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
      || (RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
      || (RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
    {
    {
      if (!word_align_p)
      if (!word_align_p)
        {
        {
          if (fragp->insn_addr < 2)
          if (fragp->insn_addr < 2)
            {
            {
              fragp->insn_addr += 2;
              fragp->insn_addr += 2;
              grows += 2;
              grows += 2;
            }
            }
          else
          else
            {
            {
              fragp->insn_addr -= 2;
              fragp->insn_addr -= 2;
              grows -= 2;
              grows -= 2;
            }
            }
        }
        }
 
 
      if (fragp->fr_opcode)
      if (fragp->fr_opcode)
        fragp->fr_fix = RELAX_NEW (fragp->fr_subtype) + fragp->insn_addr;
        fragp->fr_fix = RELAX_NEW (fragp->fr_subtype) + fragp->insn_addr;
      else
      else
        fragp->fr_fix = RELAX_OLD (fragp->fr_subtype) + fragp->insn_addr;
        fragp->fr_fix = RELAX_OLD (fragp->fr_subtype) + fragp->insn_addr;
    }
    }
  else
  else
    {
    {
      if (RELAX_TYPE (fragp->fr_subtype) == PC_DISP19div2)
      if (RELAX_TYPE (fragp->fr_subtype) == PC_DISP19div2)
        b32_relax_to_b16 (fragp);
        b32_relax_to_b16 (fragp);
 
 
      relaxable_p = RELAX_OPT (fragp->fr_subtype);
      relaxable_p = RELAX_OPT (fragp->fr_subtype);
      next_fragp = fragp->fr_next;
      next_fragp = fragp->fr_next;
      while ((next_fragp) && (next_fragp->fr_type != rs_machine_dependent))
      while ((next_fragp) && (next_fragp->fr_type != rs_machine_dependent))
        {
        {
          next_fragp = next_fragp->fr_next;
          next_fragp = next_fragp->fr_next;
        }
        }
 
 
      if (next_fragp)
      if (next_fragp)
        {
        {
          int n_insn_size;
          int n_insn_size;
          int n_relaxable_p = 0;
          int n_relaxable_p = 0;
 
 
          if (next_fragp->fr_opcode)
          if (next_fragp->fr_opcode)
            {
            {
              n_insn_size = RELAX_NEW (next_fragp->fr_subtype);
              n_insn_size = RELAX_NEW (next_fragp->fr_subtype);
            }
            }
          else
          else
            {
            {
              n_insn_size = RELAX_OLD (next_fragp->fr_subtype);
              n_insn_size = RELAX_OLD (next_fragp->fr_subtype);
            }
            }
 
 
          if (RELAX_TYPE (next_fragp->fr_subtype) == PC_DISP19div2)
          if (RELAX_TYPE (next_fragp->fr_subtype) == PC_DISP19div2)
            b32_relax_to_b16 (next_fragp);
            b32_relax_to_b16 (next_fragp);
          n_relaxable_p = RELAX_OPT (next_fragp->fr_subtype);
          n_relaxable_p = RELAX_OPT (next_fragp->fr_subtype);
 
 
          if (word_align_p)
          if (word_align_p)
            {
            {
              if (insn_size == 4)
              if (insn_size == 4)
                {
                {
                  /* 32 -> 16.  */
                  /* 32 -> 16.  */
                  if (relaxable_p && ((n_insn_size == 2) || n_relaxable_p))
                  if (relaxable_p && ((n_insn_size == 2) || n_relaxable_p))
                    {
                    {
                      grows -= 2;
                      grows -= 2;
                      do_relax_p = 1;
                      do_relax_p = 1;
                    }
                    }
                }
                }
              else if (insn_size == 2)
              else if (insn_size == 2)
                {
                {
                  /* 16 -> 32.  */
                  /* 16 -> 32.  */
                  if (relaxable_p && (((n_insn_size == 4) && !n_relaxable_p) || (n_insn_size > 4)))
                  if (relaxable_p && (((n_insn_size == 4) && !n_relaxable_p) || (n_insn_size > 4)))
                    {
                    {
                      grows += 2;
                      grows += 2;
                      do_relax_p = 1;
                      do_relax_p = 1;
                    }
                    }
                }
                }
              else
              else
                {
                {
                  abort ();
                  abort ();
                }
                }
            }
            }
          else
          else
            {
            {
              if (insn_size == 4)
              if (insn_size == 4)
                {
                {
                  /* 32 -> 16.  */
                  /* 32 -> 16.  */
                  if (relaxable_p)
                  if (relaxable_p)
                    {
                    {
                      grows -= 2;
                      grows -= 2;
                      do_relax_p = 1;
                      do_relax_p = 1;
                    }
                    }
                  /* Make the 32 bit insturction word align.  */
                  /* Make the 32 bit insturction word align.  */
                  else
                  else
                    {
                    {
                      fragp->insn_addr += 2;
                      fragp->insn_addr += 2;
                      grows += 2;
                      grows += 2;
                    }
                    }
                }
                }
              else if (insn_size == 2)
              else if (insn_size == 2)
                {
                {
                  /* Do nothing.  */
                  /* Do nothing.  */
                }
                }
              else
              else
                {
                {
                  abort ();
                  abort ();
                }
                }
            }
            }
        }
        }
      else
      else
        {
        {
          /* Here, try best to do relax regardless fragp->fr_next->fr_type.  */
          /* Here, try best to do relax regardless fragp->fr_next->fr_type.  */
          if (word_align_p == FALSE)
          if (word_align_p == FALSE)
            {
            {
              if (insn_size % 4 == 0)
              if (insn_size % 4 == 0)
                {
                {
                  /* 32 -> 16.  */
                  /* 32 -> 16.  */
                  if (relaxable_p)
                  if (relaxable_p)
                    {
                    {
                      grows -= 2;
                      grows -= 2;
                      do_relax_p = 1;
                      do_relax_p = 1;
                    }
                    }
                  else
                  else
                    {
                    {
                      fragp->insn_addr += 2;
                      fragp->insn_addr += 2;
                      grows += 2;
                      grows += 2;
                    }
                    }
                }
                }
            }
            }
          else
          else
            {
            {
              /* Do nothing.  */
              /* Do nothing.  */
            }
            }
        }
        }
 
 
      /* fragp->fr_opcode indicates whether this frag should be relaxed.  */
      /* fragp->fr_opcode indicates whether this frag should be relaxed.  */
      if (do_relax_p)
      if (do_relax_p)
        {
        {
          if (fragp->fr_opcode)
          if (fragp->fr_opcode)
            {
            {
              fragp->fr_opcode = NULL;
              fragp->fr_opcode = NULL;
              /* Guarantee estimate stage is correct.  */
              /* Guarantee estimate stage is correct.  */
              fragp->fr_fix = RELAX_OLD (fragp->fr_subtype);
              fragp->fr_fix = RELAX_OLD (fragp->fr_subtype);
              fragp->fr_fix += fragp->insn_addr;
              fragp->fr_fix += fragp->insn_addr;
            }
            }
          else
          else
            {
            {
              fragp->fr_opcode = fragp->fr_literal + RELAX_RELOC1 (fragp->fr_subtype);
              fragp->fr_opcode = fragp->fr_literal + RELAX_RELOC1 (fragp->fr_subtype);
              /* Guarantee estimate stage is correct.  */
              /* Guarantee estimate stage is correct.  */
              fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
              fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
              fragp->fr_fix += fragp->insn_addr;
              fragp->fr_fix += fragp->insn_addr;
            }
            }
        }
        }
      else
      else
        {
        {
          if (fragp->fr_opcode)
          if (fragp->fr_opcode)
            {
            {
              /* Guarantee estimate stage is correct.  */
              /* Guarantee estimate stage is correct.  */
              fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
              fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
              fragp->fr_fix += fragp->insn_addr;
              fragp->fr_fix += fragp->insn_addr;
            }
            }
          else
          else
            {
            {
              /* Guarantee estimate stage is correct.  */
              /* Guarantee estimate stage is correct.  */
              fragp->fr_fix = RELAX_OLD (fragp->fr_subtype);
              fragp->fr_fix = RELAX_OLD (fragp->fr_subtype);
              fragp->fr_fix += fragp->insn_addr;
              fragp->fr_fix += fragp->insn_addr;
            }
            }
        }
        }
    }
    }
 
 
  return grows;
  return grows;
}
}
 
 
void
void
md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp)
md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp)
{
{
  int old;
  int old;
  int new;
  int new;
  char backup[20];
  char backup[20];
  fixS *fixp;
  fixS *fixp;
 
 
  old = RELAX_OLD (fragp->fr_subtype);
  old = RELAX_OLD (fragp->fr_subtype);
  new = RELAX_NEW (fragp->fr_subtype);
  new = RELAX_NEW (fragp->fr_subtype);
 
 
  /* fragp->fr_opcode indicates whether this frag should be relaxed.  */
  /* fragp->fr_opcode indicates whether this frag should be relaxed.  */
  if (fragp->fr_opcode == NULL)
  if (fragp->fr_opcode == NULL)
    {
    {
      memcpy (backup, fragp->fr_literal, old);
      memcpy (backup, fragp->fr_literal, old);
      fragp->fr_fix = old;
      fragp->fr_fix = old;
    }
    }
  else
  else
    {
    {
      memcpy (backup, fragp->fr_literal + old, new);
      memcpy (backup, fragp->fr_literal + old, new);
      fragp->fr_fix = new;
      fragp->fr_fix = new;
    }
    }
 
 
  fixp = fragp->tc_frag_data.fixp;
  fixp = fragp->tc_frag_data.fixp;
  while (fixp && fixp->fx_frag == fragp && fixp->fx_where < old)
  while (fixp && fixp->fx_frag == fragp && fixp->fx_where < old)
    {
    {
      if (fragp->fr_opcode)
      if (fragp->fr_opcode)
        fixp->fx_done = 1;
        fixp->fx_done = 1;
      fixp = fixp->fx_next;
      fixp = fixp->fx_next;
    }
    }
  while (fixp && fixp->fx_frag == fragp)
  while (fixp && fixp->fx_frag == fragp)
    {
    {
      if (fragp->fr_opcode)
      if (fragp->fr_opcode)
        fixp->fx_where -= old + fragp->insn_addr;
        fixp->fx_where -= old + fragp->insn_addr;
      else
      else
        fixp->fx_done = 1;
        fixp->fx_done = 1;
      fixp = fixp->fx_next;
      fixp = fixp->fx_next;
    }
    }
 
 
  if (fragp->insn_addr)
  if (fragp->insn_addr)
    {
    {
      md_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
      md_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
    }
    }
  memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
  memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
  fragp->fr_fix += fragp->insn_addr;
  fragp->fr_fix += fragp->insn_addr;
}
}
 
 
/* Implementation of md_frag_check.
/* Implementation of md_frag_check.
   Called after md_convert_frag().  */
   Called after md_convert_frag().  */
 
 
void
void
score_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
score_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
{
{
  know (fragp->insn_addr <= RELAX_PAD_BYTE);
  know (fragp->insn_addr <= RELAX_PAD_BYTE);
}
}
 
 
bfd_boolean
bfd_boolean
score_fix_adjustable (fixS * fixP)
score_fix_adjustable (fixS * fixP)
{
{
  if (fixP->fx_addsy == NULL)
  if (fixP->fx_addsy == NULL)
    {
    {
      return 1;
      return 1;
    }
    }
  else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
  else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
      && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
      && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
    {
    {
      return 0;
      return 0;
    }
    }
  else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
  else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
      || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
      || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
    {
    {
      return 0;
      return 0;
    }
    }
 
 
  return 1;
  return 1;
}
}
 
 
/* Implementation of TC_VALIDATE_FIX.
/* Implementation of TC_VALIDATE_FIX.
   Called before md_apply_fix() and after md_convert_frag().  */
   Called before md_apply_fix() and after md_convert_frag().  */
void
void
score_validate_fix (fixS *fixP)
score_validate_fix (fixS *fixP)
{
{
  fixP->fx_where += fixP->fx_frag->insn_addr;
  fixP->fx_where += fixP->fx_frag->insn_addr;
}
}
 
 
long
long
md_pcrel_from (fixS * fixP)
md_pcrel_from (fixS * fixP)
{
{
  long retval = 0;
  long retval = 0;
 
 
  if (fixP->fx_addsy
  if (fixP->fx_addsy
      && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
      && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
      && (fixP->fx_subsy == NULL))
      && (fixP->fx_subsy == NULL))
    {
    {
      retval = 0;
      retval = 0;
    }
    }
  else
  else
    {
    {
      retval = fixP->fx_where + fixP->fx_frag->fr_address;
      retval = fixP->fx_where + fixP->fx_frag->fr_address;
    }
    }
 
 
  return retval;
  return retval;
}
}
 
 
int
int
score_force_relocation (struct fix *fixp)
score_force_relocation (struct fix *fixp)
{
{
  int retval = 0;
  int retval = 0;
 
 
  if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
  if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
      || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
      || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
      || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
      || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
      || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
      || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
      || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
      || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
      || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH)
      || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH)
    {
    {
      retval = 1;
      retval = 1;
    }
    }
 
 
  return retval;
  return retval;
}
}
 
 
/* Round up a section size to the appropriate boundary.  */
/* Round up a section size to the appropriate boundary.  */
valueT
valueT
md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
{
{
  int align = bfd_get_section_alignment (stdoutput, segment);
  int align = bfd_get_section_alignment (stdoutput, segment);
 
 
  return ((size + (1 << align) - 1) & (-1 << align));
  return ((size + (1 << align) - 1) & (-1 << align));
}
}
 
 
void
void
md_apply_fix (fixS *fixP, valueT *valP, segT seg)
md_apply_fix (fixS *fixP, valueT *valP, segT seg)
{
{
  offsetT value = *valP;
  offsetT value = *valP;
  offsetT abs_value = 0;
  offsetT abs_value = 0;
  offsetT newval;
  offsetT newval;
  offsetT content;
  offsetT content;
  unsigned short HI, LO;
  unsigned short HI, LO;
 
 
  char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
  char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
 
 
  assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
  assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
  if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
  if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
    {
    {
      if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
      if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
        fixP->fx_done = 1;
        fixP->fx_done = 1;
    }
    }
 
 
  /* If this symbol is in a different section then we need to leave it for
  /* If this symbol is in a different section then we need to leave it for
     the linker to deal with.  Unfortunately, md_pcrel_from can't tell,
     the linker to deal with.  Unfortunately, md_pcrel_from can't tell,
     so we have to undo it's effects here.  */
     so we have to undo it's effects here.  */
  if (fixP->fx_pcrel)
  if (fixP->fx_pcrel)
    {
    {
      if (fixP->fx_addsy != NULL
      if (fixP->fx_addsy != NULL
          && S_IS_DEFINED (fixP->fx_addsy)
          && S_IS_DEFINED (fixP->fx_addsy)
          && S_GET_SEGMENT (fixP->fx_addsy) != seg)
          && S_GET_SEGMENT (fixP->fx_addsy) != seg)
        value += md_pcrel_from (fixP);
        value += md_pcrel_from (fixP);
    }
    }
 
 
  /* Remember value for emit_reloc.  */
  /* Remember value for emit_reloc.  */
  fixP->fx_addnumber = value;
  fixP->fx_addnumber = value;
 
 
  switch (fixP->fx_r_type)
  switch (fixP->fx_r_type)
    {
    {
    case BFD_RELOC_HI16_S:
    case BFD_RELOC_HI16_S:
      if (fixP->fx_done)
      if (fixP->fx_done)
        {                       /* For la rd, imm32.  */
        {                       /* For la rd, imm32.  */
          newval = md_chars_to_number (buf, INSN_SIZE);
          newval = md_chars_to_number (buf, INSN_SIZE);
          HI = (value) >> 16;   /* mul to 2, then take the hi 16 bit.  */
          HI = (value) >> 16;   /* mul to 2, then take the hi 16 bit.  */
          newval |= (HI & 0x3fff) << 1;
          newval |= (HI & 0x3fff) << 1;
          newval |= ((HI >> 14) & 0x3) << 16;
          newval |= ((HI >> 14) & 0x3) << 16;
          md_number_to_chars (buf, newval, INSN_SIZE);
          md_number_to_chars (buf, newval, INSN_SIZE);
        }
        }
      break;
      break;
    case BFD_RELOC_LO16:
    case BFD_RELOC_LO16:
      if (fixP->fx_done)        /* For la rd, imm32.  */
      if (fixP->fx_done)        /* For la rd, imm32.  */
        {
        {
          newval = md_chars_to_number (buf, INSN_SIZE);
          newval = md_chars_to_number (buf, INSN_SIZE);
          LO = (value) & 0xffff;
          LO = (value) & 0xffff;
          newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi.  */
          newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi.  */
          newval |= ((LO >> 14) & 0x3) << 16;
          newval |= ((LO >> 14) & 0x3) << 16;
          md_number_to_chars (buf, newval, INSN_SIZE);
          md_number_to_chars (buf, newval, INSN_SIZE);
        }
        }
      break;
      break;
    case BFD_RELOC_SCORE_JMP:
    case BFD_RELOC_SCORE_JMP:
      {
      {
        content = md_chars_to_number (buf, INSN_SIZE);
        content = md_chars_to_number (buf, INSN_SIZE);
        value = fixP->fx_offset;
        value = fixP->fx_offset;
        content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
        content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
        md_number_to_chars (buf, content, INSN_SIZE);
        md_number_to_chars (buf, content, INSN_SIZE);
      }
      }
      break;
      break;
    case BFD_RELOC_SCORE_BRANCH:
    case BFD_RELOC_SCORE_BRANCH:
      if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
      if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
        value = fixP->fx_offset;
        value = fixP->fx_offset;
      else
      else
        fixP->fx_done = 1;
        fixP->fx_done = 1;
 
 
      content = md_chars_to_number (buf, INSN_SIZE);
      content = md_chars_to_number (buf, INSN_SIZE);
      if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) != 0x80008000))
      if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) != 0x80008000))
        {
        {
          if ((value & 0x80000000) == 0x80000000)
          if ((value & 0x80000000) == 0x80000000)
            abs_value = 0xffffffff - value + 1;
            abs_value = 0xffffffff - value + 1;
          if ((abs_value & 0xffffff00) != 0)
          if ((abs_value & 0xffffff00) != 0)
            {
            {
              as_bad_where (fixP->fx_file, fixP->fx_line,
              as_bad_where (fixP->fx_file, fixP->fx_line,
                            _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int)value);
                            _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int)value);
              return;
              return;
            }
            }
          content = md_chars_to_number (buf, INSN16_SIZE);
          content = md_chars_to_number (buf, INSN16_SIZE);
          content &= 0xff00;
          content &= 0xff00;
          content = (content & 0xff00) | ((value >> 1) & 0xff);
          content = (content & 0xff00) | ((value >> 1) & 0xff);
          md_number_to_chars (buf, content, INSN16_SIZE);
          md_number_to_chars (buf, content, INSN16_SIZE);
          fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
          fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
          fixP->fx_size = 2;
          fixP->fx_size = 2;
        }
        }
      else
      else
        {
        {
          if ((value & 0x80000000) == 0x80000000)
          if ((value & 0x80000000) == 0x80000000)
            abs_value = 0xffffffff - value + 1;
            abs_value = 0xffffffff - value + 1;
          if ((abs_value & 0xfff80000) != 0)
          if ((abs_value & 0xfff80000) != 0)
            {
            {
              as_bad_where (fixP->fx_file, fixP->fx_line,
              as_bad_where (fixP->fx_file, fixP->fx_line,
                            _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
                            _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
              return;
              return;
            }
            }
          content = md_chars_to_number (buf, INSN_SIZE);
          content = md_chars_to_number (buf, INSN_SIZE);
          content &= 0xfc00fc01;
          content &= 0xfc00fc01;
          content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
          content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
          md_number_to_chars (buf, content, INSN_SIZE);
          md_number_to_chars (buf, content, INSN_SIZE);
        }
        }
      break;
      break;
    case BFD_RELOC_SCORE16_JMP:
    case BFD_RELOC_SCORE16_JMP:
      content = md_chars_to_number (buf, INSN16_SIZE);
      content = md_chars_to_number (buf, INSN16_SIZE);
      content &= 0xf001;
      content &= 0xf001;
      value = fixP->fx_offset & 0xfff;
      value = fixP->fx_offset & 0xfff;
      content = (content & 0xfc01) | (value & 0xffe);
      content = (content & 0xfc01) | (value & 0xffe);
      md_number_to_chars (buf, content, INSN16_SIZE);
      md_number_to_chars (buf, content, INSN16_SIZE);
      break;
      break;
    case BFD_RELOC_SCORE16_BRANCH:
    case BFD_RELOC_SCORE16_BRANCH:
      content = md_chars_to_number (buf, INSN_SIZE);
      content = md_chars_to_number (buf, INSN_SIZE);
      if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) == 0x80008000))
      if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) == 0x80008000))
        {
        {
          if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
          if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
              (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
              (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
            value = fixP->fx_offset;
            value = fixP->fx_offset;
          else
          else
            fixP->fx_done = 1;
            fixP->fx_done = 1;
          if ((value & 0x80000000) == 0x80000000)
          if ((value & 0x80000000) == 0x80000000)
            abs_value = 0xffffffff - value + 1;
            abs_value = 0xffffffff - value + 1;
          if ((abs_value & 0xfff80000) != 0)
          if ((abs_value & 0xfff80000) != 0)
            {
            {
              as_bad_where (fixP->fx_file, fixP->fx_line,
              as_bad_where (fixP->fx_file, fixP->fx_line,
                            _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
                            _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
              return;
              return;
            }
            }
          content = md_chars_to_number (buf, INSN_SIZE);
          content = md_chars_to_number (buf, INSN_SIZE);
          content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
          content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
          md_number_to_chars (buf, content, INSN_SIZE);
          md_number_to_chars (buf, content, INSN_SIZE);
          fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
          fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
          fixP->fx_size = 4;
          fixP->fx_size = 4;
          break;
          break;
        }
        }
      else
      else
        {
        {
          /* In differnt section.  */
          /* In differnt section.  */
          if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
          if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
              (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
              (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
            value = fixP->fx_offset;
            value = fixP->fx_offset;
          else
          else
            fixP->fx_done = 1;
            fixP->fx_done = 1;
 
 
          if ((value & 0x80000000) == 0x80000000)
          if ((value & 0x80000000) == 0x80000000)
            abs_value = 0xffffffff - value + 1;
            abs_value = 0xffffffff - value + 1;
          if ((abs_value & 0xffffff00) != 0)
          if ((abs_value & 0xffffff00) != 0)
            {
            {
              as_bad_where (fixP->fx_file, fixP->fx_line,
              as_bad_where (fixP->fx_file, fixP->fx_line,
                            _(" branch relocation truncate (0x%x)  [-2^8 ~ 2^8]"), (unsigned int)value);
                            _(" branch relocation truncate (0x%x)  [-2^8 ~ 2^8]"), (unsigned int)value);
              return;
              return;
            }
            }
          content = md_chars_to_number (buf, INSN16_SIZE);
          content = md_chars_to_number (buf, INSN16_SIZE);
          content = (content & 0xff00) | ((value >> 1) & 0xff);
          content = (content & 0xff00) | ((value >> 1) & 0xff);
          md_number_to_chars (buf, content, INSN16_SIZE);
          md_number_to_chars (buf, content, INSN16_SIZE);
          break;
          break;
        }
        }
    case BFD_RELOC_8:
    case BFD_RELOC_8:
      if (fixP->fx_done || fixP->fx_pcrel)
      if (fixP->fx_done || fixP->fx_pcrel)
        md_number_to_chars (buf, value, 1);
        md_number_to_chars (buf, value, 1);
#ifdef OBJ_ELF
#ifdef OBJ_ELF
      else
      else
        {
        {
          value = fixP->fx_offset;
          value = fixP->fx_offset;
          md_number_to_chars (buf, value, 1);
          md_number_to_chars (buf, value, 1);
        }
        }
#endif
#endif
      break;
      break;
 
 
    case BFD_RELOC_16:
    case BFD_RELOC_16:
      if (fixP->fx_done || fixP->fx_pcrel)
      if (fixP->fx_done || fixP->fx_pcrel)
        md_number_to_chars (buf, value, 2);
        md_number_to_chars (buf, value, 2);
#ifdef OBJ_ELF
#ifdef OBJ_ELF
      else
      else
        {
        {
          value = fixP->fx_offset;
          value = fixP->fx_offset;
          md_number_to_chars (buf, value, 2);
          md_number_to_chars (buf, value, 2);
        }
        }
#endif
#endif
      break;
      break;
    case BFD_RELOC_RVA:
    case BFD_RELOC_RVA:
    case BFD_RELOC_32:
    case BFD_RELOC_32:
      if (fixP->fx_done || fixP->fx_pcrel)
      if (fixP->fx_done || fixP->fx_pcrel)
        md_number_to_chars (buf, value, 4);
        md_number_to_chars (buf, value, 4);
#ifdef OBJ_ELF
#ifdef OBJ_ELF
      else
      else
        {
        {
          value = fixP->fx_offset;
          value = fixP->fx_offset;
          md_number_to_chars (buf, value, 4);
          md_number_to_chars (buf, value, 4);
        }
        }
#endif
#endif
      break;
      break;
    case BFD_RELOC_VTABLE_INHERIT:
    case BFD_RELOC_VTABLE_INHERIT:
      fixP->fx_done = 0;
      fixP->fx_done = 0;
      if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
      if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
        S_SET_WEAK (fixP->fx_addsy);
        S_SET_WEAK (fixP->fx_addsy);
      break;
      break;
    case BFD_RELOC_VTABLE_ENTRY:
    case BFD_RELOC_VTABLE_ENTRY:
      fixP->fx_done = 0;
      fixP->fx_done = 0;
      break;
      break;
    case BFD_RELOC_SCORE_GPREL15:
    case BFD_RELOC_SCORE_GPREL15:
      content = md_chars_to_number (buf, INSN_SIZE);
      content = md_chars_to_number (buf, INSN_SIZE);
      if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94188000))
      if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94188000))
        fixP->fx_r_type = BFD_RELOC_NONE;
        fixP->fx_r_type = BFD_RELOC_NONE;
      fixP->fx_done = 0;
      fixP->fx_done = 0;
      break;
      break;
    case BFD_RELOC_SCORE_GOT15:
    case BFD_RELOC_SCORE_GOT15:
    case BFD_RELOC_SCORE_DUMMY_HI16:
    case BFD_RELOC_SCORE_DUMMY_HI16:
    case BFD_RELOC_SCORE_GOT_LO16:
    case BFD_RELOC_SCORE_GOT_LO16:
    case BFD_RELOC_SCORE_CALL15:
    case BFD_RELOC_SCORE_CALL15:
    case BFD_RELOC_GPREL32:
    case BFD_RELOC_GPREL32:
      break;
      break;
    case BFD_RELOC_NONE:
    case BFD_RELOC_NONE:
    default:
    default:
      as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
      as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
    }
    }
}
}
 
 
/* Translate internal representation of relocation info to BFD target format.  */
/* Translate internal representation of relocation info to BFD target format.  */
arelent **
arelent **
tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
{
{
  static arelent *retval[MAX_RELOC_EXPANSION + 1];  /* MAX_RELOC_EXPANSION equals 2.  */
  static arelent *retval[MAX_RELOC_EXPANSION + 1];  /* MAX_RELOC_EXPANSION equals 2.  */
  arelent *reloc;
  arelent *reloc;
  bfd_reloc_code_real_type code;
  bfd_reloc_code_real_type code;
  char *type;
  char *type;
  fragS *f;
  fragS *f;
  symbolS *s;
  symbolS *s;
  expressionS e;
  expressionS e;
 
 
  reloc = retval[0] = xmalloc (sizeof (arelent));
  reloc = retval[0] = xmalloc (sizeof (arelent));
  retval[1] = NULL;
  retval[1] = NULL;
 
 
  reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
  reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
  *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
  reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
  reloc->addend = fixp->fx_offset;
  reloc->addend = fixp->fx_offset;
 
 
  /* If this is a variant frag, we may need to adjust the existing
  /* If this is a variant frag, we may need to adjust the existing
     reloc and generate a new one.  */
     reloc and generate a new one.  */
  if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
  if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
    {
    {
      /* Update instruction imm bit.  */
      /* Update instruction imm bit.  */
      offsetT newval;
      offsetT newval;
      unsigned short off;
      unsigned short off;
      char *buf;
      char *buf;
 
 
      buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
      buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
      newval = md_chars_to_number (buf, INSN_SIZE);
      newval = md_chars_to_number (buf, INSN_SIZE);
      off = fixp->fx_offset >> 16;
      off = fixp->fx_offset >> 16;
      newval |= (off & 0x3fff) << 1;
      newval |= (off & 0x3fff) << 1;
      newval |= ((off >> 14) & 0x3) << 16;
      newval |= ((off >> 14) & 0x3) << 16;
      md_number_to_chars (buf, newval, INSN_SIZE);
      md_number_to_chars (buf, newval, INSN_SIZE);
 
 
      buf += INSN_SIZE;
      buf += INSN_SIZE;
      newval = md_chars_to_number (buf, INSN_SIZE);
      newval = md_chars_to_number (buf, INSN_SIZE);
      off = fixp->fx_offset & 0xffff;
      off = fixp->fx_offset & 0xffff;
      newval |= ((off & 0x3fff) << 1);
      newval |= ((off & 0x3fff) << 1);
      newval |= (((off >> 14) & 0x3) << 16);
      newval |= (((off >> 14) & 0x3) << 16);
      md_number_to_chars (buf, newval, INSN_SIZE);
      md_number_to_chars (buf, newval, INSN_SIZE);
 
 
      retval[1] = xmalloc (sizeof (arelent));
      retval[1] = xmalloc (sizeof (arelent));
      retval[2] = NULL;
      retval[2] = NULL;
      retval[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
      retval[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
      *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
      *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
      retval[1]->address = (reloc->address + RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
      retval[1]->address = (reloc->address + RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
 
 
      f = fixp->fx_frag;
      f = fixp->fx_frag;
      s = f->fr_symbol;
      s = f->fr_symbol;
      e = s->sy_value;
      e = s->sy_value;
 
 
      retval[1]->addend = 0;
      retval[1]->addend = 0;
      retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
      retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
      assert (retval[1]->howto != NULL);
      assert (retval[1]->howto != NULL);
 
 
      fixp->fx_r_type = BFD_RELOC_HI16_S;
      fixp->fx_r_type = BFD_RELOC_HI16_S;
    }
    }
 
 
  code = fixp->fx_r_type;
  code = fixp->fx_r_type;
  switch (fixp->fx_r_type)
  switch (fixp->fx_r_type)
    {
    {
    case BFD_RELOC_32:
    case BFD_RELOC_32:
      if (fixp->fx_pcrel)
      if (fixp->fx_pcrel)
        {
        {
          code = BFD_RELOC_32_PCREL;
          code = BFD_RELOC_32_PCREL;
          break;
          break;
        }
        }
    case BFD_RELOC_HI16_S:
    case BFD_RELOC_HI16_S:
    case BFD_RELOC_LO16:
    case BFD_RELOC_LO16:
    case BFD_RELOC_SCORE_JMP:
    case BFD_RELOC_SCORE_JMP:
    case BFD_RELOC_SCORE_BRANCH:
    case BFD_RELOC_SCORE_BRANCH:
    case BFD_RELOC_SCORE16_JMP:
    case BFD_RELOC_SCORE16_JMP:
    case BFD_RELOC_SCORE16_BRANCH:
    case BFD_RELOC_SCORE16_BRANCH:
    case BFD_RELOC_VTABLE_ENTRY:
    case BFD_RELOC_VTABLE_ENTRY:
    case BFD_RELOC_VTABLE_INHERIT:
    case BFD_RELOC_VTABLE_INHERIT:
    case BFD_RELOC_SCORE_GPREL15:
    case BFD_RELOC_SCORE_GPREL15:
    case BFD_RELOC_SCORE_GOT15:
    case BFD_RELOC_SCORE_GOT15:
    case BFD_RELOC_SCORE_DUMMY_HI16:
    case BFD_RELOC_SCORE_DUMMY_HI16:
    case BFD_RELOC_SCORE_GOT_LO16:
    case BFD_RELOC_SCORE_GOT_LO16:
    case BFD_RELOC_SCORE_CALL15:
    case BFD_RELOC_SCORE_CALL15:
    case BFD_RELOC_GPREL32:
    case BFD_RELOC_GPREL32:
    case BFD_RELOC_NONE:
    case BFD_RELOC_NONE:
      code = fixp->fx_r_type;
      code = fixp->fx_r_type;
      break;
      break;
    default:
    default:
      type = _("<unknown>");
      type = _("<unknown>");
      as_bad_where (fixp->fx_file, fixp->fx_line,
      as_bad_where (fixp->fx_file, fixp->fx_line,
                    _("cannot represent %s relocation in this object file format"), type);
                    _("cannot represent %s relocation in this object file format"), type);
      return NULL;
      return NULL;
    }
    }
 
 
  reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
  reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
  if (reloc->howto == NULL)
  if (reloc->howto == NULL)
    {
    {
      as_bad_where (fixp->fx_file, fixp->fx_line,
      as_bad_where (fixp->fx_file, fixp->fx_line,
                    _("cannot represent %s relocation in this object file format1"),
                    _("cannot represent %s relocation in this object file format1"),
                    bfd_get_reloc_code_name (code));
                    bfd_get_reloc_code_name (code));
      return NULL;
      return NULL;
    }
    }
  /* HACK: Since arm ELF uses Rel instead of Rela, encode the
  /* HACK: Since arm ELF uses Rel instead of Rela, encode the
     vtable entry to be used in the relocation's section offset.  */
     vtable entry to be used in the relocation's section offset.  */
  if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
  if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
    reloc->address = fixp->fx_offset;
    reloc->address = fixp->fx_offset;
 
 
  return retval;
  return retval;
}
}
 
 
void
void
score_elf_final_processing (void)
score_elf_final_processing (void)
{
{
  if (fix_data_dependency == 1)
  if (fix_data_dependency == 1)
    {
    {
      elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
      elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
    }
    }
  if (score_pic == PIC)
  if (score_pic == PIC)
    {
    {
      elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
      elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
    }
    }
}
}
 
 
static void
static void
parse_pce_inst (char *insnstr)
parse_pce_inst (char *insnstr)
{
{
  char c;
  char c;
  char *p;
  char *p;
  char first[MAX_LITERAL_POOL_SIZE];
  char first[MAX_LITERAL_POOL_SIZE];
  char second[MAX_LITERAL_POOL_SIZE];
  char second[MAX_LITERAL_POOL_SIZE];
  struct score_it pec_part_1;
  struct score_it pec_part_1;
 
 
  /* Get first part string of PCE.  */
  /* Get first part string of PCE.  */
  p = strstr (insnstr, "||");
  p = strstr (insnstr, "||");
  c = *p;
  c = *p;
  *p = '\0';
  *p = '\0';
  sprintf (first, "%s", insnstr);
  sprintf (first, "%s", insnstr);
 
 
  /* Get second part string of PCE.  */
  /* Get second part string of PCE.  */
  *p = c;
  *p = c;
  p += 2;
  p += 2;
  sprintf (second, "%s", p);
  sprintf (second, "%s", p);
 
 
  parse_16_32_inst (first, FALSE);
  parse_16_32_inst (first, FALSE);
  if (inst.error)
  if (inst.error)
    return;
    return;
 
 
  memcpy (&pec_part_1, &inst, sizeof (inst));
  memcpy (&pec_part_1, &inst, sizeof (inst));
 
 
  parse_16_32_inst (second, FALSE);
  parse_16_32_inst (second, FALSE);
  if (inst.error)
  if (inst.error)
    return;
    return;
 
 
  if (   ((pec_part_1.size == INSN_SIZE) && (inst.size == INSN_SIZE))
  if (   ((pec_part_1.size == INSN_SIZE) && (inst.size == INSN_SIZE))
      || ((pec_part_1.size == INSN_SIZE) && (inst.size == INSN16_SIZE))
      || ((pec_part_1.size == INSN_SIZE) && (inst.size == INSN16_SIZE))
      || ((pec_part_1.size == INSN16_SIZE) && (inst.size == INSN_SIZE)))
      || ((pec_part_1.size == INSN16_SIZE) && (inst.size == INSN_SIZE)))
    {
    {
      inst.error = _("pce instruction error (16 bit || 16 bit)'");
      inst.error = _("pce instruction error (16 bit || 16 bit)'");
      sprintf (inst.str, insnstr);
      sprintf (inst.str, insnstr);
      return;
      return;
    }
    }
 
 
  if (!inst.error)
  if (!inst.error)
    gen_insn_frag (&pec_part_1, &inst);
    gen_insn_frag (&pec_part_1, &inst);
}
}
 
 
void
void
md_assemble (char *str)
md_assemble (char *str)
{
{
  know (str);
  know (str);
  know (strlen (str) < MAX_LITERAL_POOL_SIZE);
  know (strlen (str) < MAX_LITERAL_POOL_SIZE);
 
 
  memset (&inst, '\0', sizeof (inst));
  memset (&inst, '\0', sizeof (inst));
  if (INSN_IS_PCE_P (str))
  if (INSN_IS_PCE_P (str))
    parse_pce_inst (str);
    parse_pce_inst (str);
  else
  else
    parse_16_32_inst (str, TRUE);
    parse_16_32_inst (str, TRUE);
 
 
  if (inst.error)
  if (inst.error)
    as_bad (_("%s -- `%s'"), inst.error, inst.str);
    as_bad (_("%s -- `%s'"), inst.error, inst.str);
}
}
 
 
/* We handle all bad expressions here, so that we can report the faulty
/* We handle all bad expressions here, so that we can report the faulty
   instruction in the error message.  */
   instruction in the error message.  */
void
void
md_operand (expressionS * expr)
md_operand (expressionS * expr)
{
{
  if (in_my_get_expression)
  if (in_my_get_expression)
    {
    {
      expr->X_op = O_illegal;
      expr->X_op = O_illegal;
      if (inst.error == NULL)
      if (inst.error == NULL)
        {
        {
          inst.error = _("bad expression");
          inst.error = _("bad expression");
        }
        }
    }
    }
}
}
 
 
const char *md_shortopts = "nO::g::G:";
const char *md_shortopts = "nO::g::G:";
 
 
#ifdef SCORE_BI_ENDIAN
#ifdef SCORE_BI_ENDIAN
#define OPTION_EB             (OPTION_MD_BASE + 0)
#define OPTION_EB             (OPTION_MD_BASE + 0)
#define OPTION_EL             (OPTION_MD_BASE + 1)
#define OPTION_EL             (OPTION_MD_BASE + 1)
#else
#else
#if TARGET_BYTES_BIG_ENDIAN
#if TARGET_BYTES_BIG_ENDIAN
#define OPTION_EB             (OPTION_MD_BASE + 0)
#define OPTION_EB             (OPTION_MD_BASE + 0)
#else
#else
#define OPTION_EL             (OPTION_MD_BASE + 1)
#define OPTION_EL             (OPTION_MD_BASE + 1)
#endif
#endif
#endif
#endif
#define OPTION_FIXDD          (OPTION_MD_BASE + 2)
#define OPTION_FIXDD          (OPTION_MD_BASE + 2)
#define OPTION_NWARN          (OPTION_MD_BASE + 3)
#define OPTION_NWARN          (OPTION_MD_BASE + 3)
#define OPTION_SCORE5         (OPTION_MD_BASE + 4)
#define OPTION_SCORE5         (OPTION_MD_BASE + 4)
#define OPTION_SCORE5U        (OPTION_MD_BASE + 5)
#define OPTION_SCORE5U        (OPTION_MD_BASE + 5)
#define OPTION_SCORE7         (OPTION_MD_BASE + 6)
#define OPTION_SCORE7         (OPTION_MD_BASE + 6)
#define OPTION_R1             (OPTION_MD_BASE + 7)
#define OPTION_R1             (OPTION_MD_BASE + 7)
#define OPTION_O0             (OPTION_MD_BASE + 8)
#define OPTION_O0             (OPTION_MD_BASE + 8)
#define OPTION_SCORE_VERSION  (OPTION_MD_BASE + 9)
#define OPTION_SCORE_VERSION  (OPTION_MD_BASE + 9)
#define OPTION_PIC            (OPTION_MD_BASE + 10)
#define OPTION_PIC            (OPTION_MD_BASE + 10)
 
 
struct option md_longopts[] =
struct option md_longopts[] =
{
{
#ifdef OPTION_EB
#ifdef OPTION_EB
  {"EB"     , no_argument, NULL, OPTION_EB},
  {"EB"     , no_argument, NULL, OPTION_EB},
#endif
#endif
#ifdef OPTION_EL
#ifdef OPTION_EL
  {"EL"     , no_argument, NULL, OPTION_EL},
  {"EL"     , no_argument, NULL, OPTION_EL},
#endif
#endif
  {"FIXDD"  , no_argument, NULL, OPTION_FIXDD},
  {"FIXDD"  , no_argument, NULL, OPTION_FIXDD},
  {"NWARN"  , no_argument, NULL, OPTION_NWARN},
  {"NWARN"  , no_argument, NULL, OPTION_NWARN},
  {"SCORE5" , no_argument, NULL, OPTION_SCORE5},
  {"SCORE5" , no_argument, NULL, OPTION_SCORE5},
  {"SCORE5U", no_argument, NULL, OPTION_SCORE5U},
  {"SCORE5U", no_argument, NULL, OPTION_SCORE5U},
  {"SCORE7" , no_argument, NULL, OPTION_SCORE7},
  {"SCORE7" , no_argument, NULL, OPTION_SCORE7},
  {"USE_R1" , no_argument, NULL, OPTION_R1},
  {"USE_R1" , no_argument, NULL, OPTION_R1},
  {"O0"     , no_argument, NULL, OPTION_O0},
  {"O0"     , no_argument, NULL, OPTION_O0},
  {"V"      , no_argument, NULL, OPTION_SCORE_VERSION},
  {"V"      , no_argument, NULL, OPTION_SCORE_VERSION},
  {"KPIC"   , no_argument, NULL, OPTION_PIC},
  {"KPIC"   , no_argument, NULL, OPTION_PIC},
  {NULL     , no_argument, NULL, 0}
  {NULL     , no_argument, NULL, 0}
};
};
 
 
size_t md_longopts_size = sizeof (md_longopts);
size_t md_longopts_size = sizeof (md_longopts);
 
 
int
int
md_parse_option (int c, char *arg)
md_parse_option (int c, char *arg)
{
{
  switch (c)
  switch (c)
    {
    {
#ifdef OPTION_EB
#ifdef OPTION_EB
    case OPTION_EB:
    case OPTION_EB:
      target_big_endian = 1;
      target_big_endian = 1;
      break;
      break;
#endif
#endif
#ifdef OPTION_EL
#ifdef OPTION_EL
    case OPTION_EL:
    case OPTION_EL:
      target_big_endian = 0;
      target_big_endian = 0;
      break;
      break;
#endif
#endif
    case OPTION_FIXDD:
    case OPTION_FIXDD:
      fix_data_dependency = 1;
      fix_data_dependency = 1;
      break;
      break;
    case OPTION_NWARN:
    case OPTION_NWARN:
      warn_fix_data_dependency = 0;
      warn_fix_data_dependency = 0;
      break;
      break;
    case OPTION_SCORE5:
    case OPTION_SCORE5:
      score7 = 0;
      score7 = 0;
      university_version = 0;
      university_version = 0;
      vector_size = SCORE5_PIPELINE;
      vector_size = SCORE5_PIPELINE;
      break;
      break;
    case OPTION_SCORE5U:
    case OPTION_SCORE5U:
      score7 = 0;
      score7 = 0;
      university_version = 1;
      university_version = 1;
      vector_size = SCORE5_PIPELINE;
      vector_size = SCORE5_PIPELINE;
      break;
      break;
    case OPTION_SCORE7:
    case OPTION_SCORE7:
      score7 = 1;
      score7 = 1;
      university_version = 0;
      university_version = 0;
      vector_size = SCORE7_PIPELINE;
      vector_size = SCORE7_PIPELINE;
      break;
      break;
    case OPTION_R1:
    case OPTION_R1:
      nor1 = 0;
      nor1 = 0;
      break;
      break;
    case 'G':
    case 'G':
      g_switch_value = atoi (arg);
      g_switch_value = atoi (arg);
      break;
      break;
    case OPTION_O0:
    case OPTION_O0:
      g_opt = 0;
      g_opt = 0;
      break;
      break;
    case OPTION_SCORE_VERSION:
    case OPTION_SCORE_VERSION:
      printf (_("Sunplus-v2-0-0-20060510\n"));
      printf (_("Sunplus-v2-0-0-20060510\n"));
      break;
      break;
    case OPTION_PIC:
    case OPTION_PIC:
      score_pic = PIC;
      score_pic = PIC;
      g_switch_value = 0;    /* Must set -G num as 0 to generate PIC code.  */
      g_switch_value = 0;    /* Must set -G num as 0 to generate PIC code.  */
      break;
      break;
    default:
    default:
      /* as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");  */
      /* as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");  */
      return 0;
      return 0;
    }
    }
  return 1;
  return 1;
}
}
 
 
void
void
md_show_usage (FILE * fp)
md_show_usage (FILE * fp)
{
{
  fprintf (fp, _(" Score-specific assembler options:\n"));
  fprintf (fp, _(" Score-specific assembler options:\n"));
#ifdef OPTION_EB
#ifdef OPTION_EB
  fprintf (fp, _("\
  fprintf (fp, _("\
        -EB\t\tassemble code for a big-endian cpu\n"));
        -EB\t\tassemble code for a big-endian cpu\n"));
#endif
#endif
 
 
#ifdef OPTION_EL
#ifdef OPTION_EL
  fprintf (fp, _("\
  fprintf (fp, _("\
        -EL\t\tassemble code for a little-endian cpu\n"));
        -EL\t\tassemble code for a little-endian cpu\n"));
#endif
#endif
 
 
  fprintf (fp, _("\
  fprintf (fp, _("\
        -FIXDD\t\tassemble code for fix data dependency\n"));
        -FIXDD\t\tassemble code for fix data dependency\n"));
  fprintf (fp, _("\
  fprintf (fp, _("\
        -NWARN\t\tassemble code for no warning message for fix data dependency\n"));
        -NWARN\t\tassemble code for no warning message for fix data dependency\n"));
  fprintf (fp, _("\
  fprintf (fp, _("\
        -SCORE5\t\tassemble code for target is SCORE5\n"));
        -SCORE5\t\tassemble code for target is SCORE5\n"));
  fprintf (fp, _("\
  fprintf (fp, _("\
        -SCORE5U\tassemble code for target is SCORE5U\n"));
        -SCORE5U\tassemble code for target is SCORE5U\n"));
  fprintf (fp, _("\
  fprintf (fp, _("\
        -SCORE7\t\tassemble code for target is SCORE7, this is default setting\n"));
        -SCORE7\t\tassemble code for target is SCORE7, this is default setting\n"));
  fprintf (fp, _("\
  fprintf (fp, _("\
        -USE_R1\t\tassemble code for no warning message when using temp register r1\n"));
        -USE_R1\t\tassemble code for no warning message when using temp register r1\n"));
  fprintf (fp, _("\
  fprintf (fp, _("\
        -KPIC\t\tassemble code for PIC\n"));
        -KPIC\t\tassemble code for PIC\n"));
  fprintf (fp, _("\
  fprintf (fp, _("\
        -O0\t\tassembler will not perform any optimizations\n"));
        -O0\t\tassembler will not perform any optimizations\n"));
  fprintf (fp, _("\
  fprintf (fp, _("\
        -G gpnum\tassemble code for setting gpsize and default is 8 byte\n"));
        -G gpnum\tassemble code for setting gpsize and default is 8 byte\n"));
  fprintf (fp, _("\
  fprintf (fp, _("\
        -V \t\tSunplus release version \n"));
        -V \t\tSunplus release version \n"));
}
}
 
 
 
 
/* Pesudo handling functions.  */
/* Pesudo handling functions.  */
 
 
/* If we change section we must dump the literal pool first.  */
/* If we change section we must dump the literal pool first.  */
static void
static void
s_score_bss (int ignore ATTRIBUTE_UNUSED)
s_score_bss (int ignore ATTRIBUTE_UNUSED)
{
{
  subseg_set (bss_section, (subsegT) get_absolute_expression ());
  subseg_set (bss_section, (subsegT) get_absolute_expression ());
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
static void
static void
s_score_text (int ignore)
s_score_text (int ignore)
{
{
  obj_elf_text (ignore);
  obj_elf_text (ignore);
  record_alignment (now_seg, 2);
  record_alignment (now_seg, 2);
}
}
 
 
static void
static void
score_s_section (int ignore)
score_s_section (int ignore)
{
{
  obj_elf_section (ignore);
  obj_elf_section (ignore);
  if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
  if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
    record_alignment (now_seg, 2);
    record_alignment (now_seg, 2);
 
 
}
}
 
 
static void
static void
s_change_sec (int sec)
s_change_sec (int sec)
{
{
  segT seg;
  segT seg;
 
 
#ifdef OBJ_ELF
#ifdef OBJ_ELF
  /* The ELF backend needs to know that we are changing sections, so
  /* The ELF backend needs to know that we are changing sections, so
     that .previous works correctly.  We could do something like check
     that .previous works correctly.  We could do something like check
     for an obj_section_change_hook macro, but that might be confusing
     for an obj_section_change_hook macro, but that might be confusing
     as it would not be appropriate to use it in the section changing
     as it would not be appropriate to use it in the section changing
     functions in read.c, since obj-elf.c intercepts those.  FIXME:
     functions in read.c, since obj-elf.c intercepts those.  FIXME:
     This should be cleaner, somehow.  */
     This should be cleaner, somehow.  */
  obj_elf_section_change_hook ();
  obj_elf_section_change_hook ();
#endif
#endif
  switch (sec)
  switch (sec)
    {
    {
    case 'r':
    case 'r':
      seg = subseg_new (RDATA_SECTION_NAME, (subsegT) get_absolute_expression ());
      seg = subseg_new (RDATA_SECTION_NAME, (subsegT) get_absolute_expression ());
      bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA));
      bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA));
      if (strcmp (TARGET_OS, "elf") != 0)
      if (strcmp (TARGET_OS, "elf") != 0)
        record_alignment (seg, 4);
        record_alignment (seg, 4);
      demand_empty_rest_of_line ();
      demand_empty_rest_of_line ();
      break;
      break;
    case 's':
    case 's':
      seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
      seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
      bfd_set_section_flags (stdoutput, seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
      bfd_set_section_flags (stdoutput, seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
      if (strcmp (TARGET_OS, "elf") != 0)
      if (strcmp (TARGET_OS, "elf") != 0)
        record_alignment (seg, 4);
        record_alignment (seg, 4);
      demand_empty_rest_of_line ();
      demand_empty_rest_of_line ();
      break;
      break;
    }
    }
}
}
 
 
static void
static void
s_score_mask (int reg_type ATTRIBUTE_UNUSED)
s_score_mask (int reg_type ATTRIBUTE_UNUSED)
{
{
  long mask, off;
  long mask, off;
 
 
  if (cur_proc_ptr == (procS *) NULL)
  if (cur_proc_ptr == (procS *) NULL)
    {
    {
      as_warn (_(".mask outside of .ent"));
      as_warn (_(".mask outside of .ent"));
      demand_empty_rest_of_line ();
      demand_empty_rest_of_line ();
      return;
      return;
    }
    }
  if (get_absolute_expression_and_terminator (&mask) != ',')
  if (get_absolute_expression_and_terminator (&mask) != ',')
    {
    {
      as_warn (_("Bad .mask directive"));
      as_warn (_("Bad .mask directive"));
      --input_line_pointer;
      --input_line_pointer;
      demand_empty_rest_of_line ();
      demand_empty_rest_of_line ();
      return;
      return;
    }
    }
  off = get_absolute_expression ();
  off = get_absolute_expression ();
  cur_proc_ptr->reg_mask = mask;
  cur_proc_ptr->reg_mask = mask;
  cur_proc_ptr->reg_offset = off;
  cur_proc_ptr->reg_offset = off;
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
static symbolS *
static symbolS *
get_symbol (void)
get_symbol (void)
{
{
  int c;
  int c;
  char *name;
  char *name;
  symbolS *p;
  symbolS *p;
 
 
  name = input_line_pointer;
  name = input_line_pointer;
  c = get_symbol_end ();
  c = get_symbol_end ();
  p = (symbolS *) symbol_find_or_make (name);
  p = (symbolS *) symbol_find_or_make (name);
  *input_line_pointer = c;
  *input_line_pointer = c;
  return p;
  return p;
}
}
 
 
static long
static long
get_number (void)
get_number (void)
{
{
  int negative = 0;
  int negative = 0;
  long val = 0;
  long val = 0;
 
 
  if (*input_line_pointer == '-')
  if (*input_line_pointer == '-')
    {
    {
      ++input_line_pointer;
      ++input_line_pointer;
      negative = 1;
      negative = 1;
    }
    }
  if (!ISDIGIT (*input_line_pointer))
  if (!ISDIGIT (*input_line_pointer))
    as_bad (_("expected simple number"));
    as_bad (_("expected simple number"));
  if (input_line_pointer[0] == '0')
  if (input_line_pointer[0] == '0')
    {
    {
      if (input_line_pointer[1] == 'x')
      if (input_line_pointer[1] == 'x')
        {
        {
          input_line_pointer += 2;
          input_line_pointer += 2;
          while (ISXDIGIT (*input_line_pointer))
          while (ISXDIGIT (*input_line_pointer))
            {
            {
              val <<= 4;
              val <<= 4;
              val |= hex_value (*input_line_pointer++);
              val |= hex_value (*input_line_pointer++);
            }
            }
          return negative ? -val : val;
          return negative ? -val : val;
        }
        }
      else
      else
        {
        {
          ++input_line_pointer;
          ++input_line_pointer;
          while (ISDIGIT (*input_line_pointer))
          while (ISDIGIT (*input_line_pointer))
            {
            {
              val <<= 3;
              val <<= 3;
              val |= *input_line_pointer++ - '0';
              val |= *input_line_pointer++ - '0';
            }
            }
          return negative ? -val : val;
          return negative ? -val : val;
        }
        }
    }
    }
  if (!ISDIGIT (*input_line_pointer))
  if (!ISDIGIT (*input_line_pointer))
    {
    {
      printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer);
      printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer);
      as_warn (_("invalid number"));
      as_warn (_("invalid number"));
      return -1;
      return -1;
    }
    }
  while (ISDIGIT (*input_line_pointer))
  while (ISDIGIT (*input_line_pointer))
    {
    {
      val *= 10;
      val *= 10;
      val += *input_line_pointer++ - '0';
      val += *input_line_pointer++ - '0';
    }
    }
  return negative ? -val : val;
  return negative ? -val : val;
}
}
 
 
/* The .aent and .ent directives.  */
/* The .aent and .ent directives.  */
 
 
static void
static void
s_score_ent (int aent)
s_score_ent (int aent)
{
{
  symbolS *symbolP;
  symbolS *symbolP;
  int maybe_text;
  int maybe_text;
 
 
  symbolP = get_symbol ();
  symbolP = get_symbol ();
  if (*input_line_pointer == ',')
  if (*input_line_pointer == ',')
    ++input_line_pointer;
    ++input_line_pointer;
  SKIP_WHITESPACE ();
  SKIP_WHITESPACE ();
  if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
  if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
    get_number ();
    get_number ();
 
 
#ifdef BFD_ASSEMBLER
#ifdef BFD_ASSEMBLER
  if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
  if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
    maybe_text = 1;
    maybe_text = 1;
  else
  else
    maybe_text = 0;
    maybe_text = 0;
#else
#else
  if (now_seg != data_section && now_seg != bss_section)
  if (now_seg != data_section && now_seg != bss_section)
    maybe_text = 1;
    maybe_text = 1;
  else
  else
    maybe_text = 0;
    maybe_text = 0;
#endif
#endif
  if (!maybe_text)
  if (!maybe_text)
    as_warn (_(".ent or .aent not in text section."));
    as_warn (_(".ent or .aent not in text section."));
  if (!aent && cur_proc_ptr)
  if (!aent && cur_proc_ptr)
    as_warn (_("missing .end"));
    as_warn (_("missing .end"));
  if (!aent)
  if (!aent)
    {
    {
      cur_proc_ptr = &cur_proc;
      cur_proc_ptr = &cur_proc;
      cur_proc_ptr->reg_mask = 0xdeadbeaf;
      cur_proc_ptr->reg_mask = 0xdeadbeaf;
      cur_proc_ptr->reg_offset = 0xdeadbeaf;
      cur_proc_ptr->reg_offset = 0xdeadbeaf;
      cur_proc_ptr->fpreg_mask = 0xdeafbeaf;
      cur_proc_ptr->fpreg_mask = 0xdeafbeaf;
      cur_proc_ptr->leaf = 0xdeafbeaf;
      cur_proc_ptr->leaf = 0xdeafbeaf;
      cur_proc_ptr->frame_offset = 0xdeafbeaf;
      cur_proc_ptr->frame_offset = 0xdeafbeaf;
      cur_proc_ptr->frame_reg = 0xdeafbeaf;
      cur_proc_ptr->frame_reg = 0xdeafbeaf;
      cur_proc_ptr->pc_reg = 0xdeafbeaf;
      cur_proc_ptr->pc_reg = 0xdeafbeaf;
      cur_proc_ptr->isym = symbolP;
      cur_proc_ptr->isym = symbolP;
      symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
      symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
      ++numprocs;
      ++numprocs;
      if (debug_type == DEBUG_STABS)
      if (debug_type == DEBUG_STABS)
        stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP));
        stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP));
    }
    }
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
static void
static void
s_score_frame (int ignore ATTRIBUTE_UNUSED)
s_score_frame (int ignore ATTRIBUTE_UNUSED)
{
{
  char *backupstr;
  char *backupstr;
  char str[30];
  char str[30];
  long val;
  long val;
  int i = 0;
  int i = 0;
 
 
  backupstr = input_line_pointer;
  backupstr = input_line_pointer;
 
 
#ifdef OBJ_ELF
#ifdef OBJ_ELF
  if (cur_proc_ptr == (procS *) NULL)
  if (cur_proc_ptr == (procS *) NULL)
    {
    {
      as_warn (_(".frame outside of .ent"));
      as_warn (_(".frame outside of .ent"));
      demand_empty_rest_of_line ();
      demand_empty_rest_of_line ();
      return;
      return;
    }
    }
  cur_proc_ptr->frame_reg = reg_required_here ((&backupstr), 0, REG_TYPE_SCORE);
  cur_proc_ptr->frame_reg = reg_required_here ((&backupstr), 0, REG_TYPE_SCORE);
  SKIP_WHITESPACE ();
  SKIP_WHITESPACE ();
  skip_past_comma (&backupstr);
  skip_past_comma (&backupstr);
  while (*backupstr != ',')
  while (*backupstr != ',')
    {
    {
      str[i] = *backupstr;
      str[i] = *backupstr;
      i++;
      i++;
      backupstr++;
      backupstr++;
    }
    }
  str[i] = '\0';
  str[i] = '\0';
  val = atoi (str);
  val = atoi (str);
 
 
  SKIP_WHITESPACE ();
  SKIP_WHITESPACE ();
  skip_past_comma (&backupstr);
  skip_past_comma (&backupstr);
  cur_proc_ptr->frame_offset = val;
  cur_proc_ptr->frame_offset = val;
  cur_proc_ptr->pc_reg = reg_required_here ((&backupstr), 0, REG_TYPE_SCORE);
  cur_proc_ptr->pc_reg = reg_required_here ((&backupstr), 0, REG_TYPE_SCORE);
 
 
  SKIP_WHITESPACE ();
  SKIP_WHITESPACE ();
  skip_past_comma (&backupstr);
  skip_past_comma (&backupstr);
  i = 0;
  i = 0;
  while (*backupstr != '\n')
  while (*backupstr != '\n')
    {
    {
      str[i] = *backupstr;
      str[i] = *backupstr;
      i++;
      i++;
      backupstr++;
      backupstr++;
    }
    }
  str[i] = '\0';
  str[i] = '\0';
  val = atoi (str);
  val = atoi (str);
  cur_proc_ptr->leaf = val;
  cur_proc_ptr->leaf = val;
  SKIP_WHITESPACE ();
  SKIP_WHITESPACE ();
  skip_past_comma (&backupstr);
  skip_past_comma (&backupstr);
 
 
#endif /* OBJ_ELF */
#endif /* OBJ_ELF */
  while (input_line_pointer != backupstr)
  while (input_line_pointer != backupstr)
    input_line_pointer++;
    input_line_pointer++;
}
}
 
 
/* The .end directive.  */
/* The .end directive.  */
static void
static void
s_score_end (int x ATTRIBUTE_UNUSED)
s_score_end (int x ATTRIBUTE_UNUSED)
{
{
  symbolS *p;
  symbolS *p;
  int maybe_text;
  int maybe_text;
 
 
  /* Generate a .pdr section.  */
  /* Generate a .pdr section.  */
  segT saved_seg = now_seg;
  segT saved_seg = now_seg;
  subsegT saved_subseg = now_subseg;
  subsegT saved_subseg = now_subseg;
  valueT dot;
  valueT dot;
  expressionS exp;
  expressionS exp;
  char *fragp;
  char *fragp;
 
 
  if (!is_end_of_line[(unsigned char)*input_line_pointer])
  if (!is_end_of_line[(unsigned char)*input_line_pointer])
    {
    {
      p = get_symbol ();
      p = get_symbol ();
      demand_empty_rest_of_line ();
      demand_empty_rest_of_line ();
    }
    }
  else
  else
    p = NULL;
    p = NULL;
 
 
#ifdef BFD_ASSEMBLER
#ifdef BFD_ASSEMBLER
  if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
  if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
    maybe_text = 1;
    maybe_text = 1;
  else
  else
    maybe_text = 0;
    maybe_text = 0;
#else
#else
  if (now_seg != data_section && now_seg != bss_section)
  if (now_seg != data_section && now_seg != bss_section)
    maybe_text = 1;
    maybe_text = 1;
  else
  else
    maybe_text = 0;
    maybe_text = 0;
#endif
#endif
 
 
  if (!maybe_text)
  if (!maybe_text)
    as_warn (_(".end not in text section"));
    as_warn (_(".end not in text section"));
  if (!cur_proc_ptr)
  if (!cur_proc_ptr)
    {
    {
      as_warn (_(".end directive without a preceding .ent directive."));
      as_warn (_(".end directive without a preceding .ent directive."));
      demand_empty_rest_of_line ();
      demand_empty_rest_of_line ();
      return;
      return;
    }
    }
  if (p != NULL)
  if (p != NULL)
    {
    {
      assert (S_GET_NAME (p));
      assert (S_GET_NAME (p));
      if (strcmp (S_GET_NAME (p), S_GET_NAME (cur_proc_ptr->isym)))
      if (strcmp (S_GET_NAME (p), S_GET_NAME (cur_proc_ptr->isym)))
        as_warn (_(".end symbol does not match .ent symbol."));
        as_warn (_(".end symbol does not match .ent symbol."));
      if (debug_type == DEBUG_STABS)
      if (debug_type == DEBUG_STABS)
        stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p));
        stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p));
    }
    }
  else
  else
    as_warn (_(".end directive missing or unknown symbol"));
    as_warn (_(".end directive missing or unknown symbol"));
 
 
  if ((cur_proc_ptr->reg_mask == 0xdeadbeaf) ||
  if ((cur_proc_ptr->reg_mask == 0xdeadbeaf) ||
      (cur_proc_ptr->reg_offset == 0xdeadbeaf) ||
      (cur_proc_ptr->reg_offset == 0xdeadbeaf) ||
      (cur_proc_ptr->leaf == 0xdeafbeaf) ||
      (cur_proc_ptr->leaf == 0xdeafbeaf) ||
      (cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
      (cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
      (cur_proc_ptr->frame_reg == 0xdeafbeaf) || (cur_proc_ptr->pc_reg == 0xdeafbeaf));
      (cur_proc_ptr->frame_reg == 0xdeafbeaf) || (cur_proc_ptr->pc_reg == 0xdeafbeaf));
 
 
  else
  else
    {
    {
      dot = frag_now_fix ();
      dot = frag_now_fix ();
      assert (pdr_seg);
      assert (pdr_seg);
      subseg_set (pdr_seg, 0);
      subseg_set (pdr_seg, 0);
      /* Write the symbol.  */
      /* Write the symbol.  */
      exp.X_op = O_symbol;
      exp.X_op = O_symbol;
      exp.X_add_symbol = p;
      exp.X_add_symbol = p;
      exp.X_add_number = 0;
      exp.X_add_number = 0;
      emit_expr (&exp, 4);
      emit_expr (&exp, 4);
      fragp = frag_more (7 * 4);
      fragp = frag_more (7 * 4);
      md_number_to_chars (fragp, (valueT) cur_proc_ptr->reg_mask, 4);
      md_number_to_chars (fragp, (valueT) cur_proc_ptr->reg_mask, 4);
      md_number_to_chars (fragp + 4, (valueT) cur_proc_ptr->reg_offset, 4);
      md_number_to_chars (fragp + 4, (valueT) cur_proc_ptr->reg_offset, 4);
      md_number_to_chars (fragp + 8, (valueT) cur_proc_ptr->fpreg_mask, 4);
      md_number_to_chars (fragp + 8, (valueT) cur_proc_ptr->fpreg_mask, 4);
      md_number_to_chars (fragp + 12, (valueT) cur_proc_ptr->leaf, 4);
      md_number_to_chars (fragp + 12, (valueT) cur_proc_ptr->leaf, 4);
      md_number_to_chars (fragp + 16, (valueT) cur_proc_ptr->frame_offset, 4);
      md_number_to_chars (fragp + 16, (valueT) cur_proc_ptr->frame_offset, 4);
      md_number_to_chars (fragp + 20, (valueT) cur_proc_ptr->frame_reg, 4);
      md_number_to_chars (fragp + 20, (valueT) cur_proc_ptr->frame_reg, 4);
      md_number_to_chars (fragp + 24, (valueT) cur_proc_ptr->pc_reg, 4);
      md_number_to_chars (fragp + 24, (valueT) cur_proc_ptr->pc_reg, 4);
      subseg_set (saved_seg, saved_subseg);
      subseg_set (saved_seg, saved_subseg);
 
 
    }
    }
  cur_proc_ptr = NULL;
  cur_proc_ptr = NULL;
}
}
 
 
/* Handle the .set pseudo-op.  */
/* Handle the .set pseudo-op.  */
static void
static void
s_score_set (int x ATTRIBUTE_UNUSED)
s_score_set (int x ATTRIBUTE_UNUSED)
{
{
  int i = 0;
  int i = 0;
  char name[MAX_LITERAL_POOL_SIZE];
  char name[MAX_LITERAL_POOL_SIZE];
  char * orig_ilp = input_line_pointer;
  char * orig_ilp = input_line_pointer;
 
 
  while (!is_end_of_line[(unsigned char)*input_line_pointer])
  while (!is_end_of_line[(unsigned char)*input_line_pointer])
    {
    {
      name[i] = (char) * input_line_pointer;
      name[i] = (char) * input_line_pointer;
      i++;
      i++;
      ++input_line_pointer;
      ++input_line_pointer;
    }
    }
 
 
  name[i] = '\0';
  name[i] = '\0';
 
 
  if (strcmp (name, "nwarn") == 0)
  if (strcmp (name, "nwarn") == 0)
    {
    {
      warn_fix_data_dependency = 0;
      warn_fix_data_dependency = 0;
    }
    }
  else if (strcmp (name, "fixdd") == 0)
  else if (strcmp (name, "fixdd") == 0)
    {
    {
      fix_data_dependency = 1;
      fix_data_dependency = 1;
    }
    }
  else if (strcmp (name, "nofixdd") == 0)
  else if (strcmp (name, "nofixdd") == 0)
    {
    {
      fix_data_dependency = 0;
      fix_data_dependency = 0;
    }
    }
  else if (strcmp (name, "r1") == 0)
  else if (strcmp (name, "r1") == 0)
    {
    {
      nor1 = 0;
      nor1 = 0;
    }
    }
  else if (strcmp (name, "nor1") == 0)
  else if (strcmp (name, "nor1") == 0)
    {
    {
      nor1 = 1;
      nor1 = 1;
    }
    }
  else if (strcmp (name, "optimize") == 0)
  else if (strcmp (name, "optimize") == 0)
    {
    {
      g_opt = 1;
      g_opt = 1;
    }
    }
  else if (strcmp (name, "volatile") == 0)
  else if (strcmp (name, "volatile") == 0)
    {
    {
      g_opt = 0;
      g_opt = 0;
    }
    }
  else if (strcmp (name, "pic") == 0)
  else if (strcmp (name, "pic") == 0)
    {
    {
      score_pic = PIC;
      score_pic = PIC;
    }
    }
  else
  else
    {
    {
      input_line_pointer = orig_ilp;
      input_line_pointer = orig_ilp;
      s_set (0);
      s_set (0);
    }
    }
}
}
 
 
/* Handle the .cpload pseudo-op.  This is used when generating PIC code.  It sets the
/* Handle the .cpload pseudo-op.  This is used when generating PIC code.  It sets the
   $gp register for the function based on the function address, which is in the register
   $gp register for the function based on the function address, which is in the register
   named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled
   named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled
   specially by the linker.  The result is:
   specially by the linker.  The result is:
   ldis gp, %hi(GP_DISP_LABEL)
   ldis gp, %hi(GP_DISP_LABEL)
   ori  gp, %low(GP_DISP_LABEL)
   ori  gp, %low(GP_DISP_LABEL)
   add  gp, gp, .cpload argument
   add  gp, gp, .cpload argument
   The .cpload argument is normally r29.  */
   The .cpload argument is normally r29.  */
 
 
static void
static void
s_score_cpload (int ignore ATTRIBUTE_UNUSED)
s_score_cpload (int ignore ATTRIBUTE_UNUSED)
{
{
  int reg;
  int reg;
  char insn_str[MAX_LITERAL_POOL_SIZE];
  char insn_str[MAX_LITERAL_POOL_SIZE];
 
 
  /* If we are not generating PIC code, .cpload is ignored.  */
  /* If we are not generating PIC code, .cpload is ignored.  */
  if (score_pic == NO_PIC)
  if (score_pic == NO_PIC)
    {
    {
      s_ignore (0);
      s_ignore (0);
      return;
      return;
    }
    }
 
 
  if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL)
  if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL)
    return;
    return;
 
 
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
 
 
  sprintf (insn_str, "ld_i32hi r%d, %s", GP, GP_DISP_LABEL);
  sprintf (insn_str, "ld_i32hi r%d, %s", GP, GP_DISP_LABEL);
  if (append_insn (insn_str, TRUE) == (int) FAIL)
  if (append_insn (insn_str, TRUE) == (int) FAIL)
    return;
    return;
 
 
  sprintf (insn_str, "ld_i32lo r%d, %s", GP, GP_DISP_LABEL);
  sprintf (insn_str, "ld_i32lo r%d, %s", GP, GP_DISP_LABEL);
  if (append_insn (insn_str, TRUE) == (int) FAIL)
  if (append_insn (insn_str, TRUE) == (int) FAIL)
    return;
    return;
 
 
  sprintf (insn_str, "add r%d, r%d, r%d", GP, GP, reg);
  sprintf (insn_str, "add r%d, r%d, r%d", GP, GP, reg);
  if (append_insn (insn_str, TRUE) == (int) FAIL)
  if (append_insn (insn_str, TRUE) == (int) FAIL)
    return;
    return;
}
}
 
 
/* Handle the .cprestore pseudo-op.  This stores $gp into a given
/* Handle the .cprestore pseudo-op.  This stores $gp into a given
   offset from $sp.  The offset is remembered, and after making a PIC
   offset from $sp.  The offset is remembered, and after making a PIC
   call $gp is restored from that location.  */
   call $gp is restored from that location.  */
 
 
static void
static void
s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
{
{
  int reg;
  int reg;
  int cprestore_offset;
  int cprestore_offset;
  char insn_str[MAX_LITERAL_POOL_SIZE];
  char insn_str[MAX_LITERAL_POOL_SIZE];
 
 
  /* If we are not generating PIC code, .cprestore is ignored.  */
  /* If we are not generating PIC code, .cprestore is ignored.  */
  if (score_pic == NO_PIC)
  if (score_pic == NO_PIC)
    {
    {
      s_ignore (0);
      s_ignore (0);
      return;
      return;
    }
    }
 
 
  if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL
  if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL
      || skip_past_comma (&input_line_pointer) == (int) FAIL)
      || skip_past_comma (&input_line_pointer) == (int) FAIL)
    {
    {
      return;
      return;
    }
    }
 
 
  cprestore_offset = get_absolute_expression ();
  cprestore_offset = get_absolute_expression ();
 
 
  if (cprestore_offset <= 0x3fff)
  if (cprestore_offset <= 0x3fff)
    {
    {
      sprintf (insn_str, "sw r%d, [r%d, %d]", GP, reg, cprestore_offset);
      sprintf (insn_str, "sw r%d, [r%d, %d]", GP, reg, cprestore_offset);
      if (append_insn (insn_str, TRUE) == (int) FAIL)
      if (append_insn (insn_str, TRUE) == (int) FAIL)
        return;
        return;
    }
    }
  else
  else
    {
    {
      int r1_bak;
      int r1_bak;
 
 
      r1_bak = nor1;
      r1_bak = nor1;
      nor1 = 0;
      nor1 = 0;
 
 
      sprintf (insn_str, "li r1, %d", cprestore_offset);
      sprintf (insn_str, "li r1, %d", cprestore_offset);
      if (append_insn (insn_str, TRUE) == (int) FAIL)
      if (append_insn (insn_str, TRUE) == (int) FAIL)
        return;
        return;
 
 
      sprintf (insn_str, "add r1, r1, r%d", reg);
      sprintf (insn_str, "add r1, r1, r%d", reg);
      if (append_insn (insn_str, TRUE) == (int) FAIL)
      if (append_insn (insn_str, TRUE) == (int) FAIL)
        return;
        return;
 
 
      sprintf (insn_str, "sw r%d, [r1]", GP);
      sprintf (insn_str, "sw r%d, [r1]", GP);
      if (append_insn (insn_str, TRUE) == (int) FAIL)
      if (append_insn (insn_str, TRUE) == (int) FAIL)
        return;
        return;
 
 
      nor1 = r1_bak;
      nor1 = r1_bak;
    }
    }
 
 
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
/* Handle the .gpword pseudo-op.  This is used when generating PIC
/* Handle the .gpword pseudo-op.  This is used when generating PIC
   code.  It generates a 32 bit GP relative reloc.  */
   code.  It generates a 32 bit GP relative reloc.  */
static void
static void
s_score_gpword (int ignore ATTRIBUTE_UNUSED)
s_score_gpword (int ignore ATTRIBUTE_UNUSED)
{
{
  expressionS ex;
  expressionS ex;
  char *p;
  char *p;
 
 
  /* When not generating PIC code, this is treated as .word.  */
  /* When not generating PIC code, this is treated as .word.  */
  if (score_pic == NO_PIC)
  if (score_pic == NO_PIC)
    {
    {
      cons (4);
      cons (4);
      return;
      return;
    }
    }
  expression (&ex);
  expression (&ex);
  if (ex.X_op != O_symbol || ex.X_add_number != 0)
  if (ex.X_op != O_symbol || ex.X_add_number != 0)
    {
    {
      as_bad (_("Unsupported use of .gpword"));
      as_bad (_("Unsupported use of .gpword"));
      ignore_rest_of_line ();
      ignore_rest_of_line ();
    }
    }
  p = frag_more (4);
  p = frag_more (4);
  md_number_to_chars (p, (valueT) 0, 4);
  md_number_to_chars (p, (valueT) 0, 4);
  fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32);
  fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32);
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
/* Handle the .cpadd pseudo-op.  This is used when dealing with switch
/* Handle the .cpadd pseudo-op.  This is used when dealing with switch
   tables in PIC code.  */
   tables in PIC code.  */
 
 
static void
static void
s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
{
{
  int reg;
  int reg;
  char insn_str[MAX_LITERAL_POOL_SIZE];
  char insn_str[MAX_LITERAL_POOL_SIZE];
 
 
  /* If we are not generating PIC code, .cpload is ignored.  */
  /* If we are not generating PIC code, .cpload is ignored.  */
  if (score_pic == NO_PIC)
  if (score_pic == NO_PIC)
    {
    {
      s_ignore (0);
      s_ignore (0);
      return;
      return;
    }
    }
 
 
  if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL)
  if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL)
    {
    {
      return;
      return;
    }
    }
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
 
 
  /* Add $gp to the register named as an argument.  */
  /* Add $gp to the register named as an argument.  */
  sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, GP);
  sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, GP);
  if (append_insn (insn_str, TRUE) == (int) FAIL)
  if (append_insn (insn_str, TRUE) == (int) FAIL)
    return;
    return;
}
}
 
 
#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
#ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR)                \
#define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR)                \
    do                                                          \
    do                                                          \
    {                                                           \
    {                                                           \
    if ((SIZE) >= 8)                                            \
    if ((SIZE) >= 8)                                            \
    (P2VAR) = 3;                                                \
    (P2VAR) = 3;                                                \
    else if ((SIZE) >= 4)                                       \
    else if ((SIZE) >= 4)                                       \
    (P2VAR) = 2;                                                \
    (P2VAR) = 2;                                                \
    else if ((SIZE) >= 2)                                       \
    else if ((SIZE) >= 2)                                       \
    (P2VAR) = 1;                                                \
    (P2VAR) = 1;                                                \
    else                                                        \
    else                                                        \
    (P2VAR) = 0;                                         \
    (P2VAR) = 0;                                         \
    }                                                           \
    }                                                           \
  while (0)
  while (0)
#endif
#endif
 
 
static void
static void
s_score_lcomm (int bytes_p)
s_score_lcomm (int bytes_p)
{
{
  char *name;
  char *name;
  char c;
  char c;
  char *p;
  char *p;
  int temp;
  int temp;
  symbolS *symbolP;
  symbolS *symbolP;
  segT current_seg = now_seg;
  segT current_seg = now_seg;
  subsegT current_subseg = now_subseg;
  subsegT current_subseg = now_subseg;
  const int max_alignment = 15;
  const int max_alignment = 15;
  int align = 0;
  int align = 0;
  segT bss_seg = bss_section;
  segT bss_seg = bss_section;
  int needs_align = 0;
  int needs_align = 0;
 
 
  name = input_line_pointer;
  name = input_line_pointer;
  c = get_symbol_end ();
  c = get_symbol_end ();
  p = input_line_pointer;
  p = input_line_pointer;
  *p = c;
  *p = c;
 
 
  if (name == p)
  if (name == p)
    {
    {
      as_bad (_("expected symbol name"));
      as_bad (_("expected symbol name"));
      discard_rest_of_line ();
      discard_rest_of_line ();
      return;
      return;
    }
    }
 
 
  SKIP_WHITESPACE ();
  SKIP_WHITESPACE ();
 
 
  /* Accept an optional comma after the name.  The comma used to be
  /* Accept an optional comma after the name.  The comma used to be
     required, but Irix 5 cc does not generate it.  */
     required, but Irix 5 cc does not generate it.  */
  if (*input_line_pointer == ',')
  if (*input_line_pointer == ',')
    {
    {
      ++input_line_pointer;
      ++input_line_pointer;
      SKIP_WHITESPACE ();
      SKIP_WHITESPACE ();
    }
    }
 
 
  if (is_end_of_line[(unsigned char)*input_line_pointer])
  if (is_end_of_line[(unsigned char)*input_line_pointer])
    {
    {
      as_bad (_("missing size expression"));
      as_bad (_("missing size expression"));
      return;
      return;
    }
    }
 
 
  if ((temp = get_absolute_expression ()) < 0)
  if ((temp = get_absolute_expression ()) < 0)
    {
    {
      as_warn (_("BSS length (%d) < 0 ignored"), temp);
      as_warn (_("BSS length (%d) < 0 ignored"), temp);
      ignore_rest_of_line ();
      ignore_rest_of_line ();
      return;
      return;
    }
    }
 
 
#if defined (TC_SCORE)
#if defined (TC_SCORE)
  if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour)
  if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour)
    {
    {
      /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss.  */
      /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss.  */
      if ((unsigned)temp <= bfd_get_gp_size (stdoutput))
      if ((unsigned)temp <= bfd_get_gp_size (stdoutput))
        {
        {
          bss_seg = subseg_new (".sbss", 1);
          bss_seg = subseg_new (".sbss", 1);
          seg_info (bss_seg)->bss = 1;
          seg_info (bss_seg)->bss = 1;
#ifdef BFD_ASSEMBLER
#ifdef BFD_ASSEMBLER
          if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
          if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
            as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ()));
            as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ()));
#endif
#endif
        }
        }
    }
    }
#endif
#endif
 
 
  SKIP_WHITESPACE ();
  SKIP_WHITESPACE ();
  if (*input_line_pointer == ',')
  if (*input_line_pointer == ',')
    {
    {
      ++input_line_pointer;
      ++input_line_pointer;
      SKIP_WHITESPACE ();
      SKIP_WHITESPACE ();
 
 
      if (is_end_of_line[(unsigned char)*input_line_pointer])
      if (is_end_of_line[(unsigned char)*input_line_pointer])
        {
        {
          as_bad (_("missing alignment"));
          as_bad (_("missing alignment"));
          return;
          return;
        }
        }
      else
      else
        {
        {
          align = get_absolute_expression ();
          align = get_absolute_expression ();
          needs_align = 1;
          needs_align = 1;
        }
        }
    }
    }
 
 
  if (!needs_align)
  if (!needs_align)
    {
    {
      TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
      TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
 
 
      /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it.  */
      /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it.  */
      if (align)
      if (align)
        record_alignment (bss_seg, align);
        record_alignment (bss_seg, align);
    }
    }
 
 
  if (needs_align)
  if (needs_align)
    {
    {
      if (bytes_p)
      if (bytes_p)
        {
        {
          /* Convert to a power of 2.  */
          /* Convert to a power of 2.  */
          if (align != 0)
          if (align != 0)
            {
            {
              unsigned int i;
              unsigned int i;
 
 
              for (i = 0; align != 0; align >>= 1, ++i)
              for (i = 0; align != 0; align >>= 1, ++i)
                ;
                ;
              align = i - 1;
              align = i - 1;
            }
            }
        }
        }
 
 
      if (align > max_alignment)
      if (align > max_alignment)
        {
        {
          align = max_alignment;
          align = max_alignment;
          as_warn (_("alignment too large; %d assumed"), align);
          as_warn (_("alignment too large; %d assumed"), align);
        }
        }
      else if (align < 0)
      else if (align < 0)
        {
        {
          align = 0;
          align = 0;
          as_warn (_("alignment negative; 0 assumed"));
          as_warn (_("alignment negative; 0 assumed"));
        }
        }
 
 
      record_alignment (bss_seg, align);
      record_alignment (bss_seg, align);
    }
    }
  else
  else
    {
    {
      /* Assume some objects may require alignment on some systems.  */
      /* Assume some objects may require alignment on some systems.  */
#if defined (TC_ALPHA) && ! defined (VMS)
#if defined (TC_ALPHA) && ! defined (VMS)
      if (temp > 1)
      if (temp > 1)
        {
        {
          align = ffs (temp) - 1;
          align = ffs (temp) - 1;
          if (temp % (1 << align))
          if (temp % (1 << align))
            abort ();
            abort ();
        }
        }
#endif
#endif
    }
    }
 
 
  *p = 0;
  *p = 0;
  symbolP = symbol_find_or_make (name);
  symbolP = symbol_find_or_make (name);
  *p = c;
  *p = c;
 
 
  if (
  if (
#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \
#if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \
     || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT))
     || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT))
#ifdef BFD_ASSEMBLER
#ifdef BFD_ASSEMBLER
       (OUTPUT_FLAVOR != bfd_target_aout_flavour
       (OUTPUT_FLAVOR != bfd_target_aout_flavour
        || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
        || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
#else
#else
       (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
       (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
#endif
#endif
#endif
#endif
       (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
       (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
    {
    {
      char *pfrag;
      char *pfrag;
 
 
      subseg_set (bss_seg, 1);
      subseg_set (bss_seg, 1);
 
 
      if (align)
      if (align)
        frag_align (align, 0, 0);
        frag_align (align, 0, 0);
 
 
      /* Detach from old frag.  */
      /* Detach from old frag.  */
      if (S_GET_SEGMENT (symbolP) == bss_seg)
      if (S_GET_SEGMENT (symbolP) == bss_seg)
        symbol_get_frag (symbolP)->fr_symbol = NULL;
        symbol_get_frag (symbolP)->fr_symbol = NULL;
 
 
      symbol_set_frag (symbolP, frag_now);
      symbol_set_frag (symbolP, frag_now);
      pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
      pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
      *pfrag = 0;
      *pfrag = 0;
 
 
 
 
      S_SET_SEGMENT (symbolP, bss_seg);
      S_SET_SEGMENT (symbolP, bss_seg);
 
 
#ifdef OBJ_COFF
#ifdef OBJ_COFF
      /* The symbol may already have been created with a preceding
      /* The symbol may already have been created with a preceding
         ".globl" directive -- be careful not to step on storage class
         ".globl" directive -- be careful not to step on storage class
         in that case.  Otherwise, set it to static.  */
         in that case.  Otherwise, set it to static.  */
      if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
      if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
        {
        {
          S_SET_STORAGE_CLASS (symbolP, C_STAT);
          S_SET_STORAGE_CLASS (symbolP, C_STAT);
        }
        }
#endif /* OBJ_COFF */
#endif /* OBJ_COFF */
 
 
#ifdef S_SET_SIZE
#ifdef S_SET_SIZE
      S_SET_SIZE (symbolP, temp);
      S_SET_SIZE (symbolP, temp);
#endif
#endif
    }
    }
  else
  else
    as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
    as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
 
 
  subseg_set (current_seg, current_subseg);
  subseg_set (current_seg, current_subseg);
 
 
  demand_empty_rest_of_line ();
  demand_empty_rest_of_line ();
}
}
 
 
static void
static void
insert_reg (const struct reg_entry *r, struct hash_control *htab)
insert_reg (const struct reg_entry *r, struct hash_control *htab)
{
{
  int i = 0;
  int i = 0;
  int len = strlen (r->name) + 2;
  int len = strlen (r->name) + 2;
  char *buf = xmalloc (len);
  char *buf = xmalloc (len);
  char *buf2 = xmalloc (len);
  char *buf2 = xmalloc (len);
 
 
  strcpy (buf + i, r->name);
  strcpy (buf + i, r->name);
  for (i = 0; buf[i]; i++)
  for (i = 0; buf[i]; i++)
    {
    {
      buf2[i] = TOUPPER (buf[i]);
      buf2[i] = TOUPPER (buf[i]);
    }
    }
  buf2[i] = '\0';
  buf2[i] = '\0';
 
 
  hash_insert (htab, buf, (void *) r);
  hash_insert (htab, buf, (void *) r);
  hash_insert (htab, buf2, (void *) r);
  hash_insert (htab, buf2, (void *) r);
}
}
 
 
static void
static void
build_reg_hsh (struct reg_map *map)
build_reg_hsh (struct reg_map *map)
{
{
  const struct reg_entry *r;
  const struct reg_entry *r;
 
 
  if ((map->htab = hash_new ()) == NULL)
  if ((map->htab = hash_new ()) == NULL)
    {
    {
      as_fatal (_("virtual memory exhausted"));
      as_fatal (_("virtual memory exhausted"));
    }
    }
  for (r = map->names; r->name != NULL; r++)
  for (r = map->names; r->name != NULL; r++)
    {
    {
      insert_reg (r, map->htab);
      insert_reg (r, map->htab);
    }
    }
}
}
 
 
void
void
md_begin (void)
md_begin (void)
{
{
  unsigned int i;
  unsigned int i;
  segT seg;
  segT seg;
  subsegT subseg;
  subsegT subseg;
 
 
  if ((score_ops_hsh = hash_new ()) == NULL)
  if ((score_ops_hsh = hash_new ()) == NULL)
    as_fatal (_("virtual memory exhausted"));
    as_fatal (_("virtual memory exhausted"));
 
 
  build_score_ops_hsh ();
  build_score_ops_hsh ();
 
 
  if ((dependency_insn_hsh = hash_new ()) == NULL)
  if ((dependency_insn_hsh = hash_new ()) == NULL)
    as_fatal (_("virtual memory exhausted"));
    as_fatal (_("virtual memory exhausted"));
 
 
  build_dependency_insn_hsh ();
  build_dependency_insn_hsh ();
 
 
  for (i = (int)REG_TYPE_FIRST; i < (int)REG_TYPE_MAX; i++)
  for (i = (int)REG_TYPE_FIRST; i < (int)REG_TYPE_MAX; i++)
    build_reg_hsh (all_reg_maps + i);
    build_reg_hsh (all_reg_maps + i);
 
 
  /* Initialize dependency vector.  */
  /* Initialize dependency vector.  */
  init_dependency_vector ();
  init_dependency_vector ();
 
 
  bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
  bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
  seg = now_seg;
  seg = now_seg;
  subseg = now_subseg;
  subseg = now_subseg;
  pdr_seg = subseg_new (".pdr", (subsegT) 0);
  pdr_seg = subseg_new (".pdr", (subsegT) 0);
  (void)bfd_set_section_flags (stdoutput, pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
  (void)bfd_set_section_flags (stdoutput, pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
  (void)bfd_set_section_alignment (stdoutput, pdr_seg, 2);
  (void)bfd_set_section_alignment (stdoutput, pdr_seg, 2);
  subseg_set (seg, subseg);
  subseg_set (seg, subseg);
 
 
  if (USE_GLOBAL_POINTER_OPT)
  if (USE_GLOBAL_POINTER_OPT)
    bfd_set_gp_size (stdoutput, g_switch_value);
    bfd_set_gp_size (stdoutput, g_switch_value);
}
}
 
 
 
 
const pseudo_typeS md_pseudo_table[] =
const pseudo_typeS md_pseudo_table[] =
{
{
  {"bss", s_score_bss, 0},
  {"bss", s_score_bss, 0},
  {"text", s_score_text, 0},
  {"text", s_score_text, 0},
  {"word", cons, 4},
  {"word", cons, 4},
  {"long", cons, 4},
  {"long", cons, 4},
  {"extend", float_cons, 'x'},
  {"extend", float_cons, 'x'},
  {"ldouble", float_cons, 'x'},
  {"ldouble", float_cons, 'x'},
  {"packed", float_cons, 'p'},
  {"packed", float_cons, 'p'},
  {"end", s_score_end, 0},
  {"end", s_score_end, 0},
  {"ent", s_score_ent, 0},
  {"ent", s_score_ent, 0},
  {"frame", s_score_frame, 0},
  {"frame", s_score_frame, 0},
  {"rdata", s_change_sec, 'r'},
  {"rdata", s_change_sec, 'r'},
  {"sdata", s_change_sec, 's'},
  {"sdata", s_change_sec, 's'},
  {"set", s_score_set, 0},
  {"set", s_score_set, 0},
  {"mask", s_score_mask, 'R'},
  {"mask", s_score_mask, 'R'},
  {"dword", cons, 8},
  {"dword", cons, 8},
  {"lcomm", s_score_lcomm, 1},
  {"lcomm", s_score_lcomm, 1},
  {"section", score_s_section, 0},
  {"section", score_s_section, 0},
  {"cpload", s_score_cpload, 0},
  {"cpload", s_score_cpload, 0},
  {"cprestore", s_score_cprestore, 0},
  {"cprestore", s_score_cprestore, 0},
  {"gpword", s_score_gpword, 0},
  {"gpword", s_score_gpword, 0},
  {"cpadd", s_score_cpadd, 0},
  {"cpadd", s_score_cpadd, 0},
  {0, 0, 0}
  {0, 0, 0}
};
};
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.