Back to index

cell-binutils  2.17cvs20070401
tc-score.c
Go to the documentation of this file.
00001 /* tc-score.c -- Assembler for Score
00002    Copyright 2006 Free Software Foundation, Inc.
00003    Contributed by:
00004    Mei Ligang (ligang@sunnorth.com.cn)
00005    Pei-Lin Tsai (pltsai@sunplus.com)
00006 
00007    This file is part of GAS, the GNU Assembler.
00008 
00009    GAS is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 2, or (at your option)
00012    any later version.
00013 
00014    GAS is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018 
00019    You should have received a copy of the GNU General Public License
00020    along with GAS; see the file COPYING.  If not, write to the Free
00021    Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
00022    02110-1301, USA.  */
00023 
00024 #include "as.h"
00025 #include "config.h"
00026 #include "subsegs.h"
00027 #include "safe-ctype.h"
00028 #include "opcode/score-inst.h"
00029 #include "opcode/score-datadep.h"
00030 #include "struc-symbol.h"
00031 
00032 #ifdef OBJ_ELF
00033 #include "elf/score.h"
00034 #include "dwarf2dbg.h"
00035 #endif
00036 
00037 #define GP                     28
00038 #define PIC_CALL_REG           29
00039 #define MAX_LITERAL_POOL_SIZE  1024
00040 #define FAIL                 0x80000000
00041 #define SUCCESS         0
00042 #define INSN_SIZE       4
00043 #define INSN16_SIZE     2
00044 #define RELAX_INST_NUM  3
00045 
00046 /* For score5u : div/mul will pop warning message, mmu/alw/asw will pop error message.  */
00047 #define BAD_ARGS               _("bad arguments to instruction")
00048 #define BAD_PC                        _("r15 not allowed here")
00049 #define BAD_COND               _("instruction is not conditional")
00050 #define ERR_NO_ACCUM           _("acc0 expected")
00051 #define ERR_FOR_SCORE5U_MUL_DIV   _("div / mul are reserved instructions")
00052 #define ERR_FOR_SCORE5U_MMU       _("This architecture doesn't support mmu")
00053 #define ERR_FOR_SCORE5U_ATOMIC    _("This architecture doesn't support atomic instruction")
00054 #define LONG_LABEL_LEN            _("the label length is longer than 1024");
00055 #define BAD_SKIP_COMMA            BAD_ARGS
00056 #define BAD_GARBAGE               _("garbage following instruction");
00057 
00058 #define skip_whitespace(str)  while (*(str) == ' ') ++(str)
00059 
00060 /* The name of the readonly data section.  */
00061 #define RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \
00062                          ? ".data" \
00063                          : OUTPUT_FLAVOR == bfd_target_ecoff_flavour \
00064                          ? ".rdata" \
00065                          : OUTPUT_FLAVOR == bfd_target_coff_flavour \
00066                          ? ".rdata" \
00067                          : OUTPUT_FLAVOR == bfd_target_elf_flavour \
00068                          ? ".rodata" \
00069                          : (abort (), ""))
00070 
00071 #define RELAX_ENCODE(old, new, type, reloc1, reloc2, opt) \
00072   ((relax_substateT) \
00073    (((old) << 23) \
00074     | ((new) << 16) \
00075     | ((type) << 9) \
00076     | ((reloc1) << 5) \
00077     | ((reloc2) << 1) \
00078     | ((opt) ? 1 : 0)))
00079 
00080 #define RELAX_OLD(i)       (((i) >> 23) & 0x7f)
00081 #define RELAX_NEW(i)       (((i) >> 16) & 0x7f)
00082 #define RELAX_TYPE(i)      (((i) >> 9) & 0x7f)
00083 #define RELAX_RELOC1(i)    ((valueT) ((i) >> 5) & 0xf)
00084 #define RELAX_RELOC2(i)    ((valueT) ((i) >> 1) & 0xf)
00085 #define RELAX_OPT(i)       ((i) & 1)
00086 #define RELAX_OPT_CLEAR(i) ((i) & ~1)
00087 
00088 #define SET_INSN_ERROR(s) (inst.error = (s))
00089 #define INSN_IS_PCE_P(s)  (strstr (str, "||") != NULL)
00090 
00091 #define GET_INSN_CLASS(type) (get_insn_class_from_type (type))
00092 
00093 #define GET_INSN_SIZE(type) ((GET_INSN_CLASS (type) == INSN_CLASS_16) \
00094                              ? INSN16_SIZE : INSN_SIZE)
00095 
00096 /* This array holds the chars that always start a comment.  If the
00097    pre-processor is disabled, these aren't very useful.  */
00098 const char comment_chars[] = "#";
00099 const char line_comment_chars[] = "#";
00100 const char line_separator_chars[] = ";";
00101 
00102 /* Chars that can be used to separate mant from exp in floating point numbers.  */
00103 const char EXP_CHARS[] = "eE";
00104 const char FLT_CHARS[] = "rRsSfFdDxXeEpP";
00105 
00106 /* Used to contain constructed error messages.  */
00107 static char err_msg[255];
00108 
00109 fragS *score_fragp = 0;
00110 static int fix_data_dependency = 0;
00111 static int warn_fix_data_dependency = 1;
00112 static int score7 = 1;
00113 static int university_version = 0;
00114 
00115 static int in_my_get_expression = 0;
00116 
00117 #define USE_GLOBAL_POINTER_OPT 1
00118 #define SCORE_BI_ENDIAN
00119 
00120 /* Default, pop warning message when using r1.  */
00121 static int nor1 = 1;
00122 
00123 /* Default will do instruction relax, -O0 will set g_opt = 0.  */
00124 static unsigned int g_opt = 1;
00125 
00126 /* The size of the small data section.  */
00127 static unsigned int g_switch_value = 8;
00128 
00129 #ifdef OBJ_ELF
00130 /* Pre-defined "_GLOBAL_OFFSET_TABLE_"  */
00131 symbolS *GOT_symbol;
00132 #endif
00133 static segT pdr_seg;
00134 
00135 enum score_pic_level score_pic = NO_PIC;
00136 
00137 #define INSN_NAME_LEN 16
00138 struct score_it
00139 {
00140   char name[INSN_NAME_LEN];
00141   unsigned long instruction;
00142   unsigned long relax_inst;
00143   int size;
00144   int relax_size;
00145   enum score_insn_type type;
00146   char str[MAX_LITERAL_POOL_SIZE];
00147   const char *error;
00148   int bwarn;
00149   char reg[INSN_NAME_LEN];
00150   struct
00151   {
00152     bfd_reloc_code_real_type type;
00153     expressionS exp;
00154     int pc_rel;
00155   }reloc;
00156 };
00157 struct score_it inst;
00158 
00159 typedef struct proc
00160 {
00161   symbolS *isym;
00162   unsigned long reg_mask;
00163   unsigned long reg_offset;
00164   unsigned long fpreg_mask;
00165   unsigned long leaf;
00166   unsigned long frame_offset;
00167   unsigned long frame_reg;
00168   unsigned long pc_reg;
00169 }
00170 procS;
00171 
00172 static procS cur_proc;
00173 static procS *cur_proc_ptr;
00174 static int numprocs;
00175 
00176 #define SCORE7_PIPELINE 7
00177 #define SCORE5_PIPELINE 5
00178 static int vector_size = SCORE7_PIPELINE;
00179 struct score_it dependency_vector[SCORE7_PIPELINE];
00180 
00181 /* Relax will need some padding for alignment.  */
00182 #define RELAX_PAD_BYTE 3
00183 
00184 /* Number of littlenums required to hold an extended precision number.  For md_atof.  */
00185 #define NUM_FLOAT_VALS 8
00186 #define MAX_LITTLENUMS 6
00187 LITTLENUM_TYPE fp_values[NUM_FLOAT_VALS][MAX_LITTLENUMS];
00188 
00189 /* Structure for a hash table entry for a register.  */
00190 struct reg_entry
00191 {
00192   const char *name;
00193   int number;
00194 };
00195 
00196 static const struct reg_entry score_rn_table[] =
00197 {
00198   {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
00199   {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
00200   {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
00201   {"r12", 12}, {"r13", 13}, {"r14", 14}, {"r15", 15},
00202   {"r16", 16}, {"r17", 17}, {"r18", 18}, {"r19", 19},
00203   {"r20", 20}, {"r21", 21}, {"r22", 22}, {"r23", 23},
00204   {"r24", 24}, {"r25", 25}, {"r26", 26}, {"r27", 27},
00205   {"r28", 28}, {"r29", 29}, {"r30", 30}, {"r31", 31},
00206   {NULL, 0}
00207 };
00208 
00209 static const struct reg_entry score_srn_table[] =
00210 {
00211   {"sr0", 0}, {"sr1", 1}, {"sr2", 2},
00212   {NULL, 0}
00213 };
00214 
00215 static const struct reg_entry score_crn_table[] =
00216 {
00217   {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3},
00218   {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7},
00219   {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11},
00220   {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
00221   {"cr16", 16}, {"cr17", 17}, {"cr18", 18}, {"cr19", 19},
00222   {"cr20", 20}, {"cr21", 21}, {"cr22", 22}, {"cr23", 23},
00223   {"cr24", 24}, {"cr25", 25}, {"cr26", 26}, {"cr27", 27},
00224   {"cr28", 28}, {"cr29", 29}, {"cr30", 30}, {"cr31", 31},
00225   {NULL, 0}
00226 };
00227 
00228 struct reg_map
00229 {
00230   const struct reg_entry *names;
00231   int max_regno;
00232   struct hash_control *htab;
00233   const char *expected;
00234 };
00235 
00236 struct reg_map all_reg_maps[] =
00237 {
00238   {score_rn_table, 31, NULL, N_("S+core register expected")},
00239   {score_srn_table, 2, NULL, N_("S+core special-register expected")},
00240   {score_crn_table, 31, NULL, N_("S+core co-processor register expected")},
00241 };
00242 
00243 static struct hash_control *score_ops_hsh = NULL;
00244 
00245 static struct hash_control *dependency_insn_hsh = NULL;
00246 
00247 /* Enumeration matching entries in table above.  */
00248 enum score_reg_type
00249 {
00250   REG_TYPE_SCORE = 0,
00251 #define REG_TYPE_FIRST REG_TYPE_SCORE
00252   REG_TYPE_SCORE_SR = 1,
00253   REG_TYPE_SCORE_CR = 2,
00254   REG_TYPE_MAX = 3
00255 };
00256 
00257 typedef struct literalS
00258 {
00259   struct expressionS exp;
00260   struct score_it *inst;
00261 }
00262 literalT;
00263 
00264 literalT literals[MAX_LITERAL_POOL_SIZE];
00265 
00266 static void do_ldst_insn (char *);
00267 static void do_crdcrscrsimm5 (char *);
00268 static void do_ldst_unalign (char *);
00269 static void do_ldst_atomic (char *);
00270 static void do_ldst_cop (char *);
00271 static void do_macro_li_rdi32 (char *);
00272 static void do_macro_la_rdi32 (char *);
00273 static void do_macro_rdi32hi (char *);
00274 static void do_macro_rdi32lo (char *);
00275 static void do_macro_mul_rdrsrs (char *);
00276 static void do_macro_ldst_label (char *);
00277 static void do_branch (char *);
00278 static void do_jump (char *);
00279 static void do_empty (char *);
00280 static void do_rdrsrs (char *);
00281 static void do_rdsi16 (char *);
00282 static void do_rdrssi14 (char *);
00283 static void do_sub_rdsi16 (char *);
00284 static void do_sub_rdi16 (char *);
00285 static void do_sub_rdrssi14 (char *);
00286 static void do_rdrsi5 (char *);
00287 static void do_rdrsi14 (char *);
00288 static void do_rdi16 (char *);
00289 static void do_xrsi5 (char *);
00290 static void do_rdrs (char *);
00291 static void do_rdxrs (char *);
00292 static void do_rsrs (char *);
00293 static void do_rdcrs (char *);
00294 static void do_rdsrs (char *);
00295 static void do_rd (char *);
00296 static void do_rs (char *);
00297 static void do_i15 (char *);
00298 static void do_xi5x (char *);
00299 static void do_ceinst (char *);
00300 static void do_cache (char *);
00301 static void do16_rdrs (char *);
00302 static void do16_rs (char *);
00303 static void do16_xrs (char *);
00304 static void do16_mv_rdrs (char *);
00305 static void do16_hrdrs (char *);
00306 static void do16_rdhrs (char *);
00307 static void do16_rdi4 (char *);
00308 static void do16_rdi5 (char *);
00309 static void do16_xi5 (char *);
00310 static void do16_ldst_insn (char *);
00311 static void do16_ldst_imm_insn (char *);
00312 static void do16_push_pop (char *);
00313 static void do16_branch (char *);
00314 static void do16_jump (char *);
00315 static void do_rdi16_pic (char *);
00316 static void do_addi_s_pic (char *);
00317 static void do_addi_u_pic (char *);
00318 static void do_lw_pic (char *);
00319 
00320 static const struct asm_opcode score_ldst_insns[] = 
00321 {
00322   {"lw",        0x20000000, 0x3e000000, 0x2008,     Rd_rvalueRs_SI15,     do_ldst_insn},
00323   {"lw",        0x06000000, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  do_ldst_insn},
00324   {"lw",        0x0e000000, 0x3e000007, 0x200a,     Rd_rvalueRs_postSI12, do_ldst_insn},
00325   {"lh",        0x22000000, 0x3e000000, 0x2009,     Rd_rvalueRs_SI15,     do_ldst_insn},
00326   {"lh",        0x06000001, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  do_ldst_insn},
00327   {"lh",        0x0e000001, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, do_ldst_insn},
00328   {"lhu",       0x24000000, 0x3e000000, 0x8000,     Rd_rvalueRs_SI15,     do_ldst_insn},
00329   {"lhu",       0x06000002, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  do_ldst_insn},
00330   {"lhu",       0x0e000002, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, do_ldst_insn},
00331   {"lb",        0x26000000, 0x3e000000, 0x8000,     Rd_rvalueRs_SI15,     do_ldst_insn},
00332   {"lb",        0x06000003, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  do_ldst_insn},
00333   {"lb",        0x0e000003, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, do_ldst_insn},
00334   {"sw",        0x28000000, 0x3e000000, 0x200c,     Rd_lvalueRs_SI15,     do_ldst_insn},
00335   {"sw",        0x06000004, 0x3e000007, 0x200e,     Rd_lvalueRs_preSI12,  do_ldst_insn},
00336   {"sw",        0x0e000004, 0x3e000007, 0x8000,     Rd_lvalueRs_postSI12, do_ldst_insn},
00337   {"sh",        0x2a000000, 0x3e000000, 0x200d,     Rd_lvalueRs_SI15,     do_ldst_insn},
00338   {"sh",        0x06000005, 0x3e000007, 0x8000,     Rd_lvalueRs_preSI12,  do_ldst_insn},
00339   {"sh",        0x0e000005, 0x3e000007, 0x8000,     Rd_lvalueRs_postSI12, do_ldst_insn},
00340   {"lbu",       0x2c000000, 0x3e000000, 0x200b,     Rd_rvalueRs_SI15,     do_ldst_insn},
00341   {"lbu",       0x06000006, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  do_ldst_insn},
00342   {"lbu",       0x0e000006, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, do_ldst_insn},
00343   {"sb",        0x2e000000, 0x3e000000, 0x200f,     Rd_lvalueRs_SI15,     do_ldst_insn},
00344   {"sb",        0x06000007, 0x3e000007, 0x8000,     Rd_lvalueRs_preSI12,  do_ldst_insn},
00345   {"sb",        0x0e000007, 0x3e000007, 0x8000,     Rd_lvalueRs_postSI12, do_ldst_insn},
00346 };
00347 
00348 static const struct asm_opcode score_insns[] = 
00349 {
00350   {"abs",       0x3800000a, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
00351   {"abs.s",     0x3800004b, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
00352   {"add",       0x00000010, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00353   {"add.c",     0x00000011, 0x3e0003ff, 0x2000,     Rd_Rs_Rs,             do_rdrsrs},
00354   {"add.s",     0x38000048, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00355   {"addc",      0x00000012, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00356   {"addc.c",    0x00000013, 0x3e0003ff, 0x0009,     Rd_Rs_Rs,             do_rdrsrs},
00357   {"addi",      0x02000000, 0x3e0e0001, 0x8000,     Rd_SI16,              do_rdsi16},
00358   {"addi.c",    0x02000001, 0x3e0e0001, 0x8000,     Rd_SI16,              do_rdsi16},
00359   {"addis",     0x0a000000, 0x3e0e0001, 0x8000,     Rd_SI16,              do_rdi16},
00360   {"addis.c",   0x0a000001, 0x3e0e0001, 0x8000,     Rd_SI16,              do_rdi16},
00361   {"addri",     0x10000000, 0x3e000001, 0x8000,     Rd_Rs_SI14,           do_rdrssi14},
00362   {"addri.c",   0x10000001, 0x3e000001, 0x8000,     Rd_Rs_SI14,           do_rdrssi14},
00363   {"addc!",     0x0009,     0x700f,     0x00000013, Rd_Rs,                do16_rdrs},
00364   {"add!",      0x2000,     0x700f,     0x00000011, Rd_Rs,                do16_rdrs},
00365   {"addei!",    0x6000    , 0x7087,     0x02000001, Rd_I4,                do16_rdi4},
00366   {"subi",      0x02000000, 0x3e0e0001, 0x8000,     Rd_SI16,              do_sub_rdsi16},
00367   {"subi.c",    0x02000001, 0x3e0e0001, 0x8000,     Rd_SI16,              do_sub_rdsi16},
00368   {"subis",     0x0a000000, 0x3e0e0001, 0x8000,     Rd_SI16,              do_sub_rdi16},
00369   {"subis.c",   0x0a000001, 0x3e0e0001, 0x8000,     Rd_SI16,              do_sub_rdi16},
00370   {"subri",     0x10000000, 0x3e000001, 0x8000,     Rd_Rs_SI14,           do_sub_rdrssi14},
00371   {"subri.c",   0x10000001, 0x3e000001, 0x8000,     Rd_Rs_SI14,           do_sub_rdrssi14},
00372   {"and",       0x00000020, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00373   {"and.c",     0x00000021, 0x3e0003ff, 0x2004,     Rd_Rs_Rs,             do_rdrsrs},
00374   {"andi",      0x02080000, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
00375   {"andi.c",    0x02080001, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
00376   {"andis",     0x0a080000, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
00377   {"andis.c",   0x0a080001, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
00378   {"andri",     0x18000000, 0x3e000001, 0x8000,     Rd_Rs_I14,            do_rdrsi14},
00379   {"andri.c",   0x18000001, 0x3e000001, 0x8000,     Rd_Rs_I14,            do_rdrsi14},
00380   {"and!",      0x2004,     0x700f,     0x00000021, Rd_Rs,                do16_rdrs},
00381   {"bcs",       0x08000000, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
00382   {"bcc",       0x08000400, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
00383   {"bcnz",      0x08003800, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
00384   {"bcsl",      0x08000001, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
00385   {"bccl",      0x08000401, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
00386   {"bcnzl",     0x08003801, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
00387   {"bcs!",      0x4000,     0x7f00,     0x08000000, PC_DISP8div2,         do16_branch},
00388   {"bcc!",      0x4100,     0x7f00,     0x08000400, PC_DISP8div2,         do16_branch},
00389   {"bcnz!",     0x4e00,     0x7f00,     0x08003800, PC_DISP8div2,         do16_branch},
00390   {"beq",       0x08001000, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
00391   {"beql",      0x08001001, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
00392   {"beq!",      0x4400,     0x7f00,     0x08001000, PC_DISP8div2,         do16_branch},
00393   {"bgtu",      0x08000800, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
00394   {"bgt",       0x08001800, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
00395   {"bge",       0x08002000, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
00396   {"bgtul",     0x08000801, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
00397   {"bgtl",      0x08001801, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
00398   {"bgel",      0x08002001, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
00399   {"bgtu!",     0x4200,     0x7f00,     0x08000800, PC_DISP8div2,         do16_branch},
00400   {"bgt!",      0x4600,     0x7f00,     0x08001800, PC_DISP8div2,         do16_branch},
00401   {"bge!",      0x4800,     0x7f00,     0x08002000, PC_DISP8div2,         do16_branch},
00402   {"bitclr.c",  0x00000029, 0x3e0003ff, 0x6004,     Rd_Rs_I5,             do_rdrsi5},
00403   {"bitrev",    0x3800000c, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00404   {"bitset.c",  0x0000002b, 0x3e0003ff, 0x6005,     Rd_Rs_I5,             do_rdrsi5},
00405   {"bittst.c",  0x0000002d, 0x3e0003ff, 0x6006,     x_Rs_I5,              do_xrsi5},
00406   {"bittgl.c",  0x0000002f, 0x3e0003ff, 0x6007,     Rd_Rs_I5,             do_rdrsi5},
00407   {"bitclr!",   0x6004,     0x7007,     0x00000029, Rd_I5,                do16_rdi5},
00408   {"bitset!",   0x6005,     0x7007,     0x0000002b, Rd_I5,                do16_rdi5},
00409   {"bittst!",   0x6006,     0x7007,     0x0000002d, Rd_I5,                do16_rdi5},
00410   {"bittgl!",   0x6007,     0x7007,     0x0000002f, Rd_I5,                do16_rdi5},
00411   {"bleu",      0x08000c00, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
00412   {"ble",       0x08001c00, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
00413   {"blt",       0x08002400, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
00414   {"bleul",     0x08000c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
00415   {"blel",      0x08001c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
00416   {"bltl",      0x08002401, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
00417   {"bl",        0x08003c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
00418   {"bleu!",     0x4300,     0x7f00,     0x08000c00, PC_DISP8div2,         do16_branch},
00419   {"ble!",      0x4700,     0x7f00,     0x08001c00, PC_DISP8div2,         do16_branch},
00420   {"blt!",      0x4900,     0x7f00,     0x08002400, PC_DISP8div2,         do16_branch},
00421   {"bmi",       0x08002800, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
00422   {"bmil",      0x08002801, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
00423   {"bmi!",      0x00004a00, 0x00007f00, 0x08002800, PC_DISP8div2,         do16_branch},
00424   {"bne",       0x08001400, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
00425   {"bnel",      0x08001401, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
00426   {"bne!",      0x4500,     0x7f00,     0x08001400, PC_DISP8div2,         do16_branch},
00427   {"bpl",       0x08002c00, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
00428   {"bpll",      0x08002c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
00429   {"bpl!",      0x4b00,     0x7f00,     0x08002c00, PC_DISP8div2,         do16_branch},
00430   {"brcs",      0x00000008, 0x3e007fff, 0x0004,     x_Rs_x,               do_rs},
00431   {"brcc",      0x00000408, 0x3e007fff, 0x0104,     x_Rs_x,               do_rs},
00432   {"brgtu",     0x00000808, 0x3e007fff, 0x0204,     x_Rs_x,               do_rs},
00433   {"brleu",     0x00000c08, 0x3e007fff, 0x0304,     x_Rs_x,               do_rs},
00434   {"breq",      0x00001008, 0x3e007fff, 0x0404,     x_Rs_x,               do_rs},
00435   {"brne",      0x00001408, 0x3e007fff, 0x0504,     x_Rs_x,               do_rs},
00436   {"brgt",      0x00001808, 0x3e007fff, 0x0604,     x_Rs_x,               do_rs},
00437   {"brle",      0x00001c08, 0x3e007fff, 0x0704,     x_Rs_x,               do_rs},
00438   {"brge",      0x00002008, 0x3e007fff, 0x0804,     x_Rs_x,               do_rs},
00439   {"brlt",      0x00002408, 0x3e007fff, 0x0904,     x_Rs_x,               do_rs},
00440   {"brmi",      0x00002808, 0x3e007fff, 0x0a04,     x_Rs_x,               do_rs},
00441   {"brpl",      0x00002c08, 0x3e007fff, 0x0b04,     x_Rs_x,               do_rs},
00442   {"brvs",      0x00003008, 0x3e007fff, 0x0c04,     x_Rs_x,               do_rs},
00443   {"brvc",      0x00003408, 0x3e007fff, 0x0d04,     x_Rs_x,               do_rs},
00444   {"brcnz",     0x00003808, 0x3e007fff, 0x0e04,     x_Rs_x,               do_rs},
00445   {"br",        0x00003c08, 0x3e007fff, 0x0f04,     x_Rs_x,               do_rs},
00446   {"brcsl",     0x00000009, 0x3e007fff, 0x000c,     x_Rs_x,               do_rs},
00447   {"brccl",     0x00000409, 0x3e007fff, 0x010c,     x_Rs_x,               do_rs},
00448   {"brgtul",    0x00000809, 0x3e007fff, 0x020c,     x_Rs_x,               do_rs},
00449   {"brleul",    0x00000c09, 0x3e007fff, 0x030c,     x_Rs_x,               do_rs},
00450   {"breql",     0x00001009, 0x3e007fff, 0x040c,     x_Rs_x,               do_rs}, 
00451   {"brnel",     0x00001409, 0x3e007fff, 0x050c,     x_Rs_x,               do_rs},
00452   {"brgtl",     0x00001809, 0x3e007fff, 0x060c,     x_Rs_x,               do_rs},
00453   {"brlel",     0x00001c09, 0x3e007fff, 0x070c,     x_Rs_x,               do_rs},
00454   {"brgel",     0x00002009, 0x3e007fff, 0x080c,     x_Rs_x,               do_rs},
00455   {"brltl",     0x00002409, 0x3e007fff, 0x090c,     x_Rs_x,               do_rs},
00456   {"brmil",     0x00002809, 0x3e007fff, 0x0a0c,     x_Rs_x,               do_rs},
00457   {"brpll",     0x00002c09, 0x3e007fff, 0x0b0c,     x_Rs_x,               do_rs},
00458   {"brvsl",     0x00003009, 0x3e007fff, 0x0c0c,     x_Rs_x,               do_rs},
00459   {"brvcl",     0x00003409, 0x3e007fff, 0x0d0c,     x_Rs_x,               do_rs},
00460   {"brcnzl",    0x00003809, 0x3e007fff, 0x0e0c,     x_Rs_x,               do_rs},
00461   {"brl",       0x00003c09, 0x3e007fff, 0x0f0c,     x_Rs_x,               do_rs},
00462   {"brcs!",     0x0004,     0x7f0f,     0x00000008, x_Rs,                 do16_xrs},
00463   {"brcc!",     0x0104,     0x7f0f,     0x00000408, x_Rs,                 do16_xrs},
00464   {"brgtu!",    0x0204,     0x7f0f,     0x00000808, x_Rs,                 do16_xrs},
00465   {"brleu!",    0x0304,     0x7f0f,     0x00000c08, x_Rs,                 do16_xrs},
00466   {"breq!",     0x0404,     0x7f0f,     0x00001008, x_Rs,                 do16_xrs},
00467   {"brne!",     0x0504,     0x7f0f,     0x00001408, x_Rs,                 do16_xrs},
00468   {"brgt!",     0x0604,     0x7f0f,     0x00001808, x_Rs,                 do16_xrs},
00469   {"brle!",     0x0704,     0x7f0f,     0x00001c08, x_Rs,                 do16_xrs},
00470   {"brge!",     0x0804,     0x7f0f,     0x00002008, x_Rs,                 do16_xrs},
00471   {"brlt!",     0x0904,     0x7f0f,     0x00002408, x_Rs,                 do16_xrs},
00472   {"brmi!",     0x0a04,     0x7f0f,     0x00002808, x_Rs,                 do16_xrs},
00473   {"brpl!",     0x0b04,     0x7f0f,     0x00002c08, x_Rs,                 do16_xrs},
00474   {"brvs!",     0x0c04,     0x7f0f,     0x00003008, x_Rs,                 do16_xrs},
00475   {"brvc!",     0x0d04,     0x7f0f,     0x00003408, x_Rs,                 do16_xrs},
00476   {"brcnz!",    0x0e04,     0x7f0f,     0x00003808, x_Rs,                 do16_xrs},
00477   {"br!",       0x0f04,     0x7f0f,     0x00003c08, x_Rs,                 do16_xrs},
00478   {"brcsl!",    0x000c,     0x7f0f,     0x00000009, x_Rs,                 do16_xrs},
00479   {"brccl!",    0x010c,     0x7f0f,     0x00000409, x_Rs,                 do16_xrs},
00480   {"brgtul!",   0x020c,     0x7f0f,     0x00000809, x_Rs,                 do16_xrs},
00481   {"brleul!",   0x030c,     0x7f0f,     0x00000c09, x_Rs,                 do16_xrs},
00482   {"breql!",    0x040c,     0x7f0f,     0x00001009, x_Rs,                 do16_xrs},
00483   {"brnel!",    0x050c,     0x7f0f,     0x00001409, x_Rs,                 do16_xrs},
00484   {"brgtl!",    0x060c,     0x7f0f,     0x00001809, x_Rs,                 do16_xrs},
00485   {"brlel!",    0x070c,     0x7f0f,     0x00001c09, x_Rs,                 do16_xrs},
00486   {"brgel!",    0x080c,     0x7f0f,     0x00002009, x_Rs,                 do16_xrs},
00487   {"brltl!",    0x090c,     0x7f0f,     0x00002409, x_Rs,                 do16_xrs},
00488   {"brmil!",    0x0a0c,     0x7f0f,     0x00002809, x_Rs,                 do16_xrs},
00489   {"brpll!",    0x0b0c,     0x7f0f,     0x00002c09, x_Rs,                 do16_xrs},
00490   {"brvsl!",    0x0c0c,     0x7f0f,     0x00003009, x_Rs,                 do16_xrs},
00491   {"brvcl!",    0x0d0c,     0x7f0f,     0x00003409, x_Rs,                 do16_xrs},
00492   {"brcnzl!",   0x0e0c,     0x7f0f,     0x00003809, x_Rs,                 do16_xrs},
00493   {"brl!",      0x0f0c,     0x7f0f,     0x00003c09, x_Rs,                 do16_xrs},
00494   {"bvs",       0x08003000, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
00495   {"bvc",       0x08003400, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
00496   {"bvsl",      0x08003001, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
00497   {"bvcl",      0x08003401, 0x3e007c01, 0x8000,     PC_DISP19div2,        do_branch},
00498   {"bvs!",      0x4c00,     0x7f00,     0x08003000, PC_DISP8div2,         do16_branch},
00499   {"bvc!",      0x4d00,     0x7f00,     0x08003400, PC_DISP8div2,         do16_branch},
00500   {"b!",        0x4f00,     0x7f00,     0x08003c00, PC_DISP8div2,         do16_branch},
00501   {"b",         0x08003c00, 0x3e007c01, 0x4000,     PC_DISP19div2,        do_branch},
00502   {"cache",     0x30000000, 0x3ff00000, 0x8000,     OP5_rvalueRs_SI15,    do_cache},
00503   {"ceinst",    0x38000000, 0x3e000000, 0x8000,     I5_Rs_Rs_I5_OP5,      do_ceinst},
00504   {"clz",       0x3800000d, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
00505   {"cmpteq.c",  0x00000019, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00506   {"cmptmi.c",  0x00100019, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00507   {"cmp.c",     0x00300019, 0x3ff003ff, 0x2003,     x_Rs_Rs,              do_rsrs},
00508   {"cmpzteq.c", 0x0000001b, 0x3ff07fff, 0x8000,     x_Rs_x,               do_rs},
00509   {"cmpztmi.c", 0x0010001b, 0x3ff07fff, 0x8000,     x_Rs_x,               do_rs},
00510   {"cmpz.c",    0x0030001b, 0x3ff07fff, 0x8000,     x_Rs_x,               do_rs},
00511   {"cmpi.c",    0x02040001, 0x3e0e0001, 0x8000,     Rd_SI16,              do_rdsi16},
00512   {"cmp!",      0x2003,     0x700f,     0x00300019, Rd_Rs,                do16_rdrs},
00513   {"cop1",      0x0c00000c, 0x3e00001f, 0x8000,     Rd_Rs_Rs_imm,         do_crdcrscrsimm5},
00514   {"cop2",      0x0c000014, 0x3e00001f, 0x8000,     Rd_Rs_Rs_imm,         do_crdcrscrsimm5},
00515   {"cop3",      0x0c00001c, 0x3e00001f, 0x8000,     Rd_Rs_Rs_imm,         do_crdcrscrsimm5},
00516   {"drte",      0x0c0000a4, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
00517   {"extsb",     0x00000058, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
00518   {"extsb.c",   0x00000059, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
00519   {"extsh",     0x0000005a, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
00520   {"extsh.c",   0x0000005b, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
00521   {"extzb",     0x0000005c, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
00522   {"extzb.c",   0x0000005d, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
00523   {"extzh",     0x0000005e, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
00524   {"extzh.c",   0x0000005f, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
00525   {"jl",        0x04000001, 0x3e000001, 0x8000,     PC_DISP24div2,        do_jump},
00526   {"jl!",       0x3001,     0x7001,     0x04000001, PC_DISP11div2,        do16_jump},
00527   {"j!",        0x3000,     0x7001,     0x04000000, PC_DISP11div2,        do16_jump},
00528   {"j",         0x04000000, 0x3e000001, 0x8000,     PC_DISP24div2,        do_jump},
00529   {"lbu!",      0x200b,     0x0000700f, 0x2c000000, Rd_rvalueRs,          do16_ldst_insn},
00530   {"lbup!",     0x7003,     0x7007,     0x2c000000, Rd_rvalueBP_I5,       do16_ldst_imm_insn},
00531   {"alw",       0x0000000c, 0x3e0003ff, 0x8000,     Rd_rvalue32Rs,        do_ldst_atomic},
00532   {"lcb",       0x00000060, 0x3e0003ff, 0x8000,     x_rvalueRs_post4,     do_ldst_unalign},
00533   {"lcw",       0x00000062, 0x3e0003ff, 0x8000,     Rd_rvalueRs_post4,    do_ldst_unalign},
00534   {"lce",       0x00000066, 0x3e0003ff, 0x8000,     Rd_rvalueRs_post4,    do_ldst_unalign},
00535   {"ldc1",      0x0c00000a, 0x3e00001f, 0x8000,     Rd_rvalueRs_SI10,     do_ldst_cop},
00536   {"ldc2",      0x0c000012, 0x3e00001f, 0x8000,     Rd_rvalueRs_SI10,     do_ldst_cop},
00537   {"ldc3",      0x0c00001a, 0x3e00001f, 0x8000,     Rd_rvalueRs_SI10,     do_ldst_cop},
00538   {"lh!",       0x2009,     0x700f,     0x22000000, Rd_rvalueRs,          do16_ldst_insn},
00539   {"lhp!",      0x7001,     0x7007,     0x22000000, Rd_rvalueBP_I5,       do16_ldst_imm_insn},
00540   {"ldi",       0x020c0000, 0x3e0e0000, 0x5000,     Rd_SI16,              do_rdsi16},
00541   {"ldis",      0x0a0c0000, 0x3e0e0000, 0x8000,     Rd_I16,               do_rdi16},
00542   {"ldiu!",     0x5000,     0x7000,     0x020c0000, Rd_I8,                do16_ldst_imm_insn},
00543   {"lw!",       0x2008,     0x700f,     0x20000000, Rd_rvalueRs,          do16_ldst_insn},
00544   {"lwp!",      0x7000,     0x7007,     0x20000000, Rd_rvalueBP_I5,       do16_ldst_imm_insn},
00545   {"mfcel",     0x00000448, 0x3e007fff, 0x8000,     Rd_x_x,               do_rd},
00546   {"mfcel!",    0x1001,     0x7f0f,     0x00000448, x_Rs,                 do16_rs},
00547   {"mad",       0x38000000, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00548   {"mad.f!",    0x1004,     0x700f,     0x38000080, Rd_Rs,                do16_rdrs},
00549   {"madh",      0x38000203, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00550   {"madh.fs",   0x380002c3, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00551   {"madh.fs!",  0x100b,     0x700f,     0x380002c3, Rd_Rs,                do16_rdrs},
00552   {"madl",      0x38000002, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00553   {"madl.fs",   0x380000c2, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00554   {"madl.fs!",  0x100a,     0x700f,     0x380000c2, Rd_Rs,                do16_rdrs},
00555   {"madu",      0x38000020, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00556   {"madu!",     0x1005,     0x700f,     0x38000020, Rd_Rs,                do16_rdrs},
00557   {"mad.f",     0x38000080, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00558   {"max",       0x38000007, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00559   {"mazh",      0x38000303, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00560   {"mazh.f",    0x38000383, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00561   {"mazh.f!",   0x1009,     0x700f,     0x3800038c, Rd_Rs,                do16_rdrs},
00562   {"mazl",      0x38000102, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00563   {"mazl.f",    0x38000182, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00564   {"mazl.f!",   0x1008,     0x700f,     0x38000182, Rd_Rs,                do16_rdrs},
00565   {"mfceh",     0x00000848, 0x3e007fff, 0x8000,     Rd_x_x,               do_rd},
00566   {"mfceh!",    0x1101,     0x7f0f,     0x00000848, x_Rs,                 do16_rs},
00567   {"mfcehl",    0x00000c48, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
00568   {"mfsr",      0x00000050, 0x3e0003ff, 0x8000,     Rd_x_I5,              do_rdsrs},
00569   {"mfcr",      0x0c000001, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
00570   {"mfc1",      0x0c000009, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
00571   {"mfc2",      0x0c000011, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
00572   {"mfc3",      0x0c000019, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
00573   {"mfcc1",     0x0c00000f, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
00574   {"mfcc2",     0x0c000017, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
00575   {"mfcc3",     0x0c00001f, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
00576   {"mhfl!",     0x0002,     0x700f,     0x00003c56, Rd_LowRs,             do16_hrdrs},
00577   {"min",       0x38000006, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00578   {"mlfh!",     0x0001,     0x700f,     0x00003c56, Rd_HighRs,            do16_rdhrs},
00579   {"msb",       0x38000001, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00580   {"msb.f!",    0x1006,     0x700f,     0x38000081, Rd_Rs,                do16_rdrs},
00581   {"msbh",      0x38000205, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00582   {"msbh.fs",   0x380002c5, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00583   {"msbh.fs!",  0x100f,     0x700f,     0x380002c5, Rd_Rs,                do16_rdrs},
00584   {"msbl",      0x38000004, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00585   {"msbl.fs",   0x380000c4, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00586   {"msbl.fs!",  0x100e,     0x700f,     0x380000c4, Rd_Rs,                do16_rdrs},
00587   {"msbu",      0x38000021, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00588   {"msbu!",     0x1007,     0x700f,     0x38000021, Rd_Rs,                do16_rdrs},
00589   {"msb.f",     0x38000081, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00590   {"mszh",      0x38000305, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00591   {"mszh.f",    0x38000385, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00592   {"mszh.f!",   0x100d,     0x700f,     0x38000385, Rd_Rs,                do16_rdrs},
00593   {"mszl",      0x38000104, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00594   {"mszl.f",    0x38000184, 0x3ff003ff, 0x8000,     x_Rs_Rs,              do_rsrs},
00595   {"mszl.f!",   0x100c,     0x700f,     0x38000184, Rd_Rs,                do16_rdrs},
00596   {"mtcel!",    0x1000,     0x7f0f,     0x0000044a, x_Rs,                 do16_rs},
00597   {"mtcel",     0x0000044a, 0x3e007fff, 0x8000,     Rd_x_x,               do_rd},
00598   {"mtceh",     0x0000084a, 0x3e007fff, 0x8000,     Rd_x_x,               do_rd},
00599   {"mtceh!",    0x1100,     0x7f0f,     0x0000084a, x_Rs,                 do16_rs},
00600   {"mtcehl",    0x00000c4a, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
00601   {"mtsr",      0x00000052, 0x3e0003ff, 0x8000,     x_Rs_I5,              do_rdsrs},
00602   {"mtcr",      0x0c000000, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
00603   {"mtc1",      0x0c000008, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
00604   {"mtc2",      0x0c000010, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
00605   {"mtc3",      0x0c000018, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
00606   {"mtcc1",     0x0c00000e, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
00607   {"mtcc2",     0x0c000016, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
00608   {"mtcc3",     0x0c00001e, 0x3e00001f, 0x8000,     Rd_Rs_x,              do_rdcrs},
00609   {"mul.f!",    0x1002,     0x700f,     0x00000041, Rd_Rs,                do16_rdrs},
00610   {"mulu!",     0x1003,     0x700f,     0x00000042, Rd_Rs,                do16_rdrs},
00611   {"mvcs",      0x00000056, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
00612   {"mvcc",      0x00000456, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
00613   {"mvgtu",     0x00000856, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
00614   {"mvleu",     0x00000c56, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
00615   {"mveq",      0x00001056, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
00616   {"mvne",      0x00001456, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
00617   {"mvgt",      0x00001856, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
00618   {"mvle",      0x00001c56, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
00619   {"mvge",      0x00002056, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
00620   {"mvlt",      0x00002456, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
00621   {"mvmi",      0x00002856, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
00622   {"mvpl",      0x00002c56, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
00623   {"mvvs",      0x00003056, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
00624   {"mvvc",      0x00003456, 0x3e007fff, 0x8000,     Rd_Rs_x,              do_rdrs},
00625   {"mv",        0x00003c56, 0x3e007fff, 0x0003,     Rd_Rs_x,              do_rdrs},
00626   {"mv!",       0x0003,     0x700f,     0x00003c56, Rd_Rs,                do16_mv_rdrs},
00627   {"neg",       0x0000001e, 0x3e0003ff, 0x8000,     Rd_x_Rs,              do_rdxrs},
00628   {"neg.c",     0x0000001f, 0x3e0003ff, 0x2002,     Rd_x_Rs,              do_rdxrs},
00629   {"neg!",      0x2002,     0x700f,     0x0000001f, Rd_Rs,                do16_rdrs},
00630   {"nop",       0x00000000, 0x3e0003ff, 0x0000,     NO_OPD,               do_empty},
00631   {"not",       0x00000024, 0x3e0003ff, 0x8000,     Rd_Rs_x,              do_rdrs},
00632   {"not.c",     0x00000025, 0x3e0003ff, 0x2006,     Rd_Rs_x,              do_rdrs},
00633   {"nop!",      0x0000,     0x700f,     0x00000000, NO16_OPD,               do_empty},
00634   {"not!",      0x2006,     0x700f,     0x00000025, Rd_Rs,                do16_rdrs},
00635   {"or",        0x00000022, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00636   {"or.c",      0x00000023, 0x3e0003ff, 0x2005,     Rd_Rs_Rs,             do_rdrsrs},
00637   {"ori",       0x020a0000, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
00638   {"ori.c",     0x020a0001, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
00639   {"oris",      0x0a0a0000, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
00640   {"oris.c",    0x0a0a0001, 0x3e0e0001, 0x8000,     Rd_I16,               do_rdi16},
00641   {"orri",      0x1a000000, 0x3e000001, 0x8000,     Rd_Rs_I14,            do_rdrsi14},
00642   {"orri.c",    0x1a000001, 0x3e000001, 0x8000,     Rd_Rs_I14,            do_rdrsi14},
00643   {"or!",       0x2005,     0x700f,     0x00000023, Rd_Rs,                do16_rdrs},
00644   {"pflush",    0x0000000a, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
00645   {"pop!",      0x200a,     0x700f,     0x0e000000, Rd_rvalueRs,          do16_push_pop},
00646   {"push!",     0x200e,     0x700f,     0x06000004, Rd_lvalueRs,          do16_push_pop},
00647   {"ror",       0x00000038, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00648   {"ror.c",     0x00000039, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00649   {"rorc.c",    0x0000003b, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00650   {"rol",       0x0000003c, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00651   {"rol.c",     0x0000003d, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00652   {"rolc.c",    0x0000003f, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00653   {"rori",      0x00000078, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
00654   {"rori.c",    0x00000079, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
00655   {"roric.c",   0x0000007b, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
00656   {"roli",      0x0000007c, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
00657   {"roli.c",    0x0000007d, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
00658   {"rolic.c",   0x0000007f, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
00659   {"rte",       0x0c000084, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
00660   {"sb!",       0x200f,     0x700f,     0x2e000000, Rd_lvalueRs,          do16_ldst_insn},
00661   {"sbp!",      0x7007,     0x7007,     0x2e000000, Rd_lvalueBP_I5,       do16_ldst_imm_insn},
00662   {"asw",       0x0000000e, 0x3e0003ff, 0x8000,     Rd_lvalue32Rs,        do_ldst_atomic},
00663   {"scb",       0x00000068, 0x3e0003ff, 0x8000,     Rd_lvalueRs_post4,    do_ldst_unalign},
00664   {"scw",       0x0000006a, 0x3e0003ff, 0x8000,     Rd_lvalueRs_post4,    do_ldst_unalign},
00665   {"sce",       0x0000006e, 0x3e0003ff, 0x8000,     x_lvalueRs_post4,     do_ldst_unalign},
00666   {"sdbbp",     0x00000006, 0x3e0003ff, 0x6002,     x_I5_x,               do_xi5x},
00667   {"sdbbp!",    0x6002,     0x7007,     0x00000006, Rd_I5,                do16_xi5},
00668   {"sh!",       0x200d,     0x700f,     0x2a000000, Rd_lvalueRs,          do16_ldst_insn},
00669   {"shp!",      0x7005,     0x7007,     0x2a000000, Rd_lvalueBP_I5,       do16_ldst_imm_insn},
00670   {"sleep",     0x0c0000c4, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
00671   {"sll",       0x00000030, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00672   {"sll.c",     0x00000031, 0x3e0003ff, 0x0008,     Rd_Rs_Rs,             do_rdrsrs},
00673   {"sll.s",     0x3800004e, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00674   {"slli",      0x00000070, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
00675   {"slli.c",    0x00000071, 0x3e0003ff, 0x6001,     Rd_Rs_I5,             do_rdrsi5},
00676   {"sll!",      0x0008,     0x700f,     0x00000031, Rd_Rs,                do16_rdrs},
00677   {"slli!",     0x6001,     0x7007,     0x00000071, Rd_I5,                do16_rdi5},
00678   {"srl",       0x00000034, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00679   {"srl.c",     0x00000035, 0x3e0003ff, 0x000a,     Rd_Rs_Rs,             do_rdrsrs},
00680   {"sra",       0x00000036, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00681   {"sra.c",     0x00000037, 0x3e0003ff, 0x000b,     Rd_Rs_Rs,             do_rdrsrs},
00682   {"srli",      0x00000074, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
00683   {"srli.c",    0x00000075, 0x3e0003ff, 0x6003,     Rd_Rs_I5,             do_rdrsi5},
00684   {"srai",      0x00000076, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
00685   {"srai.c",    0x00000077, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             do_rdrsi5},
00686   {"srl!",      0x000a,     0x700f,     0x00000035, Rd_Rs,                do16_rdrs},
00687   {"sra!",      0x000b,     0x700f,     0x00000037, Rd_Rs,                do16_rdrs},
00688   {"srli!",     0x6003,     0x7007,     0x00000075, Rd_Rs,                do16_rdi5},
00689   {"stc1",      0x0c00000b, 0x3e00001f, 0x8000,     Rd_lvalueRs_SI10,     do_ldst_cop},
00690   {"stc2",      0x0c000013, 0x3e00001f, 0x8000,     Rd_lvalueRs_SI10,     do_ldst_cop},
00691   {"stc3",      0x0c00001b, 0x3e00001f, 0x8000,     Rd_lvalueRs_SI10,     do_ldst_cop},
00692   {"sub",       0x00000014, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00693   {"sub.c",     0x00000015, 0x3e0003ff, 0x2001,     Rd_Rs_Rs,             do_rdrsrs},
00694   {"sub.s",     0x38000049, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00695   {"subc",      0x00000016, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00696   {"subc.c",    0x00000017, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00697   {"sub!",      0x2001,     0x700f,     0x00000015, Rd_Rs,                do16_rdrs},
00698   {"subei!",    0x6080,     0x7087,     0x02000001, Rd_I4,                do16_rdi4},
00699   {"sw!",       0x200c,     0x700f,     0x28000000, Rd_lvalueRs,          do16_ldst_insn},
00700   {"swp!",      0x7004,     0x7007,     0x28000000, Rd_lvalueBP_I5,       do16_ldst_imm_insn},
00701   {"syscall",   0x00000002, 0x3e0003ff, 0x8000,     I15,                  do_i15},
00702   {"tcs",       0x00000054, 0x3e007fff, 0x0005,     NO_OPD,               do_empty},
00703   {"tcc",       0x00000454, 0x3e007fff, 0x0105,     NO_OPD,               do_empty},
00704   {"tcnz",      0x00003854, 0x3e007fff, 0x0e05,     NO_OPD,               do_empty},
00705   {"tcs!",      0x0005,     0x7f0f,     0x00000054, NO16_OPD,             do_empty},
00706   {"tcc!",      0x0105,     0x7f0f,     0x00000454, NO16_OPD,             do_empty},
00707   {"tcnz!",     0x0e05,     0x7f0f,     0x00003854, NO16_OPD,             do_empty},
00708   {"teq",       0x00001054, 0x3e007fff, 0x0405,     NO_OPD,               do_empty},
00709   {"teq!",      0x0405,     0x7f0f,     0x00001054, NO16_OPD,             do_empty},
00710   {"tgtu",      0x00000854, 0x3e007fff, 0x0205,     NO_OPD,               do_empty},
00711   {"tgt",       0x00001854, 0x3e007fff, 0x0605,     NO_OPD,               do_empty},
00712   {"tge",       0x00002054, 0x3e007fff, 0x0805,     NO_OPD,               do_empty},
00713   {"tgtu!",     0x0205,     0x7f0f,     0x00000854, NO16_OPD,             do_empty},
00714   {"tgt!",      0x0605,     0x7f0f,     0x00001854, NO16_OPD,             do_empty},
00715   {"tge!",      0x0805,     0x7f0f,     0x00002054, NO16_OPD,             do_empty},
00716   {"tleu",      0x00000c54, 0x3e007fff, 0x0305,     NO_OPD,               do_empty},
00717   {"tle",       0x00001c54, 0x3e007fff, 0x0705,     NO_OPD,               do_empty},
00718   {"tlt",       0x00002454, 0x3e007fff, 0x0905,     NO_OPD,               do_empty},
00719   {"stlb",      0x0c000004, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
00720   {"mftlb",     0x0c000024, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
00721   {"mtptlb",    0x0c000044, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
00722   {"mtrtlb",    0x0c000064, 0x3e0003ff, 0x8000,     NO_OPD,               do_empty},
00723   {"tleu!",     0x0305,     0x7f0f,     0x00000c54, NO16_OPD,             do_empty},
00724   {"tle!",      0x0705,     0x7f0f,     0x00001c54, NO16_OPD,             do_empty},
00725   {"tlt!",      0x0905,     0x7f0f,     0x00002454, NO16_OPD,             do_empty},
00726   {"tmi",       0x00002854, 0x3e007fff, 0x0a05,     NO_OPD,               do_empty},
00727   {"tmi!",      0x0a05,     0x7f0f,     0x00002854, NO16_OPD,             do_empty},
00728   {"tne",       0x00001454, 0x3e007fff, 0x0505,     NO_OPD,               do_empty},
00729   {"tne!",      0x0505,     0x7f0f,     0x00001454, NO16_OPD,             do_empty},
00730   {"tpl",       0x00002c54, 0x3e007fff, 0x0b05,     NO_OPD,               do_empty},
00731   {"tpl!",      0x0b05,     0x7f0f,     0x00002c54, NO16_OPD,             do_empty},
00732   {"trapcs",    0x00000004, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
00733   {"trapcc",    0x00000404, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
00734   {"trapgtu",   0x00000804, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
00735   {"trapleu",   0x00000c04, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
00736   {"trapeq",    0x00001004, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
00737   {"trapne",    0x00001404, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
00738   {"trapgt",    0x00001804, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
00739   {"traple",    0x00001c04, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
00740   {"trapge",    0x00002004, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
00741   {"traplt",    0x00002404, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
00742   {"trapmi",    0x00002804, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
00743   {"trappl",    0x00002c04, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
00744   {"trapvs",    0x00003004, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
00745   {"trapvc",    0x00003404, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
00746   {"trap",      0x00003c04, 0x3e007fff, 0x8000,     x_I5_x,               do_xi5x},
00747   {"tset",      0x00003c54, 0x3e007fff, 0x0f05,     NO_OPD,               do_empty},
00748   {"tset!",     0x0f05,     0x00007f0f, 0x00003c54, NO16_OPD,             do_empty},
00749   {"tvs",       0x00003054, 0x3e007fff, 0x0c05,     NO_OPD,               do_empty},
00750   {"tvc",       0x00003454, 0x3e007fff, 0x0d05,     NO_OPD,               do_empty},
00751   {"tvs!",      0x0c05,     0x7f0f,     0x00003054, NO16_OPD,             do_empty},
00752   {"tvc!",      0x0d05,     0x7f0f,     0x00003454, NO16_OPD,             do_empty},
00753   {"xor",       0x00000026, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             do_rdrsrs},
00754   {"xor.c",     0x00000027, 0x3e0003ff, 0x2007,     Rd_Rs_Rs,             do_rdrsrs},
00755   {"xor!",      0x2007,     0x700f,     0x00000027, Rd_Rs,                do16_rdrs},
00756   /* Macro instruction.  */
00757   {"li",        0x020c0000, 0x3e0e0000, 0x8000,     Insn_Type_SYN,        do_macro_li_rdi32},
00758   /* la reg, imm32        -->(1)  ldi  reg, simm16
00759                              (2)  ldis reg, %HI(imm32)        
00760                                   ori  reg, %LO(imm32) 
00761           
00762      la reg, symbol       -->(1)  lis  reg, %HI(imm32)
00763                                   ori  reg, %LO(imm32)  */
00764   {"la",        0x020c0000, 0x3e0e0000, 0x8000,     Insn_Type_SYN,        do_macro_la_rdi32},
00765   {"div",       0x00000044, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
00766   {"divu",      0x00000046, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
00767   {"rem",       0x00000044, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
00768   {"remu",      0x00000046, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
00769   {"mul",       0x00000040, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
00770   {"mulu",      0x00000042, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
00771   {"maz",       0x00000040, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
00772   {"mazu",      0x00000042, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
00773   {"mul.f",     0x00000041, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
00774   {"maz.f",     0x00000041, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        do_macro_mul_rdrsrs},
00775   {"lb",        INSN_LB,    0x00000000, 0x8000,     Insn_Type_SYN,        do_macro_ldst_label},
00776   {"lbu",       INSN_LBU,   0x00000000, 0x200b,     Insn_Type_SYN,        do_macro_ldst_label},
00777   {"lh",        INSN_LH,    0x00000000, 0x2009,     Insn_Type_SYN,        do_macro_ldst_label},
00778   {"lhu",       INSN_LHU,   0x00000000, 0x8000,     Insn_Type_SYN,        do_macro_ldst_label},
00779   {"lw",        INSN_LW,    0x00000000, 0x2008,     Insn_Type_SYN,        do_macro_ldst_label},
00780   {"sb",        INSN_SB,    0x00000000, 0x200f,     Insn_Type_SYN,        do_macro_ldst_label},
00781   {"sh",        INSN_SH,    0x00000000, 0x200d,     Insn_Type_SYN,        do_macro_ldst_label},
00782   {"sw",        INSN_SW,    0x00000000, 0x200c,     Insn_Type_SYN,        do_macro_ldst_label},
00783   /* Assembler use internal.  */
00784   {"ld_i32hi",  0x0a0c0000, 0x3e0e0000, 0x8000,     Insn_internal, do_macro_rdi32hi},
00785   {"ld_i32lo",  0x020a0000, 0x3e0e0001, 0x8000,     Insn_internal, do_macro_rdi32lo},
00786   {"ldis_pic",  0x0a0c0000, 0x3e0e0000, 0x5000,     Insn_internal, do_rdi16_pic},
00787   {"addi_s_pic",0x02000000, 0x3e0e0001, 0x8000,     Insn_internal, do_addi_s_pic},
00788   {"addi_u_pic",0x02000000, 0x3e0e0001, 0x8000,     Insn_internal, do_addi_u_pic},
00789   {"lw_pic",    0x20000000, 0x3e000000, 0x8000,     Insn_internal, do_lw_pic},
00790 };
00791 
00792 /* Next free entry in the pool.  */
00793 int next_literal_pool_place = 0;
00794 
00795 /* Next literal pool number.  */
00796 int lit_pool_num = 1;
00797 symbolS *current_poolP = NULL;
00798 
00799 static int
00800 end_of_line (char *str)
00801 {
00802   int retval = SUCCESS;
00803 
00804   skip_whitespace (str);
00805   if (*str != '\0')
00806     {
00807       retval = (int) FAIL;
00808 
00809       if (!inst.error)
00810         inst.error = BAD_GARBAGE;
00811     }
00812 
00813   return retval;
00814 }
00815 
00816 static int
00817 score_reg_parse (char **ccp, struct hash_control *htab)
00818 {
00819   char *start = *ccp;
00820   char c;
00821   char *p;
00822   struct reg_entry *reg;
00823 
00824   p = start;
00825   if (!ISALPHA (*p) || !is_name_beginner (*p))
00826     return (int) FAIL;
00827 
00828   c = *p++;
00829 
00830   while (ISALPHA (c) || ISDIGIT (c) || c == '_')
00831     c = *p++;
00832 
00833   *--p = 0;
00834   reg = (struct reg_entry *) hash_find (htab, start);
00835   *p = c;
00836 
00837   if (reg)
00838     {
00839       *ccp = p;
00840       return reg->number;
00841     }
00842   return (int) FAIL;
00843 }
00844 
00845 /* If shift <= 0, only return reg.  */
00846 
00847 static int
00848 reg_required_here (char **str, int shift, enum score_reg_type reg_type)
00849 {
00850   static char buff[MAX_LITERAL_POOL_SIZE];
00851   int reg = (int) FAIL;
00852   char *start = *str;
00853 
00854   if ((reg = score_reg_parse (str, all_reg_maps[reg_type].htab)) != (int) FAIL)
00855     {
00856       if (reg_type == REG_TYPE_SCORE)
00857         {
00858           if ((reg == 1) && (nor1 == 1) && (inst.bwarn == 0))
00859             {
00860               as_warn (_("Using temp register(r1)"));
00861               inst.bwarn = 1;
00862             }
00863         }
00864       if (shift >= 0)
00865        {
00866           if (reg_type == REG_TYPE_SCORE_CR)
00867            strcpy (inst.reg, score_crn_table[reg].name);
00868           else if (reg_type == REG_TYPE_SCORE_SR)
00869            strcpy (inst.reg, score_srn_table[reg].name);
00870           else
00871            strcpy (inst.reg, "");
00872 
00873           inst.instruction |= reg << shift;
00874        }
00875     }
00876   else
00877     {
00878       *str = start;
00879       sprintf (buff, _("register expected, not '%.100s'"), start);
00880       inst.error = buff;
00881     }
00882 
00883   return reg;
00884 }
00885 
00886 static int
00887 skip_past_comma (char **str)
00888 {
00889   char *p = *str;
00890   char c;
00891   int comma = 0;
00892 
00893   while ((c = *p) == ' ' || c == ',')
00894     {
00895       p++;
00896       if (c == ',' && comma++)
00897         {
00898           inst.error = BAD_SKIP_COMMA;
00899           return (int) FAIL;
00900         }
00901     }
00902 
00903   if ((c == '\0') || (comma == 0))
00904     {
00905       inst.error = BAD_SKIP_COMMA;
00906       return (int) FAIL;
00907     }
00908 
00909   *str = p;
00910   return comma ? SUCCESS : (int) FAIL;
00911 }
00912 
00913 static void
00914 do_rdrsrs (char *str)
00915 {
00916   skip_whitespace (str);
00917 
00918   if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
00919       || skip_past_comma (&str) == (int) FAIL
00920       || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
00921       || skip_past_comma (&str) == (int) FAIL
00922       || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
00923       || end_of_line (str) == (int) FAIL)
00924     {
00925       return;
00926     }
00927   else
00928     {
00929       if ((((inst.instruction >> 15) & 0x10) == 0)
00930           && (((inst.instruction >> 10) & 0x10) == 0)
00931           && (((inst.instruction >> 20) & 0x10) == 0)
00932           && (inst.relax_inst != 0x8000)
00933           && (((inst.instruction >> 20) & 0xf) == ((inst.instruction >> 15) & 0xf)))
00934         {
00935           inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4)
00936             | (((inst.instruction >> 15) & 0xf) << 8);
00937           inst.relax_size = 2;
00938         }
00939       else
00940         {
00941           inst.relax_inst = 0x8000;
00942         }
00943     }
00944 }
00945 
00946 static int
00947 walk_no_bignums (symbolS * sp)
00948 {
00949   if (symbol_get_value_expression (sp)->X_op == O_big)
00950     return 1;
00951 
00952   if (symbol_get_value_expression (sp)->X_add_symbol)
00953     return (walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
00954            || (symbol_get_value_expression (sp)->X_op_symbol
00955               && walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));  
00956 
00957   return 0;
00958 }
00959 
00960 static int
00961 my_get_expression (expressionS * ep, char **str)
00962 {
00963   char *save_in;
00964   segT seg;
00965 
00966   save_in = input_line_pointer;
00967   input_line_pointer = *str;
00968   in_my_get_expression = 1;
00969   seg = expression (ep);
00970   in_my_get_expression = 0;
00971 
00972   if (ep->X_op == O_illegal)
00973     {
00974       *str = input_line_pointer;
00975       input_line_pointer = save_in;
00976       inst.error = _("illegal expression");
00977       return (int) FAIL;
00978     }
00979   /* Get rid of any bignums now, so that we don't generate an error for which
00980      we can't establish a line number later on.  Big numbers are never valid
00981      in instructions, which is where this routine is always called.  */
00982   if (ep->X_op == O_big
00983       || (ep->X_add_symbol
00984           && (walk_no_bignums (ep->X_add_symbol)
00985               || (ep->X_op_symbol && walk_no_bignums (ep->X_op_symbol)))))
00986     {
00987       inst.error = _("invalid constant");
00988       *str = input_line_pointer;
00989       input_line_pointer = save_in;
00990       return (int) FAIL;
00991     }
00992 
00993   if ((ep->X_add_symbol != NULL)
00994       && (inst.type != PC_DISP19div2)
00995       && (inst.type != PC_DISP8div2)
00996       && (inst.type != PC_DISP24div2)
00997       && (inst.type != PC_DISP11div2)
00998       && (inst.type != Insn_Type_SYN)
00999       && (inst.type != Rd_rvalueRs_SI15)
01000       && (inst.type != Rd_lvalueRs_SI15)
01001       && (inst.type != Insn_internal))
01002     {
01003       inst.error = BAD_ARGS;
01004       *str = input_line_pointer;
01005       input_line_pointer = save_in;
01006       return (int) FAIL;
01007     }
01008 
01009   *str = input_line_pointer;
01010   input_line_pointer = save_in;
01011   return SUCCESS;
01012 }
01013 
01014 /* Check if an immediate is valid.  If so, convert it to the right format.  */
01015 
01016 static int
01017 validate_immediate (int val, unsigned int data_type)
01018 {
01019   switch (data_type)
01020     {
01021     case _VALUE_HI16:
01022       {
01023         int val_hi = ((val & 0xffff0000) >> 16);
01024 
01025         if (score_df_range[data_type].range[0] <= val_hi
01026             && val_hi <= score_df_range[data_type].range[1])
01027          return val_hi;
01028       }
01029       break;
01030 
01031     case _VALUE_LO16:
01032       {
01033         int val_lo = (val & 0xffff);
01034 
01035         if (score_df_range[data_type].range[0] <= val_lo
01036             && val_lo <= score_df_range[data_type].range[1])
01037          return val_lo;
01038       }
01039       break;
01040 
01041     case _VALUE:
01042       return val;
01043       break;
01044 
01045     default:
01046       if (data_type == _SIMM14_NEG || data_type == _SIMM16_NEG || data_type == _IMM16_NEG)
01047        val = -val;
01048 
01049       if (score_df_range[data_type].range[0] <= val
01050           && val <= score_df_range[data_type].range[1])
01051        return val;
01052 
01053       break;
01054     }
01055 
01056   return (int) FAIL;
01057 }
01058 
01059 static int
01060 data_op2 (char **str, int shift, enum score_data_type data_type)
01061 {
01062   int value;
01063   char data_exp[MAX_LITERAL_POOL_SIZE];
01064   char *dataptr;
01065   int cnt = 0;
01066   char *pp = NULL;
01067 
01068   skip_whitespace (*str);
01069   inst.error = NULL;
01070   dataptr = * str;
01071 
01072   while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= MAX_LITERAL_POOL_SIZE))     /* 0x7c = ='|' */
01073     {
01074       data_exp[cnt] = *dataptr;
01075       dataptr++;
01076       cnt++;
01077     }
01078 
01079   data_exp[cnt] = '\0';
01080   pp = (char *)&data_exp;
01081 
01082   if (*dataptr == '|')          /* process PCE */
01083     {
01084       if (my_get_expression (&inst.reloc.exp, &pp) == (int) FAIL)
01085         return (int) FAIL;
01086       end_of_line (pp);
01087       if (inst.error != 0)
01088         return (int) FAIL;       /* to ouptut_inst to printf out the error */
01089       *str = dataptr;
01090     }
01091   else                          /* process  16 bit */
01092     {
01093       if (my_get_expression (&inst.reloc.exp, str) == (int) FAIL)
01094         {
01095           return (int) FAIL;
01096         }
01097 
01098       dataptr = (char *)data_exp;
01099       for (; *dataptr != '\0'; dataptr++)
01100         {
01101           *dataptr = TOLOWER (*dataptr);
01102           if (*dataptr == '!' || *dataptr == ' ')
01103             break;
01104         }
01105       dataptr = (char *)data_exp;
01106 
01107       if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
01108           && (data_type != _SIMM16_LA)
01109           && (data_type != _VALUE_HI16)
01110           && (data_type != _VALUE_LO16)
01111           && (data_type != _IMM16)
01112           && (data_type != _IMM15)
01113           && (data_type != _IMM14)
01114           && (data_type != _IMM4)
01115           && (data_type != _IMM5)
01116           && (data_type != _IMM8)
01117           && (data_type != _IMM5_RSHIFT_1)
01118           && (data_type != _IMM5_RSHIFT_2)
01119           && (data_type != _SIMM14_NEG)
01120           && (data_type != _IMM10_RSHIFT_2)
01121           && (data_type != _GP_IMM15))
01122         {
01123           data_type += 24;
01124         }
01125 
01126       if ((inst.reloc.exp.X_add_number == 0)
01127           && (inst.type != Insn_Type_SYN)
01128           && (inst.type != Rd_rvalueRs_SI15)
01129           && (inst.type != Rd_lvalueRs_SI15)
01130           && (inst.type != Insn_internal)
01131           && (((*dataptr >= 'a') && (*dataptr <= 'z'))
01132              || ((*dataptr == '0') && (*(dataptr + 1) == 'x') && (*(dataptr + 2) != '0'))
01133              || ((*dataptr == '+') && (*(dataptr + 1) != '0'))
01134              || ((*dataptr == '-') && (*(dataptr + 1) != '0'))))
01135         {
01136           inst.error = BAD_ARGS;
01137           return (int) FAIL;
01138         }
01139     }
01140 
01141   if ((inst.reloc.exp.X_add_symbol)
01142       && ((data_type == _SIMM16)
01143           || (data_type == _SIMM16_NEG)
01144           || (data_type == _IMM16_NEG)
01145           || (data_type == _SIMM14)
01146           || (data_type == _SIMM14_NEG)
01147           || (data_type == _IMM5)
01148           || (data_type == _IMM14)
01149           || (data_type == _IMM20)
01150           || (data_type == _IMM16)
01151           || (data_type == _IMM15)
01152           || (data_type == _IMM4)))
01153     {
01154       inst.error = BAD_ARGS;
01155       return (int) FAIL;
01156     }
01157 
01158   if (inst.reloc.exp.X_add_symbol)
01159     {
01160       switch (data_type)
01161         {
01162         case _SIMM16_LA:
01163           return (int) FAIL;
01164         case _VALUE_HI16:
01165           inst.reloc.type = BFD_RELOC_HI16_S;
01166           inst.reloc.pc_rel = 0;
01167           break;
01168         case _VALUE_LO16:
01169           inst.reloc.type = BFD_RELOC_LO16;
01170           inst.reloc.pc_rel = 0;
01171           break;
01172         case _GP_IMM15:
01173           inst.reloc.type = BFD_RELOC_SCORE_GPREL15;
01174           inst.reloc.pc_rel = 0;
01175           break;
01176         case _SIMM16_pic:
01177         case _IMM16_LO16_pic:
01178           inst.reloc.type = BFD_RELOC_SCORE_GOT_LO16;
01179           inst.reloc.pc_rel = 0;
01180           break;
01181         default:
01182           inst.reloc.type = BFD_RELOC_32;
01183           inst.reloc.pc_rel = 0;
01184           break;
01185         }
01186     }
01187   else
01188     {
01189       if (data_type == _IMM16_pic)
01190        {
01191           inst.reloc.type = BFD_RELOC_SCORE_DUMMY_HI16;
01192           inst.reloc.pc_rel = 0;
01193        }
01194 
01195       if (data_type == _SIMM16_LA && inst.reloc.exp.X_unsigned == 1)
01196         {
01197           value = validate_immediate (inst.reloc.exp.X_add_number, _SIMM16_LA_POS);
01198           if (value == (int) FAIL)       /* for advance to check if this is ldis */
01199             if ((inst.reloc.exp.X_add_number & 0xffff) == 0)
01200               {
01201                 inst.instruction |= 0x8000000;
01202                 inst.instruction |= ((inst.reloc.exp.X_add_number >> 16) << 1) & 0x1fffe;
01203                 return SUCCESS;
01204               }
01205         }
01206       else
01207         {
01208           value = validate_immediate (inst.reloc.exp.X_add_number, data_type);
01209         }
01210 
01211       if (value == (int) FAIL)
01212         {
01213           if ((data_type != _SIMM14_NEG) && (data_type != _SIMM16_NEG) && (data_type != _IMM16_NEG))
01214             {
01215               sprintf (err_msg,
01216                        _("invalid constant: %d bit expression not in range %d..%d"),
01217                        score_df_range[data_type].bits,
01218                        score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
01219             }
01220           else
01221             {
01222               sprintf (err_msg,
01223                        _("invalid constant: %d bit expression not in range %d..%d"),
01224                        score_df_range[data_type].bits,
01225                        -score_df_range[data_type].range[1], -score_df_range[data_type].range[0]);
01226             }
01227 
01228           inst.error = err_msg;
01229           return (int) FAIL;
01230         }
01231 
01232       if ((score_df_range[data_type].range[0] != 0) || (data_type == _IMM5_RANGE_8_31))
01233         {
01234           value &= (1 << score_df_range[data_type].bits) - 1;
01235         }
01236 
01237       inst.instruction |= value << shift;
01238     }
01239 
01240   if ((inst.instruction & 0xf0000000) == 0x30000000)
01241     {
01242       if ((((inst.instruction >> 20) & 0x1F) != 0)
01243           && (((inst.instruction >> 20) & 0x1F) != 1)
01244           && (((inst.instruction >> 20) & 0x1F) != 2)
01245           && (((inst.instruction >> 20) & 0x1F) != 3)
01246           && (((inst.instruction >> 20) & 0x1F) != 4)
01247           && (((inst.instruction >> 20) & 0x1F) != 8)
01248           && (((inst.instruction >> 20) & 0x1F) != 9)
01249           && (((inst.instruction >> 20) & 0x1F) != 0xa)
01250           && (((inst.instruction >> 20) & 0x1F) != 0xb)
01251           && (((inst.instruction >> 20) & 0x1F) != 0xc)
01252           && (((inst.instruction >> 20) & 0x1F) != 0xd)
01253           && (((inst.instruction >> 20) & 0x1F) != 0xe)
01254           && (((inst.instruction >> 20) & 0x1F) != 0x10)
01255           && (((inst.instruction >> 20) & 0x1F) != 0x11)
01256           && (((inst.instruction >> 20) & 0x1F) != 0x18)
01257           && (((inst.instruction >> 20) & 0x1F) != 0x1A)
01258           && (((inst.instruction >> 20) & 0x1F) != 0x1B)
01259           && (((inst.instruction >> 20) & 0x1F) != 0x1d)
01260           && (((inst.instruction >> 20) & 0x1F) != 0x1e)
01261           && (((inst.instruction >> 20) & 0x1F) != 0x1f))
01262         {
01263           inst.error = _("invalid constant: bit expression not defined");
01264           return (int) FAIL;
01265         }
01266     }
01267 
01268   return SUCCESS;
01269 }
01270 
01271 /* Handle addi/addi.c/addis.c/cmpi.c/addis.c/ldi.  */
01272 
01273 static void
01274 do_rdsi16 (char *str)
01275 {
01276   skip_whitespace (str);
01277 
01278   if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
01279       || skip_past_comma (&str) == (int) FAIL
01280       || data_op2 (&str, 1, _SIMM16) == (int) FAIL
01281       || end_of_line (str) == (int) FAIL)
01282     return;
01283 
01284   /* ldi.  */
01285   if ((inst.instruction & 0x20c0000) == 0x20c0000)
01286     {
01287       if ((((inst.instruction >> 20) & 0x10) == 0x10) || ((inst.instruction & 0x1fe00) != 0))
01288         {
01289           inst.relax_inst = 0x8000;
01290         }
01291       else
01292         {
01293           inst.relax_inst |= (inst.instruction >> 1) & 0xff;
01294           inst.relax_inst |= (((inst.instruction >> 20) & 0xf) << 8);
01295           inst.relax_size = 2;
01296         }
01297     }
01298   else if (((inst.instruction >> 20) & 0x10) == 0x10)
01299     {
01300       inst.relax_inst = 0x8000;
01301     }
01302 }
01303 
01304 /* Handle subi/subi.c.  */
01305 
01306 static void
01307 do_sub_rdsi16 (char *str)
01308 {
01309   skip_whitespace (str);
01310 
01311   if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
01312       && skip_past_comma (&str) != (int) FAIL
01313       && data_op2 (&str, 1, _SIMM16_NEG) != (int) FAIL)
01314     end_of_line (str);
01315 }
01316 
01317 /* Handle subis/subis.c.  */
01318 
01319 static void
01320 do_sub_rdi16 (char *str)
01321 {
01322   skip_whitespace (str);
01323 
01324   if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
01325       && skip_past_comma (&str) != (int) FAIL
01326       && data_op2 (&str, 1, _IMM16_NEG) != (int) FAIL)
01327     end_of_line (str);
01328 }
01329 
01330 /* Handle addri/addri.c.  */
01331 
01332 static void
01333 do_rdrssi14 (char *str)         /* -(2^13)~((2^13)-1) */
01334 {
01335   skip_whitespace (str);
01336 
01337   if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
01338       && skip_past_comma (&str) != (int) FAIL
01339       && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
01340       && skip_past_comma (&str) != (int) FAIL)
01341     data_op2 (&str, 1, _SIMM14);
01342 }
01343 
01344 /* Handle subri.c/subri.  */
01345 static void
01346 do_sub_rdrssi14 (char *str)     /* -(2^13)~((2^13)-1) */
01347 {
01348   skip_whitespace (str);
01349 
01350   if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
01351       && skip_past_comma (&str) != (int) FAIL
01352       && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
01353       && skip_past_comma (&str) != (int) FAIL
01354       && data_op2 (&str, 1, _SIMM14_NEG) != (int) FAIL)
01355     end_of_line (str);
01356 }
01357 
01358 /* Handle bitclr.c/bitset.c/bittgl.c/slli.c/srai.c/srli.c/roli.c/rori.c/rolic.c.  */
01359 static void
01360 do_rdrsi5 (char *str)           /* 0~((2^14)-1) */
01361 {
01362   skip_whitespace (str);
01363 
01364   if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
01365       || skip_past_comma (&str) == (int) FAIL
01366       || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
01367       || skip_past_comma (&str) == (int) FAIL
01368       || data_op2 (&str, 10, _IMM5) == (int) FAIL
01369       || end_of_line (str) == (int) FAIL)
01370     return;
01371 
01372   if ((((inst.instruction >> 20) & 0x1f) == ((inst.instruction >> 15) & 0x1f))
01373       && (inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
01374     {
01375       inst.relax_inst |= (((inst.instruction >> 10) & 0x1f) << 3) | (((inst.instruction >> 15) & 0xf) << 8);
01376       inst.relax_size = 2;
01377     }
01378   else
01379     inst.relax_inst = 0x8000;
01380 }
01381 
01382 /* Handle andri/orri/andri.c/orri.c.  */
01383 
01384 static void
01385 do_rdrsi14 (char *str)          /* 0 ~ ((2^14)-1)  */
01386 {
01387   skip_whitespace (str);
01388 
01389   if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
01390       && skip_past_comma (&str) != (int) FAIL
01391       && reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
01392       && skip_past_comma (&str) != (int) FAIL
01393       && data_op2 (&str, 1, _IMM14) != (int) FAIL)
01394     end_of_line (str);
01395 }
01396 
01397 /* Handle bittst.c.  */
01398 static void
01399 do_xrsi5 (char *str)
01400 {
01401   skip_whitespace (str);
01402 
01403   if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
01404       || skip_past_comma (&str) == (int) FAIL
01405       || data_op2 (&str, 10, _IMM5) == (int) FAIL
01406       || end_of_line (str) == (int) FAIL)
01407     return;
01408 
01409   if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
01410     {
01411       inst.relax_inst |= (((inst.instruction >> 10) & 0x1f) << 3) | (((inst.instruction >> 15) & 0xf) << 8);
01412       inst.relax_size = 2;
01413     }
01414   else
01415     inst.relax_inst = 0x8000;
01416 }
01417 
01418 /* Handle addis/andi/ori/andis/oris/ldis.  */
01419 static void
01420 do_rdi16 (char *str)
01421 {
01422   skip_whitespace (str);
01423 
01424   if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
01425       || skip_past_comma (&str) == (int) FAIL
01426       || data_op2 (&str, 1, _IMM16) == (int) FAIL
01427       || end_of_line (str) == (int) FAIL)
01428     return;
01429   /*
01430   if (((inst.instruction & 0xa0dfffe) != 0xa0c0000) || ((((inst.instruction >> 20) & 0x1f) & 0x10) == 0x10))
01431     inst.relax_inst = 0x8000;
01432   else
01433     inst.relax_size = 2;
01434   */
01435 }
01436 
01437 static void
01438 do_macro_rdi32hi (char *str)
01439 {
01440   skip_whitespace (str);
01441 
01442   /* Do not handle end_of_line().  */
01443   if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
01444       && skip_past_comma (&str) != (int) FAIL)
01445     data_op2 (&str, 1, _VALUE_HI16);
01446 }
01447 
01448 static void
01449 do_macro_rdi32lo (char *str)
01450 {
01451   skip_whitespace (str);
01452 
01453   /* Do not handle end_of_line().  */
01454   if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
01455       && skip_past_comma (&str) != (int) FAIL)
01456     data_op2 (&str, 1, _VALUE_LO16);
01457 }
01458 
01459 /* Handle ldis_pic.  */
01460 
01461 static void
01462 do_rdi16_pic (char *str)
01463 {
01464   skip_whitespace (str);
01465 
01466   if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
01467       && skip_past_comma (&str) != (int) FAIL
01468       && data_op2 (&str, 1, _IMM16_pic) != (int) FAIL)
01469     end_of_line (str);
01470 }
01471 
01472 /* Handle addi_s_pic to generate R_SCORE_GOT_LO16 .  */
01473 
01474 static void
01475 do_addi_s_pic (char *str)
01476 {
01477   skip_whitespace (str);
01478 
01479   if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
01480       && skip_past_comma (&str) != (int) FAIL
01481       && data_op2 (&str, 1, _SIMM16_pic) != (int) FAIL)
01482     end_of_line (str);
01483 }
01484 
01485 /* Handle addi_u_pic to generate R_SCORE_GOT_LO16 .  */
01486 
01487 static void
01488 do_addi_u_pic (char *str)
01489 {
01490   skip_whitespace (str);
01491 
01492   if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
01493       && skip_past_comma (&str) != (int) FAIL
01494       && data_op2 (&str, 1, _IMM16_LO16_pic) != (int) FAIL)
01495     end_of_line (str);
01496 }
01497 
01498 /* Handle mfceh/mfcel/mtceh/mtchl.  */
01499 
01500 static void
01501 do_rd (char *str)
01502 {
01503   skip_whitespace (str);
01504 
01505   if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL)
01506     end_of_line (str);
01507 }
01508 
01509 static void
01510 do_rs (char *str)
01511 {
01512   skip_whitespace (str);
01513 
01514   if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
01515       || end_of_line (str) == (int) FAIL)
01516     return;
01517 
01518   if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 15) & 0x10) == 0))
01519     {
01520       inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 8) | (((inst.instruction >> 15) & 0xf) << 4);
01521       inst.relax_size = 2;
01522     }
01523   else
01524     inst.relax_inst = 0x8000;
01525 }
01526 
01527 static void
01528 do_i15 (char *str)
01529 {
01530   skip_whitespace (str);
01531 
01532   if (data_op2 (&str, 10, _IMM15) != (int) FAIL)
01533     end_of_line (str);
01534 }
01535 
01536 static void
01537 do_xi5x (char *str)
01538 {
01539   skip_whitespace (str);
01540 
01541   if (data_op2 (&str, 15, _IMM5) == (int) FAIL || end_of_line (str) == (int) FAIL)
01542     return;
01543 
01544   if (inst.relax_inst != 0x8000)
01545     {
01546       inst.relax_inst |= (((inst.instruction >> 15) & 0x1f) << 3);
01547       inst.relax_size = 2;
01548     }
01549 }
01550 
01551 static void
01552 do_rdrs (char *str)
01553 {
01554   skip_whitespace (str);
01555 
01556   if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
01557       || skip_past_comma (&str) == (int) FAIL
01558       || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
01559       || end_of_line (str) == (int) FAIL)
01560     return;
01561 
01562   if (inst.relax_inst != 0x8000)
01563     {
01564       if (((inst.instruction & 0x7f) == 0x56))  /* adjust mv -> mv! / mlfh! / mhfl! */
01565         {
01566           /* mlfh */
01567           if ((((inst.instruction >> 15) & 0x10) != 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
01568             {
01569               inst.relax_inst = 0x00000001 | (((inst.instruction >> 15) & 0xf) << 4)
01570                 | (((inst.instruction >> 20) & 0xf) << 8);
01571               inst.relax_size = 2;
01572             }
01573           /* mhfl */
01574           else if ((((inst.instruction >> 15) & 0x10) == 0x0) && ((inst.instruction >> 20) & 0x10) != 0)
01575             {
01576               inst.relax_inst = 0x00000002 | (((inst.instruction >> 15) & 0xf) << 4)
01577                 | (((inst.instruction >> 20) & 0xf) << 8);
01578               inst.relax_size = 2;
01579             }
01580           else if ((((inst.instruction >> 15) & 0x10) == 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
01581             {
01582               inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
01583                 | (((inst.instruction >> 20) & 0xf) << 8);
01584               inst.relax_size = 2;
01585             }
01586           else
01587             {
01588               inst.relax_inst = 0x8000;
01589             }
01590         }
01591       else if ((((inst.instruction >> 15) & 0x10) == 0x0) && (((inst.instruction >> 20) & 0x10) == 0))
01592         {
01593           inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
01594             | (((inst.instruction >> 20) & 0xf) << 8);
01595           inst.relax_size = 2;
01596         }
01597       else
01598         {
01599           inst.relax_inst = 0x8000;
01600         }
01601     }
01602 }
01603 
01604 /* Handle mfcr/mtcr.  */
01605 static void
01606 do_rdcrs (char *str)
01607 {
01608   skip_whitespace (str);
01609 
01610   if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
01611       && skip_past_comma (&str) != (int) FAIL
01612       && reg_required_here (&str, 15, REG_TYPE_SCORE_CR) != (int) FAIL)
01613     end_of_line (str);
01614 }
01615 
01616 /* Handle mfsr/mtsr.  */
01617 
01618 static void
01619 do_rdsrs (char *str)
01620 {
01621   skip_whitespace (str);
01622 
01623   /* mfsr */
01624   if ((inst.instruction & 0xff) == 0x50)
01625     {
01626       if (reg_required_here (&str, 20, REG_TYPE_SCORE) != (int) FAIL
01627           && skip_past_comma (&str) != (int) FAIL
01628           && reg_required_here (&str, 10, REG_TYPE_SCORE_SR) != (int) FAIL)
01629        end_of_line (str);
01630     }
01631   else
01632     {
01633       if (reg_required_here (&str, 15, REG_TYPE_SCORE) != (int) FAIL
01634           && skip_past_comma (&str) != (int) FAIL)
01635        reg_required_here (&str, 10, REG_TYPE_SCORE_SR);
01636     }
01637 }
01638 
01639 /* Handle neg.  */
01640 
01641 static void
01642 do_rdxrs (char *str)
01643 {
01644   skip_whitespace (str);
01645 
01646   if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL
01647       || skip_past_comma (&str) == (int) FAIL
01648       || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
01649       || end_of_line (str) == (int) FAIL)
01650     return;
01651 
01652   if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 10) & 0x10) == 0)
01653       && (((inst.instruction >> 20) & 0x10) == 0))
01654     {
01655       inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) | (((inst.instruction >> 20) & 0xf) << 8);
01656       inst.relax_size = 2;
01657     }
01658   else
01659     inst.relax_inst = 0x8000;
01660 }
01661 
01662 /* Handle cmp.c/cmp<cond>.  */
01663 static void
01664 do_rsrs (char *str)
01665 {
01666   skip_whitespace (str);
01667 
01668   if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
01669       || skip_past_comma (&str) == (int) FAIL
01670       || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
01671       || end_of_line (str) == (int) FAIL)
01672     return;
01673 
01674   if ((inst.relax_inst != 0x8000) && (((inst.instruction >> 20) & 0x1f) == 3)
01675       && (((inst.instruction >> 10) & 0x10) == 0) && (((inst.instruction >> 15) & 0x10) == 0))
01676     {
01677       inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 4) | (((inst.instruction >> 15) & 0xf) << 8);
01678       inst.relax_size = 2;
01679     }
01680   else
01681     inst.relax_inst = 0x8000;
01682 }
01683 
01684 static void
01685 do_ceinst (char *str)
01686 {
01687   char *strbak;
01688 
01689   strbak = str;
01690   skip_whitespace (str);
01691 
01692   if (data_op2 (&str, 20, _IMM5) == (int) FAIL
01693       || skip_past_comma (&str) == (int) FAIL
01694       || reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL
01695       || skip_past_comma (&str) == (int) FAIL
01696       || reg_required_here (&str, 10, REG_TYPE_SCORE) == (int) FAIL
01697       || skip_past_comma (&str) == (int) FAIL
01698       || data_op2 (&str, 5, _IMM5) == (int) FAIL
01699       || skip_past_comma (&str) == (int) FAIL
01700       || data_op2 (&str, 0, _IMM5) == (int) FAIL
01701       || end_of_line (str) == (int) FAIL)
01702     {
01703       return;
01704     }
01705   else
01706     {
01707       str = strbak;
01708       if (data_op2 (&str, 0, _IMM25) == (int) FAIL)
01709        return;
01710     }
01711 }
01712 
01713 static int
01714 reglow_required_here (char **str, int shift)
01715 {
01716   static char buff[MAX_LITERAL_POOL_SIZE];
01717   int reg;
01718   char *start = *str;
01719 
01720   if ((reg = score_reg_parse (str, all_reg_maps[REG_TYPE_SCORE].htab)) != (int) FAIL)
01721     {
01722       if ((reg == 1) && (nor1 == 1) && (inst.bwarn == 0))
01723         {
01724           as_warn (_("Using temp register(r1)"));
01725           inst.bwarn = 1;
01726         }
01727       if (reg < 16)
01728         {
01729           if (shift >= 0)
01730             inst.instruction |= reg << shift;
01731 
01732           return reg;
01733         }
01734     }
01735 
01736   /* Restore the start point, we may have got a reg of the wrong class.  */
01737   *str = start;
01738   sprintf (buff, _("low register(r0-r15)expected, not '%.100s'"), start);
01739   inst.error = buff;
01740   return (int) FAIL;
01741 }
01742 
01743 /* Handle addc!/add!/and!/cmp!/neg!/not!/or!/sll!/srl!/sra!/xor!/sub!.  */
01744 static void
01745 do16_rdrs (char *str)
01746 {
01747   skip_whitespace (str);
01748 
01749   if (reglow_required_here (&str, 8) == (int) FAIL
01750       || skip_past_comma (&str) == (int) FAIL
01751       || reglow_required_here (&str, 4) == (int) FAIL
01752       || end_of_line (str) == (int) FAIL)
01753     {
01754       return;
01755     }
01756   else
01757     {
01758       if ((inst.instruction & 0x700f) == 0x2003)        /* cmp!  */
01759         {
01760           inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 15)
01761             | (((inst.instruction >> 4) & 0xf) << 10);
01762         }
01763       else if ((inst.instruction & 0x700f) == 0x2006)   /* not!  */
01764        {
01765          inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
01766            | (((inst.instruction >> 4) & 0xf) << 15);
01767        }
01768       else
01769         {
01770           inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
01771             | (((inst.instruction >> 8) & 0xf) << 15) | (((inst.instruction >> 4) & 0xf) << 10);
01772         }
01773       inst.relax_size = 4;
01774     }
01775 }
01776 
01777 static void
01778 do16_rs (char *str)
01779 {
01780   int rd = 0;
01781 
01782   skip_whitespace (str);
01783 
01784   if ((rd = reglow_required_here (&str, 4)) == (int) FAIL
01785       || end_of_line (str) == (int) FAIL)
01786     {
01787       return;
01788     }
01789   else
01790     {
01791       inst.relax_inst |= rd << 20;
01792       inst.relax_size = 4;
01793     }
01794 }
01795 
01796 /* Handle br!/brl!.  */
01797 static void
01798 do16_xrs (char *str)
01799 {
01800   skip_whitespace (str);
01801 
01802   if (reglow_required_here (&str, 4) == (int) FAIL || end_of_line (str) == (int) FAIL)
01803     {
01804       return;
01805     }
01806   else
01807     {
01808       inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 10)
01809                       | (((inst.instruction >> 4) & 0xf) << 15);
01810       inst.relax_size = 4;
01811     }
01812 }
01813 
01814 static int
01815 reghigh_required_here (char **str, int shift)
01816 {
01817   static char buff[MAX_LITERAL_POOL_SIZE];
01818   int reg;
01819   char *start = *str;
01820 
01821   if ((reg = score_reg_parse (str, all_reg_maps[REG_TYPE_SCORE].htab)) != (int) FAIL)
01822     {
01823       if (15 < reg && reg < 32)
01824         {
01825           if (shift >= 0)
01826             inst.instruction |= (reg & 0xf) << shift;
01827 
01828           return reg;
01829         }
01830     }
01831 
01832   *str = start;
01833   sprintf (buff, _("high register(r16-r31)expected, not '%.100s'"), start);
01834   inst.error = buff;
01835   return (int) FAIL;
01836 }
01837 
01838 /* Handle mhfl!.  */
01839 static void
01840 do16_hrdrs (char *str)
01841 {
01842   skip_whitespace (str);
01843 
01844   if (reghigh_required_here (&str, 8) != (int) FAIL
01845       && skip_past_comma (&str) != (int) FAIL
01846       && reglow_required_here (&str, 4) != (int) FAIL
01847       && end_of_line (str) != (int) FAIL)
01848     {
01849       inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
01850         | (((inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
01851       inst.relax_size = 4;
01852     }
01853 }
01854 
01855 /* Handle mlfh!.  */
01856 static void
01857 do16_rdhrs (char *str)
01858 {
01859   skip_whitespace (str);
01860 
01861   if (reglow_required_here (&str, 8) != (int) FAIL
01862       && skip_past_comma (&str) != (int) FAIL
01863       && reghigh_required_here (&str, 4) != (int) FAIL
01864       && end_of_line (str) != (int) FAIL)
01865     {
01866       inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
01867         | ((((inst.instruction >> 4) & 0xf) | 0x10) << 15) | (0xf << 10);
01868       inst.relax_size = 4;
01869     }
01870 }
01871 
01872 /* We need to be able to fix up arbitrary expressions in some statements.
01873    This is so that we can handle symbols that are an arbitrary distance from
01874    the pc.  The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
01875    which returns part of an address in a form which will be valid for
01876    a data instruction.  We do this by pushing the expression into a symbol
01877    in the expr_section, and creating a fix for that.  */
01878 static fixS *
01879 fix_new_score (fragS * frag, int where, short int size, expressionS * exp, int pc_rel, int reloc)
01880 {
01881   fixS *new_fix;
01882 
01883   switch (exp->X_op)
01884     {
01885     case O_constant:
01886     case O_symbol:
01887     case O_add:
01888     case O_subtract:
01889       new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
01890       break;
01891     default:
01892       new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0, pc_rel, reloc);
01893       break;
01894     }
01895   return new_fix;
01896 }
01897 
01898 static void
01899 init_dependency_vector (void)
01900 {
01901   int i;
01902 
01903   for (i = 0; i < vector_size; i++)
01904     memset (&dependency_vector[i], '\0', sizeof (dependency_vector[i]));
01905 
01906   return;
01907 }
01908 
01909 static enum insn_type_for_dependency
01910 dependency_type_from_insn (char *insn_name)
01911 {
01912   char name[INSN_NAME_LEN];
01913   const struct insn_to_dependency *tmp;
01914 
01915   strcpy (name, insn_name);
01916   tmp = (const struct insn_to_dependency *) hash_find (dependency_insn_hsh, name);
01917 
01918   if (tmp)
01919     return tmp->type;
01920 
01921   return D_all_insn;
01922 }
01923 
01924 static int
01925 check_dependency (char *pre_insn, char *pre_reg,
01926                   char *cur_insn, char *cur_reg, int *warn_or_error)
01927 {
01928   int bubbles = 0;
01929   unsigned int i;
01930   enum insn_type_for_dependency pre_insn_type;
01931   enum insn_type_for_dependency cur_insn_type;
01932 
01933   pre_insn_type = dependency_type_from_insn (pre_insn);
01934   cur_insn_type = dependency_type_from_insn (cur_insn);
01935 
01936   for (i = 0; i < sizeof (data_dependency_table) / sizeof (data_dependency_table[0]); i++)
01937     {
01938       if ((pre_insn_type == data_dependency_table[i].pre_insn_type)
01939           && (D_all_insn == data_dependency_table[i].cur_insn_type
01940               || cur_insn_type == data_dependency_table[i].cur_insn_type)
01941           && (strcmp (data_dependency_table[i].pre_reg, "") == 0
01942               || strcmp (data_dependency_table[i].pre_reg, pre_reg) == 0)
01943           && (strcmp (data_dependency_table[i].cur_reg, "") == 0
01944               || strcmp (data_dependency_table[i].cur_reg, cur_reg) == 0))
01945         {
01946           bubbles = (score7) ? data_dependency_table[i].bubblenum_7 : data_dependency_table[i].bubblenum_5;
01947           *warn_or_error = data_dependency_table[i].warn_or_error;
01948           break;
01949         }
01950     }
01951 
01952   return bubbles;
01953 }
01954 
01955 static void
01956 build_one_frag (struct score_it one_inst)
01957 {
01958   char *p;
01959   int relaxable_p = g_opt;
01960   int relax_size = 0;
01961 
01962   /* Start a new frag if frag_now is not empty.  */
01963   if (frag_now_fix () != 0)
01964     {
01965       if (!frag_now->tc_frag_data.is_insn)
01966        frag_wane (frag_now);
01967 
01968       frag_new (0);
01969     }
01970   frag_grow (20);
01971 
01972   p = frag_more (one_inst.size);
01973   md_number_to_chars (p, one_inst.instruction, one_inst.size);
01974 
01975 #ifdef OBJ_ELF
01976   dwarf2_emit_insn (one_inst.size);
01977 #endif
01978 
01979   relaxable_p &= (one_inst.relax_size != 0);
01980   relax_size = relaxable_p ? one_inst.relax_size : 0;
01981 
01982   p = frag_var (rs_machine_dependent, relax_size + RELAX_PAD_BYTE, 0,
01983                 RELAX_ENCODE (one_inst.size, one_inst.relax_size,
01984                               one_inst.type, 0, 0, relaxable_p),
01985                 NULL, 0, NULL);
01986 
01987   if (relaxable_p)
01988     md_number_to_chars (p, one_inst.relax_inst, relax_size);
01989 }
01990 
01991 static void
01992 handle_dependency (struct score_it *theinst)
01993 {
01994   int i;
01995   int warn_or_error = 0;   /* warn - 0; error - 1  */
01996   int bubbles = 0;
01997   int remainder_bubbles = 0;
01998   char cur_insn[INSN_NAME_LEN];
01999   char pre_insn[INSN_NAME_LEN];
02000   struct score_it nop_inst;
02001   struct score_it pflush_inst;
02002 
02003   nop_inst.instruction = 0x0000;
02004   nop_inst.size = 2;
02005   nop_inst.relax_inst = 0x80008000;
02006   nop_inst.relax_size = 4;
02007   nop_inst.type = NO16_OPD;
02008 
02009   pflush_inst.instruction = 0x8000800a;
02010   pflush_inst.size = 4;
02011   pflush_inst.relax_inst = 0x8000;
02012   pflush_inst.relax_size = 0;
02013   pflush_inst.type = NO_OPD;
02014 
02015   /* pflush will clear all data dependency.  */
02016   if (strcmp (theinst->name, "pflush") == 0)
02017     {
02018       init_dependency_vector ();
02019       return;
02020     }
02021 
02022   /* Push current instruction to dependency_vector[0].  */
02023   for (i = vector_size - 1; i > 0; i--)
02024     memcpy (&dependency_vector[i], &dependency_vector[i - 1], sizeof (dependency_vector[i]));
02025 
02026   memcpy (&dependency_vector[0], theinst, sizeof (dependency_vector[i]));
02027 
02028   /* There is no dependency between nop and any instruction.  */
02029   if (strcmp (dependency_vector[0].name, "nop") == 0
02030       || strcmp (dependency_vector[0].name, "nop!") == 0)
02031     return;
02032 
02033   /* "pce" is defined in insn_to_dependency_table.  */
02034 #define PCE_NAME "pce"
02035 
02036   if (dependency_vector[0].type == Insn_Type_PCE)
02037     strcpy (cur_insn, PCE_NAME);
02038   else
02039     strcpy (cur_insn, dependency_vector[0].name);
02040 
02041   for (i = 1; i < vector_size; i++)
02042     {
02043       /* The element of dependency_vector is NULL.  */
02044       if (dependency_vector[i].name[0] == '\0')
02045        continue;
02046 
02047       if (dependency_vector[i].type == Insn_Type_PCE)
02048        strcpy (pre_insn, PCE_NAME);
02049       else
02050        strcpy (pre_insn, dependency_vector[i].name);
02051 
02052       bubbles = check_dependency (pre_insn, dependency_vector[i].reg,
02053                                   cur_insn, dependency_vector[0].reg, &warn_or_error);
02054       remainder_bubbles = bubbles - i + 1;
02055 
02056       if (remainder_bubbles > 0)
02057         {
02058           int j;
02059 
02060           if (fix_data_dependency == 1)
02061             {
02062              if (remainder_bubbles <= 2)
02063               {
02064                 if (warn_fix_data_dependency)
02065                   as_warn (_("Fix data dependency: %s %s -- %s %s  (insert %d nop!/%d)"),
02066                           dependency_vector[i].name, dependency_vector[i].reg,
02067                           dependency_vector[0].name, dependency_vector[0].reg,
02068                           remainder_bubbles, bubbles);
02069 
02070                   for (j = (vector_size - 1); (j - remainder_bubbles) > 0; j--)
02071                   memcpy (&dependency_vector[j], &dependency_vector[j - remainder_bubbles],
02072                          sizeof (dependency_vector[j]));
02073 
02074                   for (j = 1; j <= remainder_bubbles; j++)
02075                     {
02076                       memset (&dependency_vector[j], '\0', sizeof (dependency_vector[j]));
02077                     /* Insert nop!.  */
02078                     build_one_frag (nop_inst);
02079                     }
02080               }
02081              else
02082               {
02083                 if (warn_fix_data_dependency)
02084                   as_warn (_("Fix data dependency: %s %s -- %s %s  (insert 1 pflush/%d)"),
02085                           dependency_vector[i].name, dependency_vector[i].reg,
02086                           dependency_vector[0].name, dependency_vector[0].reg,
02087                           bubbles);
02088 
02089                   for (j = 1; j < vector_size; j++)
02090                   memset (&dependency_vector[j], '\0', sizeof (dependency_vector[j]));
02091 
02092                   /* Insert pflush.  */
02093                   build_one_frag (pflush_inst);
02094               }
02095             }
02096           else
02097             {
02098              if (warn_or_error)
02099               {
02100                   as_bad (_("data dependency: %s %s -- %s %s  (%d/%d bubble)"),
02101                            dependency_vector[i].name, dependency_vector[i].reg,
02102                            dependency_vector[0].name, dependency_vector[0].reg,
02103                            remainder_bubbles, bubbles);
02104               }
02105              else
02106               {
02107                   as_warn (_("data dependency: %s %s -- %s %s  (%d/%d bubble)"),
02108                            dependency_vector[i].name, dependency_vector[i].reg,
02109                            dependency_vector[0].name, dependency_vector[0].reg,
02110                            remainder_bubbles, bubbles);
02111               }
02112             }
02113         }
02114     }
02115 }
02116 
02117 static enum insn_class
02118 get_insn_class_from_type (enum score_insn_type type)
02119 {
02120   enum insn_class retval = (int) FAIL;
02121 
02122   switch (type)
02123     {
02124     case Rd_I4:
02125     case Rd_I5:
02126     case Rd_rvalueBP_I5:
02127     case Rd_lvalueBP_I5:
02128     case Rd_I8:
02129     case PC_DISP8div2:
02130     case PC_DISP11div2:
02131     case Rd_Rs:
02132     case Rd_HighRs:
02133     case Rd_lvalueRs:
02134     case Rd_rvalueRs:
02135     case x_Rs:
02136     case Rd_LowRs:
02137     case NO16_OPD:
02138       retval = INSN_CLASS_16;
02139       break;
02140     case Rd_Rs_I5:
02141     case x_Rs_I5:
02142     case x_I5_x:
02143     case Rd_Rs_I14:
02144     case I15:
02145     case Rd_I16:
02146     case Rd_SI16:
02147     case Rd_rvalueRs_SI10:
02148     case Rd_lvalueRs_SI10:
02149     case Rd_rvalueRs_preSI12:
02150     case Rd_rvalueRs_postSI12:
02151     case Rd_lvalueRs_preSI12:
02152     case Rd_lvalueRs_postSI12:
02153     case Rd_Rs_SI14:
02154     case Rd_rvalueRs_SI15:
02155     case Rd_lvalueRs_SI15:
02156     case PC_DISP19div2:
02157     case PC_DISP24div2:
02158     case Rd_Rs_Rs:
02159     case x_Rs_x:
02160     case x_Rs_Rs:
02161     case Rd_Rs_x:
02162     case Rd_x_Rs:
02163     case Rd_x_x:
02164     case OP5_rvalueRs_SI15:
02165     case I5_Rs_Rs_I5_OP5:
02166     case x_rvalueRs_post4:
02167     case Rd_rvalueRs_post4:
02168     case Rd_x_I5:
02169     case Rd_lvalueRs_post4:
02170     case x_lvalueRs_post4:
02171     case Rd_Rs_Rs_imm:
02172     case NO_OPD:
02173     case Rd_lvalue32Rs:
02174     case Rd_rvalue32Rs:
02175     case Insn_GP:
02176     case Insn_PIC:
02177     case Insn_internal:
02178       retval = INSN_CLASS_32;
02179       break;
02180     case Insn_Type_PCE:
02181       retval = INSN_CLASS_PCE;
02182       break;
02183     case Insn_Type_SYN:
02184       retval = INSN_CLASS_SYN;
02185       break;
02186     default:
02187       abort ();
02188       break;
02189     }
02190   return retval;
02191 }
02192 
02193 static unsigned long
02194 adjust_paritybit (unsigned long m_code, enum insn_class class)
02195 {
02196   unsigned long result = 0;
02197   unsigned long m_code_high = 0;
02198   unsigned long m_code_low = 0;
02199   unsigned long pb_high = 0;
02200   unsigned long pb_low = 0;
02201 
02202   if (class == INSN_CLASS_32)
02203     {
02204       pb_high = 0x80000000;
02205       pb_low = 0x00008000;
02206     }
02207   else if (class == INSN_CLASS_16)
02208     {
02209       pb_high = 0;
02210       pb_low = 0;
02211     }
02212   else if (class == INSN_CLASS_PCE)
02213     {
02214       pb_high = 0;
02215       pb_low = 0x00008000;
02216     }
02217   else if (class == INSN_CLASS_SYN)
02218     {
02219       /* FIXME.  at this time, INSN_CLASS_SYN must be 32 bit, but, instruction type should
02220          be changed if macro instruction has been expanded.  */
02221       pb_high = 0x80000000;
02222       pb_low = 0x00008000;
02223     }
02224   else
02225     {
02226       abort ();
02227     }
02228 
02229   m_code_high = m_code & 0x3fff8000;
02230   m_code_low = m_code & 0x00007fff;
02231   result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
02232   return result;
02233 
02234 }
02235 
02236 static void
02237 gen_insn_frag (struct score_it *part_1, struct score_it *part_2)
02238 {
02239   char *p;
02240   bfd_boolean pce_p = FALSE;
02241   int relaxable_p = g_opt;
02242   int relax_size = 0;
02243   struct score_it *inst1 = part_1;
02244   struct score_it *inst2 = part_2;
02245   struct score_it backup_inst1;
02246 
02247   pce_p = (inst2) ? TRUE : FALSE;
02248   memcpy (&backup_inst1, inst1, sizeof (struct score_it));
02249 
02250   /* Adjust instruction opcode and to be relaxed instruction opcode.  */
02251   if (pce_p)
02252     {
02253       backup_inst1.instruction = ((backup_inst1.instruction & 0x7FFF) << 15)
02254                                   | (inst2->instruction & 0x7FFF);
02255       backup_inst1.instruction = adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE);
02256       backup_inst1.relax_inst = 0x8000;
02257       backup_inst1.size = INSN_SIZE;
02258       backup_inst1.relax_size = 0;
02259       backup_inst1.type = Insn_Type_PCE;
02260     }
02261   else
02262     {
02263       backup_inst1.instruction = adjust_paritybit (backup_inst1.instruction,
02264                                              GET_INSN_CLASS (backup_inst1.type));
02265     }
02266 
02267   if (backup_inst1.relax_size != 0)
02268     {
02269       enum insn_class tmp;
02270 
02271       tmp = (backup_inst1.size == INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32;
02272       backup_inst1.relax_inst = adjust_paritybit (backup_inst1.relax_inst, tmp);
02273     }
02274 
02275   /* Check data dependency.  */
02276   handle_dependency (&backup_inst1);
02277 
02278   /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains
02279      data produced by .ascii etc.  Doing this is to make one instruction per frag.  */
02280   if (frag_now_fix () != 0)
02281     {
02282       if (!frag_now->tc_frag_data.is_insn)
02283        frag_wane (frag_now);
02284 
02285       frag_new (0);
02286     }
02287 
02288   /* Here, we must call frag_grow in order to keep the instruction frag type is
02289      rs_machine_dependent.
02290      For, frag_var may change frag_now->fr_type to rs_fill by calling frag_grow which
02291      acturally will call frag_wane.
02292      Calling frag_grow first will create a new frag_now which free size is 20 that is enough
02293      for frag_var.  */
02294   frag_grow (20);
02295 
02296   p = frag_more (backup_inst1.size);
02297   md_number_to_chars (p, backup_inst1.instruction, backup_inst1.size);
02298 
02299 #ifdef OBJ_ELF
02300   dwarf2_emit_insn (backup_inst1.size);
02301 #endif
02302 
02303   /* Generate fixup structure.  */
02304   if (pce_p)
02305     {
02306       if (inst1->reloc.type != BFD_RELOC_NONE)
02307        fix_new_score (frag_now, p - frag_now->fr_literal,
02308                      inst1->size, &inst1->reloc.exp,
02309                      inst1->reloc.pc_rel, inst1->reloc.type);
02310 
02311       if (inst2->reloc.type != BFD_RELOC_NONE)
02312        fix_new_score (frag_now, p - frag_now->fr_literal + 2,
02313                      inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type);
02314     }
02315   else
02316     {
02317       if (backup_inst1.reloc.type != BFD_RELOC_NONE)
02318        fix_new_score (frag_now, p - frag_now->fr_literal,
02319                      backup_inst1.size, &backup_inst1.reloc.exp,
02320                      backup_inst1.reloc.pc_rel, backup_inst1.reloc.type);
02321     }
02322 
02323   /* relax_size may be 2, 4, 12 or 0, 0 indicates no relaxation.  */
02324   relaxable_p &= (backup_inst1.relax_size != 0);
02325   relax_size = relaxable_p ? backup_inst1.relax_size : 0;
02326 
02327   p = frag_var (rs_machine_dependent, relax_size + RELAX_PAD_BYTE, 0,
02328                 RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size,
02329                               backup_inst1.type, 0, 0, relaxable_p),
02330                 backup_inst1.reloc.exp.X_add_symbol, 0, NULL);
02331 
02332   if (relaxable_p)
02333     md_number_to_chars (p, backup_inst1.relax_inst, relax_size);
02334 
02335   memcpy (inst1, &backup_inst1, sizeof (struct score_it));
02336 }
02337 
02338 static void
02339 parse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p)
02340 {
02341   char c;
02342   char *p;
02343   char *operator = insnstr;
02344   const struct asm_opcode *opcode;
02345 
02346   /* Parse operator and operands.  */
02347   skip_whitespace (operator);
02348 
02349   for (p = operator; *p != '\0'; p++)
02350     if ((*p == ' ') || (*p == '!'))
02351       break;
02352 
02353   if (*p == '!')
02354     p++;
02355 
02356   c = *p;
02357   *p = '\0';
02358 
02359   opcode = (const struct asm_opcode *) hash_find (score_ops_hsh, operator);
02360   *p = c;
02361 
02362   memset (&inst, '\0', sizeof (inst));
02363   sprintf (inst.str, "%s", insnstr);
02364   if (opcode)
02365     {
02366       inst.instruction = opcode->value;
02367       inst.relax_inst = opcode->relax_value;
02368       inst.type = opcode->type;
02369       inst.size = GET_INSN_SIZE (inst.type);
02370       inst.relax_size = 0;
02371       inst.bwarn = 0;
02372       sprintf (inst.name, "%s", opcode->template);
02373       strcpy (inst.reg, "");
02374       inst.error = NULL;
02375       inst.reloc.type = BFD_RELOC_NONE;
02376 
02377       (*opcode->parms) (p);
02378 
02379       /* It indicates current instruction is a macro instruction if inst.bwarn equals -1.  */
02380       if ((inst.bwarn != -1) && (!inst.error) && (gen_frag_p))
02381        gen_insn_frag (&inst, NULL);
02382     }
02383   else
02384     inst.error = _("unrecognized opcode");
02385 }
02386 
02387 static int
02388 append_insn (char *str, bfd_boolean gen_frag_p)
02389 {
02390   int retval = SUCCESS;
02391 
02392   parse_16_32_inst (str, gen_frag_p);
02393 
02394   if (inst.error)
02395     {
02396       retval = (int) FAIL;
02397       as_bad (_("%s -- `%s'"), inst.error, inst.str);
02398       inst.error = NULL;
02399     }
02400 
02401   return retval;
02402 }
02403 
02404 /* Handle mv! reg_high, reg_low;
02405           mv! reg_low, reg_high;
02406           mv! reg_low, reg_low;  */
02407 static void
02408 do16_mv_rdrs (char *str)
02409 {
02410   int reg_rd;
02411   int reg_rs;
02412   char *backupstr = NULL;
02413 
02414   backupstr = str;
02415   skip_whitespace (str);
02416 
02417   if ((reg_rd = reg_required_here (&str, 8, REG_TYPE_SCORE)) == (int) FAIL
02418       || skip_past_comma (&str) == (int) FAIL
02419       || (reg_rs = reg_required_here (&str, 4, REG_TYPE_SCORE)) == (int) FAIL
02420       || end_of_line (str) == (int) FAIL)
02421     {
02422       return;
02423     }
02424   else
02425     {
02426       /* Case 1 : mv! or mlfh!.  */
02427       if (reg_rd < 16)
02428         {
02429           if (reg_rs < 16)
02430             {
02431               inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
02432                 | (((inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
02433               inst.relax_size = 4;
02434             }
02435           else
02436             {
02437               char append_str[MAX_LITERAL_POOL_SIZE];
02438 
02439               sprintf (append_str, "mlfh! %s", backupstr);
02440               if (append_insn (append_str, TRUE) == (int) FAIL)
02441               return;
02442               /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
02443               inst.bwarn = -1;
02444             }
02445         }
02446       /* Case 2 : mhfl!.  */
02447       else
02448         {
02449           if (reg_rs > 16)
02450             {
02451               SET_INSN_ERROR (BAD_ARGS);
02452               return;
02453             }
02454           else
02455             {
02456               char append_str[MAX_LITERAL_POOL_SIZE];
02457 
02458               sprintf (append_str, "mhfl! %s", backupstr);
02459               if (append_insn (append_str, TRUE) == (int) FAIL)
02460               return;
02461 
02462               /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
02463               inst.bwarn = -1;
02464             }
02465         }
02466     }
02467 }
02468 
02469 static void
02470 do16_rdi4 (char *str)
02471 {
02472   skip_whitespace (str);
02473 
02474   if (reglow_required_here (&str, 8) == (int) FAIL
02475       || skip_past_comma (&str) == (int) FAIL
02476       || data_op2 (&str, 3, _IMM4) == (int) FAIL
02477       || end_of_line (str) == (int) FAIL)
02478     {
02479       return;
02480     }
02481   else
02482     {
02483       if (((inst.instruction >> 3) & 0x10) == 0)        /* for judge is addei or subei : bit 5 =0 : addei */
02484         {
02485           if (((inst.instruction >> 3) & 0xf) != 0xf)
02486             {
02487               inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
02488                 | ((1 << ((inst.instruction >> 3) & 0xf)) << 1);
02489               inst.relax_size = 4;
02490             }
02491           else
02492             {
02493               inst.relax_inst = 0x8000;
02494             }
02495         }
02496       else
02497         {
02498           if (((inst.instruction >> 3) & 0xf) != 0xf)
02499             {
02500               inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
02501                 | (((-(1 << ((inst.instruction >> 3) & 0xf))) & 0xffff) << 1);
02502               inst.relax_size = 4;
02503             }
02504           else
02505             {
02506               inst.relax_inst = 0x8000;
02507             }
02508         }
02509     }
02510 }
02511 
02512 static void
02513 do16_rdi5 (char *str)
02514 {
02515   skip_whitespace (str);
02516 
02517   if (reglow_required_here (&str, 8) == (int) FAIL
02518       || skip_past_comma (&str) == (int) FAIL
02519       || data_op2 (&str, 3, _IMM5) == (int) FAIL
02520       || end_of_line (str) == (int) FAIL)
02521     return;
02522   else
02523     {
02524       inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
02525         | (((inst.instruction >> 8) & 0xf) << 15) | (((inst.instruction >> 3) & 0x1f) << 10);
02526       inst.relax_size = 4;
02527     }
02528 }
02529 
02530 /* Handle sdbbp.  */
02531 static void
02532 do16_xi5 (char *str)
02533 {
02534   skip_whitespace (str);
02535 
02536   if (data_op2 (&str, 3, _IMM5) == (int) FAIL || end_of_line (str) == (int) FAIL)
02537     return;
02538   else
02539     {
02540       inst.relax_inst |= (((inst.instruction >> 3) & 0x1f) << 15);
02541       inst.relax_size = 4;
02542     }
02543 }
02544 
02545 /* Check that an immediate is word alignment or half word alignment.
02546    If so, convert it to the right format.  */
02547 static int
02548 validate_immediate_align (int val, unsigned int data_type)
02549 {
02550   if (data_type == _IMM5_RSHIFT_1)
02551     {
02552       if (val % 2)
02553         {
02554           inst.error = _("address offset must be half word alignment");
02555           return (int) FAIL;
02556         }
02557     }
02558   else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
02559     {
02560       if (val % 4)
02561         {
02562           inst.error = _("address offset must be word alignment");
02563           return (int) FAIL;
02564         }
02565     }
02566 
02567   return SUCCESS;
02568 }
02569 
02570 static int
02571 exp_ldst_offset (char **str, int shift, unsigned int data_type)
02572 {
02573   char *dataptr;
02574 
02575   dataptr = * str;
02576 
02577   if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
02578       && (data_type != _SIMM16_LA)
02579       && (data_type != _VALUE_HI16)
02580       && (data_type != _VALUE_LO16)
02581       && (data_type != _IMM16)
02582       && (data_type != _IMM15)
02583       && (data_type != _IMM14)
02584       && (data_type != _IMM4)
02585       && (data_type != _IMM5)
02586       && (data_type != _IMM8)
02587       && (data_type != _IMM5_RSHIFT_1)
02588       && (data_type != _IMM5_RSHIFT_2)
02589       && (data_type != _SIMM14_NEG)
02590       && (data_type != _IMM10_RSHIFT_2))
02591     {
02592       data_type += 24;
02593     }
02594 
02595   if (my_get_expression (&inst.reloc.exp, str) == (int) FAIL)
02596     return (int) FAIL;
02597 
02598   if (inst.reloc.exp.X_op == O_constant)
02599     {
02600       /* Need to check the immediate align.  */
02601       int value = validate_immediate_align (inst.reloc.exp.X_add_number, data_type);
02602 
02603       if (value == (int) FAIL)
02604        return (int) FAIL;
02605 
02606       value = validate_immediate (inst.reloc.exp.X_add_number, data_type);
02607       if (value == (int) FAIL)
02608         {
02609           if (data_type < 30)
02610             sprintf (err_msg,
02611                      _("invalid constant: %d bit expression not in range %d..%d"),
02612                      score_df_range[data_type].bits,
02613                      score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
02614           else
02615             sprintf (err_msg,
02616                      _("invalid constant: %d bit expression not in range %d..%d"),
02617                      score_df_range[data_type - 24].bits,
02618                      score_df_range[data_type - 24].range[0], score_df_range[data_type - 24].range[1]);
02619           inst.error = err_msg;
02620           return (int) FAIL;
02621         }
02622 
02623       if (data_type == _IMM5_RSHIFT_1)
02624         {
02625           value >>= 1;
02626         }
02627       else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
02628         {
02629           value >>= 2;
02630         }
02631 
02632       if (score_df_range[data_type].range[0] != 0)
02633         {
02634           value &= (1 << score_df_range[data_type].bits) - 1;
02635         }
02636 
02637       inst.instruction |= value << shift;
02638     }
02639   else
02640     {
02641       inst.reloc.pc_rel = 0;
02642     }
02643 
02644   return SUCCESS;
02645 }
02646 
02647 static void
02648 do_ldst_insn (char *str)
02649 {
02650   int pre_inc = 0;
02651   int conflict_reg;
02652   int value;
02653   char * temp;
02654   char *strbak;
02655   char *dataptr;
02656   int reg;
02657   int ldst_idx = 0;
02658 
02659   strbak = str;
02660   skip_whitespace (str);
02661 
02662   if (((conflict_reg = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
02663       || (skip_past_comma (&str) == (int) FAIL))
02664     return;
02665 
02666   /* ld/sw rD, [rA, simm15]    ld/sw rD, [rA]+, simm12     ld/sw rD, [rA, simm12]+.  */
02667   if (*str == '[')
02668     {
02669       str++;
02670       skip_whitespace (str);
02671 
02672       if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
02673        return;
02674 
02675       /* Conflicts can occur on stores as well as loads.  */
02676       conflict_reg = (conflict_reg == reg);
02677       skip_whitespace (str);
02678       temp = str + 1;    /* The latter will process decimal/hex expression.  */
02679 
02680       /* ld/sw rD, [rA]+, simm12    ld/sw rD, [rA]+.  */
02681       if (*str == ']')
02682         {
02683           str++;
02684           if (*str == '+')
02685             {
02686               str++;
02687               /* ld/sw rD, [rA]+, simm12.  */
02688               if (skip_past_comma (&str) == SUCCESS)
02689                 {
02690                   if ((exp_ldst_offset (&str, 3, _SIMM12) == (int) FAIL)
02691                       || (end_of_line (str) == (int) FAIL))
02692                   return;
02693 
02694                   if (conflict_reg)
02695                     {
02696                       unsigned int ldst_func = inst.instruction & OPC_PSEUDOLDST_MASK;
02697 
02698                       if ((ldst_func == INSN_LH)
02699                           || (ldst_func == INSN_LHU)
02700                           || (ldst_func == INSN_LW)
02701                           || (ldst_func == INSN_LB)
02702                           || (ldst_func == INSN_LBU))
02703                         {
02704                           inst.error = _("register same as write-back base");
02705                           return;
02706                         }
02707                     }
02708 
02709                   ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
02710                   inst.instruction &= ~OPC_PSEUDOLDST_MASK;
02711                   inst.instruction |= score_ldst_insns[ldst_idx * 3 + LDST_POST].value;
02712 
02713                   /* lw rD, [rA]+, 4 convert to pop rD, [rA].  */
02714                   if ((inst.instruction & 0x3e000007) == 0x0e000000)
02715                     {
02716                       /* rs =  r0-r7, offset = 4 */
02717                       if ((((inst.instruction >> 15) & 0x18) == 0)
02718                           && (((inst.instruction >> 3) & 0xfff) == 4))
02719                         {
02720                           /* Relax to pophi.  */
02721                           if ((((inst.instruction >> 20) & 0x10) == 0x10))
02722                             {
02723                               inst.relax_inst = 0x0000200a | (((inst.instruction >> 20) & 0xf)
02724                                                               << 8) | 1 << 7 |
02725                                 (((inst.instruction >> 15) & 0x7) << 4);
02726                             }
02727                           /* Relax to pop.  */
02728                           else
02729                             {
02730                               inst.relax_inst = 0x0000200a | (((inst.instruction >> 20) & 0xf)
02731                                                               << 8) | 0 << 7 |
02732                                 (((inst.instruction >> 15) & 0x7) << 4);
02733                             }
02734                           inst.relax_size = 2;
02735                         }
02736                     }
02737                   return;
02738                 }
02739               /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+.  */
02740               else
02741                 {
02742                   SET_INSN_ERROR (NULL);
02743                   if (end_of_line (str) == (int) FAIL)
02744                     {
02745                       return;
02746                     }
02747 
02748                   pre_inc = 1;
02749                   value = validate_immediate (inst.reloc.exp.X_add_number, _SIMM12);
02750                   value &= (1 << score_df_range[_SIMM12].bits) - 1;
02751                   ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
02752                   inst.instruction &= ~OPC_PSEUDOLDST_MASK;
02753                   inst.instruction |= score_ldst_insns[ldst_idx * 3 + pre_inc].value;
02754                   inst.instruction |= value << 3;
02755                   inst.relax_inst = 0x8000;
02756                   return;
02757                 }
02758             }
02759           /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15].  */
02760           else
02761             {
02762               if (end_of_line (str) == (int) FAIL)
02763               return;
02764 
02765               ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
02766               inst.instruction &= ~OPC_PSEUDOLDST_MASK;
02767               inst.instruction |= score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value;
02768 
02769               /* lbu rd, [rs] -> lbu! rd, [rs]  */
02770               if (ldst_idx == INSN_LBU)
02771                 {
02772                   inst.relax_inst = INSN16_LBU;
02773                 }
02774               else if (ldst_idx == INSN_LH)
02775                 {
02776                   inst.relax_inst = INSN16_LH;
02777                 }
02778               else if (ldst_idx == INSN_LW)
02779                 {
02780                   inst.relax_inst = INSN16_LW;
02781                 }
02782               else if (ldst_idx == INSN_SB)
02783                 {
02784                   inst.relax_inst = INSN16_SB;
02785                 }
02786               else if (ldst_idx == INSN_SH)
02787                 {
02788                   inst.relax_inst = INSN16_SH;
02789                 }
02790               else if (ldst_idx == INSN_SW)
02791                 {
02792                   inst.relax_inst = INSN16_SW;
02793                 }
02794               else
02795                 {
02796                   inst.relax_inst = 0x8000;
02797                 }
02798 
02799               /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction.  */
02800               if ((ldst_idx == INSN_LBU)
02801                   || (ldst_idx == INSN_LH)
02802                   || (ldst_idx == INSN_LW)
02803                   || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))
02804                 {
02805                   if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
02806                     {
02807                       inst.relax_inst |= (2 << 12) | (((inst.instruction >> 20) & 0xf) << 8) |
02808                         (((inst.instruction >> 15) & 0xf) << 4);
02809                       inst.relax_size = 2;
02810                     }
02811                 }
02812 
02813               return;
02814             }
02815         }
02816       /* ld/sw rD, [rA, simm15]    ld/sw rD, [rA, simm12]+.  */
02817       else
02818         {
02819           if (skip_past_comma (&str) == (int) FAIL)
02820             {
02821               inst.error = _("pre-indexed expression expected");
02822               return;
02823             }
02824 
02825           if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL)
02826            return;
02827 
02828           skip_whitespace (str);
02829           if (*str++ != ']')
02830             {
02831               inst.error = _("missing ]");
02832               return;
02833             }
02834 
02835           skip_whitespace (str);
02836           /* ld/sw rD, [rA, simm12]+.  */
02837           if (*str == '+')
02838             {
02839               str++;
02840               pre_inc = 1;
02841               if (conflict_reg)
02842                 {
02843                   unsigned int ldst_func = inst.instruction & OPC_PSEUDOLDST_MASK;
02844 
02845                   if ((ldst_func == INSN_LH)
02846                       || (ldst_func == INSN_LHU)
02847                       || (ldst_func == INSN_LW)
02848                       || (ldst_func == INSN_LB)
02849                       || (ldst_func == INSN_LBU))
02850                     {
02851                       inst.error = _("register same as write-back base");
02852                       return;
02853                     }
02854                 }
02855             }
02856 
02857           if (end_of_line (str) == (int) FAIL)
02858            return;
02859 
02860           if (inst.reloc.exp.X_op == O_constant)
02861             {
02862               int value;
02863               unsigned int data_type;
02864 
02865               if (pre_inc == 1)
02866                 data_type = _SIMM12;
02867               else
02868                 data_type = _SIMM15;
02869               dataptr = temp;
02870 
02871               if ((*dataptr == '0') && (*(dataptr + 1) == 'x')
02872                   && (data_type != _SIMM16_LA)
02873                   && (data_type != _VALUE_HI16)
02874                   && (data_type != _VALUE_LO16)
02875                   && (data_type != _IMM16)
02876                   && (data_type != _IMM15)
02877                   && (data_type != _IMM14)
02878                   && (data_type != _IMM4)
02879                   && (data_type != _IMM5)
02880                   && (data_type != _IMM8)
02881                   && (data_type != _IMM5_RSHIFT_1)
02882                   && (data_type != _IMM5_RSHIFT_2)
02883                   && (data_type != _SIMM14_NEG)
02884                   && (data_type != _IMM10_RSHIFT_2))
02885                 {
02886                   data_type += 24;
02887                 }
02888 
02889               value = validate_immediate (inst.reloc.exp.X_add_number, data_type);
02890               if (value == (int) FAIL)
02891                 {
02892                   if (data_type < 30)
02893                     sprintf (err_msg,
02894                              _("invalid constant: %d bit expression not in range %d..%d"),
02895                              score_df_range[data_type].bits,
02896                              score_df_range[data_type].range[0], score_df_range[data_type].range[1]);
02897                   else
02898                     sprintf (err_msg,
02899                              _("invalid constant: %d bit expression not in range %d..%d"),
02900                              score_df_range[data_type - 24].bits,
02901                              score_df_range[data_type - 24].range[0],
02902                              score_df_range[data_type - 24].range[1]);
02903                   inst.error = err_msg;
02904                   return;
02905                 }
02906 
02907               value &= (1 << score_df_range[data_type].bits) - 1;
02908               ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
02909               inst.instruction &= ~OPC_PSEUDOLDST_MASK;
02910               inst.instruction |= score_ldst_insns[ldst_idx * 3 + pre_inc].value;
02911               if (pre_inc == 1)
02912                 inst.instruction |= value << 3;
02913               else
02914                 inst.instruction |= value;
02915 
02916               /* lw rD, [rA, simm15]  */
02917               if ((inst.instruction & 0x3e000000) == 0x20000000)
02918                 {
02919                   /* Both rD and rA are in [r0 - r15].  */
02920                   if ((((inst.instruction >> 15) & 0x10) == 0)
02921                       && (((inst.instruction >> 20) & 0x10) == 0))
02922                     {
02923                       /* simm15 = 0, lw -> lw!.  */
02924                       if ((inst.instruction & 0x7fff) == 0)
02925                         {
02926                           inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
02927                             | (((inst.instruction >> 20) & 0xf) << 8);
02928                           inst.relax_size = 2;
02929                         }
02930                       /* rA = r2, lw -> lwp!.  */
02931                       else if ((((inst.instruction >> 15) & 0xf) == 2)
02932                                && ((inst.instruction & 0x3) == 0)
02933                                && ((inst.instruction & 0x7fff) < 128))
02934                         {
02935                           inst.relax_inst = 0x7000 | (((inst.instruction >> 20) & 0xf) << 8)
02936                             | (((inst.instruction & 0x7fff) >> 2) << 3);
02937                           inst.relax_size = 2;
02938                         }
02939                       else
02940                         {
02941                           inst.relax_inst = 0x8000;
02942                         }
02943                     }
02944                   else
02945                     {
02946                       inst.relax_inst = 0x8000;
02947                     }
02948                 }
02949               /* sw rD, [rA, simm15]  */
02950               else if ((inst.instruction & 0x3e000000) == 0x28000000)
02951                 {
02952                   /* Both rD and rA are in [r0 - r15].  */
02953                   if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
02954                     {
02955                       /* simm15 = 0, sw -> sw!.  */
02956                       if ((inst.instruction & 0x7fff) == 0)
02957                         {
02958                           inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
02959                             | (((inst.instruction >> 20) & 0xf) << 8);
02960                           inst.relax_size = 2;
02961                         }
02962                       /* rA = r2, sw -> swp!.  */
02963                       else if ((((inst.instruction >> 15) & 0xf) == 2)
02964                                && ((inst.instruction & 0x3) == 0)
02965                                && ((inst.instruction & 0x7fff) < 128))
02966                         {
02967                           inst.relax_inst = 0x7004 | (((inst.instruction >> 20) & 0xf) << 8)
02968                             | (((inst.instruction & 0x7fff) >> 2) << 3);
02969                           inst.relax_size = 2;
02970                         }
02971                       else
02972                         {
02973                           inst.relax_inst = 0x8000;
02974                         }
02975                     }
02976                   else
02977                     {
02978                       inst.relax_inst = 0x8000;
02979                     }
02980                 }
02981               /* sw rD, [rA, simm15]+    sw pre.  */
02982               else if ((inst.instruction & 0x3e000007) == 0x06000004)
02983                 {
02984                   /* rA is in [r0 - r7], and simm15 = -4.  */
02985                   if ((((inst.instruction >> 15) & 0x18) == 0)
02986                       && (((inst.instruction >> 3) & 0xfff) == 0xffc))
02987                     {
02988                       /* sw -> pushhi!.  */
02989                       if ((((inst.instruction >> 20) & 0x10) == 0x10))
02990                         {
02991                           inst.relax_inst = 0x0000200e | (((inst.instruction >> 20) & 0xf) << 8)
02992                             | 1 << 7 | (((inst.instruction >> 15) & 0x7) << 4);
02993                           inst.relax_size = 2;
02994                         }
02995                       /* sw -> push!.  */
02996                       else
02997                         {
02998                           inst.relax_inst = 0x0000200e | (((inst.instruction >> 20) & 0xf) << 8)
02999                             | 0 << 7 | (((inst.instruction >> 15) & 0x7) << 4);
03000                           inst.relax_size = 2;
03001                         }
03002                     }
03003                   else
03004                     {
03005                       inst.relax_inst = 0x8000;
03006                     }
03007                 }
03008               /* lh rD, [rA, simm15]  */
03009               else if ((inst.instruction & 0x3e000000) == 0x22000000)
03010                 {
03011                   /* Both rD and rA are in [r0 - r15].  */
03012                   if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
03013                     {
03014                       /* simm15 = 0, lh -> lh!.  */
03015                       if ((inst.instruction & 0x7fff) == 0)
03016                         {
03017                           inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
03018                             | (((inst.instruction >> 20) & 0xf) << 8);
03019                           inst.relax_size = 2;
03020                         }
03021                       /* rA = r2, lh -> lhp!.  */
03022                       else if ((((inst.instruction >> 15) & 0xf) == 2)
03023                                && ((inst.instruction & 0x1) == 0)
03024                                && ((inst.instruction & 0x7fff) < 64))
03025                         {
03026                           inst.relax_inst = 0x7001 | (((inst.instruction >> 20) & 0xf) << 8)
03027                             | (((inst.instruction & 0x7fff) >> 1) << 3);
03028                           inst.relax_size = 2;
03029                         }
03030                       else
03031                         {
03032                           inst.relax_inst = 0x8000;
03033                         }
03034                     }
03035                   else
03036                     {
03037                       inst.relax_inst = 0x8000;
03038                     }
03039                 }
03040               /* sh rD, [rA, simm15]  */
03041               else if ((inst.instruction & 0x3e000000) == 0x2a000000)
03042                 {
03043                   /* Both rD and rA are in [r0 - r15].  */
03044                   if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
03045                     {
03046                       /* simm15 = 0, sh -> sh!.  */
03047                       if ((inst.instruction & 0x7fff) == 0)
03048                         {
03049                           inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
03050                             | (((inst.instruction >> 20) & 0xf) << 8);
03051                           inst.relax_size = 2;
03052                         }
03053                       /* rA = r2, sh -> shp!.  */
03054                       else if ((((inst.instruction >> 15) & 0xf) == 2)
03055                                && ((inst.instruction & 0x1) == 0)
03056                                && ((inst.instruction & 0x7fff) < 64))
03057                         {
03058                           inst.relax_inst = 0x7005 | (((inst.instruction >> 20) & 0xf) << 8)
03059                             | (((inst.instruction & 0x7fff) >> 1) << 3);
03060                           inst.relax_size = 2;
03061                         }
03062                       else
03063                         {
03064                           inst.relax_inst = 0x8000;
03065                         }
03066                     }
03067                   else
03068                     {
03069                       inst.relax_inst = 0x8000;
03070                     }
03071                 }
03072               /* lbu rD, [rA, simm15]  */
03073               else if ((inst.instruction & 0x3e000000) == 0x2c000000)
03074                 {
03075                   /* Both rD and rA are in [r0 - r15].  */
03076                   if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
03077                     {
03078                       /* simm15 = 0, lbu -> lbu!.  */
03079                       if ((inst.instruction & 0x7fff) == 0)
03080                         {
03081                           inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
03082                             | (((inst.instruction >> 20) & 0xf) << 8);
03083                           inst.relax_size = 2;
03084                         }
03085                       /* rA = r2, lbu -> lbup!.  */
03086                       else if ((((inst.instruction >> 15) & 0xf) == 2)
03087                                && ((inst.instruction & 0x7fff) < 32))
03088                         {
03089                           inst.relax_inst = 0x7003 | (((inst.instruction >> 20) & 0xf) << 8)
03090                             | ((inst.instruction & 0x7fff) << 3);
03091                           inst.relax_size = 2;
03092                         }
03093                       else
03094                         {
03095                           inst.relax_inst = 0x8000;
03096                         }
03097                     }
03098                   else
03099                     {
03100                       inst.relax_inst = 0x8000;
03101                     }
03102                 }
03103               /* sb rD, [rA, simm15]  */
03104               else if ((inst.instruction & 0x3e000000) == 0x2e000000)
03105                 {
03106                   /* Both rD and rA are in [r0 - r15].  */
03107                   if ((((inst.instruction >> 15) & 0x10) == 0) && (((inst.instruction >> 20) & 0x10) == 0))
03108                     {
03109                       /* simm15 = 0, sb -> sb!.  */
03110                       if ((inst.instruction & 0x7fff) == 0)
03111                         {
03112                           inst.relax_inst |= (((inst.instruction >> 15) & 0xf) << 4)
03113                             | (((inst.instruction >> 20) & 0xf) << 8);
03114                           inst.relax_size = 2;
03115                         }
03116                       /* rA = r2, sb -> sb!.  */
03117                       else if ((((inst.instruction >> 15) & 0xf) == 2)
03118                                && ((inst.instruction & 0x7fff) < 32))
03119                         {
03120                           inst.relax_inst = 0x7007 | (((inst.instruction >> 20) & 0xf) << 8)
03121                             | ((inst.instruction & 0x7fff) << 3);
03122                           inst.relax_size = 2;
03123                         }
03124                       else
03125                         {
03126                           inst.relax_inst = 0x8000;
03127                         }
03128                     }
03129                   else
03130                     {
03131                       inst.relax_inst = 0x8000;
03132                     }
03133                 }
03134               else
03135                 {
03136                   inst.relax_inst = 0x8000;
03137                 }
03138 
03139               return;
03140             }
03141           else
03142             {
03143               /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
03144               inst.reloc.pc_rel = 0;
03145             }
03146         }
03147     }
03148   else
03149     {
03150       inst.error = BAD_ARGS;
03151     }
03152 }
03153 
03154 /* Handle cache.  */
03155 
03156 static void
03157 do_cache (char *str)
03158 {
03159   skip_whitespace (str);
03160 
03161   if ((data_op2 (&str, 20, _IMM5) == (int) FAIL) || (skip_past_comma (&str) == (int) FAIL))
03162     {
03163       return;
03164     }
03165   else
03166     {
03167       int cache_op;
03168 
03169       cache_op = (inst.instruction >> 20) & 0x1F;
03170       sprintf (inst.name, "cache %d", cache_op);
03171     }
03172 
03173   if (*str == '[')
03174     {
03175       str++;
03176       skip_whitespace (str);
03177 
03178       if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL)
03179        return;
03180 
03181       skip_whitespace (str);
03182 
03183       /* cache op, [rA]  */
03184       if (skip_past_comma (&str) == (int) FAIL)
03185         {
03186           SET_INSN_ERROR (NULL);
03187           if (*str != ']')
03188             {
03189               inst.error = _("missing ]");
03190               return;
03191             }
03192           str++;
03193         }
03194       /* cache op, [rA, simm15]  */
03195       else
03196         {
03197           if (exp_ldst_offset (&str, 0, _SIMM15) == (int) FAIL)
03198             {
03199               return;
03200             }
03201 
03202           skip_whitespace (str);
03203           if (*str++ != ']')
03204             {
03205               inst.error = _("missing ]");
03206               return;
03207             }
03208         }
03209 
03210       if (end_of_line (str) == (int) FAIL)
03211        return;
03212     }
03213   else
03214     {
03215       inst.error = BAD_ARGS;
03216     }
03217 }
03218 
03219 static void
03220 do_crdcrscrsimm5 (char *str)
03221 {
03222   char *strbak;
03223 
03224   strbak = str;
03225   skip_whitespace (str);
03226 
03227   if (reg_required_here (&str, 20, REG_TYPE_SCORE_CR) == (int) FAIL
03228       || skip_past_comma (&str) == (int) FAIL
03229       || reg_required_here (&str, 15, REG_TYPE_SCORE_CR) == (int) FAIL
03230       || skip_past_comma (&str) == (int) FAIL
03231       || reg_required_here (&str, 10, REG_TYPE_SCORE_CR) == (int) FAIL
03232       || skip_past_comma (&str) == (int) FAIL)
03233     {
03234       str = strbak;
03235       /* cop1 cop_code20.  */
03236       if (data_op2 (&str, 5, _IMM20) == (int) FAIL)
03237        return;
03238     }
03239   else
03240     {
03241       if (data_op2 (&str, 5, _IMM5) == (int) FAIL)
03242        return;
03243     }
03244 
03245   end_of_line (str);
03246 }
03247 
03248 /* Handle ldc/stc.  */
03249 static void
03250 do_ldst_cop (char *str)
03251 {
03252   skip_whitespace (str);
03253 
03254   if ((reg_required_here (&str, 15, REG_TYPE_SCORE_CR) == (int) FAIL)
03255       || (skip_past_comma (&str) == (int) FAIL))
03256     return;
03257 
03258   if (*str == '[')
03259     {
03260       str++;
03261       skip_whitespace (str);
03262 
03263       if (reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL)
03264        return;
03265 
03266       skip_whitespace (str);
03267 
03268       if (*str++ != ']')
03269         {
03270           if (exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) FAIL)
03271            return;
03272 
03273           skip_whitespace (str);
03274           if (*str++ != ']')
03275             {
03276               inst.error = _("missing ]");
03277               return;
03278             }
03279         }
03280 
03281       end_of_line (str);
03282     }
03283   else
03284     inst.error = BAD_ARGS;
03285 }
03286 
03287 static void
03288 do16_ldst_insn (char *str)
03289 {
03290   skip_whitespace (str);
03291 
03292   if ((reglow_required_here (&str, 8) == (int) FAIL) || (skip_past_comma (&str) == (int) FAIL))
03293     return;
03294 
03295   if (*str == '[')
03296     {
03297       int reg;
03298 
03299       str++;
03300       skip_whitespace (str);
03301 
03302       if ((reg = reglow_required_here (&str, 4)) == (int) FAIL)
03303        return;
03304 
03305       skip_whitespace (str);
03306       if (*str++ == ']')
03307         {
03308           if (end_of_line (str) == (int) FAIL)
03309            return;
03310           else
03311             {
03312               inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
03313                               | (((inst.instruction >> 4) & 0xf) << 15);
03314              inst.relax_size = 4;
03315             }
03316         }
03317       else
03318         {
03319           inst.error = _("missing ]");
03320         }
03321     }
03322   else
03323     {
03324       inst.error = BAD_ARGS;
03325     }
03326 }
03327 
03328 /* Handle lbup!/lhp!/ldiu!/lwp!/sbp!/shp!/swp!.  */
03329 static void
03330 do16_ldst_imm_insn (char *str)
03331 {
03332   char data_exp[MAX_LITERAL_POOL_SIZE];
03333   int reg_rd;
03334   char *dataptr = NULL, *pp = NULL;
03335   int cnt = 0;
03336   int assign_data = (int) FAIL;
03337   unsigned int ldst_func;
03338 
03339   skip_whitespace (str);
03340 
03341   if (((reg_rd = reglow_required_here (&str, 8)) == (int) FAIL)
03342       || (skip_past_comma (&str) == (int) FAIL))
03343     return;
03344 
03345   skip_whitespace (str);
03346   dataptr = str;
03347 
03348   while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= MAX_LITERAL_POOL_SIZE))
03349     {
03350       data_exp[cnt] = *dataptr;
03351       dataptr++;
03352       cnt++;
03353     }
03354 
03355   data_exp[cnt] = '\0';
03356   pp = &data_exp[0];
03357 
03358   str = dataptr;
03359 
03360   ldst_func = inst.instruction & LDST16_RI_MASK;
03361   if (ldst_func == N16_LIU)
03362     assign_data = exp_ldst_offset (&pp, 0, _IMM8);
03363   else if (ldst_func == N16_LHP || ldst_func == N16_SHP)
03364     assign_data = exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_1);
03365   else if (ldst_func == N16_LWP || ldst_func == N16_SWP)
03366     assign_data = exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_2);
03367   else
03368     assign_data = exp_ldst_offset (&pp, 3, _IMM5);
03369 
03370   if ((assign_data == (int) FAIL) || (end_of_line (pp) == (int) FAIL))
03371     return;
03372   else
03373     {
03374       if ((inst.instruction & 0x7000) == N16_LIU)
03375         {
03376           inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20
03377                           | ((inst.instruction & 0xff) << 1);
03378         }
03379       else if (((inst.instruction & 0x7007) == N16_LHP)
03380                || ((inst.instruction & 0x7007) == N16_SHP))
03381         {
03382           inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
03383                           | (((inst.instruction >> 3) & 0x1f) << 1);
03384         }
03385       else if (((inst.instruction & 0x7007) == N16_LWP)
03386                || ((inst.instruction & 0x7007) == N16_SWP))
03387         {
03388           inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
03389                           | (((inst.instruction >> 3) & 0x1f) << 2);
03390         }
03391       else if (((inst.instruction & 0x7007) == N16_LBUP)
03392                || ((inst.instruction & 0x7007) == N16_SBP))
03393         {
03394           inst.relax_inst |= ((inst.instruction >> 8) & 0xf) << 20 | 2 << 15
03395                           | (((inst.instruction >> 3) & 0x1f));
03396         }
03397 
03398       inst.relax_size = 4;
03399     }
03400 }
03401 
03402 static void
03403 do16_push_pop (char *str)
03404 {
03405   int reg_rd;
03406   int H_bit_mask = 0;
03407 
03408   skip_whitespace (str);
03409   if (((reg_rd = reg_required_here (&str, 8, REG_TYPE_SCORE)) == (int) FAIL)
03410       || (skip_past_comma (&str) == (int) FAIL))
03411     return;
03412 
03413   if (reg_rd >= 16)
03414     H_bit_mask = 1;
03415 
03416   /* reg_required_here will change bit 12 of opcode, so we must restore bit 12.  */
03417   inst.instruction &= ~(1 << 12);
03418 
03419   inst.instruction |= H_bit_mask << 7;
03420 
03421   if (*str == '[')
03422     {
03423       int reg;
03424 
03425       str++;
03426       skip_whitespace (str);
03427       if ((reg = reg_required_here (&str, 4, REG_TYPE_SCORE)) == (int) FAIL)
03428        return;
03429       else if (reg > 7)
03430         {
03431           if (!inst.error)
03432            inst.error = _("base register nums are over 3 bit");
03433 
03434           return;
03435         }
03436 
03437       skip_whitespace (str);
03438       if ((*str++ != ']') || (end_of_line (str) == (int) FAIL))
03439         {
03440           if (!inst.error)
03441            inst.error = _("missing ]");
03442 
03443           return;
03444         }
03445 
03446       /* pop! */
03447       if ((inst.instruction & 0xf) == 0xa)
03448         {
03449           if (H_bit_mask)
03450             {
03451               inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
03452                                   | (((inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
03453             }
03454           else
03455             {
03456               inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
03457                                   | (((inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
03458             }
03459         }
03460       /* push! */
03461       else
03462         {
03463           if (H_bit_mask)
03464             {
03465               inst.relax_inst |= ((((inst.instruction >> 8) & 0xf) | 0x10) << 20)
03466                                   | (((inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
03467             }
03468           else
03469             {
03470               inst.relax_inst |= (((inst.instruction >> 8) & 0xf) << 20)
03471                                   | (((inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
03472             }
03473         }
03474       inst.relax_size = 4;
03475     }
03476   else
03477     {
03478       inst.error = BAD_ARGS;
03479     }
03480 }
03481 
03482 /* Handle lcb/lcw/lce/scb/scw/sce.  */
03483 static void
03484 do_ldst_unalign (char *str)
03485 {
03486   int conflict_reg;
03487 
03488   if (university_version == 1)
03489     {
03490       inst.error = ERR_FOR_SCORE5U_ATOMIC;
03491       return;
03492     }
03493 
03494   skip_whitespace (str);
03495 
03496   /* lcb/scb [rA]+.  */
03497   if (*str == '[')
03498     {
03499       str++;
03500       skip_whitespace (str);
03501 
03502       if (reg_required_here (&str, 15, REG_TYPE_SCORE) == (int) FAIL)
03503        return;
03504 
03505       if (*str++ == ']')
03506         {
03507           if (*str++ != '+')
03508             {
03509               inst.error = _("missing +");
03510               return;
03511             }
03512         }
03513       else
03514         {
03515           inst.error = _("missing ]");
03516           return;
03517         }
03518 
03519       if (end_of_line (str) == (int) FAIL)
03520        return;
03521     }
03522   /* lcw/lce/scb/sce rD, [rA]+.  */
03523   else
03524     {
03525       if (((conflict_reg = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
03526           || (skip_past_comma (&str) == (int) FAIL))
03527         {
03528           return;
03529         }
03530 
03531       skip_whitespace (str);
03532       if (*str++ == '[')
03533         {
03534           int reg;
03535 
03536           skip_whitespace (str);
03537           if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
03538             {
03539               return;
03540             }
03541 
03542           /* Conflicts can occur on stores as well as loads.  */
03543           conflict_reg = (conflict_reg == reg);
03544           skip_whitespace (str);
03545           if (*str++ == ']')
03546             {
03547               unsigned int ldst_func = inst.instruction & LDST_UNALIGN_MASK;
03548 
03549               if (*str++ == '+')
03550                 {
03551                   if (conflict_reg)
03552                     {
03553                       as_warn (_("%s register same as write-back base"),
03554                                ((ldst_func & UA_LCE) || (ldst_func & UA_LCW)
03555                                 ? _("destination") : _("source")));
03556                     }
03557                 }
03558               else
03559                 {
03560                   inst.error = _("missing +");
03561                   return;
03562                 }
03563 
03564               if (end_of_line (str) == (int) FAIL)
03565               return;
03566             }
03567           else
03568             {
03569               inst.error = _("missing ]");
03570               return;
03571             }
03572         }
03573       else
03574         {
03575           inst.error = BAD_ARGS;
03576           return;
03577         }
03578     }
03579 }
03580 
03581 /* Handle alw/asw.  */
03582 static void
03583 do_ldst_atomic (char *str)
03584 {
03585   if (university_version == 1)
03586     {
03587       inst.error = ERR_FOR_SCORE5U_ATOMIC;
03588       return;
03589     }
03590 
03591   skip_whitespace (str);
03592 
03593   if ((reg_required_here (&str, 20, REG_TYPE_SCORE) == (int) FAIL)
03594       || (skip_past_comma (&str) == (int) FAIL))
03595     {
03596       return;
03597     }
03598   else
03599     {
03600 
03601       skip_whitespace (str);
03602       if (*str++ == '[')
03603         {
03604           int reg;
03605 
03606           skip_whitespace (str);
03607           if ((reg = reg_required_here (&str, 15, REG_TYPE_SCORE)) == (int) FAIL)
03608             {
03609               return;
03610             }
03611 
03612           skip_whitespace (str);
03613           if (*str++ != ']')
03614             {
03615               inst.error = _("missing ]");
03616               return;
03617             }
03618 
03619           end_of_line (str);
03620         }
03621       else
03622        inst.error = BAD_ARGS;
03623     }
03624 }
03625 
03626 static void
03627 build_relax_frag (struct score_it fix_insts[RELAX_INST_NUM], int fix_num ATTRIBUTE_UNUSED,
03628                   struct score_it var_insts[RELAX_INST_NUM], int var_num,
03629                   symbolS *add_symbol)
03630 {
03631   int i;
03632   char *p;
03633   fixS *fixp = NULL;
03634   fixS *cur_fixp = NULL;
03635   long where;
03636   struct score_it inst_main;
03637 
03638   memcpy (&inst_main, &fix_insts[0], sizeof (struct score_it));
03639 
03640   /* Adjust instruction opcode and to be relaxed instruction opcode.  */
03641   inst_main.instruction = adjust_paritybit (inst_main.instruction, GET_INSN_CLASS (inst_main.type));
03642   inst_main.type = Insn_PIC;
03643 
03644   for (i = 0; i < var_num; i++)
03645     {
03646       inst_main.relax_size += var_insts[i].size;
03647       var_insts[i].instruction = adjust_paritybit (var_insts[i].instruction,
03648                                                    GET_INSN_CLASS (var_insts[i].type));
03649     }
03650 
03651   /* Check data dependency.  */
03652   handle_dependency (&inst_main);
03653 
03654   /* Start a new frag if frag_now is not empty.  */
03655   if (frag_now_fix () != 0)
03656     {
03657       if (!frag_now->tc_frag_data.is_insn)
03658        {
03659           frag_wane (frag_now);
03660        }
03661       frag_new (0);
03662     }
03663   frag_grow (20);
03664 
03665   /* Write fr_fix part.  */
03666   p = frag_more (inst_main.size);
03667   md_number_to_chars (p, inst_main.instruction, inst_main.size);
03668 
03669   if (inst_main.reloc.type != BFD_RELOC_NONE)
03670     fixp = fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
03671                        &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
03672 
03673   frag_now->tc_frag_data.fixp = fixp;
03674   cur_fixp = frag_now->tc_frag_data.fixp;
03675 
03676 #ifdef OBJ_ELF
03677   dwarf2_emit_insn (inst_main.size);
03678 #endif
03679 
03680   where = p - frag_now->fr_literal + inst_main.size;
03681   for (i = 0; i < var_num; i++)
03682     {
03683       if (i > 0)
03684         where += var_insts[i - 1].size;
03685 
03686       if (var_insts[i].reloc.type != BFD_RELOC_NONE)
03687         {
03688           fixp = fix_new_score (frag_now, where, var_insts[i].size,
03689                                 &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel,
03690                                 var_insts[i].reloc.type);
03691           if (fixp)
03692             {
03693               if (cur_fixp)
03694                 {
03695                   cur_fixp->fx_next = fixp;
03696                   cur_fixp = cur_fixp->fx_next;
03697                 }
03698               else
03699                 {
03700                   frag_now->tc_frag_data.fixp = fixp;
03701                   cur_fixp = frag_now->tc_frag_data.fixp;
03702                 }
03703            }
03704         }
03705     }
03706 
03707   p = frag_var (rs_machine_dependent, inst_main.relax_size + RELAX_PAD_BYTE, 0,
03708                 RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type,
03709                 0, inst_main.size, 0), add_symbol, 0, NULL);
03710 
03711   /* Write fr_var part.
03712      no calling gen_insn_frag, no fixS will be generated.  */
03713   for (i = 0; i < var_num; i++)
03714     {
03715       md_number_to_chars (p, var_insts[i].instruction, var_insts[i].size);
03716       p += var_insts[i].size;
03717     }
03718   /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
03719   inst.bwarn = -1;
03720 }
03721 
03722 /* Build a relax frag for la instruction when generating PIC,
03723    external symbol first and local symbol second.  */
03724 
03725 static void
03726 build_la_pic (int reg_rd, expressionS exp)
03727 {
03728   symbolS *add_symbol = exp.X_add_symbol;
03729   offsetT add_number = exp.X_add_number;
03730   struct score_it fix_insts[RELAX_INST_NUM];
03731   struct score_it var_insts[RELAX_INST_NUM];
03732   int fix_num = 0;
03733   int var_num = 0;
03734   char tmp[MAX_LITERAL_POOL_SIZE];
03735   int r1_bak;
03736 
03737   r1_bak = nor1;
03738   nor1 = 0;
03739 
03740   if (add_number == 0)
03741     {
03742       fix_num = 1;
03743       var_num = 2;
03744 
03745       /* For an external symbol, only one insn is generated; 
03746          For a local symbol, two insns are generated.  */
03747       /* Fix part
03748          For an external symbol: lw rD, <sym>($gp)
03749                                  (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15)  */
03750       sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
03751       if (append_insn (tmp, FALSE) == (int) FAIL)
03752        return;
03753 
03754       if (reg_rd == PIC_CALL_REG)
03755         inst.reloc.type = BFD_RELOC_SCORE_CALL15;
03756       memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
03757 
03758       /* Var part
03759         For a local symbol :
03760          lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)
03761         addi rD, <sym>       (BFD_RELOC_GOT_LO16) */
03762       inst.reloc.type = BFD_RELOC_SCORE_GOT15;
03763       memcpy (&var_insts[0], &inst, sizeof (struct score_it));
03764       sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, add_symbol->bsym->name);
03765       if (append_insn (tmp, FALSE) == (int) FAIL)
03766        return;
03767 
03768       memcpy (&var_insts[1], &inst, sizeof (struct score_it));
03769       build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
03770     }
03771   else if (add_number >= -0x8000 && add_number <= 0x7fff)
03772     {
03773       /* Insn 1: lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)  */
03774       sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
03775       if (append_insn (tmp, TRUE) == (int) FAIL)
03776        return;
03777 
03778       /* Insn 2  */
03779       fix_num = 1;
03780       var_num = 1;
03781       /* Fix part
03782          For an external symbol: addi rD, <constant> */
03783       sprintf (tmp, "addi r%d, %d", reg_rd, (int)add_number);
03784       if (append_insn (tmp, FALSE) == (int) FAIL)
03785        return;
03786 
03787       memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
03788 
03789       /* Var part
03790         For a local symbol: addi rD, <sym>+<constant>    (BFD_RELOC_GOT_LO16)  */
03791       sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd, add_symbol->bsym->name, (int)add_number);
03792       if (append_insn (tmp, FALSE) == (int) FAIL)
03793        return;
03794 
03795       memcpy (&var_insts[0], &inst, sizeof (struct score_it));
03796       build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
03797     }
03798   else
03799     {
03800       int hi = (add_number >> 16) & 0x0000FFFF;
03801       int lo = add_number & 0x0000FFFF;
03802 
03803       /* Insn 1: lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)  */
03804       sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
03805       if (append_insn (tmp, TRUE) == (int) FAIL)
03806        return;
03807 
03808       /* Insn 2  */
03809       fix_num = 1;
03810       var_num = 1;
03811       /* Fix part
03812         For an external symbol: ldis r1, HI%<constant>  */
03813       sprintf (tmp, "ldis r1, %d", hi);
03814       if (append_insn (tmp, FALSE) == (int) FAIL)
03815        return;
03816 
03817       memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
03818 
03819       /* Var part
03820         For a local symbol: ldis r1, HI%<constant>
03821          but, if lo is outof 16 bit, make hi plus 1  */
03822       if ((lo < -0x8000) || (lo > 0x7fff))
03823        {
03824          hi += 1;
03825        }
03826       sprintf (tmp, "ldis_pic r1, %d", hi);
03827       if (append_insn (tmp, FALSE) == (int) FAIL)
03828        return;
03829 
03830       memcpy (&var_insts[0], &inst, sizeof (struct score_it));
03831       build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
03832 
03833       /* Insn 3  */
03834       fix_num = 1;
03835       var_num = 1;
03836       /* Fix part
03837         For an external symbol: ori r1, LO%<constant>  */
03838       sprintf (tmp, "ori r1, %d", lo);
03839       if (append_insn (tmp, FALSE) == (int) FAIL)
03840        return;
03841 
03842       memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
03843 
03844       /* Var part
03845         For a local symbol: addi r1, <sym>+LO%<constant>    (BFD_RELOC_GOT_LO16)  */
03846       sprintf (tmp, "addi_u_pic r1, %s + %d", add_symbol->bsym->name, lo);
03847       if (append_insn (tmp, FALSE) == (int) FAIL)
03848        return;
03849 
03850       memcpy (&var_insts[0], &inst, sizeof (struct score_it));
03851       build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
03852 
03853       /* Insn 4: add rD, rD, r1  */
03854       sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd);
03855       if (append_insn (tmp, TRUE) == (int) FAIL)
03856        return;
03857 
03858      /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
03859      inst.bwarn = -1;
03860     }
03861 
03862   nor1 = r1_bak;
03863 }
03864 
03865 /* Handle la.  */
03866 static void
03867 do_macro_la_rdi32 (char *str)
03868 {
03869   int reg_rd;
03870 
03871   skip_whitespace (str);
03872   if ((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL
03873       || skip_past_comma (&str) == (int) FAIL)
03874     {
03875       return;
03876     }
03877   else
03878     {
03879       char append_str[MAX_LITERAL_POOL_SIZE];
03880       char *keep_data = str;
03881 
03882       /* la rd, simm16.  */
03883       if (data_op2 (&str, 1, _SIMM16_LA) != (int) FAIL)
03884         {
03885           end_of_line (str);
03886           return;
03887         }
03888       /* la rd, imm32 or la rd, label.  */
03889       else
03890         {
03891           SET_INSN_ERROR (NULL);
03892           str = keep_data;
03893           if ((data_op2 (&str, 1, _VALUE_HI16) == (int) FAIL)
03894               || (end_of_line (str) == (int) FAIL))
03895             {
03896               return;
03897             }
03898           else
03899             {
03900               if ((score_pic == NO_PIC) || (!inst.reloc.exp.X_add_symbol))
03901                 {
03902                   sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
03903                   if (append_insn (append_str, TRUE) == (int) FAIL)
03904                   return;
03905 
03906                   sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
03907                   if (append_insn (append_str, TRUE) == (int) FAIL)
03908                   return;
03909               }
03910              else
03911               {
03912                 assert (inst.reloc.exp.X_add_symbol);
03913                 build_la_pic (reg_rd, inst.reloc.exp);
03914               }
03915 
03916               /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
03917               inst.bwarn = -1;
03918             }
03919         }
03920     }
03921 }
03922 
03923 /* Handle li.  */
03924 static void
03925 do_macro_li_rdi32 (char *str){
03926 
03927   int reg_rd;
03928 
03929   skip_whitespace (str);
03930   if ((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL
03931       || skip_past_comma (&str) == (int) FAIL)
03932     {
03933       return;
03934     }
03935   else
03936     {
03937       char *keep_data = str;
03938 
03939       /* li rd, simm16.  */
03940       if (data_op2 (&str, 1, _SIMM16_LA) != (int) FAIL)
03941         {
03942           end_of_line (str);
03943           return;
03944         }
03945       /* li rd, imm32.  */
03946       else
03947         {
03948           char append_str[MAX_LITERAL_POOL_SIZE];
03949 
03950           str = keep_data;
03951 
03952           if ((data_op2 (&str, 1, _VALUE_HI16) == (int) FAIL)
03953               || (end_of_line (str) == (int) FAIL))
03954             {
03955               return;
03956             }
03957           else if (inst.reloc.exp.X_add_symbol)
03958             {
03959               inst.error = _("li rd label isn't correct instruction form");
03960               return;
03961             }
03962           else
03963             {
03964               sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
03965 
03966               if (append_insn (append_str, TRUE) == (int) FAIL)
03967               return;
03968               else
03969                 {
03970                   sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
03971                   if (append_insn (append_str, TRUE) == (int) FAIL)
03972                   return;
03973 
03974                   /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
03975                   inst.bwarn = -1;
03976                 }
03977             }
03978         }
03979     }
03980 }
03981 
03982 /* Handle mul/mulu/div/divu/rem/remu.  */
03983 static void
03984 do_macro_mul_rdrsrs (char *str)
03985 {
03986   int reg_rd;
03987   int reg_rs1;
03988   int reg_rs2;
03989   char *backupstr;
03990   char append_str[MAX_LITERAL_POOL_SIZE];
03991 
03992   if (university_version == 1)
03993     as_warn ("%s", ERR_FOR_SCORE5U_MUL_DIV);
03994 
03995   strcpy (append_str, str);
03996   backupstr = append_str;
03997   skip_whitespace (backupstr);
03998   if (((reg_rd = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
03999       || (skip_past_comma (&backupstr) == (int) FAIL)
04000       || ((reg_rs1 = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL))
04001     {
04002       inst.error = BAD_ARGS;
04003       return;
04004     }
04005 
04006   if (skip_past_comma (&backupstr) == (int) FAIL)
04007     {
04008       /* rem/remu rA, rB is error format.  */
04009       if (strcmp (inst.name, "rem") == 0 || strcmp (inst.name, "remu") == 0)
04010         {
04011           SET_INSN_ERROR (BAD_ARGS);
04012         }
04013       else
04014         {
04015           SET_INSN_ERROR (NULL);
04016           do_rsrs (str);
04017         }
04018       return;
04019     }
04020   else
04021     {
04022       SET_INSN_ERROR (NULL);
04023       if (((reg_rs2 = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
04024           || (end_of_line (backupstr) == (int) FAIL))
04025         {
04026           return;
04027         }
04028       else
04029         {
04030           char append_str1[MAX_LITERAL_POOL_SIZE];
04031 
04032           if (strcmp (inst.name, "rem") == 0)
04033             {
04034               sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2);
04035               sprintf (append_str1, "mfceh  r%d", reg_rd);
04036             }
04037           else if (strcmp (inst.name, "remu") == 0)
04038             {
04039               sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2);
04040               sprintf (append_str1, "mfceh  r%d", reg_rd);
04041             }
04042           else
04043             {
04044               sprintf (append_str, "%s r%d, r%d", inst.name, reg_rs1, reg_rs2);
04045               sprintf (append_str1, "mfcel  r%d", reg_rd);
04046             }
04047 
04048           /* Output mul/mulu or div/divu or rem/remu.  */
04049           if (append_insn (append_str, TRUE) == (int) FAIL)
04050            return;
04051 
04052           /* Output mfcel or mfceh.  */
04053           if (append_insn (append_str1, TRUE) == (int) FAIL)
04054            return;
04055 
04056           /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
04057           inst.bwarn = -1;
04058         }
04059     }
04060 }
04061 
04062 static void
04063 exp_macro_ldst_abs (char *str)
04064 {
04065   int reg_rd;
04066   char *backupstr, *tmp;
04067   char append_str[MAX_LITERAL_POOL_SIZE];
04068   char verifystr[MAX_LITERAL_POOL_SIZE];
04069   struct score_it inst_backup;
04070   int r1_bak = 0;
04071 
04072   r1_bak = nor1;
04073   nor1 = 0;
04074   memcpy (&inst_backup, &inst, sizeof (struct score_it));
04075 
04076   strcpy (verifystr, str);
04077   backupstr = verifystr;
04078   skip_whitespace (backupstr);
04079   if ((reg_rd = reg_required_here (&backupstr, -1, REG_TYPE_SCORE)) == (int) FAIL)
04080     return;
04081 
04082   tmp = backupstr;
04083   if (skip_past_comma (&backupstr) == (int) FAIL)
04084     return;
04085 
04086   backupstr = tmp;
04087   sprintf (append_str, "li r1  %s", backupstr);
04088   append_insn (append_str, TRUE);
04089 
04090   memcpy (&inst, &inst_backup, sizeof (struct score_it));
04091   sprintf (append_str, " r%d, [r1,0]", reg_rd);
04092   do_ldst_insn (append_str);
04093 
04094   nor1 = r1_bak;
04095 }
04096 
04097 static int
04098 nopic_need_relax (symbolS * sym, int before_relaxing)
04099 {
04100   if (sym == NULL)
04101     return 0;
04102   else if (USE_GLOBAL_POINTER_OPT && g_switch_value > 0)
04103     {
04104       const char *symname;
04105       const char *segname;
04106 
04107       /* Find out whether this symbol can be referenced off the $gp
04108          register.  It can be if it is smaller than the -G size or if
04109          it is in the .sdata or .sbss section.  Certain symbols can
04110          not be referenced off the $gp, although it appears as though
04111          they can.  */
04112       symname = S_GET_NAME (sym);
04113       if (symname != (const char *)NULL
04114           && (strcmp (symname, "eprol") == 0
04115               || strcmp (symname, "etext") == 0
04116               || strcmp (symname, "_gp") == 0
04117               || strcmp (symname, "edata") == 0
04118               || strcmp (symname, "_fbss") == 0
04119               || strcmp (symname, "_fdata") == 0
04120               || strcmp (symname, "_ftext") == 0
04121               || strcmp (symname, "end") == 0
04122               || strcmp (symname, GP_DISP_LABEL) == 0))
04123         {
04124           return 1;
04125         }
04126       else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0
04127       /* We must defer this decision until after the whole file has been read,
04128          since there might be a .extern after the first use of this symbol.  */
04129                || (before_relaxing
04130                    && S_GET_VALUE (sym) == 0)
04131                || (S_GET_VALUE (sym) != 0
04132                    && S_GET_VALUE (sym) <= g_switch_value)))
04133         {
04134           return 0;
04135         }
04136 
04137       segname = segment_name (S_GET_SEGMENT (sym));
04138       return (strcmp (segname, ".sdata") != 0
04139              && strcmp (segname, ".sbss") != 0
04140              && strncmp (segname, ".sdata.", 7) != 0
04141              && strncmp (segname, ".gnu.linkonce.s.", 16) != 0);
04142     }
04143   /* We are not optimizing for the $gp register.  */
04144   else
04145     return 1;
04146 }
04147 
04148 /* Build a relax frag for lw/st instruction when generating PIC,
04149    external symbol first and local symbol second.  */
04150 
04151 static void
04152 build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name)
04153 {
04154   symbolS *add_symbol = exp.X_add_symbol;
04155   int add_number = exp.X_add_number;
04156   struct score_it fix_insts[RELAX_INST_NUM];
04157   struct score_it var_insts[RELAX_INST_NUM];
04158   int fix_num = 0;
04159   int var_num = 0;
04160   char tmp[MAX_LITERAL_POOL_SIZE];
04161   int r1_bak;
04162 
04163   r1_bak = nor1;
04164   nor1 = 0;
04165 
04166   if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff))
04167     {
04168       fix_num = 1;
04169       var_num = 2;
04170 
04171       /* For an external symbol, two insns are generated;
04172          For a local symbol, three insns are generated.  */
04173       /* Fix part
04174          For an external symbol: lw rD, <sym>($gp)
04175                                  (BFD_RELOC_SCORE_GOT15)  */
04176       sprintf (tmp, "lw_pic r1, %s", add_symbol->bsym->name);
04177       if (append_insn (tmp, FALSE) == (int) FAIL)
04178         return;
04179 
04180       memcpy (&fix_insts[0], &inst, sizeof (struct score_it));
04181 
04182       /* Var part
04183         For a local symbol :
04184          lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)
04185         addi rD, <sym>       (BFD_RELOC_GOT_LO16) */
04186       inst.reloc.type = BFD_RELOC_SCORE_GOT15;
04187       memcpy (&var_insts[0], &inst, sizeof (struct score_it));
04188       sprintf (tmp, "addi_s_pic r1, %s", add_symbol->bsym->name);
04189       if (append_insn (tmp, FALSE) == (int) FAIL)
04190         return;
04191 
04192       memcpy (&var_insts[1], &inst, sizeof (struct score_it));
04193       build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
04194 
04195       /* Insn 2 or Insn 3: lw/st rD, [r1, constant]  */
04196       sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number);
04197       if (append_insn (tmp, TRUE) == (int) FAIL)
04198         return;
04199 
04200       /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
04201       inst.bwarn = -1;
04202     }
04203   else
04204     {
04205       inst.error = _("PIC code offset overflow (max 16 signed bits)");
04206       return;
04207     }
04208 
04209   nor1 = r1_bak;
04210 }
04211 
04212 static void
04213 do_macro_ldst_label (char *str)
04214 {
04215   int i;
04216   int ldst_gp_p = 0;
04217   int reg_rd;
04218   int r1_bak;
04219   char *backup_str;
04220   char *label_str;
04221   char *absolute_value;
04222   char append_str[3][MAX_LITERAL_POOL_SIZE];
04223   char verifystr[MAX_LITERAL_POOL_SIZE];
04224   struct score_it inst_backup;
04225   struct score_it inst_expand[3];
04226   struct score_it inst_main;
04227 
04228   memcpy (&inst_backup, &inst, sizeof (struct score_it));
04229   strcpy (verifystr, str);
04230   backup_str = verifystr;
04231 
04232   skip_whitespace (backup_str);
04233   if ((reg_rd = reg_required_here (&backup_str, -1, REG_TYPE_SCORE)) == (int) FAIL)
04234     return;
04235 
04236   if (skip_past_comma (&backup_str) == (int) FAIL)
04237     return;
04238 
04239   label_str = backup_str;
04240 
04241   /* Ld/st rD, [rA, imm]      ld/st rD, [rA]+, imm      ld/st rD, [rA, imm]+.  */
04242   if (*backup_str == '[')
04243     {
04244       inst.type = Rd_rvalueRs_preSI12;
04245       do_ldst_insn (str);
04246       return;
04247     }
04248 
04249   /* Ld/st rD, imm.  */
04250   absolute_value = backup_str;
04251   inst.type = Rd_rvalueRs_SI15;
04252   if ((my_get_expression (&inst.reloc.exp, &backup_str) == (int) FAIL)
04253       || (validate_immediate (inst.reloc.exp.X_add_number, _VALUE) == (int) FAIL)
04254       || (end_of_line (backup_str) == (int) FAIL))
04255     {
04256       return;
04257     }
04258   else
04259     {
04260       if (inst.reloc.exp.X_add_symbol == 0)
04261         {
04262           memcpy (&inst, &inst_backup, sizeof (struct score_it));
04263           exp_macro_ldst_abs (str);
04264           return;
04265         }
04266     }
04267 
04268   /* Ld/st rD, label.  */
04269   inst.type = Rd_rvalueRs_SI15;
04270   backup_str = absolute_value;
04271   if ((data_op2 (&backup_str, 1, _GP_IMM15) == (int) FAIL)
04272       || (end_of_line (backup_str) == (int) FAIL))
04273     {
04274       return;
04275     }
04276   else
04277     {
04278       if (inst.reloc.exp.X_add_symbol == 0)
04279         {
04280           if (!inst.error)
04281            inst.error = BAD_ARGS;
04282 
04283           return;
04284         }
04285 
04286       if (score_pic == PIC)
04287         {
04288           int ldst_idx = 0;
04289           ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
04290           build_lwst_pic (reg_rd, inst.reloc.exp, score_ldst_insns[ldst_idx * 3 + 0].template);
04291           return;
04292         }
04293       else
04294        {
04295           if ((inst.reloc.exp.X_add_number <= 0x3fff)
04296                && (inst.reloc.exp.X_add_number >= -0x4000)
04297                && (!nopic_need_relax (inst.reloc.exp.X_add_symbol, 1)))
04298            {
04299               int ldst_idx = 0;
04300 
04301               /* Assign the real opcode.  */
04302               ldst_idx = inst.instruction & OPC_PSEUDOLDST_MASK;
04303               inst.instruction &= ~OPC_PSEUDOLDST_MASK;
04304               inst.instruction |= score_ldst_insns[ldst_idx * 3 + 0].value;
04305               inst.instruction |= reg_rd << 20;
04306               inst.instruction |= GP << 15;
04307               inst.relax_inst = 0x8000;
04308               inst.relax_size = 0;
04309               ldst_gp_p = 1;
04310            }
04311        }
04312     }
04313 
04314   /* Backup inst.  */
04315   memcpy (&inst_main, &inst, sizeof (struct score_it));
04316   r1_bak = nor1;
04317   nor1 = 0;
04318 
04319   /* Determine which instructions should be output.  */
04320   sprintf (append_str[0], "ld_i32hi r1, %s", label_str);
04321   sprintf (append_str[1], "ld_i32lo r1, %s", label_str);
04322   sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd);
04323 
04324   /* Generate three instructions.
04325      la r1, label
04326      ld/st rd, [r1, 0]  */
04327   for (i = 0; i < 3; i++)
04328     {
04329       if (append_insn (append_str[i], FALSE) == (int) FAIL)
04330        return;
04331 
04332       memcpy (&inst_expand[i], &inst, sizeof (struct score_it));
04333     }
04334 
04335   if (ldst_gp_p)
04336     {
04337       char *p;
04338 
04339       /* Adjust instruction opcode and to be relaxed instruction opcode.  */
04340       inst_main.instruction = adjust_paritybit (inst_main.instruction, GET_INSN_CLASS (inst_main.type));
04341       inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size;
04342       inst_main.type = Insn_GP;
04343 
04344       for (i = 0; i < 3; i++)
04345        inst_expand[i].instruction = adjust_paritybit (inst_expand[i].instruction
04346                                                  , GET_INSN_CLASS (inst_expand[i].type));
04347 
04348       /* Check data dependency.  */
04349       handle_dependency (&inst_main);
04350 
04351       /* Start a new frag if frag_now is not empty.  */
04352       if (frag_now_fix () != 0)
04353         {
04354           if (!frag_now->tc_frag_data.is_insn)
04355            frag_wane (frag_now);
04356 
04357           frag_new (0);
04358         }
04359       frag_grow (20);
04360 
04361       /* Write fr_fix part.  */
04362       p = frag_more (inst_main.size);
04363       md_number_to_chars (p, inst_main.instruction, inst_main.size);
04364 
04365       if (inst_main.reloc.type != BFD_RELOC_NONE)
04366         {
04367           fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
04368                          &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
04369         }
04370 
04371 #ifdef OBJ_ELF
04372       dwarf2_emit_insn (inst_main.size);
04373 #endif
04374 
04375       /* GP instruction can not do optimization, only can do relax between
04376          1 instruction and 3 instructions.  */
04377       p = frag_var (rs_machine_dependent, inst_main.relax_size + RELAX_PAD_BYTE, 0,
04378                     RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0),
04379                     inst_main.reloc.exp.X_add_symbol, 0, NULL);
04380 
04381       /* Write fr_var part.
04382          no calling gen_insn_frag, no fixS will be generated.  */
04383       md_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
04384       p += inst_expand[0].size;
04385       md_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
04386       p += inst_expand[1].size;
04387       md_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size);
04388     }
04389   else
04390     {
04391       gen_insn_frag (&inst_expand[0], NULL);
04392       gen_insn_frag (&inst_expand[1], NULL);
04393       gen_insn_frag (&inst_expand[2], NULL);
04394     }
04395   nor1 = r1_bak;
04396 
04397   /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
04398   inst.bwarn = -1;
04399 }
04400 
04401 static void
04402 do_lw_pic (char *str)
04403 {
04404   int reg_rd;
04405 
04406   skip_whitespace (str);
04407   if (((reg_rd = reg_required_here (&str, 20, REG_TYPE_SCORE)) == (int) FAIL)
04408       || (skip_past_comma (&str) == (int) FAIL)
04409       || (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL)
04410       || (end_of_line (str) == (int) FAIL))
04411     {
04412       return;
04413     }
04414   else
04415     {
04416       if (inst.reloc.exp.X_add_symbol == 0)
04417         {
04418           if (!inst.error)
04419            inst.error = BAD_ARGS;
04420 
04421           return;
04422         }
04423 
04424       inst.instruction |= GP << 15;
04425       inst.reloc.type = BFD_RELOC_SCORE_GOT15;
04426     }
04427 }
04428 
04429 static void
04430 do_empty (char *str)
04431 {
04432   str = str;
04433   if (university_version == 1)
04434     {
04435       if (((inst.instruction & 0x3e0003ff) == 0x0c000004)
04436           || ((inst.instruction & 0x3e0003ff) == 0x0c000024)
04437           || ((inst.instruction & 0x3e0003ff) == 0x0c000044)
04438           || ((inst.instruction & 0x3e0003ff) == 0x0c000064))
04439         {
04440           inst.error = ERR_FOR_SCORE5U_MMU;
04441           return;
04442         }
04443     }
04444   if (end_of_line (str) == (int) FAIL)
04445     return;
04446 
04447   if (inst.relax_inst != 0x8000)
04448     {
04449       if (inst.type == NO_OPD)
04450         {
04451           inst.relax_size = 2;
04452         }
04453       else
04454         {
04455           inst.relax_size = 4;
04456         }
04457     }
04458 }
04459 
04460 static void
04461 do_jump (char *str)
04462 {
04463   char *save_in;
04464 
04465   skip_whitespace (str);
04466   if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
04467       || end_of_line (str) == (int) FAIL)
04468     return;
04469 
04470   if (inst.reloc.exp.X_add_symbol == 0)
04471     {
04472       inst.error = _("lacking label  ");
04473       return;
04474     }
04475 
04476   if (((inst.reloc.exp.X_add_number & 0xff000000) != 0)
04477       && ((inst.reloc.exp.X_add_number & 0xff000000) != 0xff000000))
04478     {
04479       inst.error = _("invalid constant: 25 bit expression not in range -2^24..2^24");
04480       return;
04481     }
04482 
04483   save_in = input_line_pointer;
04484   input_line_pointer = str;
04485   inst.reloc.type = BFD_RELOC_SCORE_JMP;
04486   inst.reloc.pc_rel = 1;
04487   input_line_pointer = save_in;
04488 }
04489 
04490 static void
04491 do16_jump (char *str)
04492 {
04493   skip_whitespace (str);
04494   if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
04495       || end_of_line (str) == (int) FAIL)
04496     {
04497       return;
04498     }
04499   else if (inst.reloc.exp.X_add_symbol == 0)
04500     {
04501       inst.error = _("lacking label  ");
04502       return;
04503     }
04504   else if (((inst.reloc.exp.X_add_number & 0xfffff800) != 0)
04505            && ((inst.reloc.exp.X_add_number & 0xfffff800) != 0xfffff800))
04506     {
04507       inst.error = _("invalid constant: 12 bit expression not in range -2^11..2^11");
04508       return;
04509     }
04510 
04511   inst.reloc.type = BFD_RELOC_SCORE16_JMP;
04512   inst.reloc.pc_rel = 1;
04513 }
04514 
04515 static void
04516 do_branch (char *str)
04517 {
04518   unsigned long abs_value = 0;
04519 
04520   if (my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
04521       || end_of_line (str) == (int) FAIL)
04522     {
04523       return;
04524     }
04525   else if (inst.reloc.exp.X_add_symbol == 0)
04526     {
04527       inst.error = _("lacking label  ");
04528       return;
04529     }
04530   else if (((inst.reloc.exp.X_add_number & 0xff000000) != 0)
04531            && ((inst.reloc.exp.X_add_number & 0xff000000) != 0xff000000))
04532     {
04533       inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19");
04534       return;
04535     }
04536 
04537   inst.reloc.type = BFD_RELOC_SCORE_BRANCH;
04538   inst.reloc.pc_rel = 1;
04539 
04540   /* Branch 32  offset field : 20 bit, 16 bit branch offset field : 8 bit.  */
04541   inst.instruction |= (inst.reloc.exp.X_add_number & 0x3fe) | ((inst.reloc.exp.X_add_number & 0xffc00) << 5);
04542 
04543   /* Compute 16 bit branch instruction.  */
04544   if ((inst.relax_inst != 0x8000) && (abs_value & 0xfffffe00) == 0)
04545     {
04546       inst.relax_inst |= (((inst.instruction >> 10) & 0xf) << 8);
04547       inst.relax_inst |= ((inst.reloc.exp.X_add_number >> 1) & 0xff);
04548       inst.relax_size = 2;
04549     }
04550   else
04551     {
04552       inst.relax_inst = 0x8000;
04553     }
04554 }
04555 
04556 static void
04557 do16_branch (char *str)
04558 {
04559   if ((my_get_expression (&inst.reloc.exp, &str) == (int) FAIL
04560       || end_of_line (str) == (int) FAIL))
04561     {
04562       ;
04563     }
04564   else if (inst.reloc.exp.X_add_symbol == 0)
04565     {
04566       inst.error = _("lacking label");
04567     }
04568   else if (((inst.reloc.exp.X_add_number & 0xffffff00) != 0)
04569            && ((inst.reloc.exp.X_add_number & 0xffffff00) != 0xffffff00))
04570     {
04571       inst.error = _("invalid constant: 9 bit expression not in range -2^8..2^8");
04572     }
04573   else
04574     {
04575       inst.reloc.type = BFD_RELOC_SCORE16_BRANCH;
04576       inst.reloc.pc_rel = 1;
04577       inst.instruction |= ((inst.reloc.exp.X_add_number >> 1) & 0xff);
04578     }
04579 }
04580 
04581 /* Iterate over the base tables to create the instruction patterns.  */
04582 static void
04583 build_score_ops_hsh (void)
04584 {
04585   unsigned int i;
04586   static struct obstack insn_obstack;
04587 
04588   obstack_begin (&insn_obstack, 4000);
04589   for (i = 0; i < sizeof (score_insns) / sizeof (struct asm_opcode); i++)
04590     {
04591       const struct asm_opcode *insn = score_insns + i;
04592       unsigned len = strlen (insn->template);
04593       struct asm_opcode *new;
04594       char *template;
04595       new = obstack_alloc (&insn_obstack, sizeof (struct asm_opcode));
04596       template = obstack_alloc (&insn_obstack, len + 1);
04597 
04598       strcpy (template, insn->template);
04599       new->template = template;
04600       new->parms = insn->parms;
04601       new->value = insn->value;
04602       new->relax_value = insn->relax_value;
04603       new->type = insn->type;
04604       new->bitmask = insn->bitmask;
04605       hash_insert (score_ops_hsh, new->template, (void *) new);
04606     }
04607 }
04608 
04609 static void
04610 build_dependency_insn_hsh (void)
04611 {
04612   unsigned int i;
04613   static struct obstack dependency_obstack;
04614 
04615   obstack_begin (&dependency_obstack, 4000);
04616   for (i = 0; i < sizeof (insn_to_dependency_table) / sizeof (insn_to_dependency_table[0]); i++)
04617     {
04618       const struct insn_to_dependency *tmp = insn_to_dependency_table + i;
04619       unsigned len = strlen (tmp->insn_name);
04620       struct insn_to_dependency *new;
04621 
04622       new = obstack_alloc (&dependency_obstack, sizeof (struct insn_to_dependency));
04623       new->insn_name = obstack_alloc (&dependency_obstack, len + 1);
04624 
04625       strcpy (new->insn_name, tmp->insn_name);
04626       new->type = tmp->type;
04627       hash_insert (dependency_insn_hsh, new->insn_name, (void *) new);
04628     }
04629 }
04630 
04631 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
04632    for use in the a.out file, and stores them in the array pointed to by buf.
04633    This knows about the endian-ness of the target machine and does
04634    THE RIGHT THING, whatever it is.  Possible values for n are 1 (byte)
04635    2 (short) and 4 (long)  Floating numbers are put out as a series of
04636    LITTLENUMS (shorts, here at least).  */
04637 
04638 void
04639 md_number_to_chars (char *buf, valueT val, int n)
04640 {
04641   if (target_big_endian)
04642     number_to_chars_bigendian (buf, val, n);
04643   else
04644     number_to_chars_littleendian (buf, val, n);
04645 }
04646 
04647 static valueT
04648 md_chars_to_number (char *buf, int n)
04649 {
04650   valueT result = 0;
04651   unsigned char *where = (unsigned char *)buf;
04652 
04653   if (target_big_endian)
04654     {
04655       while (n--)
04656         {
04657           result <<= 8;
04658           result |= (*where++ & 255);
04659         }
04660     }
04661   else
04662     {
04663       while (n--)
04664         {
04665           result <<= 8;
04666           result |= (where[n] & 255);
04667         }
04668     }
04669 
04670   return result;
04671 }
04672 
04673 /* Turn a string in input_line_pointer into a floating point constant
04674    of type TYPE, and store the appropriate bytes in *LITP.  The number
04675    of LITTLENUMS emitted is stored in *SIZEP.  An error message is
04676    returned, or NULL on OK.
04677 
04678    Note that fp constants aren't represent in the normal way on the ARM.
04679    In big endian mode, things are as expected.  However, in little endian
04680    mode fp constants are big-endian word-wise, and little-endian byte-wise
04681    within the words.  For example, (double) 1.1 in big endian mode is
04682    the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
04683    the byte sequence 99 99 f1 3f 9a 99 99 99.  */
04684 
04685 char *
04686 md_atof (int type, char *litP, int *sizeP)
04687 {
04688   int prec;
04689   LITTLENUM_TYPE words[MAX_LITTLENUMS];
04690   char *t;
04691   int i;
04692 
04693   switch (type)
04694     {
04695     case 'f':
04696     case 'F':
04697     case 's':
04698     case 'S':
04699       prec = 2;
04700       break;
04701     case 'd':
04702     case 'D':
04703     case 'r':
04704     case 'R':
04705       prec = 4;
04706       break;
04707     case 'x':
04708     case 'X':
04709     case 'p':
04710     case 'P':
04711       prec = 6;
04712       break;
04713     default:
04714       *sizeP = 0;
04715       return _("bad call to MD_ATOF()");
04716     }
04717 
04718   t = atof_ieee (input_line_pointer, type, words);
04719   if (t)
04720     input_line_pointer = t;
04721   *sizeP = prec * 2;
04722 
04723   if (target_big_endian)
04724     {
04725       for (i = 0; i < prec; i++)
04726         {
04727           md_number_to_chars (litP, (valueT) words[i], 2);
04728           litP += 2;
04729         }
04730     }
04731   else
04732     {
04733       for (i = 0; i < prec; i += 2)
04734         {
04735           md_number_to_chars (litP, (valueT) words[i + 1], 2);
04736           md_number_to_chars (litP + 2, (valueT) words[i], 2);
04737           litP += 4;
04738         }
04739     }
04740 
04741   return 0;
04742 }
04743 
04744 /* Return true if the given symbol should be considered local for PIC.  */
04745 
04746 static bfd_boolean
04747 pic_need_relax (symbolS *sym, asection *segtype)
04748 {
04749   asection *symsec;
04750   bfd_boolean linkonce;
04751 
04752   /* Handle the case of a symbol equated to another symbol.  */
04753   while (symbol_equated_reloc_p (sym))
04754     {
04755       symbolS *n;
04756 
04757       /* It's possible to get a loop here in a badly written
04758         program.  */
04759       n = symbol_get_value_expression (sym)->X_add_symbol;
04760       if (n == sym)
04761        break;
04762       sym = n;
04763     }
04764 
04765   symsec = S_GET_SEGMENT (sym);
04766 
04767   /* duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
04768   linkonce = FALSE;
04769   if (symsec != segtype && ! S_IS_LOCAL (sym))
04770     {
04771       if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE) != 0)
04772        linkonce = TRUE;
04773 
04774       /* The GNU toolchain uses an extension for ELF: a section
04775          beginning with the magic string .gnu.linkonce is a linkonce
04776          section.  */
04777       if (strncmp (segment_name (symsec), ".gnu.linkonce",
04778                  sizeof ".gnu.linkonce" - 1) == 0)
04779        linkonce = TRUE;
04780     }
04781 
04782   /* This must duplicate the test in adjust_reloc_syms.  */
04783   return (symsec != &bfd_und_section
04784            && symsec != &bfd_abs_section
04785          && ! bfd_is_com_section (symsec)
04786            && !linkonce
04787 #ifdef OBJ_ELF
04788          /* A global or weak symbol is treated as external.  */
04789          && (OUTPUT_FLAVOR != bfd_target_elf_flavour
04790              || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
04791 #endif
04792          );
04793 }
04794 
04795 static int
04796 judge_size_before_relax (fragS * fragp, asection *sec)
04797 {
04798   int change = 0;
04799 
04800   if (score_pic == NO_PIC)
04801     change = nopic_need_relax (fragp->fr_symbol, 0);
04802   else
04803     change = pic_need_relax (fragp->fr_symbol, sec);
04804 
04805   if (change == 1)
04806     {
04807       /* Only at the first time determining whether GP instruction relax should be done,
04808          return the difference between insntruction size and instruction relax size.  */
04809       if (fragp->fr_opcode == NULL)
04810        {
04811          fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
04812          fragp->fr_opcode = fragp->fr_literal + RELAX_RELOC1 (fragp->fr_subtype);
04813           return RELAX_NEW (fragp->fr_subtype) - RELAX_OLD (fragp->fr_subtype);
04814        }
04815     }
04816 
04817   return 0;
04818 }
04819 
04820 /* In this function, we determine whether GP instruction should do relaxation,
04821    for the label being against was known now.
04822    Doing this here but not in md_relax_frag() can induce iteration times
04823    in stage of doing relax.  */
04824 int
04825 md_estimate_size_before_relax (fragS * fragp, asection * sec ATTRIBUTE_UNUSED)
04826 {
04827   if ((RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
04828       || (RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
04829     return judge_size_before_relax (fragp, sec);
04830 
04831   return 0;
04832 }
04833 
04834 static int
04835 b32_relax_to_b16 (fragS * fragp)
04836 {
04837   int grows = 0;
04838   int relaxable_p = 0;
04839   int old;
04840   int new;
04841   int frag_addr = fragp->fr_address + fragp->insn_addr;
04842 
04843   addressT symbol_address = 0;
04844   symbolS *s;
04845   offsetT offset;
04846   unsigned long value;
04847   unsigned long abs_value;
04848 
04849   /* FIXME : here may be able to modify better .
04850      I don't know how to get the fragp's section ,
04851      so in relax stage , it may be wrong to calculate the symbol's offset when the frag's section
04852      is different from the symbol's.  */
04853 
04854   old = RELAX_OLD (fragp->fr_subtype);
04855   new = RELAX_NEW (fragp->fr_subtype);
04856   relaxable_p = RELAX_OPT (fragp->fr_subtype);
04857 
04858   s = fragp->fr_symbol;
04859   /* b/bl immediate  */
04860   if (s == NULL)
04861     frag_addr = 0;
04862   else
04863     {
04864       if (s->bsym != 0)
04865        symbol_address = (addressT) s->sy_frag->fr_address;
04866     }
04867 
04868   value = md_chars_to_number (fragp->fr_literal, INSN_SIZE);
04869 
04870   /* b 32's offset : 20 bit, b 16's tolerate field : 0xff.  */
04871   offset = ((value & 0x3ff0000) >> 6) | (value & 0x3fe);
04872   if ((offset & 0x80000) == 0x80000)
04873     offset |= 0xfff00000;
04874 
04875   abs_value = offset + symbol_address - frag_addr;
04876   if ((abs_value & 0x80000000) == 0x80000000)
04877     abs_value = 0xffffffff - abs_value + 1;
04878 
04879   /* Relax branch 32 to branch 16.  */
04880   if (relaxable_p && (s->bsym != NULL) && ((abs_value & 0xffffff00) == 0)
04881       && (S_IS_DEFINED (s) && !S_IS_COMMON (s) && !S_IS_EXTERNAL (s)))
04882     {
04883       /* do nothing.  */
04884     }
04885   else
04886     {
04887       /* Branch 32 can not be relaxed to b 16, so clear OPT bit.  */
04888       fragp->fr_opcode = NULL;
04889       fragp->fr_subtype = RELAX_OPT_CLEAR (fragp->fr_subtype);
04890     }
04891 
04892   return grows;
04893 }
04894 
04895 /* Main purpose is to determine whether one frag should do relax.
04896    frag->fr_opcode indicates this point.  */
04897 
04898 int
04899 score_relax_frag (asection * sec ATTRIBUTE_UNUSED, fragS * fragp, long stretch ATTRIBUTE_UNUSED)
04900 {
04901   int grows = 0;
04902   int insn_size;
04903   int insn_relax_size;
04904   int do_relax_p = 0;           /* Indicate doing relaxation for this frag.  */
04905   int relaxable_p = 0;
04906   bfd_boolean word_align_p = FALSE;
04907   fragS *next_fragp;
04908 
04909   /* If the instruction address is odd, make it half word align first.  */
04910   if ((fragp->fr_address) % 2 != 0)
04911     {
04912       if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
04913        {
04914           fragp->insn_addr = 1;
04915           grows += 1;
04916        }
04917     }
04918 
04919   word_align_p = ((fragp->fr_address + fragp->insn_addr) % 4 == 0) ? TRUE : FALSE;
04920 
04921   /* Get instruction size and relax size after the last relaxation.  */
04922   if (fragp->fr_opcode)
04923     {
04924       insn_size = RELAX_NEW (fragp->fr_subtype);
04925       insn_relax_size = RELAX_OLD (fragp->fr_subtype);
04926     }
04927   else
04928     {
04929       insn_size = RELAX_OLD (fragp->fr_subtype);
04930       insn_relax_size = RELAX_NEW (fragp->fr_subtype);
04931     }
04932 
04933   /* Handle specially for GP instruction.  for, judge_size_before_relax() has already determine
04934      whether the GP instruction should do relax.  */
04935   if ((RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
04936       || (RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
04937     {
04938       if (!word_align_p)
04939         {
04940           if (fragp->insn_addr < 2)
04941             {
04942               fragp->insn_addr += 2;
04943               grows += 2;
04944             }
04945           else
04946             {
04947               fragp->insn_addr -= 2;
04948               grows -= 2;
04949             }
04950         }
04951 
04952       if (fragp->fr_opcode)
04953        fragp->fr_fix = RELAX_NEW (fragp->fr_subtype) + fragp->insn_addr;
04954       else
04955        fragp->fr_fix = RELAX_OLD (fragp->fr_subtype) + fragp->insn_addr;
04956     }
04957   else
04958     {
04959       if (RELAX_TYPE (fragp->fr_subtype) == PC_DISP19div2)
04960        b32_relax_to_b16 (fragp);
04961 
04962       relaxable_p = RELAX_OPT (fragp->fr_subtype);
04963       next_fragp = fragp->fr_next;
04964       while ((next_fragp) && (next_fragp->fr_type != rs_machine_dependent))
04965        {
04966           next_fragp = next_fragp->fr_next;
04967        }
04968 
04969       if (next_fragp)
04970         {
04971           int n_insn_size;
04972           int n_relaxable_p = 0;
04973 
04974           if (next_fragp->fr_opcode)
04975             {
04976               n_insn_size = RELAX_NEW (next_fragp->fr_subtype);
04977             }
04978           else
04979             {
04980               n_insn_size = RELAX_OLD (next_fragp->fr_subtype);
04981             }
04982 
04983           if (RELAX_TYPE (next_fragp->fr_subtype) == PC_DISP19div2)
04984             b32_relax_to_b16 (next_fragp);
04985           n_relaxable_p = RELAX_OPT (next_fragp->fr_subtype);
04986 
04987           if (word_align_p)
04988             {
04989               if (insn_size == 4)
04990                 {
04991                   /* 32 -> 16.  */
04992                   if (relaxable_p && ((n_insn_size == 2) || n_relaxable_p))
04993                     {
04994                       grows -= 2;
04995                       do_relax_p = 1;
04996                     }
04997                 }
04998               else if (insn_size == 2)
04999                 {
05000                   /* 16 -> 32.  */
05001                   if (relaxable_p && (((n_insn_size == 4) && !n_relaxable_p) || (n_insn_size > 4)))
05002                     {
05003                       grows += 2;
05004                       do_relax_p = 1;
05005                     }
05006                 }
05007               else
05008                 {
05009                 abort ();
05010                 }
05011             }
05012           else
05013             {
05014               if (insn_size == 4)
05015                 {
05016                   /* 32 -> 16.  */
05017                   if (relaxable_p)
05018                     {
05019                       grows -= 2;
05020                       do_relax_p = 1;
05021                     }
05022                   /* Make the 32 bit insturction word align.  */
05023                   else
05024                     {
05025                       fragp->insn_addr += 2;
05026                       grows += 2;
05027                   }
05028                 }
05029               else if (insn_size == 2)
05030                 {
05031                   /* Do nothing.  */
05032                 }
05033               else
05034                 {
05035                 abort ();
05036                 }
05037             }
05038         }
05039       else
05040         {
05041          /* Here, try best to do relax regardless fragp->fr_next->fr_type.  */
05042           if (word_align_p == FALSE)
05043             {
05044               if (insn_size % 4 == 0)
05045                 {
05046                   /* 32 -> 16.  */
05047                   if (relaxable_p)
05048                     {
05049                       grows -= 2;
05050                       do_relax_p = 1;
05051                     }
05052                   else
05053                     {
05054                       fragp->insn_addr += 2;
05055                       grows += 2;
05056                     }
05057                 }
05058             }
05059           else
05060             {
05061              /* Do nothing.  */
05062             }
05063         }
05064 
05065       /* fragp->fr_opcode indicates whether this frag should be relaxed.  */
05066       if (do_relax_p)
05067         {
05068           if (fragp->fr_opcode)
05069             {
05070               fragp->fr_opcode = NULL;
05071              /* Guarantee estimate stage is correct.  */
05072               fragp->fr_fix = RELAX_OLD (fragp->fr_subtype);
05073               fragp->fr_fix += fragp->insn_addr;
05074             }
05075           else
05076             {
05077               fragp->fr_opcode = fragp->fr_literal + RELAX_RELOC1 (fragp->fr_subtype);
05078              /* Guarantee estimate stage is correct.  */
05079               fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
05080               fragp->fr_fix += fragp->insn_addr;
05081             }
05082         }
05083       else
05084        {
05085           if (fragp->fr_opcode)
05086             {
05087              /* Guarantee estimate stage is correct.  */
05088               fragp->fr_fix = RELAX_NEW (fragp->fr_subtype);
05089               fragp->fr_fix += fragp->insn_addr;
05090             }
05091           else
05092             {
05093              /* Guarantee estimate stage is correct.  */
05094               fragp->fr_fix = RELAX_OLD (fragp->fr_subtype);
05095               fragp->fr_fix += fragp->insn_addr;
05096             }
05097        }
05098     }
05099 
05100   return grows;
05101 }
05102 
05103 void
05104 md_convert_frag (bfd * abfd ATTRIBUTE_UNUSED, segT sec ATTRIBUTE_UNUSED, fragS * fragp)
05105 {
05106   int old;
05107   int new;
05108   char backup[20];
05109   fixS *fixp;
05110 
05111   old = RELAX_OLD (fragp->fr_subtype);
05112   new = RELAX_NEW (fragp->fr_subtype);
05113 
05114   /* fragp->fr_opcode indicates whether this frag should be relaxed.  */
05115   if (fragp->fr_opcode == NULL)
05116     {
05117       memcpy (backup, fragp->fr_literal, old);
05118       fragp->fr_fix = old;
05119     }
05120   else
05121     {
05122       memcpy (backup, fragp->fr_literal + old, new);
05123       fragp->fr_fix = new;
05124     }
05125 
05126   fixp = fragp->tc_frag_data.fixp;
05127   while (fixp && fixp->fx_frag == fragp && fixp->fx_where < old)
05128     {
05129       if (fragp->fr_opcode)
05130        fixp->fx_done = 1;
05131       fixp = fixp->fx_next;
05132     }
05133   while (fixp && fixp->fx_frag == fragp)
05134     {
05135       if (fragp->fr_opcode)
05136        fixp->fx_where -= old + fragp->insn_addr;
05137       else
05138        fixp->fx_done = 1;
05139       fixp = fixp->fx_next;
05140     }
05141 
05142   if (fragp->insn_addr)
05143     {
05144       md_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
05145     }
05146   memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
05147   fragp->fr_fix += fragp->insn_addr;
05148 }
05149 
05150 /* Implementation of md_frag_check.
05151    Called after md_convert_frag().  */
05152 
05153 void
05154 score_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
05155 {
05156   know (fragp->insn_addr <= RELAX_PAD_BYTE);
05157 }
05158 
05159 bfd_boolean
05160 score_fix_adjustable (fixS * fixP)
05161 {
05162   if (fixP->fx_addsy == NULL)
05163     {
05164       return 1;
05165     }
05166   else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
05167       && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
05168     {
05169       return 0;
05170     }
05171   else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
05172       || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
05173     {
05174       return 0;
05175     }
05176 
05177   return 1;
05178 }
05179 
05180 /* Implementation of TC_VALIDATE_FIX.
05181    Called before md_apply_fix() and after md_convert_frag().  */
05182 void
05183 score_validate_fix (fixS *fixP)
05184 {
05185   fixP->fx_where += fixP->fx_frag->insn_addr;
05186 }
05187 
05188 long
05189 md_pcrel_from (fixS * fixP)
05190 {
05191   long retval = 0;
05192 
05193   if (fixP->fx_addsy
05194       && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
05195       && (fixP->fx_subsy == NULL))
05196     {
05197       retval = 0;
05198     }
05199   else
05200     {
05201       retval = fixP->fx_where + fixP->fx_frag->fr_address;
05202     }
05203 
05204   return retval;
05205 }
05206 
05207 int
05208 score_force_relocation (struct fix *fixp)
05209 {
05210   int retval = 0;
05211 
05212   if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
05213       || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
05214       || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
05215       || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
05216       || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
05217       || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH)
05218     {
05219       retval = 1;
05220     }
05221 
05222   return retval;
05223 }
05224 
05225 /* Round up a section size to the appropriate boundary.  */
05226 valueT
05227 md_section_align (segT segment ATTRIBUTE_UNUSED, valueT size)
05228 {
05229   int align = bfd_get_section_alignment (stdoutput, segment);
05230 
05231   return ((size + (1 << align) - 1) & (-1 << align));
05232 }
05233 
05234 void
05235 md_apply_fix (fixS *fixP, valueT *valP, segT seg)
05236 {
05237   offsetT value = *valP;
05238   offsetT abs_value = 0;
05239   offsetT newval;
05240   offsetT content;
05241   unsigned short HI, LO;
05242 
05243   char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
05244 
05245   assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
05246   if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
05247     {
05248       if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
05249         fixP->fx_done = 1;
05250     }
05251 
05252   /* If this symbol is in a different section then we need to leave it for
05253      the linker to deal with.  Unfortunately, md_pcrel_from can't tell,
05254      so we have to undo it's effects here.  */
05255   if (fixP->fx_pcrel)
05256     {
05257       if (fixP->fx_addsy != NULL
05258          && S_IS_DEFINED (fixP->fx_addsy)
05259          && S_GET_SEGMENT (fixP->fx_addsy) != seg)
05260        value += md_pcrel_from (fixP);
05261     }
05262 
05263   /* Remember value for emit_reloc.  */
05264   fixP->fx_addnumber = value;
05265 
05266   switch (fixP->fx_r_type)
05267     {
05268     case BFD_RELOC_HI16_S:
05269       if (fixP->fx_done)
05270         {                       /* For la rd, imm32.  */
05271           newval = md_chars_to_number (buf, INSN_SIZE);
05272           HI = (value) >> 16;   /* mul to 2, then take the hi 16 bit.  */
05273           newval |= (HI & 0x3fff) << 1;
05274           newval |= ((HI >> 14) & 0x3) << 16;
05275           md_number_to_chars (buf, newval, INSN_SIZE);
05276         }
05277       break;
05278     case BFD_RELOC_LO16:
05279       if (fixP->fx_done)        /* For la rd, imm32.  */
05280         {
05281           newval = md_chars_to_number (buf, INSN_SIZE);
05282           LO = (value) & 0xffff;
05283           newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi.  */
05284           newval |= ((LO >> 14) & 0x3) << 16;
05285           md_number_to_chars (buf, newval, INSN_SIZE);
05286         }
05287       break;
05288     case BFD_RELOC_SCORE_JMP:
05289       {
05290         content = md_chars_to_number (buf, INSN_SIZE);
05291         value = fixP->fx_offset;
05292         content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
05293         md_number_to_chars (buf, content, INSN_SIZE);
05294       }
05295       break;
05296     case BFD_RELOC_SCORE_BRANCH:
05297       if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
05298         value = fixP->fx_offset;
05299       else
05300         fixP->fx_done = 1;
05301 
05302       content = md_chars_to_number (buf, INSN_SIZE);
05303       if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) != 0x80008000))
05304         {
05305           if ((value & 0x80000000) == 0x80000000)
05306             abs_value = 0xffffffff - value + 1;
05307           if ((abs_value & 0xffffff00) != 0)
05308             {
05309               as_bad_where (fixP->fx_file, fixP->fx_line,
05310                             _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int)value);
05311               return;
05312             }
05313           content = md_chars_to_number (buf, INSN16_SIZE);
05314           content &= 0xff00;
05315           content = (content & 0xff00) | ((value >> 1) & 0xff);
05316           md_number_to_chars (buf, content, INSN16_SIZE);
05317           fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
05318           fixP->fx_size = 2;
05319         }
05320       else
05321         {
05322           if ((value & 0x80000000) == 0x80000000)
05323             abs_value = 0xffffffff - value + 1;
05324           if ((abs_value & 0xfff80000) != 0)
05325             {
05326               as_bad_where (fixP->fx_file, fixP->fx_line,
05327                             _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
05328               return;
05329             }
05330           content = md_chars_to_number (buf, INSN_SIZE);
05331           content &= 0xfc00fc01;
05332           content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
05333           md_number_to_chars (buf, content, INSN_SIZE);
05334         }
05335       break;
05336     case BFD_RELOC_SCORE16_JMP:
05337       content = md_chars_to_number (buf, INSN16_SIZE);
05338       content &= 0xf001;
05339       value = fixP->fx_offset & 0xfff;
05340       content = (content & 0xfc01) | (value & 0xffe);
05341       md_number_to_chars (buf, content, INSN16_SIZE);
05342       break;
05343     case BFD_RELOC_SCORE16_BRANCH:
05344       content = md_chars_to_number (buf, INSN_SIZE);
05345       if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) == 0x80008000))
05346         {
05347           if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
05348               (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
05349             value = fixP->fx_offset;
05350           else
05351             fixP->fx_done = 1;
05352           if ((value & 0x80000000) == 0x80000000)
05353             abs_value = 0xffffffff - value + 1;
05354           if ((abs_value & 0xfff80000) != 0)
05355             {
05356               as_bad_where (fixP->fx_file, fixP->fx_line,
05357                             _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"), (unsigned int)value);
05358               return;
05359             }
05360           content = md_chars_to_number (buf, INSN_SIZE);
05361           content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
05362           md_number_to_chars (buf, content, INSN_SIZE);
05363           fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
05364           fixP->fx_size = 4;
05365           break;
05366         }
05367       else
05368         {
05369           /* In differnt section.  */
05370           if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
05371               (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
05372             value = fixP->fx_offset;
05373           else
05374             fixP->fx_done = 1;
05375 
05376           if ((value & 0x80000000) == 0x80000000)
05377             abs_value = 0xffffffff - value + 1;
05378           if ((abs_value & 0xffffff00) != 0)
05379             {
05380               as_bad_where (fixP->fx_file, fixP->fx_line,
05381                             _(" branch relocation truncate (0x%x)  [-2^8 ~ 2^8]"), (unsigned int)value);
05382               return;
05383             }
05384           content = md_chars_to_number (buf, INSN16_SIZE);
05385           content = (content & 0xff00) | ((value >> 1) & 0xff);
05386           md_number_to_chars (buf, content, INSN16_SIZE);
05387           break;
05388         }
05389     case BFD_RELOC_8:
05390       if (fixP->fx_done || fixP->fx_pcrel)
05391        md_number_to_chars (buf, value, 1);
05392 #ifdef OBJ_ELF
05393       else
05394         {
05395           value = fixP->fx_offset;
05396           md_number_to_chars (buf, value, 1);
05397         }
05398 #endif
05399       break;
05400 
05401     case BFD_RELOC_16:
05402       if (fixP->fx_done || fixP->fx_pcrel)
05403         md_number_to_chars (buf, value, 2);
05404 #ifdef OBJ_ELF
05405       else
05406         {
05407           value = fixP->fx_offset;
05408           md_number_to_chars (buf, value, 2);
05409         }
05410 #endif
05411       break;
05412     case BFD_RELOC_RVA:
05413     case BFD_RELOC_32:
05414       if (fixP->fx_done || fixP->fx_pcrel)
05415         md_number_to_chars (buf, value, 4);
05416 #ifdef OBJ_ELF
05417       else
05418         {
05419           value = fixP->fx_offset;
05420           md_number_to_chars (buf, value, 4);
05421         }
05422 #endif
05423       break;
05424     case BFD_RELOC_VTABLE_INHERIT:
05425       fixP->fx_done = 0;
05426       if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
05427         S_SET_WEAK (fixP->fx_addsy);
05428       break;
05429     case BFD_RELOC_VTABLE_ENTRY:
05430       fixP->fx_done = 0;
05431       break;
05432     case BFD_RELOC_SCORE_GPREL15:
05433       content = md_chars_to_number (buf, INSN_SIZE);
05434       if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94188000))
05435         fixP->fx_r_type = BFD_RELOC_NONE;
05436       fixP->fx_done = 0;
05437       break;
05438     case BFD_RELOC_SCORE_GOT15:
05439     case BFD_RELOC_SCORE_DUMMY_HI16:
05440     case BFD_RELOC_SCORE_GOT_LO16:
05441     case BFD_RELOC_SCORE_CALL15:
05442     case BFD_RELOC_GPREL32:
05443       break;
05444     case BFD_RELOC_NONE:
05445     default:
05446       as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
05447     }
05448 }
05449 
05450 /* Translate internal representation of relocation info to BFD target format.  */
05451 arelent **
05452 tc_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
05453 {
05454   static arelent *retval[MAX_RELOC_EXPANSION + 1];  /* MAX_RELOC_EXPANSION equals 2.  */
05455   arelent *reloc;
05456   bfd_reloc_code_real_type code;
05457   char *type;
05458   fragS *f;
05459   symbolS *s;
05460   expressionS e;
05461 
05462   reloc = retval[0] = xmalloc (sizeof (arelent));
05463   retval[1] = NULL;
05464 
05465   reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
05466   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
05467   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
05468   reloc->addend = fixp->fx_offset;
05469 
05470   /* If this is a variant frag, we may need to adjust the existing
05471      reloc and generate a new one.  */
05472   if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
05473     {
05474       /* Update instruction imm bit.  */
05475       offsetT newval;
05476       unsigned short off;
05477       char *buf;
05478 
05479       buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
05480       newval = md_chars_to_number (buf, INSN_SIZE);
05481       off = fixp->fx_offset >> 16;
05482       newval |= (off & 0x3fff) << 1;
05483       newval |= ((off >> 14) & 0x3) << 16;
05484       md_number_to_chars (buf, newval, INSN_SIZE);
05485 
05486       buf += INSN_SIZE;
05487       newval = md_chars_to_number (buf, INSN_SIZE);
05488       off = fixp->fx_offset & 0xffff;
05489       newval |= ((off & 0x3fff) << 1);
05490       newval |= (((off >> 14) & 0x3) << 16);
05491       md_number_to_chars (buf, newval, INSN_SIZE);
05492 
05493       retval[1] = xmalloc (sizeof (arelent));
05494       retval[2] = NULL;
05495       retval[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
05496       *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
05497       retval[1]->address = (reloc->address + RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
05498 
05499       f = fixp->fx_frag;
05500       s = f->fr_symbol;
05501       e = s->sy_value;
05502 
05503       retval[1]->addend = 0;
05504       retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
05505       assert (retval[1]->howto != NULL);
05506 
05507       fixp->fx_r_type = BFD_RELOC_HI16_S;
05508     }
05509 
05510   code = fixp->fx_r_type;
05511   switch (fixp->fx_r_type)
05512     {
05513     case BFD_RELOC_32:
05514       if (fixp->fx_pcrel)
05515         {
05516           code = BFD_RELOC_32_PCREL;
05517           break;
05518         }
05519     case BFD_RELOC_HI16_S:
05520     case BFD_RELOC_LO16:
05521     case BFD_RELOC_SCORE_JMP:
05522     case BFD_RELOC_SCORE_BRANCH:
05523     case BFD_RELOC_SCORE16_JMP:
05524     case BFD_RELOC_SCORE16_BRANCH:
05525     case BFD_RELOC_VTABLE_ENTRY:
05526     case BFD_RELOC_VTABLE_INHERIT:
05527     case BFD_RELOC_SCORE_GPREL15:
05528     case BFD_RELOC_SCORE_GOT15:
05529     case BFD_RELOC_SCORE_DUMMY_HI16:
05530     case BFD_RELOC_SCORE_GOT_LO16:
05531     case BFD_RELOC_SCORE_CALL15:
05532     case BFD_RELOC_GPREL32:
05533     case BFD_RELOC_NONE:
05534       code = fixp->fx_r_type;
05535       break;
05536     default:
05537       type = _("<unknown>");
05538       as_bad_where (fixp->fx_file, fixp->fx_line,
05539                     _("cannot represent %s relocation in this object file format"), type);
05540       return NULL;
05541     }
05542 
05543   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
05544   if (reloc->howto == NULL)
05545     {
05546       as_bad_where (fixp->fx_file, fixp->fx_line,
05547                     _("cannot represent %s relocation in this object file format1"),
05548                     bfd_get_reloc_code_name (code));
05549       return NULL;
05550     }
05551   /* HACK: Since arm ELF uses Rel instead of Rela, encode the
05552      vtable entry to be used in the relocation's section offset.  */
05553   if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
05554     reloc->address = fixp->fx_offset;
05555 
05556   return retval;
05557 }
05558 
05559 void
05560 score_elf_final_processing (void)
05561 {
05562   if (fix_data_dependency == 1)
05563     {
05564       elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
05565     }
05566   if (score_pic == PIC)
05567     {
05568       elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
05569     }
05570 }
05571 
05572 static void
05573 parse_pce_inst (char *insnstr)
05574 {
05575   char c;
05576   char *p;
05577   char first[MAX_LITERAL_POOL_SIZE];
05578   char second[MAX_LITERAL_POOL_SIZE];
05579   struct score_it pec_part_1;
05580 
05581   /* Get first part string of PCE.  */
05582   p = strstr (insnstr, "||");
05583   c = *p;
05584   *p = '\0';
05585   sprintf (first, "%s", insnstr);
05586 
05587   /* Get second part string of PCE.  */
05588   *p = c;
05589   p += 2;
05590   sprintf (second, "%s", p);
05591 
05592   parse_16_32_inst (first, FALSE);
05593   if (inst.error)
05594     return;
05595 
05596   memcpy (&pec_part_1, &inst, sizeof (inst));
05597 
05598   parse_16_32_inst (second, FALSE);
05599   if (inst.error)
05600     return;
05601 
05602   if (   ((pec_part_1.size == INSN_SIZE) && (inst.size == INSN_SIZE))
05603       || ((pec_part_1.size == INSN_SIZE) && (inst.size == INSN16_SIZE))
05604       || ((pec_part_1.size == INSN16_SIZE) && (inst.size == INSN_SIZE)))
05605     {
05606       inst.error = _("pce instruction error (16 bit || 16 bit)'");
05607       sprintf (inst.str, insnstr);
05608       return;
05609     }
05610 
05611   if (!inst.error)
05612     gen_insn_frag (&pec_part_1, &inst);
05613 }
05614 
05615 void
05616 md_assemble (char *str)
05617 {
05618   know (str);
05619   know (strlen (str) < MAX_LITERAL_POOL_SIZE);
05620 
05621   memset (&inst, '\0', sizeof (inst));
05622   if (INSN_IS_PCE_P (str))
05623     parse_pce_inst (str);
05624   else
05625     parse_16_32_inst (str, TRUE);
05626 
05627   if (inst.error)
05628     as_bad (_("%s -- `%s'"), inst.error, inst.str);
05629 }
05630 
05631 /* We handle all bad expressions here, so that we can report the faulty
05632    instruction in the error message.  */
05633 void
05634 md_operand (expressionS * expr)
05635 {
05636   if (in_my_get_expression)
05637     {
05638       expr->X_op = O_illegal;
05639       if (inst.error == NULL)
05640         {
05641           inst.error = _("bad expression");
05642         }
05643     }
05644 }
05645 
05646 const char *md_shortopts = "nO::g::G:";
05647 
05648 #ifdef SCORE_BI_ENDIAN
05649 #define OPTION_EB             (OPTION_MD_BASE + 0)
05650 #define OPTION_EL             (OPTION_MD_BASE + 1)
05651 #else
05652 #if TARGET_BYTES_BIG_ENDIAN
05653 #define OPTION_EB             (OPTION_MD_BASE + 0)
05654 #else
05655 #define OPTION_EL             (OPTION_MD_BASE + 1)
05656 #endif
05657 #endif
05658 #define OPTION_FIXDD          (OPTION_MD_BASE + 2)
05659 #define OPTION_NWARN          (OPTION_MD_BASE + 3)
05660 #define OPTION_SCORE5         (OPTION_MD_BASE + 4)
05661 #define OPTION_SCORE5U        (OPTION_MD_BASE + 5)
05662 #define OPTION_SCORE7         (OPTION_MD_BASE + 6)
05663 #define OPTION_R1             (OPTION_MD_BASE + 7)
05664 #define OPTION_O0             (OPTION_MD_BASE + 8)
05665 #define OPTION_SCORE_VERSION  (OPTION_MD_BASE + 9)
05666 #define OPTION_PIC            (OPTION_MD_BASE + 10)
05667 
05668 struct option md_longopts[] =
05669 {
05670 #ifdef OPTION_EB
05671   {"EB"     , no_argument, NULL, OPTION_EB},
05672 #endif
05673 #ifdef OPTION_EL
05674   {"EL"     , no_argument, NULL, OPTION_EL},
05675 #endif
05676   {"FIXDD"  , no_argument, NULL, OPTION_FIXDD},
05677   {"NWARN"  , no_argument, NULL, OPTION_NWARN},
05678   {"SCORE5" , no_argument, NULL, OPTION_SCORE5},
05679   {"SCORE5U", no_argument, NULL, OPTION_SCORE5U},
05680   {"SCORE7" , no_argument, NULL, OPTION_SCORE7},
05681   {"USE_R1" , no_argument, NULL, OPTION_R1},
05682   {"O0"     , no_argument, NULL, OPTION_O0},
05683   {"V"      , no_argument, NULL, OPTION_SCORE_VERSION},
05684   {"KPIC"   , no_argument, NULL, OPTION_PIC},
05685   {NULL     , no_argument, NULL, 0}
05686 };
05687 
05688 size_t md_longopts_size = sizeof (md_longopts);
05689 
05690 int
05691 md_parse_option (int c, char *arg)
05692 {
05693   switch (c)
05694     {
05695 #ifdef OPTION_EB
05696     case OPTION_EB:
05697       target_big_endian = 1;
05698       break;
05699 #endif
05700 #ifdef OPTION_EL
05701     case OPTION_EL:
05702       target_big_endian = 0;
05703       break;
05704 #endif
05705     case OPTION_FIXDD:
05706       fix_data_dependency = 1;
05707       break;
05708     case OPTION_NWARN:
05709       warn_fix_data_dependency = 0;
05710       break;
05711     case OPTION_SCORE5:
05712       score7 = 0;
05713       university_version = 0;
05714       vector_size = SCORE5_PIPELINE;
05715       break;
05716     case OPTION_SCORE5U:
05717       score7 = 0;
05718       university_version = 1;
05719       vector_size = SCORE5_PIPELINE;
05720       break;
05721     case OPTION_SCORE7:
05722       score7 = 1;
05723       university_version = 0;
05724       vector_size = SCORE7_PIPELINE;
05725       break;
05726     case OPTION_R1:
05727       nor1 = 0;
05728       break;
05729     case 'G':
05730       g_switch_value = atoi (arg);
05731       break;
05732     case OPTION_O0:
05733       g_opt = 0;
05734       break;
05735     case OPTION_SCORE_VERSION:
05736       printf (_("Sunplus-v2-0-0-20060510\n"));
05737       break;
05738     case OPTION_PIC:
05739       score_pic = PIC;
05740       g_switch_value = 0;    /* Must set -G num as 0 to generate PIC code.  */
05741       break;
05742     default:
05743       /* as_bad (_("unrecognized option `-%c%s'"), c, arg ? arg : "");  */
05744       return 0;
05745     }
05746   return 1;
05747 }
05748 
05749 void
05750 md_show_usage (FILE * fp)
05751 {
05752   fprintf (fp, _(" Score-specific assembler options:\n"));
05753 #ifdef OPTION_EB
05754   fprintf (fp, _("\
05755         -EB\t\tassemble code for a big-endian cpu\n"));
05756 #endif
05757 
05758 #ifdef OPTION_EL
05759   fprintf (fp, _("\
05760         -EL\t\tassemble code for a little-endian cpu\n"));
05761 #endif
05762 
05763   fprintf (fp, _("\
05764         -FIXDD\t\tassemble code for fix data dependency\n"));
05765   fprintf (fp, _("\
05766         -NWARN\t\tassemble code for no warning message for fix data dependency\n"));
05767   fprintf (fp, _("\
05768         -SCORE5\t\tassemble code for target is SCORE5\n"));
05769   fprintf (fp, _("\
05770         -SCORE5U\tassemble code for target is SCORE5U\n"));
05771   fprintf (fp, _("\
05772         -SCORE7\t\tassemble code for target is SCORE7, this is default setting\n"));
05773   fprintf (fp, _("\
05774         -USE_R1\t\tassemble code for no warning message when using temp register r1\n"));
05775   fprintf (fp, _("\
05776         -KPIC\t\tassemble code for PIC\n"));
05777   fprintf (fp, _("\
05778         -O0\t\tassembler will not perform any optimizations\n"));
05779   fprintf (fp, _("\
05780         -G gpnum\tassemble code for setting gpsize and default is 8 byte\n"));
05781   fprintf (fp, _("\
05782         -V \t\tSunplus release version \n"));
05783 }
05784 
05785 
05786 /* Pesudo handling functions.  */
05787 
05788 /* If we change section we must dump the literal pool first.  */
05789 static void
05790 s_score_bss (int ignore ATTRIBUTE_UNUSED)
05791 {
05792   subseg_set (bss_section, (subsegT) get_absolute_expression ());
05793   demand_empty_rest_of_line ();
05794 }
05795 
05796 static void
05797 s_score_text (int ignore)
05798 {
05799   obj_elf_text (ignore);
05800   record_alignment (now_seg, 2);
05801 }
05802 
05803 static void
05804 score_s_section (int ignore)
05805 {
05806   obj_elf_section (ignore);
05807   if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
05808     record_alignment (now_seg, 2);
05809 
05810 }
05811 
05812 static void
05813 s_change_sec (int sec)
05814 {
05815   segT seg;
05816 
05817 #ifdef OBJ_ELF
05818   /* The ELF backend needs to know that we are changing sections, so
05819      that .previous works correctly.  We could do something like check
05820      for an obj_section_change_hook macro, but that might be confusing
05821      as it would not be appropriate to use it in the section changing
05822      functions in read.c, since obj-elf.c intercepts those.  FIXME:
05823      This should be cleaner, somehow.  */
05824   obj_elf_section_change_hook ();
05825 #endif
05826   switch (sec)
05827     {
05828     case 'r':
05829       seg = subseg_new (RDATA_SECTION_NAME, (subsegT) get_absolute_expression ());
05830       bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA));
05831       if (strcmp (TARGET_OS, "elf") != 0)
05832         record_alignment (seg, 4);
05833       demand_empty_rest_of_line ();
05834       break;
05835     case 's':
05836       seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
05837       bfd_set_section_flags (stdoutput, seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
05838       if (strcmp (TARGET_OS, "elf") != 0)
05839         record_alignment (seg, 4);
05840       demand_empty_rest_of_line ();
05841       break;
05842     }
05843 }
05844 
05845 static void
05846 s_score_mask (int reg_type ATTRIBUTE_UNUSED)
05847 {
05848   long mask, off;
05849 
05850   if (cur_proc_ptr == (procS *) NULL)
05851     {
05852       as_warn (_(".mask outside of .ent"));
05853       demand_empty_rest_of_line ();
05854       return;
05855     }
05856   if (get_absolute_expression_and_terminator (&mask) != ',')
05857     {
05858       as_warn (_("Bad .mask directive"));
05859       --input_line_pointer;
05860       demand_empty_rest_of_line ();
05861       return;
05862     }
05863   off = get_absolute_expression ();
05864   cur_proc_ptr->reg_mask = mask;
05865   cur_proc_ptr->reg_offset = off;
05866   demand_empty_rest_of_line ();
05867 }
05868 
05869 static symbolS *
05870 get_symbol (void)
05871 {
05872   int c;
05873   char *name;
05874   symbolS *p;
05875 
05876   name = input_line_pointer;
05877   c = get_symbol_end ();
05878   p = (symbolS *) symbol_find_or_make (name);
05879   *input_line_pointer = c;
05880   return p;
05881 }
05882 
05883 static long
05884 get_number (void)
05885 {
05886   int negative = 0;
05887   long val = 0;
05888 
05889   if (*input_line_pointer == '-')
05890     {
05891       ++input_line_pointer;
05892       negative = 1;
05893     }
05894   if (!ISDIGIT (*input_line_pointer))
05895     as_bad (_("expected simple number"));
05896   if (input_line_pointer[0] == '0')
05897     {
05898       if (input_line_pointer[1] == 'x')
05899         {
05900           input_line_pointer += 2;
05901           while (ISXDIGIT (*input_line_pointer))
05902             {
05903               val <<= 4;
05904               val |= hex_value (*input_line_pointer++);
05905             }
05906           return negative ? -val : val;
05907         }
05908       else
05909         {
05910           ++input_line_pointer;
05911           while (ISDIGIT (*input_line_pointer))
05912             {
05913               val <<= 3;
05914               val |= *input_line_pointer++ - '0';
05915             }
05916           return negative ? -val : val;
05917         }
05918     }
05919   if (!ISDIGIT (*input_line_pointer))
05920     {
05921       printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer);
05922       as_warn (_("invalid number"));
05923       return -1;
05924     }
05925   while (ISDIGIT (*input_line_pointer))
05926     {
05927       val *= 10;
05928       val += *input_line_pointer++ - '0';
05929     }
05930   return negative ? -val : val;
05931 }
05932 
05933 /* The .aent and .ent directives.  */
05934 
05935 static void
05936 s_score_ent (int aent)
05937 {
05938   symbolS *symbolP;
05939   int maybe_text;
05940 
05941   symbolP = get_symbol ();
05942   if (*input_line_pointer == ',')
05943     ++input_line_pointer;
05944   SKIP_WHITESPACE ();
05945   if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
05946     get_number ();
05947 
05948 #ifdef BFD_ASSEMBLER
05949   if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
05950     maybe_text = 1;
05951   else
05952     maybe_text = 0;
05953 #else
05954   if (now_seg != data_section && now_seg != bss_section)
05955     maybe_text = 1;
05956   else
05957     maybe_text = 0;
05958 #endif
05959   if (!maybe_text)
05960     as_warn (_(".ent or .aent not in text section."));
05961   if (!aent && cur_proc_ptr)
05962     as_warn (_("missing .end"));
05963   if (!aent)
05964     {
05965       cur_proc_ptr = &cur_proc;
05966       cur_proc_ptr->reg_mask = 0xdeadbeaf;
05967       cur_proc_ptr->reg_offset = 0xdeadbeaf;
05968       cur_proc_ptr->fpreg_mask = 0xdeafbeaf;
05969       cur_proc_ptr->leaf = 0xdeafbeaf;
05970       cur_proc_ptr->frame_offset = 0xdeafbeaf;
05971       cur_proc_ptr->frame_reg = 0xdeafbeaf;
05972       cur_proc_ptr->pc_reg = 0xdeafbeaf;
05973       cur_proc_ptr->isym = symbolP;
05974       symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
05975       ++numprocs;
05976       if (debug_type == DEBUG_STABS)
05977         stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP));
05978     }
05979   demand_empty_rest_of_line ();
05980 }
05981 
05982 static void
05983 s_score_frame (int ignore ATTRIBUTE_UNUSED)
05984 {
05985   char *backupstr;
05986   char str[30];
05987   long val;
05988   int i = 0;
05989 
05990   backupstr = input_line_pointer;
05991 
05992 #ifdef OBJ_ELF
05993   if (cur_proc_ptr == (procS *) NULL)
05994     {
05995       as_warn (_(".frame outside of .ent"));
05996       demand_empty_rest_of_line ();
05997       return;
05998     }
05999   cur_proc_ptr->frame_reg = reg_required_here ((&backupstr), 0, REG_TYPE_SCORE);
06000   SKIP_WHITESPACE ();
06001   skip_past_comma (&backupstr);
06002   while (*backupstr != ',')
06003     {
06004       str[i] = *backupstr;
06005       i++;
06006       backupstr++;
06007     }
06008   str[i] = '\0';
06009   val = atoi (str);
06010 
06011   SKIP_WHITESPACE ();
06012   skip_past_comma (&backupstr);
06013   cur_proc_ptr->frame_offset = val;
06014   cur_proc_ptr->pc_reg = reg_required_here ((&backupstr), 0, REG_TYPE_SCORE);
06015 
06016   SKIP_WHITESPACE ();
06017   skip_past_comma (&backupstr);
06018   i = 0;
06019   while (*backupstr != '\n')
06020     {
06021       str[i] = *backupstr;
06022       i++;
06023       backupstr++;
06024     }
06025   str[i] = '\0';
06026   val = atoi (str);
06027   cur_proc_ptr->leaf = val;
06028   SKIP_WHITESPACE ();
06029   skip_past_comma (&backupstr);
06030 
06031 #endif /* OBJ_ELF */
06032   while (input_line_pointer != backupstr)
06033     input_line_pointer++;
06034 }
06035 
06036 /* The .end directive.  */
06037 static void
06038 s_score_end (int x ATTRIBUTE_UNUSED)
06039 {
06040   symbolS *p;
06041   int maybe_text;
06042 
06043   /* Generate a .pdr section.  */
06044   segT saved_seg = now_seg;
06045   subsegT saved_subseg = now_subseg;
06046   valueT dot;
06047   expressionS exp;
06048   char *fragp;
06049 
06050   if (!is_end_of_line[(unsigned char)*input_line_pointer])
06051     {
06052       p = get_symbol ();
06053       demand_empty_rest_of_line ();
06054     }
06055   else
06056     p = NULL;
06057 
06058 #ifdef BFD_ASSEMBLER
06059   if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
06060     maybe_text = 1;
06061   else
06062     maybe_text = 0;
06063 #else
06064   if (now_seg != data_section && now_seg != bss_section)
06065     maybe_text = 1;
06066   else
06067     maybe_text = 0;
06068 #endif
06069 
06070   if (!maybe_text)
06071     as_warn (_(".end not in text section"));
06072   if (!cur_proc_ptr)
06073     {
06074       as_warn (_(".end directive without a preceding .ent directive."));
06075       demand_empty_rest_of_line ();
06076       return;
06077     }
06078   if (p != NULL)
06079     {
06080       assert (S_GET_NAME (p));
06081       if (strcmp (S_GET_NAME (p), S_GET_NAME (cur_proc_ptr->isym)))
06082         as_warn (_(".end symbol does not match .ent symbol."));
06083       if (debug_type == DEBUG_STABS)
06084         stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p));
06085     }
06086   else
06087     as_warn (_(".end directive missing or unknown symbol"));
06088 
06089   if ((cur_proc_ptr->reg_mask == 0xdeadbeaf) ||
06090       (cur_proc_ptr->reg_offset == 0xdeadbeaf) ||
06091       (cur_proc_ptr->leaf == 0xdeafbeaf) ||
06092       (cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
06093       (cur_proc_ptr->frame_reg == 0xdeafbeaf) || (cur_proc_ptr->pc_reg == 0xdeafbeaf));
06094 
06095   else
06096     {
06097       dot = frag_now_fix ();
06098       assert (pdr_seg);
06099       subseg_set (pdr_seg, 0);
06100       /* Write the symbol.  */
06101       exp.X_op = O_symbol;
06102       exp.X_add_symbol = p;
06103       exp.X_add_number = 0;
06104       emit_expr (&exp, 4);
06105       fragp = frag_more (7 * 4);
06106       md_number_to_chars (fragp, (valueT) cur_proc_ptr->reg_mask, 4);
06107       md_number_to_chars (fragp + 4, (valueT) cur_proc_ptr->reg_offset, 4);
06108       md_number_to_chars (fragp + 8, (valueT) cur_proc_ptr->fpreg_mask, 4);
06109       md_number_to_chars (fragp + 12, (valueT) cur_proc_ptr->leaf, 4);
06110       md_number_to_chars (fragp + 16, (valueT) cur_proc_ptr->frame_offset, 4);
06111       md_number_to_chars (fragp + 20, (valueT) cur_proc_ptr->frame_reg, 4);
06112       md_number_to_chars (fragp + 24, (valueT) cur_proc_ptr->pc_reg, 4);
06113       subseg_set (saved_seg, saved_subseg);
06114 
06115     }
06116   cur_proc_ptr = NULL;
06117 }
06118 
06119 /* Handle the .set pseudo-op.  */
06120 static void
06121 s_score_set (int x ATTRIBUTE_UNUSED)
06122 {
06123   int i = 0;
06124   char name[MAX_LITERAL_POOL_SIZE];
06125   char * orig_ilp = input_line_pointer;
06126 
06127   while (!is_end_of_line[(unsigned char)*input_line_pointer])
06128     {
06129       name[i] = (char) * input_line_pointer;
06130       i++;
06131       ++input_line_pointer;
06132     }
06133 
06134   name[i] = '\0';
06135 
06136   if (strcmp (name, "nwarn") == 0)
06137     {
06138       warn_fix_data_dependency = 0;
06139     }
06140   else if (strcmp (name, "fixdd") == 0)
06141     {
06142       fix_data_dependency = 1;
06143     }
06144   else if (strcmp (name, "nofixdd") == 0)
06145     {
06146       fix_data_dependency = 0;
06147     }
06148   else if (strcmp (name, "r1") == 0)
06149     {
06150       nor1 = 0;
06151     }
06152   else if (strcmp (name, "nor1") == 0)
06153     {
06154       nor1 = 1;
06155     }
06156   else if (strcmp (name, "optimize") == 0)
06157     {
06158       g_opt = 1;
06159     }
06160   else if (strcmp (name, "volatile") == 0)
06161     {
06162       g_opt = 0;
06163     }
06164   else if (strcmp (name, "pic") == 0)
06165     {
06166       score_pic = PIC;
06167     }
06168   else
06169     {
06170       input_line_pointer = orig_ilp;
06171       s_set (0);
06172     }
06173 }
06174 
06175 /* Handle the .cpload pseudo-op.  This is used when generating PIC code.  It sets the
06176    $gp register for the function based on the function address, which is in the register
06177    named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled
06178    specially by the linker.  The result is:
06179    ldis gp, %hi(GP_DISP_LABEL)
06180    ori  gp, %low(GP_DISP_LABEL)
06181    add  gp, gp, .cpload argument
06182    The .cpload argument is normally r29.  */
06183 
06184 static void
06185 s_score_cpload (int ignore ATTRIBUTE_UNUSED)
06186 {
06187   int reg;
06188   char insn_str[MAX_LITERAL_POOL_SIZE];
06189 
06190   /* If we are not generating PIC code, .cpload is ignored.  */
06191   if (score_pic == NO_PIC)
06192     {
06193       s_ignore (0);
06194       return;
06195     }
06196 
06197   if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL)
06198     return;
06199 
06200   demand_empty_rest_of_line ();
06201 
06202   sprintf (insn_str, "ld_i32hi r%d, %s", GP, GP_DISP_LABEL);
06203   if (append_insn (insn_str, TRUE) == (int) FAIL)
06204     return;
06205 
06206   sprintf (insn_str, "ld_i32lo r%d, %s", GP, GP_DISP_LABEL);
06207   if (append_insn (insn_str, TRUE) == (int) FAIL)
06208     return;
06209 
06210   sprintf (insn_str, "add r%d, r%d, r%d", GP, GP, reg);
06211   if (append_insn (insn_str, TRUE) == (int) FAIL)
06212     return;
06213 }
06214 
06215 /* Handle the .cprestore pseudo-op.  This stores $gp into a given
06216    offset from $sp.  The offset is remembered, and after making a PIC
06217    call $gp is restored from that location.  */
06218 
06219 static void
06220 s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
06221 {
06222   int reg;
06223   int cprestore_offset;
06224   char insn_str[MAX_LITERAL_POOL_SIZE];
06225 
06226   /* If we are not generating PIC code, .cprestore is ignored.  */
06227   if (score_pic == NO_PIC)
06228     {
06229       s_ignore (0);
06230       return;
06231     }
06232 
06233   if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL
06234       || skip_past_comma (&input_line_pointer) == (int) FAIL)
06235     {
06236       return;
06237     }
06238 
06239   cprestore_offset = get_absolute_expression ();
06240 
06241   if (cprestore_offset <= 0x3fff)
06242     {
06243       sprintf (insn_str, "sw r%d, [r%d, %d]", GP, reg, cprestore_offset);
06244       if (append_insn (insn_str, TRUE) == (int) FAIL)
06245         return;
06246     }
06247   else
06248     {
06249       int r1_bak;
06250 
06251       r1_bak = nor1;
06252       nor1 = 0;
06253 
06254       sprintf (insn_str, "li r1, %d", cprestore_offset);
06255       if (append_insn (insn_str, TRUE) == (int) FAIL)
06256         return;
06257 
06258       sprintf (insn_str, "add r1, r1, r%d", reg);
06259       if (append_insn (insn_str, TRUE) == (int) FAIL)
06260         return;
06261 
06262       sprintf (insn_str, "sw r%d, [r1]", GP);
06263       if (append_insn (insn_str, TRUE) == (int) FAIL)
06264         return;
06265 
06266       nor1 = r1_bak;
06267     }
06268 
06269   demand_empty_rest_of_line ();
06270 }
06271 
06272 /* Handle the .gpword pseudo-op.  This is used when generating PIC
06273    code.  It generates a 32 bit GP relative reloc.  */
06274 static void
06275 s_score_gpword (int ignore ATTRIBUTE_UNUSED)
06276 {
06277   expressionS ex;
06278   char *p;
06279 
06280   /* When not generating PIC code, this is treated as .word.  */
06281   if (score_pic == NO_PIC)
06282     {
06283       cons (4);
06284       return;
06285     }
06286   expression (&ex);
06287   if (ex.X_op != O_symbol || ex.X_add_number != 0)
06288     {
06289       as_bad (_("Unsupported use of .gpword"));
06290       ignore_rest_of_line ();
06291     }
06292   p = frag_more (4);
06293   md_number_to_chars (p, (valueT) 0, 4);
06294   fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32);
06295   demand_empty_rest_of_line ();
06296 }
06297 
06298 /* Handle the .cpadd pseudo-op.  This is used when dealing with switch
06299    tables in PIC code.  */
06300 
06301 static void
06302 s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
06303 {
06304   int reg;
06305   char insn_str[MAX_LITERAL_POOL_SIZE];
06306 
06307   /* If we are not generating PIC code, .cpload is ignored.  */
06308   if (score_pic == NO_PIC)
06309     {
06310       s_ignore (0);
06311       return;
06312     }
06313 
06314   if ((reg = reg_required_here (&input_line_pointer, -1, REG_TYPE_SCORE)) == (int) FAIL)
06315     {
06316       return;
06317     }
06318   demand_empty_rest_of_line ();
06319 
06320   /* Add $gp to the register named as an argument.  */
06321   sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, GP);
06322   if (append_insn (insn_str, TRUE) == (int) FAIL)
06323     return;
06324 }
06325 
06326 #ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
06327 #define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR)               \
06328     do                                                  \
06329     {                                                          \
06330     if ((SIZE) >= 8)                                           \
06331     (P2VAR) = 3;                                               \
06332     else if ((SIZE) >= 4)                                      \
06333     (P2VAR) = 2;                                               \
06334     else if ((SIZE) >= 2)                                      \
06335     (P2VAR) = 1;                                               \
06336     else                                                       \
06337     (P2VAR) = 0;                                               \
06338     }                                                   \
06339   while (0)
06340 #endif
06341 
06342 static void
06343 s_score_lcomm (int bytes_p)
06344 {
06345   char *name;
06346   char c;
06347   char *p;
06348   int temp;
06349   symbolS *symbolP;
06350   segT current_seg = now_seg;
06351   subsegT current_subseg = now_subseg;
06352   const int max_alignment = 15;
06353   int align = 0;
06354   segT bss_seg = bss_section;
06355   int needs_align = 0;
06356 
06357   name = input_line_pointer;
06358   c = get_symbol_end ();
06359   p = input_line_pointer;
06360   *p = c;
06361 
06362   if (name == p)
06363     {
06364       as_bad (_("expected symbol name"));
06365       discard_rest_of_line ();
06366       return;
06367     }
06368 
06369   SKIP_WHITESPACE ();
06370 
06371   /* Accept an optional comma after the name.  The comma used to be
06372      required, but Irix 5 cc does not generate it.  */
06373   if (*input_line_pointer == ',')
06374     {
06375       ++input_line_pointer;
06376       SKIP_WHITESPACE ();
06377     }
06378 
06379   if (is_end_of_line[(unsigned char)*input_line_pointer])
06380     {
06381       as_bad (_("missing size expression"));
06382       return;
06383     }
06384 
06385   if ((temp = get_absolute_expression ()) < 0)
06386     {
06387       as_warn (_("BSS length (%d) < 0 ignored"), temp);
06388       ignore_rest_of_line ();
06389       return;
06390     }
06391 
06392 #if defined (TC_SCORE)
06393   if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour)
06394     {
06395       /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss.  */
06396       if ((unsigned)temp <= bfd_get_gp_size (stdoutput))
06397         {
06398           bss_seg = subseg_new (".sbss", 1);
06399           seg_info (bss_seg)->bss = 1;
06400 #ifdef BFD_ASSEMBLER
06401           if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
06402             as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ()));
06403 #endif
06404         }
06405     }
06406 #endif
06407 
06408   SKIP_WHITESPACE ();
06409   if (*input_line_pointer == ',')
06410     {
06411       ++input_line_pointer;
06412       SKIP_WHITESPACE ();
06413 
06414       if (is_end_of_line[(unsigned char)*input_line_pointer])
06415         {
06416           as_bad (_("missing alignment"));
06417           return;
06418         }
06419       else
06420         {
06421           align = get_absolute_expression ();
06422           needs_align = 1;
06423         }
06424     }
06425 
06426   if (!needs_align)
06427     {
06428       TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
06429 
06430       /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it.  */
06431       if (align)
06432         record_alignment (bss_seg, align);
06433     }
06434 
06435   if (needs_align)
06436     {
06437       if (bytes_p)
06438         {
06439           /* Convert to a power of 2.  */
06440           if (align != 0)
06441             {
06442               unsigned int i;
06443 
06444               for (i = 0; align != 0; align >>= 1, ++i)
06445                 ;
06446               align = i - 1;
06447             }
06448         }
06449 
06450       if (align > max_alignment)
06451         {
06452           align = max_alignment;
06453           as_warn (_("alignment too large; %d assumed"), align);
06454         }
06455       else if (align < 0)
06456         {
06457           align = 0;
06458           as_warn (_("alignment negative; 0 assumed"));
06459         }
06460 
06461       record_alignment (bss_seg, align);
06462     }
06463   else
06464     {
06465       /* Assume some objects may require alignment on some systems.  */
06466 #if defined (TC_ALPHA) && ! defined (VMS)
06467       if (temp > 1)
06468         {
06469           align = ffs (temp) - 1;
06470           if (temp % (1 << align))
06471             abort ();
06472         }
06473 #endif
06474     }
06475 
06476   *p = 0;
06477   symbolP = symbol_find_or_make (name);
06478   *p = c;
06479 
06480   if (
06481 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \
06482      || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT))
06483 #ifdef BFD_ASSEMBLER
06484        (OUTPUT_FLAVOR != bfd_target_aout_flavour
06485         || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
06486 #else
06487        (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
06488 #endif
06489 #endif
06490        (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
06491     {
06492       char *pfrag;
06493 
06494       subseg_set (bss_seg, 1);
06495 
06496       if (align)
06497         frag_align (align, 0, 0);
06498 
06499       /* Detach from old frag.  */
06500       if (S_GET_SEGMENT (symbolP) == bss_seg)
06501         symbol_get_frag (symbolP)->fr_symbol = NULL;
06502 
06503       symbol_set_frag (symbolP, frag_now);
06504       pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
06505       *pfrag = 0;
06506 
06507 
06508       S_SET_SEGMENT (symbolP, bss_seg);
06509 
06510 #ifdef OBJ_COFF
06511       /* The symbol may already have been created with a preceding
06512          ".globl" directive -- be careful not to step on storage class
06513          in that case.  Otherwise, set it to static.  */
06514       if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
06515         {
06516           S_SET_STORAGE_CLASS (symbolP, C_STAT);
06517         }
06518 #endif /* OBJ_COFF */
06519 
06520 #ifdef S_SET_SIZE
06521       S_SET_SIZE (symbolP, temp);
06522 #endif
06523     }
06524   else
06525     as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
06526 
06527   subseg_set (current_seg, current_subseg);
06528 
06529   demand_empty_rest_of_line ();
06530 }
06531 
06532 static void
06533 insert_reg (const struct reg_entry *r, struct hash_control *htab)
06534 {
06535   int i = 0;
06536   int len = strlen (r->name) + 2;
06537   char *buf = xmalloc (len);
06538   char *buf2 = xmalloc (len);
06539 
06540   strcpy (buf + i, r->name);
06541   for (i = 0; buf[i]; i++)
06542     {
06543       buf2[i] = TOUPPER (buf[i]);
06544     }
06545   buf2[i] = '\0';
06546 
06547   hash_insert (htab, buf, (void *) r);
06548   hash_insert (htab, buf2, (void *) r);
06549 }
06550 
06551 static void
06552 build_reg_hsh (struct reg_map *map)
06553 {
06554   const struct reg_entry *r;
06555 
06556   if ((map->htab = hash_new ()) == NULL)
06557     {
06558       as_fatal (_("virtual memory exhausted"));
06559     }
06560   for (r = map->names; r->name != NULL; r++)
06561     {
06562       insert_reg (r, map->htab);
06563     }
06564 }
06565 
06566 void
06567 md_begin (void)
06568 {
06569   unsigned int i;
06570   segT seg;
06571   subsegT subseg;
06572 
06573   if ((score_ops_hsh = hash_new ()) == NULL)
06574     as_fatal (_("virtual memory exhausted"));
06575 
06576   build_score_ops_hsh ();
06577 
06578   if ((dependency_insn_hsh = hash_new ()) == NULL)
06579     as_fatal (_("virtual memory exhausted"));
06580 
06581   build_dependency_insn_hsh ();
06582 
06583   for (i = (int)REG_TYPE_FIRST; i < (int)REG_TYPE_MAX; i++)
06584     build_reg_hsh (all_reg_maps + i);
06585 
06586   /* Initialize dependency vector.  */
06587   init_dependency_vector ();
06588 
06589   bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
06590   seg = now_seg;
06591   subseg = now_subseg;
06592   pdr_seg = subseg_new (".pdr", (subsegT) 0);
06593   (void)bfd_set_section_flags (stdoutput, pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
06594   (void)bfd_set_section_alignment (stdoutput, pdr_seg, 2);
06595   subseg_set (seg, subseg);
06596 
06597   if (USE_GLOBAL_POINTER_OPT)
06598     bfd_set_gp_size (stdoutput, g_switch_value);
06599 }
06600 
06601 
06602 const pseudo_typeS md_pseudo_table[] =
06603 {
06604   {"bss", s_score_bss, 0},
06605   {"text", s_score_text, 0},
06606   {"word", cons, 4},
06607   {"long", cons, 4},
06608   {"extend", float_cons, 'x'},
06609   {"ldouble", float_cons, 'x'},
06610   {"packed", float_cons, 'p'},
06611   {"end", s_score_end, 0},
06612   {"ent", s_score_ent, 0},
06613   {"frame", s_score_frame, 0},
06614   {"rdata", s_change_sec, 'r'},
06615   {"sdata", s_change_sec, 's'},
06616   {"set", s_score_set, 0},
06617   {"mask", s_score_mask, 'R'},
06618   {"dword", cons, 8},
06619   {"lcomm", s_score_lcomm, 1},
06620   {"section", score_s_section, 0},
06621   {"cpload", s_score_cpload, 0},
06622   {"cprestore", s_score_cprestore, 0},
06623   {"gpword", s_score_gpword, 0},
06624   {"cpadd", s_score_cpadd, 0},
06625   {0, 0, 0}
06626 };
06627