Home | History | Annotate | Download | only in config
      1 /* tc-score7.c -- Assembler for Score7
      2    Copyright (C) 2009-2016 Free Software Foundation, Inc.
      3    Contributed by:
      4    Brain.lin (brain.lin (at) sunplusct.com)
      5    Mei Ligang (ligang (at) sunnorth.com.cn)
      6    Pei-Lin Tsai (pltsai (at) sunplus.com)
      7 
      8    This file is part of GAS, the GNU Assembler.
      9 
     10    GAS is free software; you can redistribute it and/or modify
     11    it under the terms of the GNU General Public License as published by
     12    the Free Software Foundation; either version 3, or (at your option)
     13    any later version.
     14 
     15    GAS is distributed in the hope that it will be useful,
     16    but WITHOUT ANY WARRANTY; without even the implied warranty of
     17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     18    GNU General Public License for more details.
     19 
     20    You should have received a copy of the GNU General Public License
     21    along with GAS; see the file COPYING.  If not, write to the Free
     22    Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     23    MA 02110-1301, USA.  */
     24 
     25 #include "as.h"
     26 #include "config.h"
     27 #include "subsegs.h"
     28 #include "safe-ctype.h"
     29 #include "opcode/score-inst.h"
     30 #include "struc-symbol.h"
     31 #include "libiberty.h"
     32 
     33 #ifdef OBJ_ELF
     34 #include "elf/score.h"
     35 #include "dwarf2dbg.h"
     36 #endif
     37 
     38 static void s7_do_ldst_insn (char *);
     39 static void s7_do_crdcrscrsimm5 (char *);
     40 static void s7_do_ldst_unalign (char *);
     41 static void s7_do_ldst_atomic (char *);
     42 static void s7_do_ldst_cop (char *);
     43 static void s7_do_macro_li_rdi32 (char *);
     44 static void s7_do_macro_la_rdi32 (char *);
     45 static void s7_do_macro_rdi32hi (char *);
     46 static void s7_do_macro_rdi32lo (char *);
     47 static void s7_do_macro_mul_rdrsrs (char *);
     48 static void s7_do_macro_ldst_label (char *);
     49 static void s7_do_branch (char *);
     50 static void s7_do_jump (char *);
     51 static void s7_do_empty (char *);
     52 static void s7_do_rdrsrs (char *);
     53 static void s7_do_rdsi16 (char *);
     54 static void s7_do_rdrssi14 (char *);
     55 static void s7_do_sub_rdsi16 (char *);
     56 static void s7_do_sub_rdrssi14 (char *);
     57 static void s7_do_rdrsi5 (char *);
     58 static void s7_do_rdrsi14 (char *);
     59 static void s7_do_rdi16 (char *);
     60 static void s7_do_xrsi5 (char *);
     61 static void s7_do_rdrs (char *);
     62 static void s7_do_rdxrs (char *);
     63 static void s7_do_rsrs (char *);
     64 static void s7_do_rdcrs (char *);
     65 static void s7_do_rdsrs (char *);
     66 static void s7_do_rd (char *);
     67 static void s7_do_rs (char *);
     68 static void s7_do_i15 (char *);
     69 static void s7_do_xi5x (char *);
     70 static void s7_do_ceinst (char *);
     71 static void s7_do_cache (char *);
     72 static void s7_do16_rdrs (char *);
     73 static void s7_do16_rs (char *);
     74 static void s7_do16_xrs (char *);
     75 static void s7_do16_mv_rdrs (char *);
     76 static void s7_do16_hrdrs (char *);
     77 static void s7_do16_rdhrs (char *);
     78 static void s7_do16_rdi4 (char *);
     79 static void s7_do16_rdi5 (char *);
     80 static void s7_do16_xi5 (char *);
     81 static void s7_do16_ldst_insn (char *);
     82 static void s7_do16_ldst_imm_insn (char *);
     83 static void s7_do16_push_pop (char *);
     84 static void s7_do16_branch (char *);
     85 static void s7_do16_jump (char *);
     86 static void s7_do_rdi16_pic (char *);
     87 static void s7_do_addi_s_pic (char *);
     88 static void s7_do_addi_u_pic (char *);
     89 static void s7_do_lw_pic (char *);
     90 
     91 #define s7_GP                     28
     92 #define s7_PIC_CALL_REG           29
     93 #define s7_MAX_LITERAL_POOL_SIZE  1024
     94 #define s7_FAIL	               0x80000000
     95 #define s7_SUCCESS         0
     96 #define s7_INSN_SIZE       4
     97 #define s7_INSN16_SIZE     2
     98 #define s7_RELAX_INST_NUM  3
     99 
    100 /* For score5u : div/mul will pop warning message, mmu/alw/asw will pop error message.  */
    101 #define s7_BAD_ARGS 	             _("bad arguments to instruction")
    102 #define s7_ERR_FOR_SCORE5U_MUL_DIV   _("div / mul are reserved instructions")
    103 #define s7_ERR_FOR_SCORE5U_MMU       _("This architecture doesn't support mmu")
    104 #define s7_ERR_FOR_SCORE5U_ATOMIC    _("This architecture doesn't support atomic instruction")
    105 #define s7_BAD_SKIP_COMMA            s7_BAD_ARGS
    106 #define s7_BAD_GARBAGE               _("garbage following instruction");
    107 
    108 #define s7_skip_whitespace(str)  while (*(str) == ' ') ++(str)
    109 
    110 /* The name of the readonly data section.  */
    111 #define s7_RDATA_SECTION_NAME (OUTPUT_FLAVOR == bfd_target_aout_flavour \
    112 			    ? ".data" \
    113 			    : OUTPUT_FLAVOR == bfd_target_ecoff_flavour \
    114 			    ? ".rdata" \
    115 			    : OUTPUT_FLAVOR == bfd_target_coff_flavour \
    116 			    ? ".rdata" \
    117 			    : OUTPUT_FLAVOR == bfd_target_elf_flavour \
    118 			    ? ".rodata" \
    119 			    : (abort (), ""))
    120 
    121 #define s7_RELAX_ENCODE(old, new, type, reloc1, reloc2, opt) \
    122   ((relax_substateT) \
    123    (((old) << 23) \
    124     | ((new) << 16) \
    125     | ((type) << 9) \
    126     | ((reloc1) << 5) \
    127     | ((reloc2) << 1) \
    128     | ((opt) ? 1 : 0)))
    129 
    130 #define s7_RELAX_OLD(i)       (((i) >> 23) & 0x7f)
    131 #define s7_RELAX_NEW(i)       (((i) >> 16) & 0x7f)
    132 #define s7_RELAX_TYPE(i)      (((i) >> 9) & 0x7f)
    133 #define s7_RELAX_RELOC1(i)    ((valueT) ((i) >> 5) & 0xf)
    134 #define s7_RELAX_RELOC2(i)    ((valueT) ((i) >> 1) & 0xf)
    135 #define s7_RELAX_OPT(i)       ((i) & 1)
    136 #define s7_RELAX_OPT_CLEAR(i) ((i) & ~1)
    137 
    138 #define s7_SET_INSN_ERROR(s) (s7_inst.error = (s))
    139 #define s7_INSN_IS_PCE_P(s)  (strstr (str, "||") != NULL)
    140 
    141 #define s7_GET_INSN_CLASS(type) (s7_get_insn_class_from_type (type))
    142 
    143 #define s7_GET_INSN_SIZE(type) ((s7_GET_INSN_CLASS (type) == INSN_CLASS_16) \
    144                              ? s7_INSN16_SIZE : s7_INSN_SIZE)
    145 
    146 #define s7_MAX_LITTLENUMS 6
    147 #define s7_INSN_NAME_LEN 16
    148 
    149 /* Relax will need some padding for alignment.  */
    150 #define s7_RELAX_PAD_BYTE 3
    151 
    152 #define s7_USE_GLOBAL_POINTER_OPT 1
    153 
    154 
    155 
    157 /* Enumeration matching entries in table above.  */
    158 enum s7_score_reg_type
    159 {
    160   s7_REG_TYPE_SCORE = 0,
    161 #define REG_TYPE_FIRST s7_REG_TYPE_SCORE
    162   s7_REG_TYPE_SCORE_SR = 1,
    163   s7_REG_TYPE_SCORE_CR = 2,
    164   s7_REG_TYPE_MAX = 3
    165 };
    166 
    167 enum s7_score_pic_level
    168 {
    169   s7_NO_PIC,
    170   s7_PIC
    171 };
    172 static enum s7_score_pic_level s7_score_pic = s7_NO_PIC;
    173 
    174 enum s7_insn_type_for_dependency
    175 {
    176   s7_D_pce,
    177   s7_D_cond_br,
    178   s7_D_cond_mv,
    179   s7_D_cached,
    180   s7_D_cachei,
    181   s7_D_ldst,
    182   s7_D_ldcombine,
    183   s7_D_mtcr,
    184   s7_D_mfcr,
    185   s7_D_mfsr,
    186   s7_D_mftlb,
    187   s7_D_mtptlb,
    188   s7_D_mtrtlb,
    189   s7_D_stlb,
    190   s7_D_all_insn
    191 };
    192 
    193 struct s7_insn_to_dependency
    194 {
    195   const char *insn_name;
    196   enum s7_insn_type_for_dependency type;
    197 };
    198 
    199 struct s7_data_dependency
    200 {
    201   enum s7_insn_type_for_dependency pre_insn_type;
    202   char pre_reg[6];
    203   enum s7_insn_type_for_dependency cur_insn_type;
    204   char cur_reg[6];
    205   int bubblenum_7;
    206   int bubblenum_5;
    207   int warn_or_error;           /* warning - 0; error - 1  */
    208 };
    209 
    210 static const struct s7_insn_to_dependency s7_insn_to_dependency_table[] =
    211 {
    212   /* pce instruction.  */
    213   {"pce",       s7_D_pce},
    214   /* conditional branch instruction.  */
    215   {"bcs",       s7_D_cond_br},
    216   {"bcc",       s7_D_cond_br},
    217   {"bgtu",      s7_D_cond_br},
    218   {"bleu",      s7_D_cond_br},
    219   {"beq",       s7_D_cond_br},
    220   {"bne",       s7_D_cond_br},
    221   {"bgt",       s7_D_cond_br},
    222   {"ble",       s7_D_cond_br},
    223   {"bge",       s7_D_cond_br},
    224   {"blt",       s7_D_cond_br},
    225   {"bmi",       s7_D_cond_br},
    226   {"bpl",       s7_D_cond_br},
    227   {"bvs",       s7_D_cond_br},
    228   {"bvc",       s7_D_cond_br},
    229   {"bcsl",      s7_D_cond_br},
    230   {"bccl",      s7_D_cond_br},
    231   {"bgtul",     s7_D_cond_br},
    232   {"bleul",     s7_D_cond_br},
    233   {"beql",      s7_D_cond_br},
    234   {"bnel",      s7_D_cond_br},
    235   {"bgtl",      s7_D_cond_br},
    236   {"blel",      s7_D_cond_br},
    237   {"bgel",      s7_D_cond_br},
    238   {"bltl",      s7_D_cond_br},
    239   {"bmil",      s7_D_cond_br},
    240   {"bpll",      s7_D_cond_br},
    241   {"bvsl",      s7_D_cond_br},
    242   {"bvcl",      s7_D_cond_br},
    243   {"bcs!",      s7_D_cond_br},
    244   {"bcc!",      s7_D_cond_br},
    245   {"bgtu!",     s7_D_cond_br},
    246   {"bleu!",     s7_D_cond_br},
    247   {"beq!",      s7_D_cond_br},
    248   {"bne!",      s7_D_cond_br},
    249   {"bgt!",      s7_D_cond_br},
    250   {"ble!",      s7_D_cond_br},
    251   {"bge!",      s7_D_cond_br},
    252   {"blt!",      s7_D_cond_br},
    253   {"bmi!",      s7_D_cond_br},
    254   {"bpl!",      s7_D_cond_br},
    255   {"bvs!",      s7_D_cond_br},
    256   {"bvc!",      s7_D_cond_br},
    257   {"brcs",      s7_D_cond_br},
    258   {"brcc",      s7_D_cond_br},
    259   {"brgtu",     s7_D_cond_br},
    260   {"brleu",     s7_D_cond_br},
    261   {"breq",      s7_D_cond_br},
    262   {"brne",      s7_D_cond_br},
    263   {"brgt",      s7_D_cond_br},
    264   {"brle",      s7_D_cond_br},
    265   {"brge",      s7_D_cond_br},
    266   {"brlt",      s7_D_cond_br},
    267   {"brmi",      s7_D_cond_br},
    268   {"brpl",      s7_D_cond_br},
    269   {"brvs",      s7_D_cond_br},
    270   {"brvc",      s7_D_cond_br},
    271   {"brcsl",     s7_D_cond_br},
    272   {"brccl",     s7_D_cond_br},
    273   {"brgtul",    s7_D_cond_br},
    274   {"brleul",    s7_D_cond_br},
    275   {"breql",     s7_D_cond_br},
    276   {"brnel",     s7_D_cond_br},
    277   {"brgtl",     s7_D_cond_br},
    278   {"brlel",     s7_D_cond_br},
    279   {"brgel",     s7_D_cond_br},
    280   {"brltl",     s7_D_cond_br},
    281   {"brmil",     s7_D_cond_br},
    282   {"brpll",     s7_D_cond_br},
    283   {"brvsl",     s7_D_cond_br},
    284   {"brvcl",     s7_D_cond_br},
    285   {"brcs!",     s7_D_cond_br},
    286   {"brcc!",     s7_D_cond_br},
    287   {"brgtu!",    s7_D_cond_br},
    288   {"brleu!",    s7_D_cond_br},
    289   {"breq!",     s7_D_cond_br},
    290   {"brne!",     s7_D_cond_br},
    291   {"brgt!",     s7_D_cond_br},
    292   {"brle!",     s7_D_cond_br},
    293   {"brge!",     s7_D_cond_br},
    294   {"brlt!",     s7_D_cond_br},
    295   {"brmi!",     s7_D_cond_br},
    296   {"brpl!",     s7_D_cond_br},
    297   {"brvs!",     s7_D_cond_br},
    298   {"brvc!",     s7_D_cond_br},
    299   {"brcsl!",    s7_D_cond_br},
    300   {"brccl!",    s7_D_cond_br},
    301   {"brgtul!",   s7_D_cond_br},
    302   {"brleul!",   s7_D_cond_br},
    303   {"breql!",    s7_D_cond_br},
    304   {"brnel!",    s7_D_cond_br},
    305   {"brgtl!",    s7_D_cond_br},
    306   {"brlel!",    s7_D_cond_br},
    307   {"brgel!",    s7_D_cond_br},
    308   {"brltl!",    s7_D_cond_br},
    309   {"brmil!",    s7_D_cond_br},
    310   {"brpll!",    s7_D_cond_br},
    311   {"brvsl!",    s7_D_cond_br},
    312   {"brvcl!",    s7_D_cond_br},
    313   /* conditional move instruction.  */
    314   {"mvcs",      s7_D_cond_mv},
    315   {"mvcc",      s7_D_cond_mv},
    316   {"mvgtu",     s7_D_cond_mv},
    317   {"mvleu",     s7_D_cond_mv},
    318   {"mveq",      s7_D_cond_mv},
    319   {"mvne",      s7_D_cond_mv},
    320   {"mvgt",      s7_D_cond_mv},
    321   {"mvle",      s7_D_cond_mv},
    322   {"mvge",      s7_D_cond_mv},
    323   {"mvlt",      s7_D_cond_mv},
    324   {"mvmi",      s7_D_cond_mv},
    325   {"mvpl",      s7_D_cond_mv},
    326   {"mvvs",      s7_D_cond_mv},
    327   {"mvvc",      s7_D_cond_mv},
    328   /* move spectial instruction.  */
    329   {"mtcr",      s7_D_mtcr},
    330   {"mftlb",     s7_D_mftlb},
    331   {"mtptlb",    s7_D_mtptlb},
    332   {"mtrtlb",    s7_D_mtrtlb},
    333   {"stlb",      s7_D_stlb},
    334   {"mfcr",      s7_D_mfcr},
    335   {"mfsr",      s7_D_mfsr},
    336   /* cache instruction.  */
    337   {"cache 8",   s7_D_cached},
    338   {"cache 9",   s7_D_cached},
    339   {"cache 10",  s7_D_cached},
    340   {"cache 11",  s7_D_cached},
    341   {"cache 12",  s7_D_cached},
    342   {"cache 13",  s7_D_cached},
    343   {"cache 14",  s7_D_cached},
    344   {"cache 24",  s7_D_cached},
    345   {"cache 26",  s7_D_cached},
    346   {"cache 27",  s7_D_cached},
    347   {"cache 29",  s7_D_cached},
    348   {"cache 30",  s7_D_cached},
    349   {"cache 31",  s7_D_cached},
    350   {"cache 0",   s7_D_cachei},
    351   {"cache 1",   s7_D_cachei},
    352   {"cache 2",   s7_D_cachei},
    353   {"cache 3",   s7_D_cachei},
    354   {"cache 4",   s7_D_cachei},
    355   {"cache 16",  s7_D_cachei},
    356   {"cache 17",  s7_D_cachei},
    357   /* load/store instruction.  */
    358   {"lb",        s7_D_ldst},
    359   {"lbu",       s7_D_ldst},
    360   {"lbu!",      s7_D_ldst},
    361   {"lbup!",     s7_D_ldst},
    362   {"lh",        s7_D_ldst},
    363   {"lhu",       s7_D_ldst},
    364   {"lh!",       s7_D_ldst},
    365   {"lhp!",      s7_D_ldst},
    366   {"lw",        s7_D_ldst},
    367   {"lw!",       s7_D_ldst},
    368   {"lwp!",      s7_D_ldst},
    369   {"sb",        s7_D_ldst},
    370   {"sb!",       s7_D_ldst},
    371   {"sbp!",      s7_D_ldst},
    372   {"sh",        s7_D_ldst},
    373   {"sh!",       s7_D_ldst},
    374   {"shp!",      s7_D_ldst},
    375   {"sw",        s7_D_ldst},
    376   {"sw!",       s7_D_ldst},
    377   {"swp!",      s7_D_ldst},
    378   {"alw",       s7_D_ldst},
    379   {"asw",       s7_D_ldst},
    380   {"push!",     s7_D_ldst},
    381   {"pushhi!",   s7_D_ldst},
    382   {"pop!",      s7_D_ldst},
    383   {"pophi!",    s7_D_ldst},
    384   {"ldc1",      s7_D_ldst},
    385   {"ldc2",      s7_D_ldst},
    386   {"ldc3",      s7_D_ldst},
    387   {"stc1",      s7_D_ldst},
    388   {"stc2",      s7_D_ldst},
    389   {"stc3",      s7_D_ldst},
    390   {"scb",       s7_D_ldst},
    391   {"scw",       s7_D_ldst},
    392   {"sce",       s7_D_ldst},
    393   /* load combine instruction.  */
    394   {"lcb",       s7_D_ldcombine},
    395   {"lcw",       s7_D_ldcombine},
    396   {"lce",       s7_D_ldcombine},
    397 };
    398 
    399 static const struct s7_data_dependency s7_data_dependency_table[] =
    400 {
    401   /* Condition register.  */
    402   {s7_D_mtcr, "cr1", s7_D_pce, "", 2, 1, 0},
    403   {s7_D_mtcr, "cr1", s7_D_cond_br, "", 1, 0, 1},
    404   {s7_D_mtcr, "cr1", s7_D_cond_mv, "", 1, 0, 1},
    405   /* Status regiser.  */
    406   {s7_D_mtcr, "cr0", s7_D_all_insn, "", 5, 4, 0},
    407   /* CCR regiser.  */
    408   {s7_D_mtcr, "cr4", s7_D_all_insn, "", 6, 5, 0},
    409   /* EntryHi/EntryLo register.  */
    410   {s7_D_mftlb, "", s7_D_mtptlb, "", 1, 1, 1},
    411   {s7_D_mftlb, "", s7_D_mtrtlb, "", 1, 1, 1},
    412   {s7_D_mftlb, "", s7_D_stlb, "", 1, 1,1},
    413   {s7_D_mftlb, "", s7_D_mfcr, "cr11", 1, 1, 1},
    414   {s7_D_mftlb, "", s7_D_mfcr, "cr12", 1, 1, 1},
    415   /* Index register.  */
    416   {s7_D_stlb, "", s7_D_mtptlb, "", 1, 1, 1},
    417   {s7_D_stlb, "", s7_D_mftlb, "", 1, 1, 1},
    418   {s7_D_stlb, "", s7_D_mfcr, "cr8", 2, 2, 1},
    419   /* Cache.  */
    420   {s7_D_cached, "", s7_D_ldst, "", 1, 1, 0},
    421   {s7_D_cached, "", s7_D_ldcombine, "", 1, 1, 0},
    422   {s7_D_cachei, "", s7_D_all_insn, "", 5, 4, 0},
    423   /* Load combine.  */
    424   {s7_D_ldcombine, "", s7_D_mfsr, "sr1", 3, 3, 1},
    425 };
    426 
    427 
    428 
    430 /* Used to contain constructed error messages.  */
    431 static char s7_err_msg[255];
    432 static int s7_fix_data_dependency = 0;
    433 static int s7_warn_fix_data_dependency = 1;
    434 
    435 static int s7_in_my_get_expression = 0;
    436 
    437 /* Default, pop warning message when using r1.  */
    438 static int s7_nor1 = 1;
    439 
    440 /* Default will do instruction relax, -O0 will set s7_g_opt = 0.  */
    441 static unsigned int s7_g_opt = 1;
    442 
    443 /* The size of the small data section.  */
    444 static unsigned int s7_g_switch_value = 8;
    445 
    446 static segT s7_pdr_seg;
    447 
    448 struct s7_score_it
    449 {
    450   char name[s7_INSN_NAME_LEN];
    451   unsigned long instruction;
    452   unsigned long relax_inst;
    453   int size;
    454   int relax_size;
    455   enum score_insn_type type;
    456   char str[s7_MAX_LITERAL_POOL_SIZE];
    457   const char *error;
    458   int bwarn;
    459   char reg[s7_INSN_NAME_LEN];
    460   struct
    461   {
    462     bfd_reloc_code_real_type type;
    463     expressionS exp;
    464     int pc_rel;
    465   }reloc;
    466 };
    467 static struct s7_score_it s7_inst;
    468 
    469 typedef struct proc
    470 {
    471   symbolS *isym;
    472   unsigned long reg_mask;
    473   unsigned long reg_offset;
    474   unsigned long fpreg_mask;
    475   unsigned long leaf;
    476   unsigned long frame_offset;
    477   unsigned long frame_reg;
    478   unsigned long pc_reg;
    479 } s7_procS;
    480 static s7_procS s7_cur_proc;
    481 static s7_procS *s7_cur_proc_ptr;
    482 static int s7_numprocs;
    483 
    484 /* Structure for a hash table entry for a register.  */
    485 struct s7_reg_entry
    486 {
    487   const char *name;
    488   int number;
    489 };
    490 
    491 static const struct s7_reg_entry s7_score_rn_table[] =
    492 {
    493   {"r0", 0}, {"r1", 1}, {"r2", 2}, {"r3", 3},
    494   {"r4", 4}, {"r5", 5}, {"r6", 6}, {"r7", 7},
    495   {"r8", 8}, {"r9", 9}, {"r10", 10}, {"r11", 11},
    496   {"r12", 12}, {"r13", 13}, {"r14", 14}, {"r15", 15},
    497   {"r16", 16}, {"r17", 17}, {"r18", 18}, {"r19", 19},
    498   {"r20", 20}, {"r21", 21}, {"r22", 22}, {"r23", 23},
    499   {"r24", 24}, {"r25", 25}, {"r26", 26}, {"r27", 27},
    500   {"r28", 28}, {"r29", 29}, {"r30", 30}, {"r31", 31},
    501   {NULL, 0}
    502 };
    503 
    504 static const struct s7_reg_entry s7_score_srn_table[] =
    505 {
    506   {"sr0", 0}, {"sr1", 1}, {"sr2", 2},
    507   {NULL, 0}
    508 };
    509 
    510 static const struct s7_reg_entry s7_score_crn_table[] =
    511 {
    512   {"cr0", 0}, {"cr1", 1}, {"cr2", 2}, {"cr3", 3},
    513   {"cr4", 4}, {"cr5", 5}, {"cr6", 6}, {"cr7", 7},
    514   {"cr8", 8}, {"cr9", 9}, {"cr10", 10}, {"cr11", 11},
    515   {"cr12", 12}, {"cr13", 13}, {"cr14", 14}, {"cr15", 15},
    516   {"cr16", 16}, {"cr17", 17}, {"cr18", 18}, {"cr19", 19},
    517   {"cr20", 20}, {"cr21", 21}, {"cr22", 22}, {"cr23", 23},
    518   {"cr24", 24}, {"cr25", 25}, {"cr26", 26}, {"cr27", 27},
    519   {"cr28", 28}, {"cr29", 29}, {"cr30", 30}, {"cr31", 31},
    520   {NULL, 0}
    521 };
    522 
    523 struct s7_reg_map
    524 {
    525   const struct s7_reg_entry *names;
    526   int max_regno;
    527   struct hash_control *htab;
    528   const char *expected;
    529 };
    530 
    531 static struct s7_reg_map s7_all_reg_maps[] =
    532 {
    533   {s7_score_rn_table, 31, NULL, N_("S+core register expected")},
    534   {s7_score_srn_table, 2, NULL, N_("S+core special-register expected")},
    535   {s7_score_crn_table, 31, NULL, N_("S+core co-processor register expected")},
    536 };
    537 
    538 static struct hash_control *s7_score_ops_hsh = NULL;
    539 static struct hash_control *s7_dependency_insn_hsh = NULL;
    540 
    541 
    542 struct s7_datafield_range
    544 {
    545   int data_type;
    546   int bits;
    547   int range[2];
    548 };
    549 
    550 static struct s7_datafield_range s7_score_df_range[] =
    551 {
    552   {_IMM4,             4,  {0, (1 << 4) - 1}},	        /* (     0 ~ 15   ) */
    553   {_IMM5,             5,  {0, (1 << 5) - 1}},	        /* (     0 ~ 31   ) */
    554   {_IMM8,             8,  {0, (1 << 8) - 1}},	        /* (     0 ~ 255  ) */
    555   {_IMM14,            14, {0, (1 << 14) - 1}},	        /* (     0 ~ 16383) */
    556   {_IMM15,            15, {0, (1 << 15) - 1}},	        /* (     0 ~ 32767) */
    557   {_IMM16,            16, {0, (1 << 16) - 1}},	        /* (     0 ~ 65535) */
    558   {_SIMM10,           10, {-(1 << 9), (1 << 9) - 1}},	/* (  -512 ~ 511  ) */
    559   {_SIMM12,           12, {-(1 << 11), (1 << 11) - 1}},	/* ( -2048 ~ 2047 ) */
    560   {_SIMM14,           14, {-(1 << 13), (1 << 13) - 1}},	/* ( -8192 ~ 8191 ) */
    561   {_SIMM15,           15, {-(1 << 14), (1 << 14) - 1}},	/* (-16384 ~ 16383) */
    562   {_SIMM16,           16, {-(1 << 15), (1 << 15) - 1}},	/* (-32768 ~ 32767) */
    563   {_SIMM14_NEG,       14, {-(1 << 13), (1 << 13) - 1}},	/* ( -8191 ~ 8192 ) */
    564   {_IMM16_NEG,        16, {0, (1 << 16) - 1}},	        /* (-65535 ~ 0    ) */
    565   {_SIMM16_NEG,       16, {-(1 << 15), (1 << 15) - 1}},	/* (-32768 ~ 32767) */
    566   {_IMM20,            20, {0, (1 << 20) - 1}},
    567   {_IMM25,            25, {0, (1 << 25) - 1}},
    568   {_DISP8div2,        8,  {-(1 << 8), (1 << 8) - 1}},	/* (  -256 ~ 255  ) */
    569   {_DISP11div2,       11, {0, 0}},
    570   {_DISP19div2,       19, {-(1 << 19), (1 << 19) - 1}},	/* (-524288 ~ 524287) */
    571   {_DISP24div2,       24, {0, 0}},
    572   {_VALUE,            32, {0, ((unsigned int)1 << 31) - 1}},
    573   {_VALUE_HI16,       16, {0, (1 << 16) - 1}},
    574   {_VALUE_LO16,       16, {0, (1 << 16) - 1}},
    575   {_VALUE_LDST_LO16,  16, {0, (1 << 16) - 1}},
    576   {_SIMM16_LA,        16, {-(1 << 15), (1 << 15) - 1}},	/* (-32768 ~ 32767) */
    577   {_IMM5_RSHIFT_1,    5,  {0, (1 << 6) - 1}},	        /* (     0 ~ 63   ) */
    578   {_IMM5_RSHIFT_2,    5,  {0, (1 << 7) - 1}},	        /* (     0 ~ 127  ) */
    579   {_SIMM16_LA_POS,    16, {0, (1 << 15) - 1}},	        /* (     0 ~ 32767) */
    580   {_IMM5_RANGE_8_31,  5,  {8, 31}},	                /* But for cop0 the valid data : (8 ~ 31). */
    581   {_IMM10_RSHIFT_2,   10, {-(1 << 11), (1 << 11) - 1}},	/* For ldc#, stc#. */
    582   {_SIMM10,           10, {0, (1 << 10) - 1}},	        /* ( -1024 ~ 1023 ) */
    583   {_SIMM12,           12, {0, (1 << 12) - 1}},	        /* ( -2048 ~ 2047 ) */
    584   {_SIMM14,           14, {0, (1 << 14) - 1}},          /* ( -8192 ~ 8191 ) */
    585   {_SIMM15,           15, {0, (1 << 15) - 1}},	        /* (-16384 ~ 16383) */
    586   {_SIMM16,           16, {0, (1 << 16) - 1}},	        /* (-65536 ~ 65536) */
    587   {_SIMM14_NEG,       14, {0, (1 << 16) - 1}},          /* ( -8191 ~ 8192 ) */
    588   {_IMM16_NEG,        16, {0, (1 << 16) - 1}},	        /* ( 65535 ~ 0    ) */
    589   {_SIMM16_NEG,       16, {0, (1 << 16) - 1}},	        /* ( 65535 ~ 0    ) */
    590   {_IMM20,            20, {0, (1 << 20) - 1}},	        /* (-32768 ~ 32767) */
    591   {_IMM25,            25, {0, (1 << 25) - 1}},	        /* (-32768 ~ 32767) */
    592   {_GP_IMM15,         15, {0, (1 << 15) - 1}},	        /* (     0 ~ 65535) */
    593   {_GP_IMM14,         14, {0, (1 << 14) - 1}},	        /* (     0 ~ 65535) */
    594   {_SIMM16_pic,       16, {-(1 << 15), (1 << 15) - 1}},	/* (-32768 ~ 32767) */
    595   {_IMM16_LO16_pic,   16, {0, (1 << 16) - 1}},	        /* ( 65535 ~ 0    ) */
    596   {_IMM16_pic,        16, {0, (1 << 16) - 1}},	        /* (     0 ~ 65535) */
    597 };
    598 
    599 
    600 struct s7_asm_opcode
    602 {
    603   /* Instruction name.  */
    604   const char *template_name;
    605 
    606   /* Instruction Opcode.  */
    607   bfd_vma value;
    608 
    609   /* Instruction bit mask.  */
    610   bfd_vma bitmask;
    611 
    612   /* Relax instruction opcode.  0x8000 imply no relaxation.  */
    613   bfd_vma relax_value;
    614 
    615   /* Instruction type.  */
    616   enum score_insn_type type;
    617 
    618   /* Function to call to parse args.  */
    619   void (*parms) (char *);
    620 };
    621 
    622 static const struct s7_asm_opcode s7_score_ldst_insns[] =
    623 {
    624   {"lw",        0x20000000, 0x3e000000, 0x2008,     Rd_rvalueRs_SI15,     s7_do_ldst_insn},
    625   {"lw",        0x06000000, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  s7_do_ldst_insn},
    626   {"lw",        0x0e000000, 0x3e000007, 0x200a,     Rd_rvalueRs_postSI12, s7_do_ldst_insn},
    627   {"lh",        0x22000000, 0x3e000000, 0x2009,     Rd_rvalueRs_SI15,     s7_do_ldst_insn},
    628   {"lh",        0x06000001, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  s7_do_ldst_insn},
    629   {"lh",        0x0e000001, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, s7_do_ldst_insn},
    630   {"lhu",       0x24000000, 0x3e000000, 0x8000,     Rd_rvalueRs_SI15,     s7_do_ldst_insn},
    631   {"lhu",       0x06000002, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  s7_do_ldst_insn},
    632   {"lhu",       0x0e000002, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, s7_do_ldst_insn},
    633   {"lb",        0x26000000, 0x3e000000, 0x8000,     Rd_rvalueRs_SI15,     s7_do_ldst_insn},
    634   {"lb",        0x06000003, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  s7_do_ldst_insn},
    635   {"lb",        0x0e000003, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, s7_do_ldst_insn},
    636   {"sw",        0x28000000, 0x3e000000, 0x200c,     Rd_lvalueRs_SI15,     s7_do_ldst_insn},
    637   {"sw",        0x06000004, 0x3e000007, 0x200e,     Rd_lvalueRs_preSI12,  s7_do_ldst_insn},
    638   {"sw",        0x0e000004, 0x3e000007, 0x8000,     Rd_lvalueRs_postSI12, s7_do_ldst_insn},
    639   {"sh",        0x2a000000, 0x3e000000, 0x200d,     Rd_lvalueRs_SI15,     s7_do_ldst_insn},
    640   {"sh",        0x06000005, 0x3e000007, 0x8000,     Rd_lvalueRs_preSI12,  s7_do_ldst_insn},
    641   {"sh",        0x0e000005, 0x3e000007, 0x8000,     Rd_lvalueRs_postSI12, s7_do_ldst_insn},
    642   {"lbu",       0x2c000000, 0x3e000000, 0x200b,     Rd_rvalueRs_SI15,     s7_do_ldst_insn},
    643   {"lbu",       0x06000006, 0x3e000007, 0x8000,     Rd_rvalueRs_preSI12,  s7_do_ldst_insn},
    644   {"lbu",       0x0e000006, 0x3e000007, 0x8000,     Rd_rvalueRs_postSI12, s7_do_ldst_insn},
    645   {"sb",        0x2e000000, 0x3e000000, 0x200f,     Rd_lvalueRs_SI15,     s7_do_ldst_insn},
    646   {"sb",        0x06000007, 0x3e000007, 0x8000,     Rd_lvalueRs_preSI12,  s7_do_ldst_insn},
    647   {"sb",        0x0e000007, 0x3e000007, 0x8000,     Rd_lvalueRs_postSI12, s7_do_ldst_insn},
    648 };
    649 
    650 static const struct s7_asm_opcode s7_score_insns[] =
    651 {
    652   {"abs",       0x3800000a, 0x3e007fff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    653   {"abs.s",     0x3800004b, 0x3e007fff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    654   {"add",       0x00000010, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    655   {"add.c",     0x00000011, 0x3e0003ff, 0x2000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    656   {"add.s",     0x38000048, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    657   {"addc",      0x00000012, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    658   {"addc.c",    0x00000013, 0x3e0003ff, 0x0009,     Rd_Rs_Rs,             s7_do_rdrsrs},
    659   {"addi",      0x02000000, 0x3e0e0001, 0x8000,     Rd_SI16,              s7_do_rdsi16},
    660   {"addi.c",    0x02000001, 0x3e0e0001, 0x8000,     Rd_SI16,              s7_do_rdsi16},
    661   {"addis",     0x0a000000, 0x3e0e0001, 0x8000,     Rd_SI16,              s7_do_rdi16},
    662   {"addis.c",   0x0a000001, 0x3e0e0001, 0x8000,     Rd_SI16,              s7_do_rdi16},
    663   {"addri",     0x10000000, 0x3e000001, 0x8000,     Rd_Rs_SI14,           s7_do_rdrssi14},
    664   {"addri.c",   0x10000001, 0x3e000001, 0x8000,     Rd_Rs_SI14,           s7_do_rdrssi14},
    665   {"addc!",     0x0009,     0x700f,     0x00000013, Rd_Rs,                s7_do16_rdrs},
    666   {"add!",      0x2000,     0x700f,     0x00000011, Rd_Rs,                s7_do16_rdrs},
    667   {"addei!",    0x6000    , 0x7087,     0x02000001, Rd_I4,                s7_do16_rdi4},
    668   {"subi",      0x02000000, 0x3e0e0001, 0x8000,     Rd_SI16,              s7_do_sub_rdsi16},
    669   {"subi.c",    0x02000001, 0x3e0e0001, 0x8000,     Rd_SI16,              s7_do_sub_rdsi16},
    670   {"subri",     0x10000000, 0x3e000001, 0x8000,     Rd_Rs_SI14,           s7_do_sub_rdrssi14},
    671   {"subri.c",   0x10000001, 0x3e000001, 0x8000,     Rd_Rs_SI14,           s7_do_sub_rdrssi14},
    672   {"and",       0x00000020, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    673   {"and.c",     0x00000021, 0x3e0003ff, 0x2004,     Rd_Rs_Rs,             s7_do_rdrsrs},
    674   {"andi",      0x02080000, 0x3e0e0001, 0x8000,     Rd_I16,               s7_do_rdi16},
    675   {"andi.c",    0x02080001, 0x3e0e0001, 0x8000,     Rd_I16,               s7_do_rdi16},
    676   {"andis",     0x0a080000, 0x3e0e0001, 0x8000,     Rd_I16,               s7_do_rdi16},
    677   {"andis.c",   0x0a080001, 0x3e0e0001, 0x8000,     Rd_I16,               s7_do_rdi16},
    678   {"andri",     0x18000000, 0x3e000001, 0x8000,     Rd_Rs_I14,            s7_do_rdrsi14},
    679   {"andri.c",   0x18000001, 0x3e000001, 0x8000,     Rd_Rs_I14,            s7_do_rdrsi14},
    680   {"and!",      0x2004,     0x700f,     0x00000021, Rd_Rs,                s7_do16_rdrs},
    681   {"bcs",       0x08000000, 0x3e007c01, 0x4000,     PC_DISP19div2,        s7_do_branch},
    682   {"bcc",       0x08000400, 0x3e007c01, 0x4000,     PC_DISP19div2,        s7_do_branch},
    683   {"bcnz",      0x08003800, 0x3e007c01, 0x4000,     PC_DISP19div2,        s7_do_branch},
    684   {"bcsl",      0x08000001, 0x3e007c01, 0x8000,     PC_DISP19div2,        s7_do_branch},
    685   {"bccl",      0x08000401, 0x3e007c01, 0x8000,     PC_DISP19div2,        s7_do_branch},
    686   {"bcnzl",     0x08003801, 0x3e007c01, 0x8000,     PC_DISP19div2,        s7_do_branch},
    687   {"bcs!",      0x4000,     0x7f00,     0x08000000, PC_DISP8div2,         s7_do16_branch},
    688   {"bcc!",      0x4100,     0x7f00,     0x08000400, PC_DISP8div2,         s7_do16_branch},
    689   {"bcnz!",     0x4e00,     0x7f00,     0x08003800, PC_DISP8div2,         s7_do16_branch},
    690   {"beq",       0x08001000, 0x3e007c01, 0x4000,     PC_DISP19div2,        s7_do_branch},
    691   {"beql",      0x08001001, 0x3e007c01, 0x8000,     PC_DISP19div2,        s7_do_branch},
    692   {"beq!",      0x4400,     0x7f00,     0x08001000, PC_DISP8div2,         s7_do16_branch},
    693   {"bgtu",      0x08000800, 0x3e007c01, 0x4000,     PC_DISP19div2,        s7_do_branch},
    694   {"bgt",       0x08001800, 0x3e007c01, 0x4000,     PC_DISP19div2,        s7_do_branch},
    695   {"bge",       0x08002000, 0x3e007c01, 0x4000,     PC_DISP19div2,        s7_do_branch},
    696   {"bgtul",     0x08000801, 0x3e007c01, 0x8000,     PC_DISP19div2,        s7_do_branch},
    697   {"bgtl",      0x08001801, 0x3e007c01, 0x8000,     PC_DISP19div2,        s7_do_branch},
    698   {"bgel",      0x08002001, 0x3e007c01, 0x8000,     PC_DISP19div2,        s7_do_branch},
    699   {"bgtu!",     0x4200,     0x7f00,     0x08000800, PC_DISP8div2,         s7_do16_branch},
    700   {"bgt!",      0x4600,     0x7f00,     0x08001800, PC_DISP8div2,         s7_do16_branch},
    701   {"bge!",      0x4800,     0x7f00,     0x08002000, PC_DISP8div2,         s7_do16_branch},
    702   {"bitclr.c",  0x00000029, 0x3e0003ff, 0x6004,     Rd_Rs_I5,             s7_do_rdrsi5},
    703   {"bitrev",    0x3800000c, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    704   {"bitset.c",  0x0000002b, 0x3e0003ff, 0x6005,     Rd_Rs_I5,             s7_do_rdrsi5},
    705   {"bittst.c",  0x0000002d, 0x3e0003ff, 0x6006,     x_Rs_I5,              s7_do_xrsi5},
    706   {"bittgl.c",  0x0000002f, 0x3e0003ff, 0x6007,     Rd_Rs_I5,             s7_do_rdrsi5},
    707   {"bitclr!",   0x6004,     0x7007,     0x00000029, Rd_I5,                s7_do16_rdi5},
    708   {"bitset!",   0x6005,     0x7007,     0x0000002b, Rd_I5,                s7_do16_rdi5},
    709   {"bittst!",   0x6006,     0x7007,     0x0000002d, Rd_I5,                s7_do16_rdi5},
    710   {"bittgl!",   0x6007,     0x7007,     0x0000002f, Rd_I5,                s7_do16_rdi5},
    711   {"bleu",      0x08000c00, 0x3e007c01, 0x4000,     PC_DISP19div2,        s7_do_branch},
    712   {"ble",       0x08001c00, 0x3e007c01, 0x4000,     PC_DISP19div2,        s7_do_branch},
    713   {"blt",       0x08002400, 0x3e007c01, 0x4000,     PC_DISP19div2,        s7_do_branch},
    714   {"bleul",     0x08000c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        s7_do_branch},
    715   {"blel",      0x08001c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        s7_do_branch},
    716   {"bltl",      0x08002401, 0x3e007c01, 0x8000,     PC_DISP19div2,        s7_do_branch},
    717   {"bl",        0x08003c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        s7_do_branch},
    718   {"bleu!",     0x4300,     0x7f00,     0x08000c00, PC_DISP8div2,         s7_do16_branch},
    719   {"ble!",      0x4700,     0x7f00,     0x08001c00, PC_DISP8div2,         s7_do16_branch},
    720   {"blt!",      0x4900,     0x7f00,     0x08002400, PC_DISP8div2,         s7_do16_branch},
    721   {"bmi",       0x08002800, 0x3e007c01, 0x4000,     PC_DISP19div2,        s7_do_branch},
    722   {"bmil",      0x08002801, 0x3e007c01, 0x8000,     PC_DISP19div2,        s7_do_branch},
    723   {"bmi!",      0x00004a00, 0x00007f00, 0x08002800, PC_DISP8div2,         s7_do16_branch},
    724   {"bne",       0x08001400, 0x3e007c01, 0x4000,     PC_DISP19div2,        s7_do_branch},
    725   {"bnel",      0x08001401, 0x3e007c01, 0x8000,     PC_DISP19div2,        s7_do_branch},
    726   {"bne!",      0x4500,     0x7f00,     0x08001400, PC_DISP8div2,         s7_do16_branch},
    727   {"bpl",       0x08002c00, 0x3e007c01, 0x4000,     PC_DISP19div2,        s7_do_branch},
    728   {"bpll",      0x08002c01, 0x3e007c01, 0x8000,     PC_DISP19div2,        s7_do_branch},
    729   {"bpl!",      0x4b00,     0x7f00,     0x08002c00, PC_DISP8div2,         s7_do16_branch},
    730   {"brcs",      0x00000008, 0x3e007fff, 0x0004,     x_Rs_x,               s7_do_rs},
    731   {"brcc",      0x00000408, 0x3e007fff, 0x0104,     x_Rs_x,               s7_do_rs},
    732   {"brgtu",     0x00000808, 0x3e007fff, 0x0204,     x_Rs_x,               s7_do_rs},
    733   {"brleu",     0x00000c08, 0x3e007fff, 0x0304,     x_Rs_x,               s7_do_rs},
    734   {"breq",      0x00001008, 0x3e007fff, 0x0404,     x_Rs_x,               s7_do_rs},
    735   {"brne",      0x00001408, 0x3e007fff, 0x0504,     x_Rs_x,               s7_do_rs},
    736   {"brgt",      0x00001808, 0x3e007fff, 0x0604,     x_Rs_x,               s7_do_rs},
    737   {"brle",      0x00001c08, 0x3e007fff, 0x0704,     x_Rs_x,               s7_do_rs},
    738   {"brge",      0x00002008, 0x3e007fff, 0x0804,     x_Rs_x,               s7_do_rs},
    739   {"brlt",      0x00002408, 0x3e007fff, 0x0904,     x_Rs_x,               s7_do_rs},
    740   {"brmi",      0x00002808, 0x3e007fff, 0x0a04,     x_Rs_x,               s7_do_rs},
    741   {"brpl",      0x00002c08, 0x3e007fff, 0x0b04,     x_Rs_x,               s7_do_rs},
    742   {"brvs",      0x00003008, 0x3e007fff, 0x0c04,     x_Rs_x,               s7_do_rs},
    743   {"brvc",      0x00003408, 0x3e007fff, 0x0d04,     x_Rs_x,               s7_do_rs},
    744   {"brcnz",     0x00003808, 0x3e007fff, 0x0e04,     x_Rs_x,               s7_do_rs},
    745   {"br",        0x00003c08, 0x3e007fff, 0x0f04,     x_Rs_x,               s7_do_rs},
    746   {"brcsl",     0x00000009, 0x3e007fff, 0x000c,     x_Rs_x,               s7_do_rs},
    747   {"brccl",     0x00000409, 0x3e007fff, 0x010c,     x_Rs_x,               s7_do_rs},
    748   {"brgtul",    0x00000809, 0x3e007fff, 0x020c,     x_Rs_x,               s7_do_rs},
    749   {"brleul",    0x00000c09, 0x3e007fff, 0x030c,     x_Rs_x,               s7_do_rs},
    750   {"breql",     0x00001009, 0x3e007fff, 0x040c,     x_Rs_x,               s7_do_rs},
    751   {"brnel",     0x00001409, 0x3e007fff, 0x050c,     x_Rs_x,               s7_do_rs},
    752   {"brgtl",     0x00001809, 0x3e007fff, 0x060c,     x_Rs_x,               s7_do_rs},
    753   {"brlel",     0x00001c09, 0x3e007fff, 0x070c,     x_Rs_x,               s7_do_rs},
    754   {"brgel",     0x00002009, 0x3e007fff, 0x080c,     x_Rs_x,               s7_do_rs},
    755   {"brltl",     0x00002409, 0x3e007fff, 0x090c,     x_Rs_x,               s7_do_rs},
    756   {"brmil",     0x00002809, 0x3e007fff, 0x0a0c,     x_Rs_x,               s7_do_rs},
    757   {"brpll",     0x00002c09, 0x3e007fff, 0x0b0c,     x_Rs_x,               s7_do_rs},
    758   {"brvsl",     0x00003009, 0x3e007fff, 0x0c0c,     x_Rs_x,               s7_do_rs},
    759   {"brvcl",     0x00003409, 0x3e007fff, 0x0d0c,     x_Rs_x,               s7_do_rs},
    760   {"brcnzl",    0x00003809, 0x3e007fff, 0x0e0c,     x_Rs_x,               s7_do_rs},
    761   {"brl",       0x00003c09, 0x3e007fff, 0x0f0c,     x_Rs_x,               s7_do_rs},
    762   {"brcs!",     0x0004,     0x7f0f,     0x00000008, x_Rs,                 s7_do16_xrs},
    763   {"brcc!",     0x0104,     0x7f0f,     0x00000408, x_Rs,                 s7_do16_xrs},
    764   {"brgtu!",    0x0204,     0x7f0f,     0x00000808, x_Rs,                 s7_do16_xrs},
    765   {"brleu!",    0x0304,     0x7f0f,     0x00000c08, x_Rs,                 s7_do16_xrs},
    766   {"breq!",     0x0404,     0x7f0f,     0x00001008, x_Rs,                 s7_do16_xrs},
    767   {"brne!",     0x0504,     0x7f0f,     0x00001408, x_Rs,                 s7_do16_xrs},
    768   {"brgt!",     0x0604,     0x7f0f,     0x00001808, x_Rs,                 s7_do16_xrs},
    769   {"brle!",     0x0704,     0x7f0f,     0x00001c08, x_Rs,                 s7_do16_xrs},
    770   {"brge!",     0x0804,     0x7f0f,     0x00002008, x_Rs,                 s7_do16_xrs},
    771   {"brlt!",     0x0904,     0x7f0f,     0x00002408, x_Rs,                 s7_do16_xrs},
    772   {"brmi!",     0x0a04,     0x7f0f,     0x00002808, x_Rs,                 s7_do16_xrs},
    773   {"brpl!",     0x0b04,     0x7f0f,     0x00002c08, x_Rs,                 s7_do16_xrs},
    774   {"brvs!",     0x0c04,     0x7f0f,     0x00003008, x_Rs,                 s7_do16_xrs},
    775   {"brvc!",     0x0d04,     0x7f0f,     0x00003408, x_Rs,                 s7_do16_xrs},
    776   {"brcnz!",    0x0e04,     0x7f0f,     0x00003808, x_Rs,                 s7_do16_xrs},
    777   {"br!",       0x0f04,     0x7f0f,     0x00003c08, x_Rs,                 s7_do16_xrs},
    778   {"brcsl!",    0x000c,     0x7f0f,     0x00000009, x_Rs,                 s7_do16_xrs},
    779   {"brccl!",    0x010c,     0x7f0f,     0x00000409, x_Rs,                 s7_do16_xrs},
    780   {"brgtul!",   0x020c,     0x7f0f,     0x00000809, x_Rs,                 s7_do16_xrs},
    781   {"brleul!",   0x030c,     0x7f0f,     0x00000c09, x_Rs,                 s7_do16_xrs},
    782   {"breql!",    0x040c,     0x7f0f,     0x00001009, x_Rs,                 s7_do16_xrs},
    783   {"brnel!",    0x050c,     0x7f0f,     0x00001409, x_Rs,                 s7_do16_xrs},
    784   {"brgtl!",    0x060c,     0x7f0f,     0x00001809, x_Rs,                 s7_do16_xrs},
    785   {"brlel!",    0x070c,     0x7f0f,     0x00001c09, x_Rs,                 s7_do16_xrs},
    786   {"brgel!",    0x080c,     0x7f0f,     0x00002009, x_Rs,                 s7_do16_xrs},
    787   {"brltl!",    0x090c,     0x7f0f,     0x00002409, x_Rs,                 s7_do16_xrs},
    788   {"brmil!",    0x0a0c,     0x7f0f,     0x00002809, x_Rs,                 s7_do16_xrs},
    789   {"brpll!",    0x0b0c,     0x7f0f,     0x00002c09, x_Rs,                 s7_do16_xrs},
    790   {"brvsl!",    0x0c0c,     0x7f0f,     0x00003009, x_Rs,                 s7_do16_xrs},
    791   {"brvcl!",    0x0d0c,     0x7f0f,     0x00003409, x_Rs,                 s7_do16_xrs},
    792   {"brcnzl!",   0x0e0c,     0x7f0f,     0x00003809, x_Rs,                 s7_do16_xrs},
    793   {"brl!",      0x0f0c,     0x7f0f,     0x00003c09, x_Rs,                 s7_do16_xrs},
    794   {"bvs",       0x08003000, 0x3e007c01, 0x4000,     PC_DISP19div2,        s7_do_branch},
    795   {"bvc",       0x08003400, 0x3e007c01, 0x4000,     PC_DISP19div2,        s7_do_branch},
    796   {"bvsl",      0x08003001, 0x3e007c01, 0x8000,     PC_DISP19div2,        s7_do_branch},
    797   {"bvcl",      0x08003401, 0x3e007c01, 0x8000,     PC_DISP19div2,        s7_do_branch},
    798   {"bvs!",      0x4c00,     0x7f00,     0x08003000, PC_DISP8div2,         s7_do16_branch},
    799   {"bvc!",      0x4d00,     0x7f00,     0x08003400, PC_DISP8div2,         s7_do16_branch},
    800   {"b!",        0x4f00,     0x7f00,     0x08003c00, PC_DISP8div2,         s7_do16_branch},
    801   {"b",         0x08003c00, 0x3e007c01, 0x4000,     PC_DISP19div2,        s7_do_branch},
    802   {"cache",     0x30000000, 0x3ff00000, 0x8000,     OP5_rvalueRs_SI15,    s7_do_cache},
    803   {"ceinst",    0x38000000, 0x3e000000, 0x8000,     I5_Rs_Rs_I5_OP5,      s7_do_ceinst},
    804   {"clz",       0x3800000d, 0x3e007fff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    805   {"cmpteq.c",  0x00000019, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    806   {"cmptmi.c",  0x00100019, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    807   {"cmp.c",     0x00300019, 0x3ff003ff, 0x2003,     x_Rs_Rs,              s7_do_rsrs},
    808   {"cmpzteq.c", 0x0000001b, 0x3ff07fff, 0x8000,     x_Rs_x,               s7_do_rs},
    809   {"cmpztmi.c", 0x0010001b, 0x3ff07fff, 0x8000,     x_Rs_x,               s7_do_rs},
    810   {"cmpz.c",    0x0030001b, 0x3ff07fff, 0x8000,     x_Rs_x,               s7_do_rs},
    811   {"cmpi.c",    0x02040001, 0x3e0e0001, 0x8000,     Rd_SI16,              s7_do_rdsi16},
    812   {"cmp!",      0x2003,     0x700f,     0x00300019, Rd_Rs,                s7_do16_rdrs},
    813   {"cop1",      0x0c00000c, 0x3e00001f, 0x8000,     Rd_Rs_Rs_imm,         s7_do_crdcrscrsimm5},
    814   {"cop2",      0x0c000014, 0x3e00001f, 0x8000,     Rd_Rs_Rs_imm,         s7_do_crdcrscrsimm5},
    815   {"cop3",      0x0c00001c, 0x3e00001f, 0x8000,     Rd_Rs_Rs_imm,         s7_do_crdcrscrsimm5},
    816   {"drte",      0x0c0000a4, 0x3e0003ff, 0x8000,     NO_OPD,               s7_do_empty},
    817   {"extsb",     0x00000058, 0x3e0003ff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    818   {"extsb.c",   0x00000059, 0x3e0003ff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    819   {"extsh",     0x0000005a, 0x3e0003ff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    820   {"extsh.c",   0x0000005b, 0x3e0003ff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    821   {"extzb",     0x0000005c, 0x3e0003ff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    822   {"extzb.c",   0x0000005d, 0x3e0003ff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    823   {"extzh",     0x0000005e, 0x3e0003ff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    824   {"extzh.c",   0x0000005f, 0x3e0003ff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    825   {"jl",        0x04000001, 0x3e000001, 0x8000,     PC_DISP24div2,        s7_do_jump},
    826   {"jl!",       0x3001,     0x7001,     0x04000001, PC_DISP11div2,        s7_do16_jump},
    827   {"j!",        0x3000,     0x7001,     0x04000000, PC_DISP11div2,        s7_do16_jump},
    828   {"j",         0x04000000, 0x3e000001, 0x8000,     PC_DISP24div2,        s7_do_jump},
    829   {"lbu!",      0x200b,     0x0000700f, 0x2c000000, Rd_rvalueRs,          s7_do16_ldst_insn},
    830   {"lbup!",     0x7003,     0x7007,     0x2c000000, Rd_rvalueBP_I5,       s7_do16_ldst_imm_insn},
    831   {"alw",       0x0000000c, 0x3e0003ff, 0x8000,     Rd_rvalue32Rs,        s7_do_ldst_atomic},
    832   {"lcb",       0x00000060, 0x3e0003ff, 0x8000,     x_rvalueRs_post4,     s7_do_ldst_unalign},
    833   {"lcw",       0x00000062, 0x3e0003ff, 0x8000,     Rd_rvalueRs_post4,    s7_do_ldst_unalign},
    834   {"lce",       0x00000066, 0x3e0003ff, 0x8000,     Rd_rvalueRs_post4,    s7_do_ldst_unalign},
    835   {"ldc1",      0x0c00000a, 0x3e00001f, 0x8000,     Rd_rvalueRs_SI10,     s7_do_ldst_cop},
    836   {"ldc2",      0x0c000012, 0x3e00001f, 0x8000,     Rd_rvalueRs_SI10,     s7_do_ldst_cop},
    837   {"ldc3",      0x0c00001a, 0x3e00001f, 0x8000,     Rd_rvalueRs_SI10,     s7_do_ldst_cop},
    838   {"lh!",       0x2009,     0x700f,     0x22000000, Rd_rvalueRs,          s7_do16_ldst_insn},
    839   {"lhp!",      0x7001,     0x7007,     0x22000000, Rd_rvalueBP_I5,       s7_do16_ldst_imm_insn},
    840   {"ldi",       0x020c0000, 0x3e0e0000, 0x5000,     Rd_SI16,              s7_do_rdsi16},
    841   {"ldis",      0x0a0c0000, 0x3e0e0000, 0x8000,     Rd_I16,               s7_do_rdi16},
    842   {"ldiu!",     0x5000,     0x7000,     0x020c0000, Rd_I8,                s7_do16_ldst_imm_insn},
    843   {"lw!",       0x2008,     0x700f,     0x20000000, Rd_rvalueRs,          s7_do16_ldst_insn},
    844   {"lwp!",      0x7000,     0x7007,     0x20000000, Rd_rvalueBP_I5,       s7_do16_ldst_imm_insn},
    845   {"mfcel",     0x00000448, 0x3e007fff, 0x8000,     Rd_x_x,               s7_do_rd},
    846   {"mfcel!",    0x1001,     0x7f0f,     0x00000448, x_Rs,                 s7_do16_rs},
    847   {"mad",       0x38000000, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    848   {"mad.f!",    0x1004,     0x700f,     0x38000080, Rd_Rs,                s7_do16_rdrs},
    849   {"madh",      0x38000203, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    850   {"madh.fs",   0x380002c3, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    851   {"madh.fs!",  0x100b,     0x700f,     0x380002c3, Rd_Rs,                s7_do16_rdrs},
    852   {"madl",      0x38000002, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    853   {"madl.fs",   0x380000c2, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    854   {"madl.fs!",  0x100a,     0x700f,     0x380000c2, Rd_Rs,                s7_do16_rdrs},
    855   {"madu",      0x38000020, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    856   {"madu!",     0x1005,     0x700f,     0x38000020, Rd_Rs,                s7_do16_rdrs},
    857   {"mad.f",     0x38000080, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    858   {"max",       0x38000007, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    859   {"mazh",      0x38000303, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    860   {"mazh.f",    0x38000383, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    861   {"mazh.f!",   0x1009,     0x700f,     0x38000383, Rd_Rs,                s7_do16_rdrs},
    862   {"mazl",      0x38000102, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    863   {"mazl.f",    0x38000182, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    864   {"mazl.f!",   0x1008,     0x700f,     0x38000182, Rd_Rs,                s7_do16_rdrs},
    865   {"mfceh",     0x00000848, 0x3e007fff, 0x8000,     Rd_x_x,               s7_do_rd},
    866   {"mfceh!",    0x1101,     0x7f0f,     0x00000848, x_Rs,                 s7_do16_rs},
    867   {"mfcehl",    0x00000c48, 0x3e007fff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    868   {"mfsr",      0x00000050, 0x3e0003ff, 0x8000,     Rd_x_I5,              s7_do_rdsrs},
    869   {"mfcr",      0x0c000001, 0x3e00001f, 0x8000,     Rd_Rs_x,              s7_do_rdcrs},
    870   {"mfc1",      0x0c000009, 0x3e00001f, 0x8000,     Rd_Rs_x,              s7_do_rdcrs},
    871   {"mfc2",      0x0c000011, 0x3e00001f, 0x8000,     Rd_Rs_x,              s7_do_rdcrs},
    872   {"mfc3",      0x0c000019, 0x3e00001f, 0x8000,     Rd_Rs_x,              s7_do_rdcrs},
    873   {"mfcc1",     0x0c00000f, 0x3e00001f, 0x8000,     Rd_Rs_x,              s7_do_rdcrs},
    874   {"mfcc2",     0x0c000017, 0x3e00001f, 0x8000,     Rd_Rs_x,              s7_do_rdcrs},
    875   {"mfcc3",     0x0c00001f, 0x3e00001f, 0x8000,     Rd_Rs_x,              s7_do_rdcrs},
    876   {"mhfl!",     0x0002,     0x700f,     0x00003c56, Rd_LowRs,             s7_do16_hrdrs},
    877   {"min",       0x38000006, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    878   {"mlfh!",     0x0001,     0x700f,     0x00003c56, Rd_HighRs,            s7_do16_rdhrs},
    879   {"msb",       0x38000001, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    880   {"msb.f!",    0x1006,     0x700f,     0x38000081, Rd_Rs,                s7_do16_rdrs},
    881   {"msbh",      0x38000205, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    882   {"msbh.fs",   0x380002c5, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    883   {"msbh.fs!",  0x100f,     0x700f,     0x380002c5, Rd_Rs,                s7_do16_rdrs},
    884   {"msbl",      0x38000004, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    885   {"msbl.fs",   0x380000c4, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    886   {"msbl.fs!",  0x100e,     0x700f,     0x380000c4, Rd_Rs,                s7_do16_rdrs},
    887   {"msbu",      0x38000021, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    888   {"msbu!",     0x1007,     0x700f,     0x38000021, Rd_Rs,                s7_do16_rdrs},
    889   {"msb.f",     0x38000081, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    890   {"mszh",      0x38000305, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    891   {"mszh.f",    0x38000385, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    892   {"mszh.f!",   0x100d,     0x700f,     0x38000385, Rd_Rs,                s7_do16_rdrs},
    893   {"mszl",      0x38000104, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    894   {"mszl.f",    0x38000184, 0x3ff003ff, 0x8000,     x_Rs_Rs,              s7_do_rsrs},
    895   {"mszl.f!",   0x100c,     0x700f,     0x38000184, Rd_Rs,                s7_do16_rdrs},
    896   {"mtcel!",    0x1000,     0x7f0f,     0x0000044a, x_Rs,                 s7_do16_rs},
    897   {"mtcel",     0x0000044a, 0x3e007fff, 0x8000,     Rd_x_x,               s7_do_rd},
    898   {"mtceh",     0x0000084a, 0x3e007fff, 0x8000,     Rd_x_x,               s7_do_rd},
    899   {"mtceh!",    0x1100,     0x7f0f,     0x0000084a, x_Rs,                 s7_do16_rs},
    900   {"mtcehl",    0x00000c4a, 0x3e007fff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    901   {"mtsr",      0x00000052, 0x3e0003ff, 0x8000,     x_Rs_I5,              s7_do_rdsrs},
    902   {"mtcr",      0x0c000000, 0x3e00001f, 0x8000,     Rd_Rs_x,              s7_do_rdcrs},
    903   {"mtc1",      0x0c000008, 0x3e00001f, 0x8000,     Rd_Rs_x,              s7_do_rdcrs},
    904   {"mtc2",      0x0c000010, 0x3e00001f, 0x8000,     Rd_Rs_x,              s7_do_rdcrs},
    905   {"mtc3",      0x0c000018, 0x3e00001f, 0x8000,     Rd_Rs_x,              s7_do_rdcrs},
    906   {"mtcc1",     0x0c00000e, 0x3e00001f, 0x8000,     Rd_Rs_x,              s7_do_rdcrs},
    907   {"mtcc2",     0x0c000016, 0x3e00001f, 0x8000,     Rd_Rs_x,              s7_do_rdcrs},
    908   {"mtcc3",     0x0c00001e, 0x3e00001f, 0x8000,     Rd_Rs_x,              s7_do_rdcrs},
    909   {"mul.f!",    0x1002,     0x700f,     0x00000041, Rd_Rs,                s7_do16_rdrs},
    910   {"mulu!",     0x1003,     0x700f,     0x00000042, Rd_Rs,                s7_do16_rdrs},
    911   {"mvcs",      0x00000056, 0x3e007fff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    912   {"mvcc",      0x00000456, 0x3e007fff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    913   {"mvgtu",     0x00000856, 0x3e007fff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    914   {"mvleu",     0x00000c56, 0x3e007fff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    915   {"mveq",      0x00001056, 0x3e007fff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    916   {"mvne",      0x00001456, 0x3e007fff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    917   {"mvgt",      0x00001856, 0x3e007fff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    918   {"mvle",      0x00001c56, 0x3e007fff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    919   {"mvge",      0x00002056, 0x3e007fff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    920   {"mvlt",      0x00002456, 0x3e007fff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    921   {"mvmi",      0x00002856, 0x3e007fff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    922   {"mvpl",      0x00002c56, 0x3e007fff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    923   {"mvvs",      0x00003056, 0x3e007fff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    924   {"mvvc",      0x00003456, 0x3e007fff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    925   {"mv",        0x00003c56, 0x3e007fff, 0x0003,     Rd_Rs_x,              s7_do_rdrs},
    926   {"mv!",       0x0003,     0x700f,     0x00003c56, Rd_Rs,                s7_do16_mv_rdrs},
    927   {"neg",       0x0000001e, 0x3e0003ff, 0x8000,     Rd_x_Rs,              s7_do_rdxrs},
    928   {"neg.c",     0x0000001f, 0x3e0003ff, 0x2002,     Rd_x_Rs,              s7_do_rdxrs},
    929   {"neg!",      0x2002,     0x700f,     0x0000001f, Rd_Rs,                s7_do16_rdrs},
    930   {"nop",       0x00000000, 0x3e0003ff, 0x0000,     NO_OPD,               s7_do_empty},
    931   {"not",       0x00000024, 0x3e0003ff, 0x8000,     Rd_Rs_x,              s7_do_rdrs},
    932   {"not.c",     0x00000025, 0x3e0003ff, 0x2006,     Rd_Rs_x,              s7_do_rdrs},
    933   {"nop!",      0x0000,     0x700f,     0x00000000, NO16_OPD,               s7_do_empty},
    934   {"not!",      0x2006,     0x700f,     0x00000025, Rd_Rs,                s7_do16_rdrs},
    935   {"or",        0x00000022, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    936   {"or.c",      0x00000023, 0x3e0003ff, 0x2005,     Rd_Rs_Rs,             s7_do_rdrsrs},
    937   {"ori",       0x020a0000, 0x3e0e0001, 0x8000,     Rd_I16,               s7_do_rdi16},
    938   {"ori.c",     0x020a0001, 0x3e0e0001, 0x8000,     Rd_I16,               s7_do_rdi16},
    939   {"oris",      0x0a0a0000, 0x3e0e0001, 0x8000,     Rd_I16,               s7_do_rdi16},
    940   {"oris.c",    0x0a0a0001, 0x3e0e0001, 0x8000,     Rd_I16,               s7_do_rdi16},
    941   {"orri",      0x1a000000, 0x3e000001, 0x8000,     Rd_Rs_I14,            s7_do_rdrsi14},
    942   {"orri.c",    0x1a000001, 0x3e000001, 0x8000,     Rd_Rs_I14,            s7_do_rdrsi14},
    943   {"or!",       0x2005,     0x700f,     0x00000023, Rd_Rs,                s7_do16_rdrs},
    944   {"pflush",    0x0000000a, 0x3e0003ff, 0x8000,     NO_OPD,               s7_do_empty},
    945   {"pop!",      0x200a,     0x700f,     0x0e000000, Rd_rvalueRs,          s7_do16_push_pop},
    946   {"push!",     0x200e,     0x700f,     0x06000004, Rd_lvalueRs,          s7_do16_push_pop},
    947   {"ror",       0x00000038, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    948   {"ror.c",     0x00000039, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    949   {"rorc.c",    0x0000003b, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    950   {"rol",       0x0000003c, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    951   {"rol.c",     0x0000003d, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    952   {"rolc.c",    0x0000003f, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    953   {"rori",      0x00000078, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s7_do_rdrsi5},
    954   {"rori.c",    0x00000079, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s7_do_rdrsi5},
    955   {"roric.c",   0x0000007b, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s7_do_rdrsi5},
    956   {"roli",      0x0000007c, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s7_do_rdrsi5},
    957   {"roli.c",    0x0000007d, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s7_do_rdrsi5},
    958   {"rolic.c",   0x0000007f, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s7_do_rdrsi5},
    959   {"rte",       0x0c000084, 0x3e0003ff, 0x8000,     NO_OPD,               s7_do_empty},
    960   {"sb!",       0x200f,     0x700f,     0x2e000000, Rd_lvalueRs,          s7_do16_ldst_insn},
    961   {"sbp!",      0x7007,     0x7007,     0x2e000000, Rd_lvalueBP_I5,       s7_do16_ldst_imm_insn},
    962   {"asw",       0x0000000e, 0x3e0003ff, 0x8000,     Rd_lvalue32Rs,        s7_do_ldst_atomic},
    963   {"scb",       0x00000068, 0x3e0003ff, 0x8000,     Rd_lvalueRs_post4,    s7_do_ldst_unalign},
    964   {"scw",       0x0000006a, 0x3e0003ff, 0x8000,     Rd_lvalueRs_post4,    s7_do_ldst_unalign},
    965   {"sce",       0x0000006e, 0x3e0003ff, 0x8000,     x_lvalueRs_post4,     s7_do_ldst_unalign},
    966   {"sdbbp",     0x00000006, 0x3e0003ff, 0x6002,     x_I5_x,               s7_do_xi5x},
    967   {"sdbbp!",    0x6002,     0x7007,     0x00000006, Rd_I5,                s7_do16_xi5},
    968   {"sh!",       0x200d,     0x700f,     0x2a000000, Rd_lvalueRs,          s7_do16_ldst_insn},
    969   {"shp!",      0x7005,     0x7007,     0x2a000000, Rd_lvalueBP_I5,       s7_do16_ldst_imm_insn},
    970   {"sleep",     0x0c0000c4, 0x3e0003ff, 0x8000,     NO_OPD,               s7_do_empty},
    971   {"sll",       0x00000030, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    972   {"sll.c",     0x00000031, 0x3e0003ff, 0x0008,     Rd_Rs_Rs,             s7_do_rdrsrs},
    973   {"sll.s",     0x3800004e, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    974   {"slli",      0x00000070, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s7_do_rdrsi5},
    975   {"slli.c",    0x00000071, 0x3e0003ff, 0x6001,     Rd_Rs_I5,             s7_do_rdrsi5},
    976   {"sll!",      0x0008,     0x700f,     0x00000031, Rd_Rs,                s7_do16_rdrs},
    977   {"slli!",     0x6001,     0x7007,     0x00000071, Rd_I5,                s7_do16_rdi5},
    978   {"srl",       0x00000034, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    979   {"srl.c",     0x00000035, 0x3e0003ff, 0x000a,     Rd_Rs_Rs,             s7_do_rdrsrs},
    980   {"sra",       0x00000036, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    981   {"sra.c",     0x00000037, 0x3e0003ff, 0x000b,     Rd_Rs_Rs,             s7_do_rdrsrs},
    982   {"srli",      0x00000074, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s7_do_rdrsi5},
    983   {"srli.c",    0x00000075, 0x3e0003ff, 0x6003,     Rd_Rs_I5,             s7_do_rdrsi5},
    984   {"srai",      0x00000076, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s7_do_rdrsi5},
    985   {"srai.c",    0x00000077, 0x3e0003ff, 0x8000,     Rd_Rs_I5,             s7_do_rdrsi5},
    986   {"srl!",      0x000a,     0x700f,     0x00000035, Rd_Rs,                s7_do16_rdrs},
    987   {"sra!",      0x000b,     0x700f,     0x00000037, Rd_Rs,                s7_do16_rdrs},
    988   {"srli!",     0x6003,     0x7007,     0x00000075, Rd_Rs,                s7_do16_rdi5},
    989   {"stc1",      0x0c00000b, 0x3e00001f, 0x8000,     Rd_lvalueRs_SI10,     s7_do_ldst_cop},
    990   {"stc2",      0x0c000013, 0x3e00001f, 0x8000,     Rd_lvalueRs_SI10,     s7_do_ldst_cop},
    991   {"stc3",      0x0c00001b, 0x3e00001f, 0x8000,     Rd_lvalueRs_SI10,     s7_do_ldst_cop},
    992   {"sub",       0x00000014, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    993   {"sub.c",     0x00000015, 0x3e0003ff, 0x2001,     Rd_Rs_Rs,             s7_do_rdrsrs},
    994   {"sub.s",     0x38000049, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    995   {"subc",      0x00000016, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    996   {"subc.c",    0x00000017, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
    997   {"sub!",      0x2001,     0x700f,     0x00000015, Rd_Rs,                s7_do16_rdrs},
    998   {"subei!",    0x6080,     0x7087,     0x02000001, Rd_I4,                s7_do16_rdi4},
    999   {"sw!",       0x200c,     0x700f,     0x28000000, Rd_lvalueRs,          s7_do16_ldst_insn},
   1000   {"swp!",      0x7004,     0x7007,     0x28000000, Rd_lvalueBP_I5,       s7_do16_ldst_imm_insn},
   1001   {"syscall",   0x00000002, 0x3e0003ff, 0x8000,     I15,                  s7_do_i15},
   1002   {"tcs",       0x00000054, 0x3e007fff, 0x0005,     NO_OPD,               s7_do_empty},
   1003   {"tcc",       0x00000454, 0x3e007fff, 0x0105,     NO_OPD,               s7_do_empty},
   1004   {"tcnz",      0x00003854, 0x3e007fff, 0x0e05,     NO_OPD,               s7_do_empty},
   1005   {"tcs!",      0x0005,     0x7f0f,     0x00000054, NO16_OPD,             s7_do_empty},
   1006   {"tcc!",      0x0105,     0x7f0f,     0x00000454, NO16_OPD,             s7_do_empty},
   1007   {"tcnz!",     0x0e05,     0x7f0f,     0x00003854, NO16_OPD,             s7_do_empty},
   1008   {"teq",       0x00001054, 0x3e007fff, 0x0405,     NO_OPD,               s7_do_empty},
   1009   {"teq!",      0x0405,     0x7f0f,     0x00001054, NO16_OPD,             s7_do_empty},
   1010   {"tgtu",      0x00000854, 0x3e007fff, 0x0205,     NO_OPD,               s7_do_empty},
   1011   {"tgt",       0x00001854, 0x3e007fff, 0x0605,     NO_OPD,               s7_do_empty},
   1012   {"tge",       0x00002054, 0x3e007fff, 0x0805,     NO_OPD,               s7_do_empty},
   1013   {"tgtu!",     0x0205,     0x7f0f,     0x00000854, NO16_OPD,             s7_do_empty},
   1014   {"tgt!",      0x0605,     0x7f0f,     0x00001854, NO16_OPD,             s7_do_empty},
   1015   {"tge!",      0x0805,     0x7f0f,     0x00002054, NO16_OPD,             s7_do_empty},
   1016   {"tleu",      0x00000c54, 0x3e007fff, 0x0305,     NO_OPD,               s7_do_empty},
   1017   {"tle",       0x00001c54, 0x3e007fff, 0x0705,     NO_OPD,               s7_do_empty},
   1018   {"tlt",       0x00002454, 0x3e007fff, 0x0905,     NO_OPD,               s7_do_empty},
   1019   {"stlb",      0x0c000004, 0x3e0003ff, 0x8000,     NO_OPD,               s7_do_empty},
   1020   {"mftlb",     0x0c000024, 0x3e0003ff, 0x8000,     NO_OPD,               s7_do_empty},
   1021   {"mtptlb",    0x0c000044, 0x3e0003ff, 0x8000,     NO_OPD,               s7_do_empty},
   1022   {"mtrtlb",    0x0c000064, 0x3e0003ff, 0x8000,     NO_OPD,               s7_do_empty},
   1023   {"tleu!",     0x0305,     0x7f0f,     0x00000c54, NO16_OPD,             s7_do_empty},
   1024   {"tle!",      0x0705,     0x7f0f,     0x00001c54, NO16_OPD,             s7_do_empty},
   1025   {"tlt!",      0x0905,     0x7f0f,     0x00002454, NO16_OPD,             s7_do_empty},
   1026   {"tmi",       0x00002854, 0x3e007fff, 0x0a05,     NO_OPD,               s7_do_empty},
   1027   {"tmi!",      0x0a05,     0x7f0f,     0x00002854, NO16_OPD,             s7_do_empty},
   1028   {"tne",       0x00001454, 0x3e007fff, 0x0505,     NO_OPD,               s7_do_empty},
   1029   {"tne!",      0x0505,     0x7f0f,     0x00001454, NO16_OPD,             s7_do_empty},
   1030   {"tpl",       0x00002c54, 0x3e007fff, 0x0b05,     NO_OPD,               s7_do_empty},
   1031   {"tpl!",      0x0b05,     0x7f0f,     0x00002c54, NO16_OPD,             s7_do_empty},
   1032   {"trapcs",    0x00000004, 0x3e007fff, 0x8000,     x_I5_x,               s7_do_xi5x},
   1033   {"trapcc",    0x00000404, 0x3e007fff, 0x8000,     x_I5_x,               s7_do_xi5x},
   1034   {"trapgtu",   0x00000804, 0x3e007fff, 0x8000,     x_I5_x,               s7_do_xi5x},
   1035   {"trapleu",   0x00000c04, 0x3e007fff, 0x8000,     x_I5_x,               s7_do_xi5x},
   1036   {"trapeq",    0x00001004, 0x3e007fff, 0x8000,     x_I5_x,               s7_do_xi5x},
   1037   {"trapne",    0x00001404, 0x3e007fff, 0x8000,     x_I5_x,               s7_do_xi5x},
   1038   {"trapgt",    0x00001804, 0x3e007fff, 0x8000,     x_I5_x,               s7_do_xi5x},
   1039   {"traple",    0x00001c04, 0x3e007fff, 0x8000,     x_I5_x,               s7_do_xi5x},
   1040   {"trapge",    0x00002004, 0x3e007fff, 0x8000,     x_I5_x,               s7_do_xi5x},
   1041   {"traplt",    0x00002404, 0x3e007fff, 0x8000,     x_I5_x,               s7_do_xi5x},
   1042   {"trapmi",    0x00002804, 0x3e007fff, 0x8000,     x_I5_x,               s7_do_xi5x},
   1043   {"trappl",    0x00002c04, 0x3e007fff, 0x8000,     x_I5_x,               s7_do_xi5x},
   1044   {"trapvs",    0x00003004, 0x3e007fff, 0x8000,     x_I5_x,               s7_do_xi5x},
   1045   {"trapvc",    0x00003404, 0x3e007fff, 0x8000,     x_I5_x,               s7_do_xi5x},
   1046   {"trap",      0x00003c04, 0x3e007fff, 0x8000,     x_I5_x,               s7_do_xi5x},
   1047   {"tset",      0x00003c54, 0x3e007fff, 0x0f05,     NO_OPD,               s7_do_empty},
   1048   {"tset!",     0x0f05,     0x00007f0f, 0x00003c54, NO16_OPD,             s7_do_empty},
   1049   {"tvs",       0x00003054, 0x3e007fff, 0x0c05,     NO_OPD,               s7_do_empty},
   1050   {"tvc",       0x00003454, 0x3e007fff, 0x0d05,     NO_OPD,               s7_do_empty},
   1051   {"tvs!",      0x0c05,     0x7f0f,     0x00003054, NO16_OPD,             s7_do_empty},
   1052   {"tvc!",      0x0d05,     0x7f0f,     0x00003454, NO16_OPD,             s7_do_empty},
   1053   {"xor",       0x00000026, 0x3e0003ff, 0x8000,     Rd_Rs_Rs,             s7_do_rdrsrs},
   1054   {"xor.c",     0x00000027, 0x3e0003ff, 0x2007,     Rd_Rs_Rs,             s7_do_rdrsrs},
   1055   {"xor!",      0x2007,     0x700f,     0x00000027, Rd_Rs,                s7_do16_rdrs},
   1056   /* Macro instruction.  */
   1057   {"li",        0x020c0000, 0x3e0e0000, 0x8000,     Insn_Type_SYN,        s7_do_macro_li_rdi32},
   1058   /* la reg, imm32        -->(1)  ldi  reg, simm16
   1059                              (2)  ldis reg, %HI(imm32)
   1060                                   ori  reg, %LO(imm32)
   1061 
   1062      la reg, symbol       -->(1)  lis  reg, %HI(imm32)
   1063                                   ori  reg, %LO(imm32)  */
   1064   {"la",        0x020c0000, 0x3e0e0000, 0x8000,     Insn_Type_SYN,        s7_do_macro_la_rdi32},
   1065   {"div",       0x00000044, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s7_do_macro_mul_rdrsrs},
   1066   {"divu",      0x00000046, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s7_do_macro_mul_rdrsrs},
   1067   {"rem",       0x00000044, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s7_do_macro_mul_rdrsrs},
   1068   {"remu",      0x00000046, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s7_do_macro_mul_rdrsrs},
   1069   {"mul",       0x00000040, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s7_do_macro_mul_rdrsrs},
   1070   {"mulu",      0x00000042, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s7_do_macro_mul_rdrsrs},
   1071   {"maz",       0x00000040, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s7_do_macro_mul_rdrsrs},
   1072   {"mazu",      0x00000042, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s7_do_macro_mul_rdrsrs},
   1073   {"mul.f",     0x00000041, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s7_do_macro_mul_rdrsrs},
   1074   {"maz.f",     0x00000041, 0x3e0003ff, 0x8000,     Insn_Type_SYN,        s7_do_macro_mul_rdrsrs},
   1075   {"lb",        INSN_LB,    0x00000000, 0x8000,     Insn_Type_SYN,        s7_do_macro_ldst_label},
   1076   {"lbu",       INSN_LBU,   0x00000000, 0x200b,     Insn_Type_SYN,        s7_do_macro_ldst_label},
   1077   {"lh",        INSN_LH,    0x00000000, 0x2009,     Insn_Type_SYN,        s7_do_macro_ldst_label},
   1078   {"lhu",       INSN_LHU,   0x00000000, 0x8000,     Insn_Type_SYN,        s7_do_macro_ldst_label},
   1079   {"lw",        INSN_LW,    0x00000000, 0x2008,     Insn_Type_SYN,        s7_do_macro_ldst_label},
   1080   {"sb",        INSN_SB,    0x00000000, 0x200f,     Insn_Type_SYN,        s7_do_macro_ldst_label},
   1081   {"sh",        INSN_SH,    0x00000000, 0x200d,     Insn_Type_SYN,        s7_do_macro_ldst_label},
   1082   {"sw",        INSN_SW,    0x00000000, 0x200c,     Insn_Type_SYN,        s7_do_macro_ldst_label},
   1083   /* Assembler use internal.  */
   1084   {"ld_i32hi",  0x0a0c0000, 0x3e0e0000, 0x8000,     Insn_internal, s7_do_macro_rdi32hi},
   1085   {"ld_i32lo",  0x020a0000, 0x3e0e0001, 0x8000,     Insn_internal, s7_do_macro_rdi32lo},
   1086   {"ldis_pic",  0x0a0c0000, 0x3e0e0000, 0x5000,     Insn_internal, s7_do_rdi16_pic},
   1087   {"addi_s_pic",0x02000000, 0x3e0e0001, 0x8000,     Insn_internal, s7_do_addi_s_pic},
   1088   {"addi_u_pic",0x02000000, 0x3e0e0001, 0x8000,     Insn_internal, s7_do_addi_u_pic},
   1089   {"lw_pic",    0x20000000, 0x3e000000, 0x8000,     Insn_internal, s7_do_lw_pic},
   1090 };
   1091 
   1092 #define s7_SCORE5_PIPELINE 5
   1093 #define s7_SCORE7_PIPELINE 7
   1094 
   1095 static int s7_university_version = 0;
   1096 static int s7_vector_size = s7_SCORE7_PIPELINE;
   1097 static struct s7_score_it s7_dependency_vector[s7_SCORE7_PIPELINE];
   1098 
   1099 static int s7_score7d = 1;
   1100 
   1101 
   1102 
   1104 static int
   1105 s7_end_of_line (char *str)
   1106 {
   1107   int retval = s7_SUCCESS;
   1108 
   1109   s7_skip_whitespace (str);
   1110   if (*str != '\0')
   1111     {
   1112       retval = (int) s7_FAIL;
   1113 
   1114       if (!s7_inst.error)
   1115         s7_inst.error = s7_BAD_GARBAGE;
   1116     }
   1117 
   1118   return retval;
   1119 }
   1120 
   1121 static int
   1122 s7_score_reg_parse (char **ccp, struct hash_control *htab)
   1123 {
   1124   char *start = *ccp;
   1125   char c;
   1126   char *p;
   1127   struct s7_reg_entry *reg;
   1128 
   1129   p = start;
   1130   if (!ISALPHA (*p) || !is_name_beginner (*p))
   1131     return (int) s7_FAIL;
   1132 
   1133   c = *p++;
   1134 
   1135   while (ISALPHA (c) || ISDIGIT (c) || c == '_')
   1136     c = *p++;
   1137 
   1138   *--p = 0;
   1139   reg = (struct s7_reg_entry *) hash_find (htab, start);
   1140   *p = c;
   1141 
   1142   if (reg)
   1143     {
   1144       *ccp = p;
   1145       return reg->number;
   1146     }
   1147   return (int) s7_FAIL;
   1148 }
   1149 
   1150 /* If shift <= 0, only return reg.  */
   1151 static int
   1152 s7_reg_required_here (char **str, int shift, enum s7_score_reg_type reg_type)
   1153 {
   1154   static char buff[s7_MAX_LITERAL_POOL_SIZE];
   1155   int reg = (int) s7_FAIL;
   1156   char *start = *str;
   1157 
   1158   if ((reg = s7_score_reg_parse (str, s7_all_reg_maps[reg_type].htab)) != (int) s7_FAIL)
   1159     {
   1160       if (reg_type == s7_REG_TYPE_SCORE)
   1161         {
   1162           if ((reg == 1) && (s7_nor1 == 1) && (s7_inst.bwarn == 0))
   1163             {
   1164               as_warn (_("Using temp register(r1)"));
   1165               s7_inst.bwarn = 1;
   1166             }
   1167         }
   1168       if (shift >= 0)
   1169 	{
   1170           if (reg_type == s7_REG_TYPE_SCORE_CR)
   1171 	    strcpy (s7_inst.reg, s7_score_crn_table[reg].name);
   1172           else if (reg_type == s7_REG_TYPE_SCORE_SR)
   1173 	    strcpy (s7_inst.reg, s7_score_srn_table[reg].name);
   1174           else
   1175 	    strcpy (s7_inst.reg, "");
   1176 
   1177           s7_inst.instruction |= reg << shift;
   1178 	}
   1179     }
   1180   else
   1181     {
   1182       *str = start;
   1183       sprintf (buff, _("register expected, not '%.100s'"), start);
   1184       s7_inst.error = buff;
   1185     }
   1186 
   1187   return reg;
   1188 }
   1189 
   1190 static int
   1191 s7_skip_past_comma (char **str)
   1192 {
   1193   char *p = *str;
   1194   char c;
   1195   int comma = 0;
   1196 
   1197   while ((c = *p) == ' ' || c == ',')
   1198     {
   1199       p++;
   1200       if (c == ',' && comma++)
   1201         {
   1202           s7_inst.error = s7_BAD_SKIP_COMMA;
   1203           return (int) s7_FAIL;
   1204         }
   1205     }
   1206 
   1207   if ((c == '\0') || (comma == 0))
   1208     {
   1209       s7_inst.error = s7_BAD_SKIP_COMMA;
   1210       return (int) s7_FAIL;
   1211     }
   1212 
   1213   *str = p;
   1214   return comma ? s7_SUCCESS : (int) s7_FAIL;
   1215 }
   1216 
   1217 static void
   1218 s7_do_rdrsrs (char *str)
   1219 {
   1220   s7_skip_whitespace (str);
   1221 
   1222   if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL
   1223       || s7_skip_past_comma (&str) == (int) s7_FAIL
   1224       || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
   1225       || s7_skip_past_comma (&str) == (int) s7_FAIL
   1226       || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE) == (int) s7_FAIL
   1227       || s7_end_of_line (str) == (int) s7_FAIL)
   1228     {
   1229       return;
   1230     }
   1231   else
   1232     {
   1233       if ((((s7_inst.instruction >> 15) & 0x10) == 0)
   1234           && (((s7_inst.instruction >> 10) & 0x10) == 0)
   1235           && (((s7_inst.instruction >> 20) & 0x10) == 0)
   1236           && (s7_inst.relax_inst != 0x8000)
   1237           && (((s7_inst.instruction >> 20) & 0xf) == ((s7_inst.instruction >> 15) & 0xf)))
   1238         {
   1239           s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 4)
   1240             | (((s7_inst.instruction >> 15) & 0xf) << 8);
   1241           s7_inst.relax_size = 2;
   1242         }
   1243       else
   1244         {
   1245           s7_inst.relax_inst = 0x8000;
   1246         }
   1247     }
   1248 }
   1249 
   1250 static int
   1251 s7_walk_no_bignums (symbolS * sp)
   1252 {
   1253   if (symbol_get_value_expression (sp)->X_op == O_big)
   1254     return 1;
   1255 
   1256   if (symbol_get_value_expression (sp)->X_add_symbol)
   1257     return (s7_walk_no_bignums (symbol_get_value_expression (sp)->X_add_symbol)
   1258 	    || (symbol_get_value_expression (sp)->X_op_symbol
   1259 		&& s7_walk_no_bignums (symbol_get_value_expression (sp)->X_op_symbol)));
   1260 
   1261   return 0;
   1262 }
   1263 
   1264 static int
   1265 s7_my_get_expression (expressionS * ep, char **str)
   1266 {
   1267   char *save_in;
   1268 
   1269   save_in = input_line_pointer;
   1270   input_line_pointer = *str;
   1271   s7_in_my_get_expression = 1;
   1272 
   1273   (void) expression (ep);
   1274   s7_in_my_get_expression = 0;
   1275 
   1276   if (ep->X_op == O_illegal)
   1277     {
   1278       *str = input_line_pointer;
   1279       input_line_pointer = save_in;
   1280       s7_inst.error = _("illegal expression");
   1281       return (int) s7_FAIL;
   1282     }
   1283   /* Get rid of any bignums now, so that we don't generate an error for which
   1284      we can't establish a line number later on.  Big numbers are never valid
   1285      in instructions, which is where this routine is always called.  */
   1286   if (ep->X_op == O_big
   1287       || (ep->X_add_symbol
   1288           && (s7_walk_no_bignums (ep->X_add_symbol)
   1289               || (ep->X_op_symbol && s7_walk_no_bignums (ep->X_op_symbol)))))
   1290     {
   1291       s7_inst.error = _("invalid constant");
   1292       *str = input_line_pointer;
   1293       input_line_pointer = save_in;
   1294       return (int) s7_FAIL;
   1295     }
   1296 
   1297   if ((ep->X_add_symbol != NULL)
   1298       && (s7_inst.type != PC_DISP19div2)
   1299       && (s7_inst.type != PC_DISP8div2)
   1300       && (s7_inst.type != PC_DISP24div2)
   1301       && (s7_inst.type != PC_DISP11div2)
   1302       && (s7_inst.type != Insn_Type_SYN)
   1303       && (s7_inst.type != Rd_rvalueRs_SI15)
   1304       && (s7_inst.type != Rd_lvalueRs_SI15)
   1305       && (s7_inst.type != Insn_internal))
   1306     {
   1307       s7_inst.error = s7_BAD_ARGS;
   1308       *str = input_line_pointer;
   1309       input_line_pointer = save_in;
   1310       return (int) s7_FAIL;
   1311     }
   1312 
   1313   *str = input_line_pointer;
   1314   input_line_pointer = save_in;
   1315   return s7_SUCCESS;
   1316 }
   1317 
   1318 /* Check if an immediate is valid.  If so, convert it to the right format.  */
   1319 
   1320 static bfd_signed_vma
   1321 s7_validate_immediate (bfd_signed_vma val, unsigned int data_type, int hex_p)
   1322 {
   1323   switch (data_type)
   1324     {
   1325     case _VALUE_HI16:
   1326       {
   1327         int val_hi = ((val & 0xffff0000) >> 16);
   1328 
   1329         if (s7_score_df_range[data_type].range[0] <= val_hi
   1330             && val_hi <= s7_score_df_range[data_type].range[1])
   1331 	  return val_hi;
   1332       }
   1333       break;
   1334 
   1335     case _VALUE_LO16:
   1336       {
   1337         int val_lo = (val & 0xffff);
   1338 
   1339         if (s7_score_df_range[data_type].range[0] <= val_lo
   1340             && val_lo <= s7_score_df_range[data_type].range[1])
   1341 	  return val_lo;
   1342       }
   1343       break;
   1344 
   1345     case _SIMM12:
   1346       if (hex_p == 1)
   1347         {
   1348           if (!(val >= -0x800 && val <= 0xfff))
   1349             {
   1350               return (int) s7_FAIL;
   1351             }
   1352         }
   1353       else
   1354         {
   1355           if (!(val >= -2048 && val <= 2047))
   1356             {
   1357               return (int) s7_FAIL;
   1358             }
   1359         }
   1360 
   1361       return val;
   1362       break;
   1363 
   1364     case _SIMM14:
   1365       if (hex_p == 1)
   1366         {
   1367           if (!(val >= -0x2000 && val <= 0x3fff))
   1368             {
   1369               return (int) s7_FAIL;
   1370             }
   1371         }
   1372       else
   1373         {
   1374           if (!(val >= -8192 && val <= 8191))
   1375             {
   1376               return (int) s7_FAIL;
   1377             }
   1378         }
   1379 
   1380       return val;
   1381       break;
   1382 
   1383     case _SIMM15:
   1384       if (hex_p == 1)
   1385         {
   1386           if (!(val >= -0x4000 && val <= 0x7fff))
   1387             {
   1388               return (int) s7_FAIL;
   1389             }
   1390         }
   1391       else
   1392         {
   1393           if (!(val >= -16384 && val <= 16383))
   1394             {
   1395               return (int) s7_FAIL;
   1396             }
   1397         }
   1398 
   1399       return val;
   1400       break;
   1401 
   1402     case _SIMM16:
   1403       if (hex_p == 1)
   1404         {
   1405           if (!(val >= -0x8000 && val <= 0xffff))
   1406             {
   1407               return (int) s7_FAIL;
   1408             }
   1409         }
   1410       else
   1411         {
   1412           if (!(val >= -32768 && val <= 32767))
   1413             {
   1414               return (int) s7_FAIL;
   1415             }
   1416         }
   1417 
   1418       return val;
   1419       break;
   1420 
   1421     case _SIMM16_NEG:
   1422       if (hex_p == 1)
   1423         {
   1424           if (!(val >= -0x7fff && val <= 0xffff && val != 0x8000))
   1425             {
   1426               return (int) s7_FAIL;
   1427             }
   1428         }
   1429       else
   1430         {
   1431           if (!(val >= -32767 && val <= 32768))
   1432             {
   1433               return (int) s7_FAIL;
   1434             }
   1435         }
   1436 
   1437       val = -val;
   1438       return val;
   1439       break;
   1440 
   1441     case _IMM32:
   1442       if (val >= 0 && val <= 0xffffffff)
   1443         {
   1444           return val;
   1445         }
   1446       else
   1447         {
   1448           return (int) s7_FAIL;
   1449         }
   1450 
   1451     default:
   1452       if (data_type == _SIMM14_NEG || data_type == _IMM16_NEG)
   1453 	val = -val;
   1454 
   1455       if (s7_score_df_range[data_type].range[0] <= val
   1456           && val <= s7_score_df_range[data_type].range[1])
   1457 	return val;
   1458 
   1459       break;
   1460     }
   1461 
   1462   return (int) s7_FAIL;
   1463 }
   1464 
   1465 static int
   1466 s7_data_op2 (char **str, int shift, enum score_data_type data_type)
   1467 {
   1468   int value;
   1469   char data_exp[s7_MAX_LITERAL_POOL_SIZE];
   1470   char *dataptr;
   1471   int cnt = 0;
   1472   char *pp = NULL;
   1473 
   1474   s7_skip_whitespace (*str);
   1475   s7_inst.error = NULL;
   1476   dataptr = * str;
   1477 
   1478   /* Set hex_p to zero.  */
   1479   int hex_p = 0;
   1480 
   1481   while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= s7_MAX_LITERAL_POOL_SIZE))     /* 0x7c = ='|' */
   1482     {
   1483       data_exp[cnt] = *dataptr;
   1484       dataptr++;
   1485       cnt++;
   1486     }
   1487 
   1488   data_exp[cnt] = '\0';
   1489   pp = (char *)&data_exp;
   1490 
   1491   if (*dataptr == '|')          /* process PCE */
   1492     {
   1493       if (s7_my_get_expression (&s7_inst.reloc.exp, &pp) == (int) s7_FAIL)
   1494         return (int) s7_FAIL;
   1495       s7_end_of_line (pp);
   1496       if (s7_inst.error != 0)
   1497         return (int) s7_FAIL;       /* to ouptut_inst to printf out the error */
   1498       *str = dataptr;
   1499     }
   1500   else                          /* process  16 bit */
   1501     {
   1502       if (s7_my_get_expression (&s7_inst.reloc.exp, str) == (int) s7_FAIL)
   1503         {
   1504           return (int) s7_FAIL;
   1505         }
   1506 
   1507       dataptr = (char *) data_exp;
   1508       for (; *dataptr != '\0'; dataptr++)
   1509         {
   1510           *dataptr = TOLOWER (*dataptr);
   1511           if (*dataptr == '!' || *dataptr == ' ')
   1512             break;
   1513         }
   1514       dataptr = (char *) data_exp;
   1515 
   1516       if ((dataptr != NULL)
   1517           && (((strstr (dataptr, "0x")) != NULL)
   1518               || ((strstr (dataptr, "0X")) != NULL)))
   1519         {
   1520           hex_p = 1;
   1521           if ((data_type != _SIMM16_LA)
   1522               && (data_type != _VALUE_HI16)
   1523               && (data_type != _VALUE_LO16)
   1524               && (data_type != _IMM16)
   1525               && (data_type != _IMM15)
   1526               && (data_type != _IMM14)
   1527               && (data_type != _IMM4)
   1528               && (data_type != _IMM5)
   1529               && (data_type != _IMM8)
   1530               && (data_type != _IMM5_RSHIFT_1)
   1531               && (data_type != _IMM5_RSHIFT_2)
   1532               && (data_type != _SIMM14)
   1533               && (data_type != _SIMM16)
   1534               && (data_type != _SIMM14_NEG)
   1535               && (data_type != _SIMM16_NEG)
   1536               && (data_type != _IMM10_RSHIFT_2)
   1537               && (data_type != _GP_IMM15))
   1538             {
   1539               data_type += 24;
   1540             }
   1541         }
   1542 
   1543       if ((s7_inst.reloc.exp.X_add_number == 0)
   1544           /* for "addi r0,-((((((32*4)+4)+4)+4)+4)&0xf)".  */
   1545           && (s7_inst.type != Rd_SI16)
   1546           && (s7_inst.type != Insn_Type_SYN)
   1547           && (s7_inst.type != Rd_rvalueRs_SI15)
   1548           && (s7_inst.type != Rd_lvalueRs_SI15)
   1549           && (s7_inst.type != Insn_internal)
   1550           && (((*dataptr >= 'a') && (*dataptr <= 'z'))
   1551              || ((*dataptr == '0') && (*(dataptr + 1) == 'x') && (*(dataptr + 2) != '0'))
   1552              || ((*dataptr == '+') && (*(dataptr + 1) != '0'))
   1553              || ((*dataptr == '-') && (*(dataptr + 1) != '0'))))
   1554         {
   1555           s7_inst.error = s7_BAD_ARGS;
   1556           return (int) s7_FAIL;
   1557         }
   1558     }
   1559 
   1560   if ((s7_inst.reloc.exp.X_add_symbol)
   1561       && ((data_type == _SIMM16)
   1562           || (data_type == _SIMM16_NEG)
   1563           || (data_type == _IMM16_NEG)
   1564           || (data_type == _SIMM14)
   1565           || (data_type == _SIMM14_NEG)
   1566           || (data_type == _IMM5)
   1567           || (data_type == _IMM14)
   1568           || (data_type == _IMM20)
   1569           || (data_type == _IMM16)
   1570           || (data_type == _IMM15)
   1571           || (data_type == _IMM4)))
   1572     {
   1573       s7_inst.error = s7_BAD_ARGS;
   1574       return (int) s7_FAIL;
   1575     }
   1576 
   1577   if (s7_inst.reloc.exp.X_add_symbol)
   1578     {
   1579       switch (data_type)
   1580         {
   1581         case _SIMM16_LA:
   1582           return (int) s7_FAIL;
   1583         case _VALUE_HI16:
   1584           s7_inst.reloc.type = BFD_RELOC_HI16_S;
   1585           s7_inst.reloc.pc_rel = 0;
   1586           break;
   1587         case _VALUE_LO16:
   1588           s7_inst.reloc.type = BFD_RELOC_LO16;
   1589           s7_inst.reloc.pc_rel = 0;
   1590           break;
   1591         case _GP_IMM15:
   1592           s7_inst.reloc.type = BFD_RELOC_SCORE_GPREL15;
   1593           s7_inst.reloc.pc_rel = 0;
   1594           break;
   1595         case _SIMM16_pic:
   1596         case _IMM16_LO16_pic:
   1597           s7_inst.reloc.type = BFD_RELOC_SCORE_GOT_LO16;
   1598           s7_inst.reloc.pc_rel = 0;
   1599           break;
   1600         default:
   1601           s7_inst.reloc.type = BFD_RELOC_32;
   1602           s7_inst.reloc.pc_rel = 0;
   1603           break;
   1604         }
   1605     }
   1606   else
   1607     {
   1608       if (data_type == _IMM16_pic)
   1609 	{
   1610           s7_inst.reloc.type = BFD_RELOC_SCORE_DUMMY_HI16;
   1611           s7_inst.reloc.pc_rel = 0;
   1612 	}
   1613 
   1614       if (data_type == _SIMM16_LA && s7_inst.reloc.exp.X_unsigned == 1)
   1615         {
   1616           value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _SIMM16_LA_POS, hex_p);
   1617           if (value == (int) s7_FAIL)       /* for advance to check if this is ldis */
   1618             if ((s7_inst.reloc.exp.X_add_number & 0xffff) == 0)
   1619               {
   1620                 s7_inst.instruction |= 0x8000000;
   1621                 s7_inst.instruction |= ((s7_inst.reloc.exp.X_add_number >> 16) << 1) & 0x1fffe;
   1622                 return s7_SUCCESS;
   1623               }
   1624         }
   1625       else
   1626         {
   1627           value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, data_type, hex_p);
   1628         }
   1629 
   1630       if (value == (int) s7_FAIL)
   1631         {
   1632           if ((data_type != _SIMM14_NEG) && (data_type != _SIMM16_NEG) && (data_type != _IMM16_NEG))
   1633             {
   1634               sprintf (s7_err_msg,
   1635                        _("invalid constant: %d bit expression not in range %d..%d"),
   1636                        s7_score_df_range[data_type].bits,
   1637                        s7_score_df_range[data_type].range[0], s7_score_df_range[data_type].range[1]);
   1638             }
   1639           else
   1640             {
   1641               sprintf (s7_err_msg,
   1642                        _("invalid constant: %d bit expression not in range %d..%d"),
   1643                        s7_score_df_range[data_type].bits,
   1644                        -s7_score_df_range[data_type].range[1], -s7_score_df_range[data_type].range[0]);
   1645             }
   1646 
   1647           s7_inst.error = s7_err_msg;
   1648           return (int) s7_FAIL;
   1649         }
   1650 
   1651       if ((s7_score_df_range[data_type].range[0] != 0) || (data_type == _IMM5_RANGE_8_31))
   1652         {
   1653           value &= (1 << s7_score_df_range[data_type].bits) - 1;
   1654         }
   1655 
   1656       s7_inst.instruction |= value << shift;
   1657     }
   1658 
   1659   if ((s7_inst.instruction & 0x3e000000) == 0x30000000)
   1660     {
   1661       if ((((s7_inst.instruction >> 20) & 0x1F) != 0)
   1662           && (((s7_inst.instruction >> 20) & 0x1F) != 1)
   1663           && (((s7_inst.instruction >> 20) & 0x1F) != 2)
   1664           && (((s7_inst.instruction >> 20) & 0x1F) != 3)
   1665           && (((s7_inst.instruction >> 20) & 0x1F) != 4)
   1666           && (((s7_inst.instruction >> 20) & 0x1F) != 8)
   1667           && (((s7_inst.instruction >> 20) & 0x1F) != 9)
   1668           && (((s7_inst.instruction >> 20) & 0x1F) != 0xa)
   1669           && (((s7_inst.instruction >> 20) & 0x1F) != 0xb)
   1670           && (((s7_inst.instruction >> 20) & 0x1F) != 0xc)
   1671           && (((s7_inst.instruction >> 20) & 0x1F) != 0xd)
   1672           && (((s7_inst.instruction >> 20) & 0x1F) != 0xe)
   1673           && (((s7_inst.instruction >> 20) & 0x1F) != 0x10)
   1674           && (((s7_inst.instruction >> 20) & 0x1F) != 0x11)
   1675           && (((s7_inst.instruction >> 20) & 0x1F) != 0x18)
   1676           && (((s7_inst.instruction >> 20) & 0x1F) != 0x1A)
   1677           && (((s7_inst.instruction >> 20) & 0x1F) != 0x1B)
   1678           && (((s7_inst.instruction >> 20) & 0x1F) != 0x1d)
   1679           && (((s7_inst.instruction >> 20) & 0x1F) != 0x1e)
   1680           && (((s7_inst.instruction >> 20) & 0x1F) != 0x1f))
   1681         {
   1682           s7_inst.error = _("invalid constant: bit expression not defined");
   1683           return (int) s7_FAIL;
   1684         }
   1685     }
   1686 
   1687   return s7_SUCCESS;
   1688 }
   1689 
   1690 /* Handle addi/addi.c/addis.c/cmpi.c/addis.c/ldi.  */
   1691 
   1692 static void
   1693 s7_do_rdsi16 (char *str)
   1694 {
   1695   s7_skip_whitespace (str);
   1696 
   1697   if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL
   1698       || s7_skip_past_comma (&str) == (int) s7_FAIL
   1699       || s7_data_op2 (&str, 1, _SIMM16) == (int) s7_FAIL
   1700       || s7_end_of_line (str) == (int) s7_FAIL)
   1701     return;
   1702 
   1703   /* ldi.  */
   1704   if ((s7_inst.instruction & 0x20c0000) == 0x20c0000)
   1705     {
   1706       if ((((s7_inst.instruction >> 20) & 0x10) == 0x10) || ((s7_inst.instruction & 0x1fe00) != 0))
   1707         {
   1708           s7_inst.relax_inst = 0x8000;
   1709         }
   1710       else
   1711         {
   1712           s7_inst.relax_inst |= (s7_inst.instruction >> 1) & 0xff;
   1713           s7_inst.relax_inst |= (((s7_inst.instruction >> 20) & 0xf) << 8);
   1714           s7_inst.relax_size = 2;
   1715         }
   1716     }
   1717   else if (((s7_inst.instruction >> 20) & 0x10) == 0x10)
   1718     {
   1719       s7_inst.relax_inst = 0x8000;
   1720     }
   1721 }
   1722 
   1723 /* Handle subi/subi.c.  */
   1724 
   1725 static void
   1726 s7_do_sub_rdsi16 (char *str)
   1727 {
   1728   s7_skip_whitespace (str);
   1729 
   1730   if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
   1731       && s7_skip_past_comma (&str) != (int) s7_FAIL
   1732       && s7_data_op2 (&str, 1, _SIMM16_NEG) != (int) s7_FAIL)
   1733     s7_end_of_line (str);
   1734 }
   1735 
   1736 
   1737 /* Handle addri/addri.c.  */
   1738 
   1739 static void
   1740 s7_do_rdrssi14 (char *str)         /* -(2^13)~((2^13)-1) */
   1741 {
   1742   s7_skip_whitespace (str);
   1743 
   1744   if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
   1745       && s7_skip_past_comma (&str) != (int) s7_FAIL
   1746       && s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) != (int) s7_FAIL
   1747       && s7_skip_past_comma (&str) != (int) s7_FAIL)
   1748     s7_data_op2 (&str, 1, _SIMM14);
   1749 }
   1750 
   1751 /* Handle subri.c/subri.  */
   1752 
   1753 static void
   1754 s7_do_sub_rdrssi14 (char *str)     /* -(2^13)~((2^13)-1) */
   1755 {
   1756   s7_skip_whitespace (str);
   1757 
   1758   if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
   1759       && s7_skip_past_comma (&str) != (int) s7_FAIL
   1760       && s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) != (int) s7_FAIL
   1761       && s7_skip_past_comma (&str) != (int) s7_FAIL
   1762       && s7_data_op2 (&str, 1, _SIMM14_NEG) != (int) s7_FAIL)
   1763     s7_end_of_line (str);
   1764 }
   1765 
   1766 /* Handle bitclr.c/bitset.c/bittgl.c/slli.c/srai.c/srli.c/roli.c/rori.c/rolic.c.  */
   1767 
   1768 static void
   1769 s7_do_rdrsi5 (char *str)           /* 0~((2^14)-1) */
   1770 {
   1771   s7_skip_whitespace (str);
   1772 
   1773   if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL
   1774       || s7_skip_past_comma (&str) == (int) s7_FAIL
   1775       || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
   1776       || s7_skip_past_comma (&str) == (int) s7_FAIL
   1777       || s7_data_op2 (&str, 10, _IMM5) == (int) s7_FAIL
   1778       || s7_end_of_line (str) == (int) s7_FAIL)
   1779     return;
   1780 
   1781   if ((((s7_inst.instruction >> 20) & 0x1f) == ((s7_inst.instruction >> 15) & 0x1f))
   1782       && (s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 15) & 0x10) == 0))
   1783     {
   1784       s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0x1f) << 3) | (((s7_inst.instruction >> 15) & 0xf) << 8);
   1785       s7_inst.relax_size = 2;
   1786     }
   1787   else
   1788     s7_inst.relax_inst = 0x8000;
   1789 }
   1790 
   1791 /* Handle andri/orri/andri.c/orri.c.  */
   1792 
   1793 static void
   1794 s7_do_rdrsi14 (char *str)          /* 0 ~ ((2^14)-1)  */
   1795 {
   1796   s7_skip_whitespace (str);
   1797 
   1798   if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
   1799       && s7_skip_past_comma (&str) != (int) s7_FAIL
   1800       && s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) != (int) s7_FAIL
   1801       && s7_skip_past_comma (&str) != (int) s7_FAIL
   1802       && s7_data_op2 (&str, 1, _IMM14) != (int) s7_FAIL)
   1803     s7_end_of_line (str);
   1804 }
   1805 
   1806 /* Handle bittst.c.  */
   1807 
   1808 static void
   1809 s7_do_xrsi5 (char *str)
   1810 {
   1811   s7_skip_whitespace (str);
   1812 
   1813   if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
   1814       || s7_skip_past_comma (&str) == (int) s7_FAIL
   1815       || s7_data_op2 (&str, 10, _IMM5) == (int) s7_FAIL
   1816       || s7_end_of_line (str) == (int) s7_FAIL)
   1817     return;
   1818 
   1819   if ((s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 15) & 0x10) == 0))
   1820     {
   1821       s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0x1f) << 3) | (((s7_inst.instruction >> 15) & 0xf) << 8);
   1822       s7_inst.relax_size = 2;
   1823     }
   1824   else
   1825     s7_inst.relax_inst = 0x8000;
   1826 }
   1827 
   1828 /* Handle addis/andi/ori/andis/oris/ldis.  */
   1829 
   1830 static void
   1831 s7_do_rdi16 (char *str)
   1832 {
   1833   s7_skip_whitespace (str);
   1834 
   1835   if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL
   1836       || s7_skip_past_comma (&str) == (int) s7_FAIL
   1837       || s7_data_op2 (&str, 1, _IMM16) == (int) s7_FAIL
   1838       || s7_end_of_line (str) == (int) s7_FAIL)
   1839     return;
   1840 }
   1841 
   1842 static void
   1843 s7_do_macro_rdi32hi (char *str)
   1844 {
   1845   s7_skip_whitespace (str);
   1846 
   1847   /* Do not handle s7_end_of_line().  */
   1848   if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
   1849       && s7_skip_past_comma (&str) != (int) s7_FAIL)
   1850     s7_data_op2 (&str, 1, _VALUE_HI16);
   1851 }
   1852 
   1853 static void
   1854 s7_do_macro_rdi32lo (char *str)
   1855 {
   1856   s7_skip_whitespace (str);
   1857 
   1858   /* Do not handle s7_end_of_line().  */
   1859   if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
   1860       && s7_skip_past_comma (&str) != (int) s7_FAIL)
   1861     s7_data_op2 (&str, 1, _VALUE_LO16);
   1862 }
   1863 
   1864 /* Handle ldis_pic.  */
   1865 
   1866 static void
   1867 s7_do_rdi16_pic (char *str)
   1868 {
   1869   s7_skip_whitespace (str);
   1870 
   1871   if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
   1872       && s7_skip_past_comma (&str) != (int) s7_FAIL
   1873       && s7_data_op2 (&str, 1, _IMM16_pic) != (int) s7_FAIL)
   1874     s7_end_of_line (str);
   1875 }
   1876 
   1877 /* Handle addi_s_pic to generate R_SCORE_GOT_LO16 .  */
   1878 
   1879 static void
   1880 s7_do_addi_s_pic (char *str)
   1881 {
   1882   s7_skip_whitespace (str);
   1883 
   1884   if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
   1885       && s7_skip_past_comma (&str) != (int) s7_FAIL
   1886       && s7_data_op2 (&str, 1, _SIMM16_pic) != (int) s7_FAIL)
   1887     s7_end_of_line (str);
   1888 }
   1889 
   1890 /* Handle addi_u_pic to generate R_SCORE_GOT_LO16 .  */
   1891 
   1892 static void
   1893 s7_do_addi_u_pic (char *str)
   1894 {
   1895   s7_skip_whitespace (str);
   1896 
   1897   if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
   1898       && s7_skip_past_comma (&str) != (int) s7_FAIL
   1899       && s7_data_op2 (&str, 1, _IMM16_LO16_pic) != (int) s7_FAIL)
   1900     s7_end_of_line (str);
   1901 }
   1902 
   1903 /* Handle mfceh/mfcel/mtceh/mtchl.  */
   1904 
   1905 static void
   1906 s7_do_rd (char *str)
   1907 {
   1908   s7_skip_whitespace (str);
   1909 
   1910   if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL)
   1911     s7_end_of_line (str);
   1912 }
   1913 
   1914 static void
   1915 s7_do_rs (char *str)
   1916 {
   1917   s7_skip_whitespace (str);
   1918 
   1919   if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
   1920       || s7_end_of_line (str) == (int) s7_FAIL)
   1921     return;
   1922 
   1923   if ((s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 15) & 0x10) == 0))
   1924     {
   1925       s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 8) | (((s7_inst.instruction >> 15) & 0xf) << 4);
   1926       s7_inst.relax_size = 2;
   1927     }
   1928   else
   1929     s7_inst.relax_inst = 0x8000;
   1930 }
   1931 
   1932 static void
   1933 s7_do_i15 (char *str)
   1934 {
   1935   s7_skip_whitespace (str);
   1936 
   1937   if (s7_data_op2 (&str, 10, _IMM15) != (int) s7_FAIL)
   1938     s7_end_of_line (str);
   1939 }
   1940 
   1941 static void
   1942 s7_do_xi5x (char *str)
   1943 {
   1944   s7_skip_whitespace (str);
   1945 
   1946   if (s7_data_op2 (&str, 15, _IMM5) == (int) s7_FAIL || s7_end_of_line (str) == (int) s7_FAIL)
   1947     return;
   1948 
   1949   if (s7_inst.relax_inst != 0x8000)
   1950     {
   1951       s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0x1f) << 3);
   1952       s7_inst.relax_size = 2;
   1953     }
   1954 }
   1955 
   1956 static void
   1957 s7_do_rdrs (char *str)
   1958 {
   1959   s7_skip_whitespace (str);
   1960 
   1961   if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL
   1962       || s7_skip_past_comma (&str) == (int) s7_FAIL
   1963       || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
   1964       || s7_end_of_line (str) == (int) s7_FAIL)
   1965     return;
   1966 
   1967   if (s7_inst.relax_inst != 0x8000)
   1968     {
   1969       if (((s7_inst.instruction & 0x7f) == 0x56))  /* adjust mv -> mv! / mlfh! / mhfl! */
   1970         {
   1971           /* mlfh */
   1972           if ((((s7_inst.instruction >> 15) & 0x10) != 0x0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
   1973             {
   1974               s7_inst.relax_inst = 0x00000001 | (((s7_inst.instruction >> 15) & 0xf) << 4)
   1975                 | (((s7_inst.instruction >> 20) & 0xf) << 8);
   1976               s7_inst.relax_size = 2;
   1977             }
   1978           /* mhfl */
   1979           else if ((((s7_inst.instruction >> 15) & 0x10) == 0x0) && ((s7_inst.instruction >> 20) & 0x10) != 0)
   1980             {
   1981               s7_inst.relax_inst = 0x00000002 | (((s7_inst.instruction >> 15) & 0xf) << 4)
   1982                 | (((s7_inst.instruction >> 20) & 0xf) << 8);
   1983               s7_inst.relax_size = 2;
   1984             }
   1985           else if ((((s7_inst.instruction >> 15) & 0x10) == 0x0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
   1986             {
   1987               s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
   1988                 | (((s7_inst.instruction >> 20) & 0xf) << 8);
   1989               s7_inst.relax_size = 2;
   1990             }
   1991           else
   1992             {
   1993               s7_inst.relax_inst = 0x8000;
   1994             }
   1995         }
   1996       else if ((((s7_inst.instruction >> 15) & 0x10) == 0x0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
   1997         {
   1998           s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
   1999             | (((s7_inst.instruction >> 20) & 0xf) << 8);
   2000           s7_inst.relax_size = 2;
   2001         }
   2002       else
   2003         {
   2004           s7_inst.relax_inst = 0x8000;
   2005         }
   2006     }
   2007 }
   2008 
   2009 /* Handle mfcr/mtcr.  */
   2010 static void
   2011 s7_do_rdcrs (char *str)
   2012 {
   2013   s7_skip_whitespace (str);
   2014 
   2015   if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
   2016       && s7_skip_past_comma (&str) != (int) s7_FAIL
   2017       && s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE_CR) != (int) s7_FAIL)
   2018     s7_end_of_line (str);
   2019 }
   2020 
   2021 /* Handle mfsr/mtsr.  */
   2022 
   2023 static void
   2024 s7_do_rdsrs (char *str)
   2025 {
   2026   s7_skip_whitespace (str);
   2027 
   2028   /* mfsr */
   2029   if ((s7_inst.instruction & 0xff) == 0x50)
   2030     {
   2031       if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) != (int) s7_FAIL
   2032           && s7_skip_past_comma (&str) != (int) s7_FAIL
   2033           && s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE_SR) != (int) s7_FAIL)
   2034 	s7_end_of_line (str);
   2035     }
   2036   else
   2037     {
   2038       if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) != (int) s7_FAIL
   2039           && s7_skip_past_comma (&str) != (int) s7_FAIL)
   2040 	s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE_SR);
   2041     }
   2042 }
   2043 
   2044 /* Handle neg.  */
   2045 
   2046 static void
   2047 s7_do_rdxrs (char *str)
   2048 {
   2049   s7_skip_whitespace (str);
   2050 
   2051   if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL
   2052       || s7_skip_past_comma (&str) == (int) s7_FAIL
   2053       || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE) == (int) s7_FAIL
   2054       || s7_end_of_line (str) == (int) s7_FAIL)
   2055     return;
   2056 
   2057   if ((s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 10) & 0x10) == 0)
   2058       && (((s7_inst.instruction >> 20) & 0x10) == 0))
   2059     {
   2060       s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 4) | (((s7_inst.instruction >> 20) & 0xf) << 8);
   2061       s7_inst.relax_size = 2;
   2062     }
   2063   else
   2064     s7_inst.relax_inst = 0x8000;
   2065 }
   2066 
   2067 /* Handle cmp.c/cmp<cond>.  */
   2068 static void
   2069 s7_do_rsrs (char *str)
   2070 {
   2071   s7_skip_whitespace (str);
   2072 
   2073   if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
   2074       || s7_skip_past_comma (&str) == (int) s7_FAIL
   2075       || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE) == (int) s7_FAIL
   2076       || s7_end_of_line (str) == (int) s7_FAIL)
   2077     return;
   2078 
   2079   if ((s7_inst.relax_inst != 0x8000) && (((s7_inst.instruction >> 20) & 0x1f) == 3)
   2080       && (((s7_inst.instruction >> 10) & 0x10) == 0) && (((s7_inst.instruction >> 15) & 0x10) == 0))
   2081     {
   2082       s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 4) | (((s7_inst.instruction >> 15) & 0xf) << 8);
   2083       s7_inst.relax_size = 2;
   2084     }
   2085   else
   2086     s7_inst.relax_inst = 0x8000;
   2087 }
   2088 
   2089 static void
   2090 s7_do_ceinst (char *str)
   2091 {
   2092   char *strbak;
   2093 
   2094   strbak = str;
   2095   s7_skip_whitespace (str);
   2096 
   2097   if (s7_data_op2 (&str, 20, _IMM5) == (int) s7_FAIL
   2098       || s7_skip_past_comma (&str) == (int) s7_FAIL
   2099       || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL
   2100       || s7_skip_past_comma (&str) == (int) s7_FAIL
   2101       || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE) == (int) s7_FAIL
   2102       || s7_skip_past_comma (&str) == (int) s7_FAIL
   2103       || s7_data_op2 (&str, 5, _IMM5) == (int) s7_FAIL
   2104       || s7_skip_past_comma (&str) == (int) s7_FAIL
   2105       || s7_data_op2 (&str, 0, _IMM5) == (int) s7_FAIL
   2106       || s7_end_of_line (str) == (int) s7_FAIL)
   2107     {
   2108       return;
   2109     }
   2110   else
   2111     {
   2112       str = strbak;
   2113       if (s7_data_op2 (&str, 0, _IMM25) == (int) s7_FAIL)
   2114 	return;
   2115     }
   2116 }
   2117 
   2118 static int
   2119 s7_reglow_required_here (char **str, int shift)
   2120 {
   2121   static char buff[s7_MAX_LITERAL_POOL_SIZE];
   2122   int reg;
   2123   char *start = *str;
   2124 
   2125   if ((reg = s7_score_reg_parse (str, s7_all_reg_maps[s7_REG_TYPE_SCORE].htab)) != (int) s7_FAIL)
   2126     {
   2127       if ((reg == 1) && (s7_nor1 == 1) && (s7_inst.bwarn == 0))
   2128         {
   2129           as_warn (_("Using temp register(r1)"));
   2130           s7_inst.bwarn = 1;
   2131         }
   2132       if (reg < 16)
   2133         {
   2134           if (shift >= 0)
   2135             s7_inst.instruction |= reg << shift;
   2136 
   2137           return reg;
   2138         }
   2139     }
   2140 
   2141   /* Restore the start point, we may have got a reg of the wrong class.  */
   2142   *str = start;
   2143   sprintf (buff, _("low register(r0-r15)expected, not '%.100s'"), start);
   2144   s7_inst.error = buff;
   2145   return (int) s7_FAIL;
   2146 }
   2147 
   2148 /* Handle addc!/add!/and!/cmp!/neg!/not!/or!/sll!/srl!/sra!/xor!/sub!.  */
   2149 
   2150 static void
   2151 s7_do16_rdrs (char *str)
   2152 {
   2153   s7_skip_whitespace (str);
   2154 
   2155   if (s7_reglow_required_here (&str, 8) == (int) s7_FAIL
   2156       || s7_skip_past_comma (&str) == (int) s7_FAIL
   2157       || s7_reglow_required_here (&str, 4) == (int) s7_FAIL
   2158       || s7_end_of_line (str) == (int) s7_FAIL)
   2159     {
   2160       return;
   2161     }
   2162   else
   2163     {
   2164       if ((s7_inst.instruction & 0x700f) == 0x2003)        /* cmp!  */
   2165         {
   2166           s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 15)
   2167             | (((s7_inst.instruction >> 4) & 0xf) << 10);
   2168         }
   2169       else if ((s7_inst.instruction & 0x700f) == 0x2006)   /* not!  */
   2170 	{
   2171 	  s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
   2172 	    | (((s7_inst.instruction >> 4) & 0xf) << 15);
   2173 	}
   2174       else if ((s7_inst.instruction & 0x700f) == 0x1009)   /* mazh.f!  */
   2175 	{
   2176           s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 15)
   2177                              | (((s7_inst.instruction >> 4) & 0xf) << 10);
   2178 	}
   2179       else
   2180         {
   2181           s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
   2182             | (((s7_inst.instruction >> 8) & 0xf) << 15) | (((s7_inst.instruction >> 4) & 0xf) << 10);
   2183         }
   2184       s7_inst.relax_size = 4;
   2185     }
   2186 }
   2187 
   2188 static void
   2189 s7_do16_rs (char *str)
   2190 {
   2191   int rd = 0;
   2192 
   2193   s7_skip_whitespace (str);
   2194 
   2195   if ((rd = s7_reglow_required_here (&str, 4)) == (int) s7_FAIL
   2196       || s7_end_of_line (str) == (int) s7_FAIL)
   2197     {
   2198       return;
   2199     }
   2200   else
   2201     {
   2202       s7_inst.relax_inst |= rd << 20;
   2203       s7_inst.relax_size = 4;
   2204     }
   2205 }
   2206 
   2207 /* Handle br!/brl!.  */
   2208 
   2209 static void
   2210 s7_do16_xrs (char *str)
   2211 {
   2212   s7_skip_whitespace (str);
   2213 
   2214   if (s7_reglow_required_here (&str, 4) == (int) s7_FAIL || s7_end_of_line (str) == (int) s7_FAIL)
   2215     {
   2216       return;
   2217     }
   2218   else
   2219     {
   2220       s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 10)
   2221                       | (((s7_inst.instruction >> 4) & 0xf) << 15);
   2222       s7_inst.relax_size = 4;
   2223     }
   2224 }
   2225 
   2226 static int
   2227 s7_reghigh_required_here (char **str, int shift)
   2228 {
   2229   static char buff[s7_MAX_LITERAL_POOL_SIZE];
   2230   int reg;
   2231   char *start = *str;
   2232 
   2233   if ((reg = s7_score_reg_parse (str, s7_all_reg_maps[s7_REG_TYPE_SCORE].htab)) != (int) s7_FAIL)
   2234     {
   2235       if (15 < reg && reg < 32)
   2236         {
   2237           if (shift >= 0)
   2238             s7_inst.instruction |= (reg & 0xf) << shift;
   2239 
   2240           return reg;
   2241         }
   2242     }
   2243 
   2244   *str = start;
   2245   sprintf (buff, _("high register(r16-r31)expected, not '%.100s'"), start);
   2246   s7_inst.error = buff;
   2247   return (int) s7_FAIL;
   2248 }
   2249 
   2250 /* Handle mhfl!.  */
   2251 
   2252 static void
   2253 s7_do16_hrdrs (char *str)
   2254 {
   2255   s7_skip_whitespace (str);
   2256 
   2257   if (s7_reghigh_required_here (&str, 8) != (int) s7_FAIL
   2258       && s7_skip_past_comma (&str) != (int) s7_FAIL
   2259       && s7_reglow_required_here (&str, 4) != (int) s7_FAIL
   2260       && s7_end_of_line (str) != (int) s7_FAIL)
   2261     {
   2262       s7_inst.relax_inst |= ((((s7_inst.instruction >> 8) & 0xf) | 0x10) << 20)
   2263         | (((s7_inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
   2264       s7_inst.relax_size = 4;
   2265     }
   2266 }
   2267 
   2268 /* Handle mlfh!.  */
   2269 
   2270 static void
   2271 s7_do16_rdhrs (char *str)
   2272 {
   2273   s7_skip_whitespace (str);
   2274 
   2275   if (s7_reglow_required_here (&str, 8) != (int) s7_FAIL
   2276       && s7_skip_past_comma (&str) != (int) s7_FAIL
   2277       && s7_reghigh_required_here (&str, 4) != (int) s7_FAIL
   2278       && s7_end_of_line (str) != (int) s7_FAIL)
   2279     {
   2280       s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
   2281         | ((((s7_inst.instruction >> 4) & 0xf) | 0x10) << 15) | (0xf << 10);
   2282       s7_inst.relax_size = 4;
   2283     }
   2284 }
   2285 
   2286 /* We need to be able to fix up arbitrary expressions in some statements.
   2287    This is so that we can handle symbols that are an arbitrary distance from
   2288    the pc.  The most common cases are of the form ((+/-sym -/+ . - 8) & mask),
   2289    which returns part of an address in a form which will be valid for
   2290    a data instruction.  We do this by pushing the expression into a symbol
   2291    in the expr_section, and creating a fix for that.  */
   2292 
   2293 static fixS *
   2294 s7_fix_new_score (fragS * frag, int where, short int size, expressionS * exp, int pc_rel, int reloc)
   2295 {
   2296   fixS *new_fix;
   2297 
   2298   switch (exp->X_op)
   2299     {
   2300     case O_constant:
   2301     case O_symbol:
   2302     case O_add:
   2303     case O_subtract:
   2304       new_fix = fix_new_exp (frag, where, size, exp, pc_rel, reloc);
   2305       break;
   2306     default:
   2307       new_fix = fix_new (frag, where, size, make_expr_symbol (exp), 0, pc_rel, reloc);
   2308       break;
   2309     }
   2310   return new_fix;
   2311 }
   2312 
   2313 static void
   2314 s7_init_dependency_vector (void)
   2315 {
   2316   int i;
   2317 
   2318   for (i = 0; i < s7_vector_size; i++)
   2319     memset (&s7_dependency_vector[i], '\0', sizeof (s7_dependency_vector[i]));
   2320 
   2321   return;
   2322 }
   2323 
   2324 static enum s7_insn_type_for_dependency
   2325 s7_dependency_type_from_insn (char *insn_name)
   2326 {
   2327   char name[s7_INSN_NAME_LEN];
   2328   const struct s7_insn_to_dependency *tmp;
   2329 
   2330   strcpy (name, insn_name);
   2331   tmp = (const struct s7_insn_to_dependency *) hash_find (s7_dependency_insn_hsh, name);
   2332 
   2333   if (tmp)
   2334     return tmp->type;
   2335 
   2336   return s7_D_all_insn;
   2337 }
   2338 
   2339 static int
   2340 s7_check_dependency (char *pre_insn, char *pre_reg,
   2341 		     char *cur_insn, char *cur_reg, int *warn_or_error)
   2342 {
   2343   int bubbles = 0;
   2344   unsigned int i;
   2345   enum s7_insn_type_for_dependency pre_insn_type;
   2346   enum s7_insn_type_for_dependency cur_insn_type;
   2347 
   2348   pre_insn_type = s7_dependency_type_from_insn (pre_insn);
   2349   cur_insn_type = s7_dependency_type_from_insn (cur_insn);
   2350 
   2351   for (i = 0; i < sizeof (s7_data_dependency_table) / sizeof (s7_data_dependency_table[0]); i++)
   2352     {
   2353       if ((pre_insn_type == s7_data_dependency_table[i].pre_insn_type)
   2354           && (s7_D_all_insn == s7_data_dependency_table[i].cur_insn_type
   2355               || cur_insn_type == s7_data_dependency_table[i].cur_insn_type)
   2356           && (strcmp (s7_data_dependency_table[i].pre_reg, "") == 0
   2357               || strcmp (s7_data_dependency_table[i].pre_reg, pre_reg) == 0)
   2358           && (strcmp (s7_data_dependency_table[i].cur_reg, "") == 0
   2359               || strcmp (s7_data_dependency_table[i].cur_reg, cur_reg) == 0))
   2360         {
   2361           if (s7_vector_size == s7_SCORE5_PIPELINE)
   2362             bubbles = s7_data_dependency_table[i].bubblenum_5;
   2363           else
   2364             bubbles = s7_data_dependency_table[i].bubblenum_7;
   2365           *warn_or_error = s7_data_dependency_table[i].warn_or_error;
   2366           break;
   2367         }
   2368     }
   2369 
   2370   return bubbles;
   2371 }
   2372 
   2373 /* Turn an integer of n bytes (in val) into a stream of bytes appropriate
   2374    for use in the a.out file, and stores them in the array pointed to by buf.
   2375    This knows about the endian-ness of the target machine and does
   2376    THE RIGHT THING, whatever it is.  Possible values for n are 1 (byte)
   2377    2 (short) and 4 (long)  Floating numbers are put out as a series of
   2378    LITTLENUMS (shorts, here at least).  */
   2379 
   2380 static void
   2381 s7_number_to_chars (char *buf, valueT val, int n)
   2382 {
   2383   if (target_big_endian)
   2384     number_to_chars_bigendian (buf, val, n);
   2385   else
   2386     number_to_chars_littleendian (buf, val, n);
   2387 }
   2388 
   2389 static void
   2390 s7_build_one_frag (struct s7_score_it one_inst)
   2391 {
   2392   char *p;
   2393   int relaxable_p = s7_g_opt;
   2394   int relax_size = 0;
   2395 
   2396   /* Start a new frag if frag_now is not empty.  */
   2397   if (frag_now_fix () != 0)
   2398     {
   2399       if (!frag_now->tc_frag_data.is_insn)
   2400 	frag_wane (frag_now);
   2401 
   2402       frag_new (0);
   2403     }
   2404   frag_grow (20);
   2405 
   2406   p = frag_more (one_inst.size);
   2407   s7_number_to_chars (p, one_inst.instruction, one_inst.size);
   2408 
   2409 #ifdef OBJ_ELF
   2410   dwarf2_emit_insn (one_inst.size);
   2411 #endif
   2412 
   2413   relaxable_p &= (one_inst.relax_size != 0);
   2414   relax_size = relaxable_p ? one_inst.relax_size : 0;
   2415 
   2416   p = frag_var (rs_machine_dependent, relax_size + s7_RELAX_PAD_BYTE, 0,
   2417                 s7_RELAX_ENCODE (one_inst.size, one_inst.relax_size,
   2418                               one_inst.type, 0, 0, relaxable_p),
   2419                 NULL, 0, NULL);
   2420 
   2421   if (relaxable_p)
   2422     s7_number_to_chars (p, one_inst.relax_inst, relax_size);
   2423 }
   2424 
   2425 static void
   2426 s7_handle_dependency (struct s7_score_it *theinst)
   2427 {
   2428   int i;
   2429   int warn_or_error = 0;   /* warn - 0; error - 1  */
   2430   int bubbles = 0;
   2431   int remainder_bubbles = 0;
   2432   char cur_insn[s7_INSN_NAME_LEN];
   2433   char pre_insn[s7_INSN_NAME_LEN];
   2434   struct s7_score_it nop_inst;
   2435   struct s7_score_it pflush_inst;
   2436 
   2437   nop_inst.instruction = 0x0000;
   2438   nop_inst.size = 2;
   2439   nop_inst.relax_inst = 0x80008000;
   2440   nop_inst.relax_size = 4;
   2441   nop_inst.type = NO16_OPD;
   2442 
   2443   pflush_inst.instruction = 0x8000800a;
   2444   pflush_inst.size = 4;
   2445   pflush_inst.relax_inst = 0x8000;
   2446   pflush_inst.relax_size = 0;
   2447   pflush_inst.type = NO_OPD;
   2448 
   2449   /* pflush will clear all data dependency.  */
   2450   if (strcmp (theinst->name, "pflush") == 0)
   2451     {
   2452       s7_init_dependency_vector ();
   2453       return;
   2454     }
   2455 
   2456   /* Push current instruction to s7_dependency_vector[0].  */
   2457   for (i = s7_vector_size - 1; i > 0; i--)
   2458     memcpy (&s7_dependency_vector[i], &s7_dependency_vector[i - 1], sizeof (s7_dependency_vector[i]));
   2459 
   2460   memcpy (&s7_dependency_vector[0], theinst, sizeof (s7_dependency_vector[i]));
   2461 
   2462   /* There is no dependency between nop and any instruction.  */
   2463   if (strcmp (s7_dependency_vector[0].name, "nop") == 0
   2464       || strcmp (s7_dependency_vector[0].name, "nop!") == 0)
   2465     return;
   2466 
   2467   /* "pce" is defined in s7_insn_to_dependency_table.  */
   2468 #define PCE_NAME "pce"
   2469 
   2470   if (s7_dependency_vector[0].type == Insn_Type_PCE)
   2471     strcpy (cur_insn, PCE_NAME);
   2472   else
   2473     strcpy (cur_insn, s7_dependency_vector[0].name);
   2474 
   2475   for (i = 1; i < s7_vector_size; i++)
   2476     {
   2477       /* The element of s7_dependency_vector is NULL.  */
   2478       if (s7_dependency_vector[i].name[0] == '\0')
   2479 	continue;
   2480 
   2481       if (s7_dependency_vector[i].type == Insn_Type_PCE)
   2482 	strcpy (pre_insn, PCE_NAME);
   2483       else
   2484 	strcpy (pre_insn, s7_dependency_vector[i].name);
   2485 
   2486       bubbles = s7_check_dependency (pre_insn, s7_dependency_vector[i].reg,
   2487                                   cur_insn, s7_dependency_vector[0].reg, &warn_or_error);
   2488       remainder_bubbles = bubbles - i + 1;
   2489 
   2490       if (remainder_bubbles > 0)
   2491         {
   2492           int j;
   2493 
   2494           if (s7_fix_data_dependency == 1)
   2495             {
   2496 	      if (remainder_bubbles <= 2)
   2497 		{
   2498 		  if (s7_warn_fix_data_dependency)
   2499 		    as_warn (_("Fix data dependency: %s %s -- %s %s  (insert %d nop!/%d)"),
   2500 			     s7_dependency_vector[i].name, s7_dependency_vector[i].reg,
   2501 			     s7_dependency_vector[0].name, s7_dependency_vector[0].reg,
   2502 			     remainder_bubbles, bubbles);
   2503 
   2504                   for (j = (s7_vector_size - 1); (j - remainder_bubbles) > 0; j--)
   2505 		    memcpy (&s7_dependency_vector[j], &s7_dependency_vector[j - remainder_bubbles],
   2506 			    sizeof (s7_dependency_vector[j]));
   2507 
   2508                   for (j = 1; j <= remainder_bubbles; j++)
   2509                     {
   2510                       memset (&s7_dependency_vector[j], '\0', sizeof (s7_dependency_vector[j]));
   2511 		      /* Insert nop!.  */
   2512     		      s7_build_one_frag (nop_inst);
   2513                     }
   2514 		}
   2515 	      else
   2516 		{
   2517 		  if (s7_warn_fix_data_dependency)
   2518 		    as_warn (_("Fix data dependency: %s %s -- %s %s  (insert 1 pflush/%d)"),
   2519 			     s7_dependency_vector[i].name, s7_dependency_vector[i].reg,
   2520 			     s7_dependency_vector[0].name, s7_dependency_vector[0].reg,
   2521 			     bubbles);
   2522 
   2523                   for (j = 1; j < s7_vector_size; j++)
   2524 		    memset (&s7_dependency_vector[j], '\0', sizeof (s7_dependency_vector[j]));
   2525 
   2526                   /* Insert pflush.  */
   2527                   s7_build_one_frag (pflush_inst);
   2528 		}
   2529             }
   2530           else
   2531             {
   2532 	      if (warn_or_error)
   2533 		{
   2534                   as_bad (_("data dependency: %s %s -- %s %s  (%d/%d bubble)"),
   2535                            s7_dependency_vector[i].name, s7_dependency_vector[i].reg,
   2536                            s7_dependency_vector[0].name, s7_dependency_vector[0].reg,
   2537                            remainder_bubbles, bubbles);
   2538 		}
   2539 	      else
   2540 		{
   2541                   as_warn (_("data dependency: %s %s -- %s %s  (%d/%d bubble)"),
   2542                            s7_dependency_vector[i].name, s7_dependency_vector[i].reg,
   2543                            s7_dependency_vector[0].name, s7_dependency_vector[0].reg,
   2544                            remainder_bubbles, bubbles);
   2545 		}
   2546             }
   2547         }
   2548     }
   2549 }
   2550 
   2551 static enum insn_class
   2552 s7_get_insn_class_from_type (enum score_insn_type type)
   2553 {
   2554   enum insn_class retval = (int) s7_FAIL;
   2555 
   2556   switch (type)
   2557     {
   2558     case Rd_I4:
   2559     case Rd_I5:
   2560     case Rd_rvalueBP_I5:
   2561     case Rd_lvalueBP_I5:
   2562     case Rd_I8:
   2563     case PC_DISP8div2:
   2564     case PC_DISP11div2:
   2565     case Rd_Rs:
   2566     case Rd_HighRs:
   2567     case Rd_lvalueRs:
   2568     case Rd_rvalueRs:
   2569     case x_Rs:
   2570     case Rd_LowRs:
   2571     case NO16_OPD:
   2572       retval = INSN_CLASS_16;
   2573       break;
   2574     case Rd_Rs_I5:
   2575     case x_Rs_I5:
   2576     case x_I5_x:
   2577     case Rd_Rs_I14:
   2578     case I15:
   2579     case Rd_I16:
   2580     case Rd_SI16:
   2581     case Rd_rvalueRs_SI10:
   2582     case Rd_lvalueRs_SI10:
   2583     case Rd_rvalueRs_preSI12:
   2584     case Rd_rvalueRs_postSI12:
   2585     case Rd_lvalueRs_preSI12:
   2586     case Rd_lvalueRs_postSI12:
   2587     case Rd_Rs_SI14:
   2588     case Rd_rvalueRs_SI15:
   2589     case Rd_lvalueRs_SI15:
   2590     case PC_DISP19div2:
   2591     case PC_DISP24div2:
   2592     case Rd_Rs_Rs:
   2593     case x_Rs_x:
   2594     case x_Rs_Rs:
   2595     case Rd_Rs_x:
   2596     case Rd_x_Rs:
   2597     case Rd_x_x:
   2598     case OP5_rvalueRs_SI15:
   2599     case I5_Rs_Rs_I5_OP5:
   2600     case x_rvalueRs_post4:
   2601     case Rd_rvalueRs_post4:
   2602     case Rd_x_I5:
   2603     case Rd_lvalueRs_post4:
   2604     case x_lvalueRs_post4:
   2605     case Rd_Rs_Rs_imm:
   2606     case NO_OPD:
   2607     case Rd_lvalue32Rs:
   2608     case Rd_rvalue32Rs:
   2609     case Insn_GP:
   2610     case Insn_PIC:
   2611     case Insn_internal:
   2612       retval = INSN_CLASS_32;
   2613       break;
   2614     case Insn_Type_PCE:
   2615       retval = INSN_CLASS_PCE;
   2616       break;
   2617     case Insn_Type_SYN:
   2618       retval = INSN_CLASS_SYN;
   2619       break;
   2620     default:
   2621       abort ();
   2622       break;
   2623     }
   2624   return retval;
   2625 }
   2626 
   2627 static unsigned long
   2628 s7_adjust_paritybit (unsigned long m_code, enum insn_class i_class)
   2629 {
   2630   unsigned long result = 0;
   2631   unsigned long m_code_high = 0;
   2632   unsigned long m_code_low = 0;
   2633   unsigned long pb_high = 0;
   2634   unsigned long pb_low = 0;
   2635 
   2636   if (i_class == INSN_CLASS_32)
   2637     {
   2638       pb_high = 0x80000000;
   2639       pb_low = 0x00008000;
   2640     }
   2641   else if (i_class == INSN_CLASS_16)
   2642     {
   2643       pb_high = 0;
   2644       pb_low = 0;
   2645     }
   2646   else if (i_class == INSN_CLASS_PCE)
   2647     {
   2648       pb_high = 0;
   2649       pb_low = 0x00008000;
   2650     }
   2651   else if (i_class == INSN_CLASS_SYN)
   2652     {
   2653       /* FIXME.  at this time, INSN_CLASS_SYN must be 32 bit, but, instruction type should
   2654          be changed if macro instruction has been expanded.  */
   2655       pb_high = 0x80000000;
   2656       pb_low = 0x00008000;
   2657     }
   2658   else
   2659     {
   2660       abort ();
   2661     }
   2662 
   2663   m_code_high = m_code & 0x3fff8000;
   2664   m_code_low = m_code & 0x00007fff;
   2665   result = pb_high | (m_code_high << 1) | pb_low | m_code_low;
   2666   return result;
   2667 
   2668 }
   2669 
   2670 static void
   2671 s7_gen_insn_frag (struct s7_score_it *part_1, struct s7_score_it *part_2)
   2672 {
   2673   char *p;
   2674   bfd_boolean pce_p = FALSE;
   2675   int relaxable_p = s7_g_opt;
   2676   int relax_size = 0;
   2677   struct s7_score_it *inst1 = part_1;
   2678   struct s7_score_it *inst2 = part_2;
   2679   struct s7_score_it backup_inst1;
   2680 
   2681   pce_p = (inst2) ? TRUE : FALSE;
   2682   memcpy (&backup_inst1, inst1, sizeof (struct s7_score_it));
   2683 
   2684   /* Adjust instruction opcode and to be relaxed instruction opcode.  */
   2685   if (pce_p)
   2686     {
   2687       backup_inst1.instruction = ((backup_inst1.instruction & 0x7FFF) << 15)
   2688                                   | (inst2->instruction & 0x7FFF);
   2689       backup_inst1.instruction = s7_adjust_paritybit (backup_inst1.instruction, INSN_CLASS_PCE);
   2690       if (!target_big_endian)
   2691         {
   2692           unsigned long tmp = backup_inst1.instruction;
   2693           backup_inst1.instruction = ((tmp & 0xffff) << 16)
   2694                                      | (tmp >> 16);
   2695         }
   2696       backup_inst1.relax_inst = 0x8000;
   2697       backup_inst1.size = s7_INSN_SIZE;
   2698       backup_inst1.relax_size = 0;
   2699       backup_inst1.type = Insn_Type_PCE;
   2700     }
   2701   else
   2702     {
   2703       backup_inst1.instruction = s7_adjust_paritybit (backup_inst1.instruction,
   2704 						   s7_GET_INSN_CLASS (backup_inst1.type));
   2705     }
   2706 
   2707   if (backup_inst1.relax_size != 0)
   2708     {
   2709       enum insn_class tmp;
   2710 
   2711       tmp = (backup_inst1.size == s7_INSN_SIZE) ? INSN_CLASS_16 : INSN_CLASS_32;
   2712       backup_inst1.relax_inst = s7_adjust_paritybit (backup_inst1.relax_inst, tmp);
   2713     }
   2714 
   2715   /* Check data dependency.  */
   2716   s7_handle_dependency (&backup_inst1);
   2717 
   2718   /* Start a new frag if frag_now is not empty and is not instruction frag, maybe it contains
   2719      data produced by .ascii etc.  Doing this is to make one instruction per frag.  */
   2720   if (frag_now_fix () != 0)
   2721     {
   2722       if (!frag_now->tc_frag_data.is_insn)
   2723 	frag_wane (frag_now);
   2724 
   2725       frag_new (0);
   2726     }
   2727 
   2728   /* Here, we must call frag_grow in order to keep the instruction frag type is
   2729      rs_machine_dependent.
   2730      For, frag_var may change frag_now->fr_type to rs_fill by calling frag_grow which
   2731      acturally will call frag_wane.
   2732      Calling frag_grow first will create a new frag_now which free size is 20 that is enough
   2733      for frag_var.  */
   2734   frag_grow (20);
   2735 
   2736   p = frag_more (backup_inst1.size);
   2737   s7_number_to_chars (p, backup_inst1.instruction, backup_inst1.size);
   2738 
   2739 #ifdef OBJ_ELF
   2740   dwarf2_emit_insn (backup_inst1.size);
   2741 #endif
   2742 
   2743   /* Generate fixup structure.  */
   2744   if (pce_p)
   2745     {
   2746       if (inst1->reloc.type != BFD_RELOC_NONE)
   2747 	s7_fix_new_score (frag_now, p - frag_now->fr_literal,
   2748 		       inst1->size, &inst1->reloc.exp,
   2749 		       inst1->reloc.pc_rel, inst1->reloc.type);
   2750 
   2751       if (inst2->reloc.type != BFD_RELOC_NONE)
   2752 	s7_fix_new_score (frag_now, p - frag_now->fr_literal + 2,
   2753 		       inst2->size, &inst2->reloc.exp, inst2->reloc.pc_rel, inst2->reloc.type);
   2754     }
   2755   else
   2756     {
   2757       if (backup_inst1.reloc.type != BFD_RELOC_NONE)
   2758 	s7_fix_new_score (frag_now, p - frag_now->fr_literal,
   2759 		       backup_inst1.size, &backup_inst1.reloc.exp,
   2760 		       backup_inst1.reloc.pc_rel, backup_inst1.reloc.type);
   2761     }
   2762 
   2763   /* relax_size may be 2, 4, 12 or 0, 0 indicates no relaxation.  */
   2764   relaxable_p &= (backup_inst1.relax_size != 0);
   2765   relax_size = relaxable_p ? backup_inst1.relax_size : 0;
   2766 
   2767   p = frag_var (rs_machine_dependent, relax_size + s7_RELAX_PAD_BYTE, 0,
   2768                 s7_RELAX_ENCODE (backup_inst1.size, backup_inst1.relax_size,
   2769                               backup_inst1.type, 0, 0, relaxable_p),
   2770                 backup_inst1.reloc.exp.X_add_symbol, 0, NULL);
   2771 
   2772   if (relaxable_p)
   2773     s7_number_to_chars (p, backup_inst1.relax_inst, relax_size);
   2774 
   2775   memcpy (inst1, &backup_inst1, sizeof (struct s7_score_it));
   2776 }
   2777 
   2778 static void
   2779 s7_parse_16_32_inst (char *insnstr, bfd_boolean gen_frag_p)
   2780 {
   2781   char c;
   2782   char *p;
   2783   char *operator = insnstr;
   2784   const struct s7_asm_opcode *opcode;
   2785 
   2786   /* Parse operator and operands.  */
   2787   s7_skip_whitespace (operator);
   2788 
   2789   for (p = operator; *p != '\0'; p++)
   2790     if ((*p == ' ') || (*p == '!'))
   2791       break;
   2792 
   2793   if (*p == '!')
   2794     p++;
   2795 
   2796   c = *p;
   2797   *p = '\0';
   2798 
   2799   opcode = (const struct s7_asm_opcode *) hash_find (s7_score_ops_hsh, operator);
   2800   *p = c;
   2801 
   2802   memset (&s7_inst, '\0', sizeof (s7_inst));
   2803   strcpy (s7_inst.str, insnstr);
   2804   if (opcode)
   2805     {
   2806       s7_inst.instruction = opcode->value;
   2807       s7_inst.relax_inst = opcode->relax_value;
   2808       s7_inst.type = opcode->type;
   2809       s7_inst.size = s7_GET_INSN_SIZE (s7_inst.type);
   2810       s7_inst.relax_size = 0;
   2811       s7_inst.bwarn = 0;
   2812       strcpy (s7_inst.name, opcode->template_name);
   2813       strcpy (s7_inst.reg, "");
   2814       s7_inst.error = NULL;
   2815       s7_inst.reloc.type = BFD_RELOC_NONE;
   2816 
   2817       (*opcode->parms) (p);
   2818 
   2819       /* It indicates current instruction is a macro instruction if s7_inst.bwarn equals -1.  */
   2820       if ((s7_inst.bwarn != -1) && (!s7_inst.error) && (gen_frag_p))
   2821 	s7_gen_insn_frag (&s7_inst, NULL);
   2822     }
   2823   else
   2824     s7_inst.error = _("unrecognized opcode");
   2825 }
   2826 
   2827 static int
   2828 s7_append_insn (char *str, bfd_boolean gen_frag_p)
   2829 {
   2830   int retval = s7_SUCCESS;
   2831 
   2832   s7_parse_16_32_inst (str, gen_frag_p);
   2833 
   2834   if (s7_inst.error)
   2835     {
   2836       retval = (int) s7_FAIL;
   2837       as_bad (_("%s -- `%s'"), s7_inst.error, s7_inst.str);
   2838       s7_inst.error = NULL;
   2839     }
   2840 
   2841   return retval;
   2842 }
   2843 
   2844 /* Handle mv! reg_high, reg_low;
   2845           mv! reg_low, reg_high;
   2846           mv! reg_low, reg_low;  */
   2847 static void
   2848 s7_do16_mv_rdrs (char *str)
   2849 {
   2850   int reg_rd;
   2851   int reg_rs;
   2852   char *backupstr = NULL;
   2853 
   2854   backupstr = str;
   2855   s7_skip_whitespace (str);
   2856 
   2857   if ((reg_rd = s7_reg_required_here (&str, 8, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
   2858       || s7_skip_past_comma (&str) == (int) s7_FAIL
   2859       || (reg_rs = s7_reg_required_here (&str, 4, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
   2860       || s7_end_of_line (str) == (int) s7_FAIL)
   2861     {
   2862       return;
   2863     }
   2864   else
   2865     {
   2866       /* Case 1 : mv! or mlfh!.  */
   2867       if (reg_rd < 16)
   2868         {
   2869           if (reg_rs < 16)
   2870             {
   2871               s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
   2872                 | (((s7_inst.instruction >> 4) & 0xf) << 15) | (0xf << 10);
   2873               s7_inst.relax_size = 4;
   2874             }
   2875           else
   2876             {
   2877               char append_str[s7_MAX_LITERAL_POOL_SIZE];
   2878 
   2879               sprintf (append_str, "mlfh! %s", backupstr);
   2880               if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
   2881 		return;
   2882               /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
   2883               s7_inst.bwarn = -1;
   2884             }
   2885         }
   2886       /* Case 2 : mhfl!.  */
   2887       else
   2888         {
   2889           if (reg_rs > 16)
   2890             {
   2891               s7_SET_INSN_ERROR (s7_BAD_ARGS);
   2892               return;
   2893             }
   2894           else
   2895             {
   2896               char append_str[s7_MAX_LITERAL_POOL_SIZE];
   2897 
   2898               sprintf (append_str, "mhfl! %s", backupstr);
   2899               if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
   2900 		return;
   2901 
   2902               /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
   2903               s7_inst.bwarn = -1;
   2904             }
   2905         }
   2906     }
   2907 }
   2908 
   2909 static void
   2910 s7_do16_rdi4 (char *str)
   2911 {
   2912   s7_skip_whitespace (str);
   2913 
   2914   if (s7_reglow_required_here (&str, 8) == (int) s7_FAIL
   2915       || s7_skip_past_comma (&str) == (int) s7_FAIL
   2916       || s7_data_op2 (&str, 3, _IMM4) == (int) s7_FAIL
   2917       || s7_end_of_line (str) == (int) s7_FAIL)
   2918     {
   2919       return;
   2920     }
   2921   else
   2922     {
   2923       if (((s7_inst.instruction >> 3) & 0x10) == 0)        /* for judge is addei or subei : bit 5 =0 : addei */
   2924         {
   2925           if (((s7_inst.instruction >> 3) & 0xf) != 0xf)
   2926             {
   2927               s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
   2928                 | ((1 << ((s7_inst.instruction >> 3) & 0xf)) << 1);
   2929               s7_inst.relax_size = 4;
   2930             }
   2931           else
   2932             {
   2933               s7_inst.relax_inst = 0x8000;
   2934             }
   2935         }
   2936       else
   2937         {
   2938           if (((s7_inst.instruction >> 3) & 0xf) != 0xf)
   2939             {
   2940               s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
   2941                 | (((-(1 << ((s7_inst.instruction >> 3) & 0xf))) & 0xffff) << 1);
   2942               s7_inst.relax_size = 4;
   2943             }
   2944           else
   2945             {
   2946               s7_inst.relax_inst = 0x8000;
   2947             }
   2948         }
   2949     }
   2950 }
   2951 
   2952 static void
   2953 s7_do16_rdi5 (char *str)
   2954 {
   2955   s7_skip_whitespace (str);
   2956 
   2957   if (s7_reglow_required_here (&str, 8) == (int) s7_FAIL
   2958       || s7_skip_past_comma (&str) == (int) s7_FAIL
   2959       || s7_data_op2 (&str, 3, _IMM5) == (int) s7_FAIL
   2960       || s7_end_of_line (str) == (int) s7_FAIL)
   2961     return;
   2962   else
   2963     {
   2964       s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
   2965         | (((s7_inst.instruction >> 8) & 0xf) << 15) | (((s7_inst.instruction >> 3) & 0x1f) << 10);
   2966       s7_inst.relax_size = 4;
   2967     }
   2968 }
   2969 
   2970 /* Handle sdbbp.  */
   2971 
   2972 static void
   2973 s7_do16_xi5 (char *str)
   2974 {
   2975   s7_skip_whitespace (str);
   2976 
   2977   if (s7_data_op2 (&str, 3, _IMM5) == (int) s7_FAIL || s7_end_of_line (str) == (int) s7_FAIL)
   2978     return;
   2979   else
   2980     {
   2981       s7_inst.relax_inst |= (((s7_inst.instruction >> 3) & 0x1f) << 15);
   2982       s7_inst.relax_size = 4;
   2983     }
   2984 }
   2985 
   2986 /* Check that an immediate is word alignment or half word alignment.
   2987    If so, convert it to the right format.  */
   2988 
   2989 static int
   2990 s7_validate_immediate_align (int val, unsigned int data_type)
   2991 {
   2992   if (data_type == _IMM5_RSHIFT_1)
   2993     {
   2994       if (val % 2)
   2995         {
   2996           s7_inst.error = _("address offset must be half word alignment");
   2997           return (int) s7_FAIL;
   2998         }
   2999     }
   3000   else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
   3001     {
   3002       if (val % 4)
   3003         {
   3004           s7_inst.error = _("address offset must be word alignment");
   3005           return (int) s7_FAIL;
   3006         }
   3007     }
   3008 
   3009   return s7_SUCCESS;
   3010 }
   3011 
   3012 static int
   3013 s7_exp_ldst_offset (char **str, int shift, unsigned int data_type)
   3014 {
   3015   char *dataptr;
   3016   int hex_p = 0;
   3017 
   3018   dataptr = * str;
   3019 
   3020   if ((dataptr != NULL)
   3021       && (((strstr (dataptr, "0x")) != NULL)
   3022           || ((strstr (dataptr, "0X")) != NULL)))
   3023     {
   3024       hex_p = 1;
   3025       if ((data_type != _SIMM16_LA)
   3026         && (data_type != _VALUE_HI16)
   3027         && (data_type != _VALUE_LO16)
   3028         && (data_type != _IMM16)
   3029         && (data_type != _IMM15)
   3030         && (data_type != _IMM14)
   3031         && (data_type != _IMM4)
   3032         && (data_type != _IMM5)
   3033         && (data_type != _IMM8)
   3034         && (data_type != _IMM5_RSHIFT_1)
   3035         && (data_type != _IMM5_RSHIFT_2)
   3036         && (data_type != _SIMM12)
   3037         && (data_type != _SIMM15)
   3038         && (data_type != _SIMM14_NEG)
   3039         && (data_type != _IMM10_RSHIFT_2))
   3040         {
   3041           data_type += 24;
   3042         }
   3043     }
   3044 
   3045   if (s7_my_get_expression (&s7_inst.reloc.exp, str) == (int) s7_FAIL)
   3046     return (int) s7_FAIL;
   3047 
   3048   if (s7_inst.reloc.exp.X_op == O_constant)
   3049     {
   3050       /* Need to check the immediate align.  */
   3051       int value = s7_validate_immediate_align (s7_inst.reloc.exp.X_add_number, data_type);
   3052 
   3053       if (value == (int) s7_FAIL)
   3054 	return (int) s7_FAIL;
   3055 
   3056       value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, data_type, hex_p);
   3057       if (value == (int) s7_FAIL)
   3058         {
   3059           if (data_type < 30)
   3060             sprintf (s7_err_msg,
   3061                      _("invalid constant: %d bit expression not in range %d..%d"),
   3062                      s7_score_df_range[data_type].bits,
   3063                      s7_score_df_range[data_type].range[0], s7_score_df_range[data_type].range[1]);
   3064           else
   3065             sprintf (s7_err_msg,
   3066                      _("invalid constant: %d bit expression not in range %d..%d"),
   3067                      s7_score_df_range[data_type - 24].bits,
   3068                      s7_score_df_range[data_type - 24].range[0], s7_score_df_range[data_type - 24].range[1]);
   3069           s7_inst.error = s7_err_msg;
   3070           return (int) s7_FAIL;
   3071         }
   3072 
   3073       if (data_type == _IMM5_RSHIFT_1)
   3074         {
   3075           value >>= 1;
   3076         }
   3077       else if ((data_type == _IMM5_RSHIFT_2) || (data_type == _IMM10_RSHIFT_2))
   3078         {
   3079           value >>= 2;
   3080         }
   3081 
   3082       if (s7_score_df_range[data_type].range[0] != 0)
   3083         {
   3084           value &= (1 << s7_score_df_range[data_type].bits) - 1;
   3085         }
   3086 
   3087       s7_inst.instruction |= value << shift;
   3088     }
   3089   else
   3090     {
   3091       s7_inst.reloc.pc_rel = 0;
   3092     }
   3093 
   3094   return s7_SUCCESS;
   3095 }
   3096 
   3097 static void
   3098 s7_do_ldst_insn (char *str)
   3099 {
   3100   int pre_inc = 0;
   3101   int conflict_reg;
   3102   int value;
   3103   char * temp;
   3104   char *dataptr;
   3105   int reg;
   3106   int ldst_idx = 0;
   3107 
   3108   int hex_p = 0;
   3109 
   3110   s7_skip_whitespace (str);
   3111 
   3112   if (((conflict_reg = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
   3113       || (s7_skip_past_comma (&str) == (int) s7_FAIL))
   3114     return;
   3115 
   3116   /* ld/sw rD, [rA, simm15]    ld/sw rD, [rA]+, simm12     ld/sw rD, [rA, simm12]+.  */
   3117   if (*str == '[')
   3118     {
   3119       str++;
   3120       s7_skip_whitespace (str);
   3121 
   3122       if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
   3123 	return;
   3124 
   3125       /* Conflicts can occur on stores as well as loads.  */
   3126       conflict_reg = (conflict_reg == reg);
   3127       s7_skip_whitespace (str);
   3128       temp = str + 1;    /* The latter will process decimal/hex expression.  */
   3129 
   3130       /* ld/sw rD, [rA]+, simm12    ld/sw rD, [rA]+.  */
   3131       if (*str == ']')
   3132         {
   3133           str++;
   3134           if (*str == '+')
   3135             {
   3136               str++;
   3137               /* ld/sw rD, [rA]+, simm12.  */
   3138               if (s7_skip_past_comma (&str) == s7_SUCCESS)
   3139                 {
   3140                   if ((s7_exp_ldst_offset (&str, 3, _SIMM12) == (int) s7_FAIL)
   3141                       || (s7_end_of_line (str) == (int) s7_FAIL))
   3142 		    return;
   3143 
   3144                   if (conflict_reg)
   3145                     {
   3146                       unsigned int ldst_func = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
   3147 
   3148                       if ((ldst_func == INSN_LH)
   3149                           || (ldst_func == INSN_LHU)
   3150                           || (ldst_func == INSN_LW)
   3151                           || (ldst_func == INSN_LB)
   3152                           || (ldst_func == INSN_LBU))
   3153                         {
   3154                           s7_inst.error = _("register same as write-back base");
   3155                           return;
   3156                         }
   3157                     }
   3158 
   3159                   ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
   3160                   s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
   3161                   s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + LDST_POST].value;
   3162 
   3163                   /* lw rD, [rA]+, 4 convert to pop rD, [rA].  */
   3164                   if ((s7_inst.instruction & 0x3e000007) == 0x0e000000)
   3165                     {
   3166                       /* rs =  r0-r7, offset = 4 */
   3167                       if ((((s7_inst.instruction >> 15) & 0x18) == 0)
   3168                           && (((s7_inst.instruction >> 3) & 0xfff) == 4))
   3169                         {
   3170                           /* Relax to pophi.  */
   3171                           if ((((s7_inst.instruction >> 20) & 0x10) == 0x10))
   3172                             {
   3173                               s7_inst.relax_inst = 0x0000200a | (((s7_inst.instruction >> 20) & 0xf)
   3174                                                               << 8) | 1 << 7 |
   3175                                 (((s7_inst.instruction >> 15) & 0x7) << 4);
   3176                             }
   3177                           /* Relax to pop.  */
   3178                           else
   3179                             {
   3180                               s7_inst.relax_inst = 0x0000200a | (((s7_inst.instruction >> 20) & 0xf)
   3181                                                               << 8) | 0 << 7 |
   3182                                 (((s7_inst.instruction >> 15) & 0x7) << 4);
   3183                             }
   3184                           s7_inst.relax_size = 2;
   3185                         }
   3186                     }
   3187                   return;
   3188                 }
   3189               /* ld/sw rD, [rA]+ convert to ld/sw rD, [rA, 0]+.  */
   3190               else
   3191                 {
   3192                   s7_SET_INSN_ERROR (NULL);
   3193                   if (s7_end_of_line (str) == (int) s7_FAIL)
   3194                     {
   3195                       return;
   3196                     }
   3197 
   3198                   pre_inc = 1;
   3199                   value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _SIMM12, 0);
   3200                   value &= (1 << s7_score_df_range[_SIMM12].bits) - 1;
   3201                   ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
   3202                   s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
   3203                   s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
   3204                   s7_inst.instruction |= value << 3;
   3205                   s7_inst.relax_inst = 0x8000;
   3206                   return;
   3207                 }
   3208             }
   3209           /* ld/sw rD, [rA] convert to ld/sw rD, [rA, simm15].  */
   3210           else
   3211             {
   3212               if (s7_end_of_line (str) == (int) s7_FAIL)
   3213 		return;
   3214 
   3215               ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
   3216               s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
   3217               s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + LDST_NOUPDATE].value;
   3218 
   3219               /* lbu rd, [rs] -> lbu! rd, [rs]  */
   3220               if (ldst_idx == INSN_LBU)
   3221                 {
   3222                   s7_inst.relax_inst = INSN16_LBU;
   3223                 }
   3224               else if (ldst_idx == INSN_LH)
   3225                 {
   3226                   s7_inst.relax_inst = INSN16_LH;
   3227                 }
   3228               else if (ldst_idx == INSN_LW)
   3229                 {
   3230                   s7_inst.relax_inst = INSN16_LW;
   3231                 }
   3232               else if (ldst_idx == INSN_SB)
   3233                 {
   3234                   s7_inst.relax_inst = INSN16_SB;
   3235                 }
   3236               else if (ldst_idx == INSN_SH)
   3237                 {
   3238                   s7_inst.relax_inst = INSN16_SH;
   3239                 }
   3240               else if (ldst_idx == INSN_SW)
   3241                 {
   3242                   s7_inst.relax_inst = INSN16_SW;
   3243                 }
   3244               else
   3245                 {
   3246                   s7_inst.relax_inst = 0x8000;
   3247                 }
   3248 
   3249               /* lw/lh/lbu/sw/sh/sb, offset = 0, relax to 16 bit instruction.  */
   3250               if ((ldst_idx == INSN_LBU)
   3251                   || (ldst_idx == INSN_LH)
   3252                   || (ldst_idx == INSN_LW)
   3253                   || (ldst_idx == INSN_SB) || (ldst_idx == INSN_SH) || (ldst_idx == INSN_SW))
   3254                 {
   3255                   if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
   3256                     {
   3257                       s7_inst.relax_inst |= (2 << 12) | (((s7_inst.instruction >> 20) & 0xf) << 8) |
   3258                         (((s7_inst.instruction >> 15) & 0xf) << 4);
   3259                       s7_inst.relax_size = 2;
   3260                     }
   3261                 }
   3262 
   3263               return;
   3264             }
   3265         }
   3266       /* ld/sw rD, [rA, simm15]    ld/sw rD, [rA, simm12]+.  */
   3267       else
   3268         {
   3269           if (s7_skip_past_comma (&str) == (int) s7_FAIL)
   3270             {
   3271               s7_inst.error = _("pre-indexed expression expected");
   3272               return;
   3273             }
   3274 
   3275           if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
   3276 	    return;
   3277 
   3278           s7_skip_whitespace (str);
   3279           if (*str++ != ']')
   3280             {
   3281               s7_inst.error = _("missing ]");
   3282               return;
   3283             }
   3284 
   3285           s7_skip_whitespace (str);
   3286           /* ld/sw rD, [rA, simm12]+.  */
   3287           if (*str == '+')
   3288             {
   3289               str++;
   3290               pre_inc = 1;
   3291               if (conflict_reg)
   3292                 {
   3293                   unsigned int ldst_func = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
   3294 
   3295                   if ((ldst_func == INSN_LH)
   3296                       || (ldst_func == INSN_LHU)
   3297                       || (ldst_func == INSN_LW)
   3298                       || (ldst_func == INSN_LB)
   3299                       || (ldst_func == INSN_LBU))
   3300                     {
   3301                       s7_inst.error = _("register same as write-back base");
   3302                       return;
   3303                     }
   3304                 }
   3305             }
   3306 
   3307           if (s7_end_of_line (str) == (int) s7_FAIL)
   3308 	    return;
   3309 
   3310           if (s7_inst.reloc.exp.X_op == O_constant)
   3311             {
   3312               unsigned int data_type;
   3313 
   3314               if (pre_inc == 1)
   3315                 data_type = _SIMM12;
   3316               else
   3317                 data_type = _SIMM15;
   3318               dataptr = temp;
   3319 
   3320             if ((dataptr != NULL)
   3321               && (((strstr (dataptr, "0x")) != NULL)
   3322                   || ((strstr (dataptr, "0X")) != NULL)))
   3323               {
   3324                 hex_p = 1;
   3325                 if ((data_type != _SIMM16_LA)
   3326                     && (data_type != _VALUE_HI16)
   3327                     && (data_type != _VALUE_LO16)
   3328                     && (data_type != _IMM16)
   3329                     && (data_type != _IMM15)
   3330                     && (data_type != _IMM14)
   3331                     && (data_type != _IMM4)
   3332                     && (data_type != _IMM5)
   3333                     && (data_type != _IMM8)
   3334                     && (data_type != _SIMM12)
   3335                     && (data_type != _SIMM15)
   3336                     && (data_type != _IMM5_RSHIFT_1)
   3337                     && (data_type != _IMM5_RSHIFT_2)
   3338                     && (data_type != _SIMM14_NEG)
   3339                     && (data_type != _IMM10_RSHIFT_2))
   3340                   {
   3341                     data_type += 24;
   3342                   }
   3343               }
   3344 
   3345               value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, data_type, hex_p);
   3346               if (value == (int) s7_FAIL)
   3347                 {
   3348                   if (data_type < 30)
   3349                     sprintf (s7_err_msg,
   3350                              _("invalid constant: %d bit expression not in range %d..%d"),
   3351                              s7_score_df_range[data_type].bits,
   3352                              s7_score_df_range[data_type].range[0], s7_score_df_range[data_type].range[1]);
   3353                   else
   3354                     sprintf (s7_err_msg,
   3355                              _("invalid constant: %d bit expression not in range %d..%d"),
   3356                              s7_score_df_range[data_type - 24].bits,
   3357                              s7_score_df_range[data_type - 24].range[0],
   3358                              s7_score_df_range[data_type - 24].range[1]);
   3359                   s7_inst.error = s7_err_msg;
   3360                   return;
   3361                 }
   3362 
   3363               value &= (1 << s7_score_df_range[data_type].bits) - 1;
   3364               ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
   3365               s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
   3366               s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
   3367               if (pre_inc == 1)
   3368                 s7_inst.instruction |= value << 3;
   3369               else
   3370                 s7_inst.instruction |= value;
   3371 
   3372               /* lw rD, [rA, simm15]  */
   3373               if ((s7_inst.instruction & 0x3e000000) == 0x20000000)
   3374                 {
   3375                   /* Both rD and rA are in [r0 - r15].  */
   3376                   if ((((s7_inst.instruction >> 15) & 0x10) == 0)
   3377                       && (((s7_inst.instruction >> 20) & 0x10) == 0))
   3378                     {
   3379                       /* simm15 = 0, lw -> lw!.  */
   3380                       if ((s7_inst.instruction & 0x7fff) == 0)
   3381                         {
   3382                           s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
   3383                             | (((s7_inst.instruction >> 20) & 0xf) << 8);
   3384                           s7_inst.relax_size = 2;
   3385                         }
   3386                       /* rA = r2, lw -> lwp!.  */
   3387                       else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
   3388                                && ((s7_inst.instruction & 0x3) == 0)
   3389                                && ((s7_inst.instruction & 0x7fff) < 128))
   3390                         {
   3391                           s7_inst.relax_inst = 0x7000 | (((s7_inst.instruction >> 20) & 0xf) << 8)
   3392                             | (((s7_inst.instruction & 0x7fff) >> 2) << 3);
   3393                           s7_inst.relax_size = 2;
   3394                         }
   3395                       else
   3396                         {
   3397                           s7_inst.relax_inst = 0x8000;
   3398                         }
   3399                     }
   3400                   else
   3401                     {
   3402                       s7_inst.relax_inst = 0x8000;
   3403                     }
   3404                 }
   3405               /* sw rD, [rA, simm15]  */
   3406               else if ((s7_inst.instruction & 0x3e000000) == 0x28000000)
   3407                 {
   3408                   /* Both rD and rA are in [r0 - r15].  */
   3409                   if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
   3410                     {
   3411                       /* simm15 = 0, sw -> sw!.  */
   3412                       if ((s7_inst.instruction & 0x7fff) == 0)
   3413                         {
   3414                           s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
   3415                             | (((s7_inst.instruction >> 20) & 0xf) << 8);
   3416                           s7_inst.relax_size = 2;
   3417                         }
   3418                       /* rA = r2, sw -> swp!.  */
   3419                       else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
   3420                                && ((s7_inst.instruction & 0x3) == 0)
   3421                                && ((s7_inst.instruction & 0x7fff) < 128))
   3422                         {
   3423                           s7_inst.relax_inst = 0x7004 | (((s7_inst.instruction >> 20) & 0xf) << 8)
   3424                             | (((s7_inst.instruction & 0x7fff) >> 2) << 3);
   3425                           s7_inst.relax_size = 2;
   3426                         }
   3427                       else
   3428                         {
   3429                           s7_inst.relax_inst = 0x8000;
   3430                         }
   3431                     }
   3432                   else
   3433                     {
   3434                       s7_inst.relax_inst = 0x8000;
   3435                     }
   3436                 }
   3437               /* sw rD, [rA, simm15]+    sw pre.  */
   3438               else if ((s7_inst.instruction & 0x3e000007) == 0x06000004)
   3439                 {
   3440                   /* rA is in [r0 - r7], and simm15 = -4.  */
   3441                   if ((((s7_inst.instruction >> 15) & 0x18) == 0)
   3442                       && (((s7_inst.instruction >> 3) & 0xfff) == 0xffc))
   3443                     {
   3444                       /* sw -> pushhi!.  */
   3445                       if ((((s7_inst.instruction >> 20) & 0x10) == 0x10))
   3446                         {
   3447                           s7_inst.relax_inst = 0x0000200e | (((s7_inst.instruction >> 20) & 0xf) << 8)
   3448                             | 1 << 7 | (((s7_inst.instruction >> 15) & 0x7) << 4);
   3449                           s7_inst.relax_size = 2;
   3450                         }
   3451                       /* sw -> push!.  */
   3452                       else
   3453                         {
   3454                           s7_inst.relax_inst = 0x0000200e | (((s7_inst.instruction >> 20) & 0xf) << 8)
   3455                             | 0 << 7 | (((s7_inst.instruction >> 15) & 0x7) << 4);
   3456                           s7_inst.relax_size = 2;
   3457                         }
   3458                     }
   3459                   else
   3460                     {
   3461                       s7_inst.relax_inst = 0x8000;
   3462                     }
   3463                 }
   3464               /* lh rD, [rA, simm15]  */
   3465               else if ((s7_inst.instruction & 0x3e000000) == 0x22000000)
   3466                 {
   3467                   /* Both rD and rA are in [r0 - r15].  */
   3468                   if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
   3469                     {
   3470                       /* simm15 = 0, lh -> lh!.  */
   3471                       if ((s7_inst.instruction & 0x7fff) == 0)
   3472                         {
   3473                           s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
   3474                             | (((s7_inst.instruction >> 20) & 0xf) << 8);
   3475                           s7_inst.relax_size = 2;
   3476                         }
   3477                       /* rA = r2, lh -> lhp!.  */
   3478                       else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
   3479                                && ((s7_inst.instruction & 0x1) == 0)
   3480                                && ((s7_inst.instruction & 0x7fff) < 64))
   3481                         {
   3482                           s7_inst.relax_inst = 0x7001 | (((s7_inst.instruction >> 20) & 0xf) << 8)
   3483                             | (((s7_inst.instruction & 0x7fff) >> 1) << 3);
   3484                           s7_inst.relax_size = 2;
   3485                         }
   3486                       else
   3487                         {
   3488                           s7_inst.relax_inst = 0x8000;
   3489                         }
   3490                     }
   3491                   else
   3492                     {
   3493                       s7_inst.relax_inst = 0x8000;
   3494                     }
   3495                 }
   3496               /* sh rD, [rA, simm15]  */
   3497               else if ((s7_inst.instruction & 0x3e000000) == 0x2a000000)
   3498                 {
   3499                   /* Both rD and rA are in [r0 - r15].  */
   3500                   if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
   3501                     {
   3502                       /* simm15 = 0, sh -> sh!.  */
   3503                       if ((s7_inst.instruction & 0x7fff) == 0)
   3504                         {
   3505                           s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
   3506                             | (((s7_inst.instruction >> 20) & 0xf) << 8);
   3507                           s7_inst.relax_size = 2;
   3508                         }
   3509                       /* rA = r2, sh -> shp!.  */
   3510                       else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
   3511                                && ((s7_inst.instruction & 0x1) == 0)
   3512                                && ((s7_inst.instruction & 0x7fff) < 64))
   3513                         {
   3514                           s7_inst.relax_inst = 0x7005 | (((s7_inst.instruction >> 20) & 0xf) << 8)
   3515                             | (((s7_inst.instruction & 0x7fff) >> 1) << 3);
   3516                           s7_inst.relax_size = 2;
   3517                         }
   3518                       else
   3519                         {
   3520                           s7_inst.relax_inst = 0x8000;
   3521                         }
   3522                     }
   3523                   else
   3524                     {
   3525                       s7_inst.relax_inst = 0x8000;
   3526                     }
   3527                 }
   3528               /* lbu rD, [rA, simm15]  */
   3529               else if ((s7_inst.instruction & 0x3e000000) == 0x2c000000)
   3530                 {
   3531                   /* Both rD and rA are in [r0 - r15].  */
   3532                   if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
   3533                     {
   3534                       /* simm15 = 0, lbu -> lbu!.  */
   3535                       if ((s7_inst.instruction & 0x7fff) == 0)
   3536                         {
   3537                           s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
   3538                             | (((s7_inst.instruction >> 20) & 0xf) << 8);
   3539                           s7_inst.relax_size = 2;
   3540                         }
   3541                       /* rA = r2, lbu -> lbup!.  */
   3542                       else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
   3543                                && ((s7_inst.instruction & 0x7fff) < 32))
   3544                         {
   3545                           s7_inst.relax_inst = 0x7003 | (((s7_inst.instruction >> 20) & 0xf) << 8)
   3546                             | ((s7_inst.instruction & 0x7fff) << 3);
   3547                           s7_inst.relax_size = 2;
   3548                         }
   3549                       else
   3550                         {
   3551                           s7_inst.relax_inst = 0x8000;
   3552                         }
   3553                     }
   3554                   else
   3555                     {
   3556                       s7_inst.relax_inst = 0x8000;
   3557                     }
   3558                 }
   3559               /* sb rD, [rA, simm15]  */
   3560               else if ((s7_inst.instruction & 0x3e000000) == 0x2e000000)
   3561                 {
   3562                   /* Both rD and rA are in [r0 - r15].  */
   3563                   if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
   3564                     {
   3565                       /* simm15 = 0, sb -> sb!.  */
   3566                       if ((s7_inst.instruction & 0x7fff) == 0)
   3567                         {
   3568                           s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
   3569                             | (((s7_inst.instruction >> 20) & 0xf) << 8);
   3570                           s7_inst.relax_size = 2;
   3571                         }
   3572                       /* rA = r2, sb -> sb!.  */
   3573                       else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
   3574                                && ((s7_inst.instruction & 0x7fff) < 32))
   3575                         {
   3576                           s7_inst.relax_inst = 0x7007 | (((s7_inst.instruction >> 20) & 0xf) << 8)
   3577                             | ((s7_inst.instruction & 0x7fff) << 3);
   3578                           s7_inst.relax_size = 2;
   3579                         }
   3580                       else
   3581                         {
   3582                           s7_inst.relax_inst = 0x8000;
   3583                         }
   3584                     }
   3585                   else
   3586                     {
   3587                       s7_inst.relax_inst = 0x8000;
   3588                     }
   3589                 }
   3590               else
   3591                 {
   3592                   s7_inst.relax_inst = 0x8000;
   3593                 }
   3594 
   3595               return;
   3596             }
   3597           else
   3598             {
   3599               /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
   3600               s7_inst.reloc.pc_rel = 0;
   3601             }
   3602         }
   3603     }
   3604   else
   3605     {
   3606       s7_inst.error = s7_BAD_ARGS;
   3607     }
   3608 }
   3609 
   3610 /* Handle cache.  */
   3611 static void
   3612 s7_do_cache (char *str)
   3613 {
   3614   s7_skip_whitespace (str);
   3615 
   3616   if ((s7_data_op2 (&str, 20, _IMM5) == (int) s7_FAIL) || (s7_skip_past_comma (&str) == (int) s7_FAIL))
   3617     {
   3618       return;
   3619     }
   3620   else
   3621     {
   3622       int cache_op;
   3623 
   3624       cache_op = (s7_inst.instruction >> 20) & 0x1F;
   3625       sprintf (s7_inst.name, "cache %d", cache_op);
   3626     }
   3627 
   3628   if (*str == '[')
   3629     {
   3630       str++;
   3631       s7_skip_whitespace (str);
   3632 
   3633       if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
   3634 	return;
   3635 
   3636       s7_skip_whitespace (str);
   3637 
   3638       /* cache op, [rA]  */
   3639       if (s7_skip_past_comma (&str) == (int) s7_FAIL)
   3640         {
   3641           s7_SET_INSN_ERROR (NULL);
   3642           if (*str != ']')
   3643             {
   3644               s7_inst.error = _("missing ]");
   3645               return;
   3646             }
   3647           str++;
   3648         }
   3649       /* cache op, [rA, simm15]  */
   3650       else
   3651         {
   3652           if (s7_exp_ldst_offset (&str, 0, _SIMM15) == (int) s7_FAIL)
   3653             {
   3654               return;
   3655             }
   3656 
   3657           s7_skip_whitespace (str);
   3658           if (*str++ != ']')
   3659             {
   3660               s7_inst.error = _("missing ]");
   3661               return;
   3662             }
   3663         }
   3664 
   3665       if (s7_end_of_line (str) == (int) s7_FAIL)
   3666 	return;
   3667     }
   3668   else
   3669     {
   3670       s7_inst.error = s7_BAD_ARGS;
   3671     }
   3672 }
   3673 
   3674 static void
   3675 s7_do_crdcrscrsimm5 (char *str)
   3676 {
   3677   char *strbak;
   3678 
   3679   strbak = str;
   3680   s7_skip_whitespace (str);
   3681 
   3682   if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL
   3683       || s7_skip_past_comma (&str) == (int) s7_FAIL
   3684       || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL
   3685       || s7_skip_past_comma (&str) == (int) s7_FAIL
   3686       || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL
   3687       || s7_skip_past_comma (&str) == (int) s7_FAIL)
   3688     {
   3689       str = strbak;
   3690       /* cop1 cop_code20.  */
   3691       if (s7_data_op2 (&str, 5, _IMM20) == (int) s7_FAIL)
   3692 	return;
   3693     }
   3694   else
   3695     {
   3696       if (s7_data_op2 (&str, 5, _IMM5) == (int) s7_FAIL)
   3697 	return;
   3698     }
   3699 
   3700   s7_end_of_line (str);
   3701 }
   3702 
   3703 /* Handle ldc/stc.  */
   3704 static void
   3705 s7_do_ldst_cop (char *str)
   3706 {
   3707   s7_skip_whitespace (str);
   3708 
   3709   if ((s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL)
   3710       || (s7_skip_past_comma (&str) == (int) s7_FAIL))
   3711     return;
   3712 
   3713   if (*str == '[')
   3714     {
   3715       str++;
   3716       s7_skip_whitespace (str);
   3717 
   3718       if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
   3719 	return;
   3720 
   3721       s7_skip_whitespace (str);
   3722 
   3723       if (*str++ != ']')
   3724         {
   3725           if (s7_exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) s7_FAIL)
   3726 	    return;
   3727 
   3728           s7_skip_whitespace (str);
   3729           if (*str++ != ']')
   3730             {
   3731               s7_inst.error = _("missing ]");
   3732               return;
   3733             }
   3734         }
   3735 
   3736       s7_end_of_line (str);
   3737     }
   3738   else
   3739     s7_inst.error = s7_BAD_ARGS;
   3740 }
   3741 
   3742 static void
   3743 s7_do16_ldst_insn (char *str)
   3744 {
   3745   s7_skip_whitespace (str);
   3746 
   3747   if ((s7_reglow_required_here (&str, 8) == (int) s7_FAIL) || (s7_skip_past_comma (&str) == (int) s7_FAIL))
   3748     return;
   3749 
   3750   if (*str == '[')
   3751     {
   3752       int reg;
   3753 
   3754       str++;
   3755       s7_skip_whitespace (str);
   3756 
   3757       if ((reg = s7_reglow_required_here (&str, 4)) == (int) s7_FAIL)
   3758 	return;
   3759 
   3760       s7_skip_whitespace (str);
   3761       if (*str++ == ']')
   3762         {
   3763           if (s7_end_of_line (str) == (int) s7_FAIL)
   3764 	    return;
   3765           else
   3766             {
   3767               s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
   3768                               | (((s7_inst.instruction >> 4) & 0xf) << 15);
   3769 	      s7_inst.relax_size = 4;
   3770             }
   3771         }
   3772       else
   3773         {
   3774           s7_inst.error = _("missing ]");
   3775         }
   3776     }
   3777   else
   3778     {
   3779       s7_inst.error = s7_BAD_ARGS;
   3780     }
   3781 }
   3782 
   3783 /* Handle lbup!/lhp!/ldiu!/lwp!/sbp!/shp!/swp!.  */
   3784 
   3785 static void
   3786 s7_do16_ldst_imm_insn (char *str)
   3787 {
   3788   char data_exp[s7_MAX_LITERAL_POOL_SIZE];
   3789   int reg_rd;
   3790   char *dataptr = NULL, *pp = NULL;
   3791   int cnt = 0;
   3792   int assign_data = (int) s7_FAIL;
   3793   unsigned int ldst_func;
   3794 
   3795   s7_skip_whitespace (str);
   3796 
   3797   if (((reg_rd = s7_reglow_required_here (&str, 8)) == (int) s7_FAIL)
   3798       || (s7_skip_past_comma (&str) == (int) s7_FAIL))
   3799     return;
   3800 
   3801   s7_skip_whitespace (str);
   3802   dataptr = str;
   3803 
   3804   while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= s7_MAX_LITERAL_POOL_SIZE))
   3805     {
   3806       data_exp[cnt] = *dataptr;
   3807       dataptr++;
   3808       cnt++;
   3809     }
   3810 
   3811   data_exp[cnt] = '\0';
   3812   pp = &data_exp[0];
   3813 
   3814   str = dataptr;
   3815 
   3816   ldst_func = s7_inst.instruction & LDST16_RI_MASK;
   3817   if (ldst_func == N16_LIU)
   3818     assign_data = s7_exp_ldst_offset (&pp, 0, _IMM8);
   3819   else if (ldst_func == N16_LHP || ldst_func == N16_SHP)
   3820     assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_1);
   3821   else if (ldst_func == N16_LWP || ldst_func == N16_SWP)
   3822     assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_2);
   3823   else
   3824     assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5);
   3825 
   3826   if ((assign_data == (int) s7_FAIL) || (s7_end_of_line (pp) == (int) s7_FAIL))
   3827     return;
   3828   else
   3829     {
   3830       if ((s7_inst.instruction & 0x7000) == N16_LIU)
   3831         {
   3832           s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20
   3833                           | ((s7_inst.instruction & 0xff) << 1);
   3834         }
   3835       else if (((s7_inst.instruction & 0x7007) == N16_LHP)
   3836                || ((s7_inst.instruction & 0x7007) == N16_SHP))
   3837         {
   3838           s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15
   3839                           | (((s7_inst.instruction >> 3) & 0x1f) << 1);
   3840         }
   3841       else if (((s7_inst.instruction & 0x7007) == N16_LWP)
   3842                || ((s7_inst.instruction & 0x7007) == N16_SWP))
   3843         {
   3844           s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15
   3845                           | (((s7_inst.instruction >> 3) & 0x1f) << 2);
   3846         }
   3847       else if (((s7_inst.instruction & 0x7007) == N16_LBUP)
   3848                || ((s7_inst.instruction & 0x7007) == N16_SBP))
   3849         {
   3850           s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15
   3851                           | (((s7_inst.instruction >> 3) & 0x1f));
   3852         }
   3853 
   3854       s7_inst.relax_size = 4;
   3855     }
   3856 }
   3857 
   3858 static void
   3859 s7_do16_push_pop (char *str)
   3860 {
   3861   int reg_rd;
   3862   int H_bit_mask = 0;
   3863 
   3864   s7_skip_whitespace (str);
   3865   if (((reg_rd = s7_reg_required_here (&str, 8, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
   3866       || (s7_skip_past_comma (&str) == (int) s7_FAIL))
   3867     return;
   3868 
   3869   if (reg_rd >= 16)
   3870     H_bit_mask = 1;
   3871 
   3872   /* s7_reg_required_here will change bit 12 of opcode, so we must restore bit 12.  */
   3873   s7_inst.instruction &= ~(1 << 12);
   3874 
   3875   s7_inst.instruction |= H_bit_mask << 7;
   3876 
   3877   if (*str == '[')
   3878     {
   3879       int reg;
   3880 
   3881       str++;
   3882       s7_skip_whitespace (str);
   3883       if ((reg = s7_reg_required_here (&str, 4, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
   3884 	return;
   3885       else if (reg > 7)
   3886         {
   3887           if (!s7_inst.error)
   3888 	    s7_inst.error = _("base register nums are over 3 bit");
   3889 
   3890           return;
   3891         }
   3892 
   3893       s7_skip_whitespace (str);
   3894       if ((*str++ != ']') || (s7_end_of_line (str) == (int) s7_FAIL))
   3895         {
   3896           if (!s7_inst.error)
   3897 	    s7_inst.error = _("missing ]");
   3898 
   3899           return;
   3900         }
   3901 
   3902       /* pop! */
   3903       if ((s7_inst.instruction & 0xf) == 0xa)
   3904         {
   3905           if (H_bit_mask)
   3906             {
   3907               s7_inst.relax_inst |= ((((s7_inst.instruction >> 8) & 0xf) | 0x10) << 20)
   3908                                   | (((s7_inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
   3909             }
   3910           else
   3911             {
   3912               s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
   3913                                   | (((s7_inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
   3914             }
   3915         }
   3916       /* push! */
   3917       else
   3918         {
   3919           if (H_bit_mask)
   3920             {
   3921               s7_inst.relax_inst |= ((((s7_inst.instruction >> 8) & 0xf) | 0x10) << 20)
   3922                                   | (((s7_inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
   3923             }
   3924           else
   3925             {
   3926               s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
   3927                                   | (((s7_inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
   3928             }
   3929         }
   3930       s7_inst.relax_size = 4;
   3931     }
   3932   else
   3933     {
   3934       s7_inst.error = s7_BAD_ARGS;
   3935     }
   3936 }
   3937 
   3938 /* Handle lcb/lcw/lce/scb/scw/sce.  */
   3939 static void
   3940 s7_do_ldst_unalign (char *str)
   3941 {
   3942   int conflict_reg;
   3943 
   3944   if (s7_university_version == 1)
   3945     {
   3946       s7_inst.error = s7_ERR_FOR_SCORE5U_ATOMIC;
   3947       return;
   3948     }
   3949 
   3950   s7_skip_whitespace (str);
   3951 
   3952   /* lcb/scb [rA]+.  */
   3953   if (*str == '[')
   3954     {
   3955       str++;
   3956       s7_skip_whitespace (str);
   3957 
   3958       if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
   3959 	return;
   3960 
   3961       if (*str++ == ']')
   3962         {
   3963           if (*str++ != '+')
   3964             {
   3965               s7_inst.error = _("missing +");
   3966               return;
   3967             }
   3968         }
   3969       else
   3970         {
   3971           s7_inst.error = _("missing ]");
   3972           return;
   3973         }
   3974 
   3975       if (s7_end_of_line (str) == (int) s7_FAIL)
   3976 	return;
   3977     }
   3978   /* lcw/lce/scb/sce rD, [rA]+.  */
   3979   else
   3980     {
   3981       if (((conflict_reg = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
   3982           || (s7_skip_past_comma (&str) == (int) s7_FAIL))
   3983         {
   3984           return;
   3985         }
   3986 
   3987       s7_skip_whitespace (str);
   3988       if (*str++ == '[')
   3989         {
   3990           int reg;
   3991 
   3992           s7_skip_whitespace (str);
   3993           if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
   3994             {
   3995               return;
   3996             }
   3997 
   3998           /* Conflicts can occur on stores as well as loads.  */
   3999           conflict_reg = (conflict_reg == reg);
   4000           s7_skip_whitespace (str);
   4001           if (*str++ == ']')
   4002             {
   4003               unsigned int ldst_func = s7_inst.instruction & LDST_UNALIGN_MASK;
   4004 
   4005               if (*str++ == '+')
   4006                 {
   4007                   if (conflict_reg)
   4008                     {
   4009                       as_warn (_("%s register same as write-back base"),
   4010                                ((ldst_func & UA_LCE) || (ldst_func & UA_LCW)
   4011                                 ? _("destination") : _("source")));
   4012                     }
   4013                 }
   4014               else
   4015                 {
   4016                   s7_inst.error = _("missing +");
   4017                   return;
   4018                 }
   4019 
   4020               if (s7_end_of_line (str) == (int) s7_FAIL)
   4021 		return;
   4022             }
   4023           else
   4024             {
   4025               s7_inst.error = _("missing ]");
   4026               return;
   4027             }
   4028         }
   4029       else
   4030         {
   4031           s7_inst.error = s7_BAD_ARGS;
   4032           return;
   4033         }
   4034     }
   4035 }
   4036 
   4037 /* Handle alw/asw.  */
   4038 
   4039 static void
   4040 s7_do_ldst_atomic (char *str)
   4041 {
   4042   if (s7_university_version == 1)
   4043     {
   4044       s7_inst.error = s7_ERR_FOR_SCORE5U_ATOMIC;
   4045       return;
   4046     }
   4047 
   4048   s7_skip_whitespace (str);
   4049 
   4050   if ((s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
   4051       || (s7_skip_past_comma (&str) == (int) s7_FAIL))
   4052     {
   4053       return;
   4054     }
   4055   else
   4056     {
   4057 
   4058       s7_skip_whitespace (str);
   4059       if (*str++ == '[')
   4060         {
   4061           int reg;
   4062 
   4063           s7_skip_whitespace (str);
   4064           if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
   4065             {
   4066               return;
   4067             }
   4068 
   4069           s7_skip_whitespace (str);
   4070           if (*str++ != ']')
   4071             {
   4072               s7_inst.error = _("missing ]");
   4073               return;
   4074             }
   4075 
   4076           s7_end_of_line (str);
   4077         }
   4078       else
   4079 	s7_inst.error = s7_BAD_ARGS;
   4080     }
   4081 }
   4082 
   4083 static void
   4084 s7_build_relax_frag (struct s7_score_it fix_insts[s7_RELAX_INST_NUM],
   4085 		     int fix_num ATTRIBUTE_UNUSED,
   4086 		     struct s7_score_it var_insts[s7_RELAX_INST_NUM], int var_num,
   4087 		     symbolS *add_symbol)
   4088 {
   4089   int i;
   4090   char *p;
   4091   fixS *fixp = NULL;
   4092   fixS *cur_fixp = NULL;
   4093   long where;
   4094   struct s7_score_it inst_main;
   4095 
   4096   memcpy (&inst_main, &fix_insts[0], sizeof (struct s7_score_it));
   4097 
   4098   /* Adjust instruction opcode and to be relaxed instruction opcode.  */
   4099   inst_main.instruction = s7_adjust_paritybit (inst_main.instruction, s7_GET_INSN_CLASS (inst_main.type));
   4100   inst_main.type = Insn_PIC;
   4101 
   4102   for (i = 0; i < var_num; i++)
   4103     {
   4104       inst_main.relax_size += var_insts[i].size;
   4105       var_insts[i].instruction = s7_adjust_paritybit (var_insts[i].instruction,
   4106                                                    s7_GET_INSN_CLASS (var_insts[i].type));
   4107     }
   4108 
   4109   /* Check data dependency.  */
   4110   s7_handle_dependency (&inst_main);
   4111 
   4112   /* Start a new frag if frag_now is not empty.  */
   4113   if (frag_now_fix () != 0)
   4114     {
   4115       if (!frag_now->tc_frag_data.is_insn)
   4116 	{
   4117           frag_wane (frag_now);
   4118 	}
   4119       frag_new (0);
   4120     }
   4121   frag_grow (20);
   4122 
   4123   /* Write fr_fix part.  */
   4124   p = frag_more (inst_main.size);
   4125   s7_number_to_chars (p, inst_main.instruction, inst_main.size);
   4126 
   4127   if (inst_main.reloc.type != BFD_RELOC_NONE)
   4128     fixp = s7_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
   4129 			  &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
   4130 
   4131   frag_now->tc_frag_data.fixp = fixp;
   4132   cur_fixp = frag_now->tc_frag_data.fixp;
   4133 
   4134 #ifdef OBJ_ELF
   4135   dwarf2_emit_insn (inst_main.size);
   4136 #endif
   4137 
   4138   where = p - frag_now->fr_literal + inst_main.size;
   4139   for (i = 0; i < var_num; i++)
   4140     {
   4141       if (i > 0)
   4142         where += var_insts[i - 1].size;
   4143 
   4144       if (var_insts[i].reloc.type != BFD_RELOC_NONE)
   4145         {
   4146           fixp = s7_fix_new_score (frag_now, where, var_insts[i].size,
   4147                                 &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel,
   4148                                 var_insts[i].reloc.type);
   4149           if (fixp)
   4150             {
   4151               if (cur_fixp)
   4152                 {
   4153                   cur_fixp->fx_next = fixp;
   4154                   cur_fixp = cur_fixp->fx_next;
   4155                 }
   4156               else
   4157                 {
   4158                   frag_now->tc_frag_data.fixp = fixp;
   4159                   cur_fixp = frag_now->tc_frag_data.fixp;
   4160                 }
   4161 	    }
   4162         }
   4163     }
   4164 
   4165   p = frag_var (rs_machine_dependent, inst_main.relax_size + s7_RELAX_PAD_BYTE, 0,
   4166                 s7_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type,
   4167                 0, inst_main.size, 0), add_symbol, 0, NULL);
   4168 
   4169   /* Write fr_var part.
   4170      no calling s7_gen_insn_frag, no fixS will be generated.  */
   4171   for (i = 0; i < var_num; i++)
   4172     {
   4173       s7_number_to_chars (p, var_insts[i].instruction, var_insts[i].size);
   4174       p += var_insts[i].size;
   4175     }
   4176   /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
   4177   s7_inst.bwarn = -1;
   4178 }
   4179 
   4180 /* Build a relax frag for la instruction when generating s7_PIC,
   4181    external symbol first and local symbol second.  */
   4182 
   4183 static void
   4184 s7_build_la_pic (int reg_rd, expressionS exp)
   4185 {
   4186   symbolS *add_symbol = exp.X_add_symbol;
   4187   offsetT add_number = exp.X_add_number;
   4188   struct s7_score_it fix_insts[s7_RELAX_INST_NUM];
   4189   struct s7_score_it var_insts[s7_RELAX_INST_NUM];
   4190   int fix_num = 0;
   4191   int var_num = 0;
   4192   char tmp[s7_MAX_LITERAL_POOL_SIZE];
   4193   int r1_bak;
   4194 
   4195   r1_bak = s7_nor1;
   4196   s7_nor1 = 0;
   4197 
   4198   if (add_number == 0)
   4199     {
   4200       fix_num = 1;
   4201       var_num = 2;
   4202 
   4203       /* For an external symbol, only one insn is generated;
   4204          For a local symbol, two insns are generated.  */
   4205       /* Fix part
   4206          For an external symbol: lw rD, <sym>($gp)
   4207                                  (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15)  */
   4208       sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
   4209       if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
   4210 	return;
   4211 
   4212       if (reg_rd == s7_PIC_CALL_REG)
   4213         s7_inst.reloc.type = BFD_RELOC_SCORE_CALL15;
   4214       memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
   4215 
   4216       /* Var part
   4217 	 For a local symbol :
   4218          lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)
   4219 	 addi rD, <sym>       (BFD_RELOC_GOT_LO16) */
   4220       s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
   4221       memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
   4222       sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, add_symbol->bsym->name);
   4223       if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
   4224 	return;
   4225 
   4226       memcpy (&var_insts[1], &s7_inst, sizeof (struct s7_score_it));
   4227       s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
   4228     }
   4229   else if (add_number >= -0x8000 && add_number <= 0x7fff)
   4230     {
   4231       /* Insn 1: lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)  */
   4232       sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
   4233       if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
   4234 	return;
   4235 
   4236       /* Insn 2  */
   4237       fix_num = 1;
   4238       var_num = 1;
   4239       /* Fix part
   4240          For an external symbol: addi rD, <constant> */
   4241       sprintf (tmp, "addi r%d, %d", reg_rd, (int) add_number);
   4242       if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
   4243 	return;
   4244 
   4245       memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
   4246 
   4247       /* Var part
   4248  	 For a local symbol: addi rD, <sym>+<constant>    (BFD_RELOC_GOT_LO16)  */
   4249       sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd, add_symbol->bsym->name, (int) add_number);
   4250       if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
   4251 	return;
   4252 
   4253       memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
   4254       s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
   4255     }
   4256   else
   4257     {
   4258       int hi = (add_number >> 16) & 0x0000FFFF;
   4259       int lo = add_number & 0x0000FFFF;
   4260 
   4261       /* Insn 1: lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)  */
   4262       sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
   4263       if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
   4264 	return;
   4265 
   4266       /* Insn 2  */
   4267       fix_num = 1;
   4268       var_num = 1;
   4269       /* Fix part
   4270 	 For an external symbol: ldis r1, HI%<constant>  */
   4271       sprintf (tmp, "ldis r1, %d", hi);
   4272       if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
   4273 	return;
   4274 
   4275       memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
   4276 
   4277       /* Var part
   4278 	 For a local symbol: ldis r1, HI%<constant>
   4279          but, if lo is outof 16 bit, make hi plus 1  */
   4280       if ((lo < -0x8000) || (lo > 0x7fff))
   4281 	{
   4282 	  hi += 1;
   4283 	}
   4284       sprintf (tmp, "ldis_pic r1, %d", hi);
   4285       if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
   4286 	return;
   4287 
   4288       memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
   4289       s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
   4290 
   4291       /* Insn 3  */
   4292       fix_num = 1;
   4293       var_num = 1;
   4294       /* Fix part
   4295 	 For an external symbol: ori r1, LO%<constant>  */
   4296       sprintf (tmp, "ori r1, %d", lo);
   4297       if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
   4298 	return;
   4299 
   4300       memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
   4301 
   4302       /* Var part
   4303   	 For a local symbol: addi r1, <sym>+LO%<constant>    (BFD_RELOC_GOT_LO16)  */
   4304       sprintf (tmp, "addi_u_pic r1, %s + %d", add_symbol->bsym->name, lo);
   4305       if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
   4306 	return;
   4307 
   4308       memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
   4309       s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
   4310 
   4311       /* Insn 4: add rD, rD, r1  */
   4312       sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd);
   4313       if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
   4314 	return;
   4315 
   4316      /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
   4317      s7_inst.bwarn = -1;
   4318     }
   4319 
   4320   s7_nor1 = r1_bak;
   4321 }
   4322 
   4323 /* Handle la.  */
   4324 
   4325 static void
   4326 s7_do_macro_la_rdi32 (char *str)
   4327 {
   4328   int reg_rd;
   4329 
   4330   s7_skip_whitespace (str);
   4331   if ((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
   4332       || s7_skip_past_comma (&str) == (int) s7_FAIL)
   4333     {
   4334       return;
   4335     }
   4336   else
   4337     {
   4338       char append_str[s7_MAX_LITERAL_POOL_SIZE];
   4339       char *keep_data = str;
   4340 
   4341       /* Check immediate value.  */
   4342       if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
   4343         {
   4344           s7_inst.error = _("expression error");
   4345           return;
   4346         }
   4347       else if ((s7_inst.reloc.exp.X_add_symbol == NULL)
   4348                && (s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _IMM32, 0) == (int) s7_FAIL))
   4349         {
   4350           s7_inst.error = _("value not in range [0, 0xffffffff]");
   4351           return;
   4352         }
   4353 
   4354       /* Reset str.  */
   4355       str = keep_data;
   4356 
   4357       /* la rd, simm16.  */
   4358       if (s7_data_op2 (&str, 1, _SIMM16_LA) != (int) s7_FAIL)
   4359         {
   4360           s7_end_of_line (str);
   4361           return;
   4362         }
   4363       /* la rd, imm32 or la rd, label.  */
   4364       else
   4365         {
   4366           s7_SET_INSN_ERROR (NULL);
   4367           str = keep_data;
   4368           if ((s7_data_op2 (&str, 1, _VALUE_HI16) == (int) s7_FAIL)
   4369               || (s7_end_of_line (str) == (int) s7_FAIL))
   4370             {
   4371               return;
   4372             }
   4373           else
   4374             {
   4375               if ((s7_score_pic == s7_NO_PIC) || (!s7_inst.reloc.exp.X_add_symbol))
   4376                 {
   4377                   sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
   4378                   if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
   4379 		    return;
   4380 
   4381                   sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
   4382                   if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
   4383 		    return;
   4384 		}
   4385 	      else
   4386 		{
   4387 		  gas_assert (s7_inst.reloc.exp.X_add_symbol);
   4388 		  s7_build_la_pic (reg_rd, s7_inst.reloc.exp);
   4389 		}
   4390 
   4391               /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
   4392               s7_inst.bwarn = -1;
   4393             }
   4394         }
   4395     }
   4396 }
   4397 
   4398 /* Handle li.  */
   4399 
   4400 static void
   4401 s7_do_macro_li_rdi32 (char *str)
   4402 {
   4403   int reg_rd;
   4404 
   4405   s7_skip_whitespace (str);
   4406   if ((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
   4407       || s7_skip_past_comma (&str) == (int) s7_FAIL)
   4408     {
   4409       return;
   4410     }
   4411   else
   4412     {
   4413       char *keep_data = str;
   4414 
   4415       /* Check immediate value.  */
   4416       if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
   4417         {
   4418           s7_inst.error = _("expression error");
   4419           return;
   4420         }
   4421       else if (!(s7_inst.reloc.exp.X_add_number >= -0xffffffffLL
   4422                  && s7_inst.reloc.exp.X_add_number <= 0xffffffffLL))
   4423         {
   4424           s7_inst.error = _("value not in range [-0xffffffff, 0xffffffff]");
   4425           return;
   4426         }
   4427 
   4428       /* Reset str.  */
   4429       str = keep_data;
   4430 
   4431       /* li rd, simm16.  */
   4432       if (s7_data_op2 (&str, 1, _SIMM16_LA) != (int) s7_FAIL)
   4433         {
   4434           s7_end_of_line (str);
   4435           return;
   4436         }
   4437       /* li rd, imm32.  */
   4438       else
   4439         {
   4440           char append_str[s7_MAX_LITERAL_POOL_SIZE];
   4441 
   4442           str = keep_data;
   4443 
   4444           if ((s7_data_op2 (&str, 1, _VALUE_HI16) == (int) s7_FAIL)
   4445               || (s7_end_of_line (str) == (int) s7_FAIL))
   4446             {
   4447               return;
   4448             }
   4449           else if (s7_inst.reloc.exp.X_add_symbol)
   4450             {
   4451               s7_inst.error = _("li rd label isn't correct instruction form");
   4452               return;
   4453             }
   4454           else
   4455             {
   4456               sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
   4457 
   4458               if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
   4459 		return;
   4460               else
   4461                 {
   4462                   sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
   4463                   if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
   4464 		    return;
   4465 
   4466                   /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
   4467                   s7_inst.bwarn = -1;
   4468                 }
   4469             }
   4470         }
   4471     }
   4472 }
   4473 
   4474 /* Handle mul/mulu/div/divu/rem/remu.  */
   4475 
   4476 static void
   4477 s7_do_macro_mul_rdrsrs (char *str)
   4478 {
   4479   int reg_rd;
   4480   int reg_rs1;
   4481   int reg_rs2;
   4482   char *backupstr;
   4483   char append_str[s7_MAX_LITERAL_POOL_SIZE];
   4484 
   4485   if (s7_university_version == 1)
   4486     as_warn ("%s", s7_ERR_FOR_SCORE5U_MUL_DIV);
   4487 
   4488   strcpy (append_str, str);
   4489   backupstr = append_str;
   4490   s7_skip_whitespace (backupstr);
   4491   if (((reg_rd = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
   4492       || (s7_skip_past_comma (&backupstr) == (int) s7_FAIL)
   4493       || ((reg_rs1 = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL))
   4494     {
   4495       s7_inst.error = s7_BAD_ARGS;
   4496       return;
   4497     }
   4498 
   4499   if (s7_skip_past_comma (&backupstr) == (int) s7_FAIL)
   4500     {
   4501       /* rem/remu rA, rB is error format.  */
   4502       if (strcmp (s7_inst.name, "rem") == 0 || strcmp (s7_inst.name, "remu") == 0)
   4503         {
   4504           s7_SET_INSN_ERROR (s7_BAD_ARGS);
   4505         }
   4506       else
   4507         {
   4508           s7_SET_INSN_ERROR (NULL);
   4509           s7_do_rsrs (str);
   4510         }
   4511       return;
   4512     }
   4513   else
   4514     {
   4515       s7_SET_INSN_ERROR (NULL);
   4516       if (((reg_rs2 = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
   4517           || (s7_end_of_line (backupstr) == (int) s7_FAIL))
   4518         {
   4519           return;
   4520         }
   4521       else
   4522         {
   4523           char append_str1[s7_MAX_LITERAL_POOL_SIZE];
   4524 
   4525           if (strcmp (s7_inst.name, "rem") == 0)
   4526             {
   4527               sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2);
   4528               sprintf (append_str1, "mfceh  r%d", reg_rd);
   4529             }
   4530           else if (strcmp (s7_inst.name, "remu") == 0)
   4531             {
   4532               sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2);
   4533               sprintf (append_str1, "mfceh  r%d", reg_rd);
   4534             }
   4535           else
   4536             {
   4537               sprintf (append_str, "%s r%d, r%d", s7_inst.name, reg_rs1, reg_rs2);
   4538               sprintf (append_str1, "mfcel  r%d", reg_rd);
   4539             }
   4540 
   4541           /* Output mul/mulu or div/divu or rem/remu.  */
   4542           if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
   4543 	    return;
   4544 
   4545           /* Output mfcel or mfceh.  */
   4546           if (s7_append_insn (append_str1, TRUE) == (int) s7_FAIL)
   4547 	    return;
   4548 
   4549           /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
   4550           s7_inst.bwarn = -1;
   4551         }
   4552     }
   4553 }
   4554 
   4555 static void
   4556 s7_exp_macro_ldst_abs (char *str)
   4557 {
   4558   int reg_rd;
   4559   char *backupstr, *tmp;
   4560   char append_str[s7_MAX_LITERAL_POOL_SIZE];
   4561   char verifystr[s7_MAX_LITERAL_POOL_SIZE];
   4562   struct s7_score_it inst_backup;
   4563   int r1_bak = 0;
   4564 
   4565   r1_bak = s7_nor1;
   4566   s7_nor1 = 0;
   4567   memcpy (&inst_backup, &s7_inst, sizeof (struct s7_score_it));
   4568 
   4569   strcpy (verifystr, str);
   4570   backupstr = verifystr;
   4571   s7_skip_whitespace (backupstr);
   4572   if ((reg_rd = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
   4573     return;
   4574 
   4575   tmp = backupstr;
   4576   if (s7_skip_past_comma (&backupstr) == (int) s7_FAIL)
   4577     return;
   4578 
   4579   backupstr = tmp;
   4580   sprintf (append_str, "li r1  %s", backupstr);
   4581   s7_append_insn (append_str, TRUE);
   4582 
   4583   memcpy (&s7_inst, &inst_backup, sizeof (struct s7_score_it));
   4584   sprintf (append_str, " r%d, [r1,0]", reg_rd);
   4585   s7_do_ldst_insn (append_str);
   4586 
   4587   s7_nor1 = r1_bak;
   4588 }
   4589 
   4590 static int
   4591 s7_nopic_need_relax (symbolS * sym, int before_relaxing)
   4592 {
   4593   if (sym == NULL)
   4594     return 0;
   4595   else if (s7_USE_GLOBAL_POINTER_OPT && s7_g_switch_value > 0)
   4596     {
   4597       const char *symname;
   4598       const char *segname;
   4599 
   4600       /* Find out whether this symbol can be referenced off the $gp
   4601          register.  It can be if it is smaller than the -G size or if
   4602          it is in the .sdata or .sbss section.  Certain symbols can
   4603          not be referenced off the $gp, although it appears as though
   4604          they can.  */
   4605       symname = S_GET_NAME (sym);
   4606       if (symname != NULL
   4607           && (strcmp (symname, "eprol") == 0
   4608               || strcmp (symname, "etext") == 0
   4609               || strcmp (symname, "_gp") == 0
   4610               || strcmp (symname, "edata") == 0
   4611               || strcmp (symname, "_fbss") == 0
   4612               || strcmp (symname, "_fdata") == 0
   4613               || strcmp (symname, "_ftext") == 0
   4614               || strcmp (symname, "end") == 0
   4615               || strcmp (symname, GP_DISP_LABEL) == 0))
   4616         {
   4617           return 1;
   4618         }
   4619       else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0
   4620       /* We must defer this decision until after the whole file has been read,
   4621          since there might be a .extern after the first use of this symbol.  */
   4622                || (before_relaxing
   4623                    && S_GET_VALUE (sym) == 0)
   4624                || (S_GET_VALUE (sym) != 0
   4625                    && S_GET_VALUE (sym) <= s7_g_switch_value)))
   4626         {
   4627           return 0;
   4628         }
   4629 
   4630       segname = segment_name (S_GET_SEGMENT (sym));
   4631       return (strcmp (segname, ".sdata") != 0
   4632 	      && strcmp (segname, ".sbss") != 0
   4633 	      && strncmp (segname, ".sdata.", 7) != 0
   4634 	      && strncmp (segname, ".gnu.linkonce.s.", 16) != 0);
   4635     }
   4636   /* We are not optimizing for the $gp register.  */
   4637   else
   4638     return 1;
   4639 }
   4640 
   4641 /* Build a relax frag for lw/st instruction when generating s7_PIC,
   4642    external symbol first and local symbol second.  */
   4643 
   4644 static void
   4645 s7_build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name)
   4646 {
   4647   symbolS *add_symbol = exp.X_add_symbol;
   4648   int add_number = exp.X_add_number;
   4649   struct s7_score_it fix_insts[s7_RELAX_INST_NUM];
   4650   struct s7_score_it var_insts[s7_RELAX_INST_NUM];
   4651   int fix_num = 0;
   4652   int var_num = 0;
   4653   char tmp[s7_MAX_LITERAL_POOL_SIZE];
   4654   int r1_bak;
   4655 
   4656   r1_bak = s7_nor1;
   4657   s7_nor1 = 0;
   4658 
   4659   if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff))
   4660     {
   4661       fix_num = 1;
   4662       var_num = 2;
   4663 
   4664       /* For an external symbol, two insns are generated;
   4665          For a local symbol, three insns are generated.  */
   4666       /* Fix part
   4667          For an external symbol: lw rD, <sym>($gp)
   4668                                  (BFD_RELOC_SCORE_GOT15)  */
   4669       sprintf (tmp, "lw_pic r1, %s", add_symbol->bsym->name);
   4670       if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
   4671         return;
   4672 
   4673       memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
   4674 
   4675       /* Var part
   4676 	 For a local symbol :
   4677          lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)
   4678 	 addi rD, <sym>       (BFD_RELOC_GOT_LO16) */
   4679       s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
   4680       memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
   4681       sprintf (tmp, "addi_s_pic r1, %s", add_symbol->bsym->name);
   4682       if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
   4683         return;
   4684 
   4685       memcpy (&var_insts[1], &s7_inst, sizeof (struct s7_score_it));
   4686       s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
   4687 
   4688       /* Insn 2 or Insn 3: lw/st rD, [r1, constant]  */
   4689       sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number);
   4690       if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
   4691         return;
   4692 
   4693       /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
   4694       s7_inst.bwarn = -1;
   4695     }
   4696   else
   4697     {
   4698       s7_inst.error = _("PIC code offset overflow (max 16 signed bits)");
   4699       return;
   4700     }
   4701 
   4702   s7_nor1 = r1_bak;
   4703 }
   4704 
   4705 static void
   4706 s7_do_macro_ldst_label (char *str)
   4707 {
   4708   int i;
   4709   int ldst_gp_p = 0;
   4710   int reg_rd;
   4711   int r1_bak;
   4712   char *backup_str;
   4713   char *label_str;
   4714   char *absolute_value;
   4715   char append_str[3][s7_MAX_LITERAL_POOL_SIZE];
   4716   char verifystr[s7_MAX_LITERAL_POOL_SIZE];
   4717   struct s7_score_it inst_backup;
   4718   struct s7_score_it inst_expand[3];
   4719   struct s7_score_it inst_main;
   4720 
   4721   memcpy (&inst_backup, &s7_inst, sizeof (struct s7_score_it));
   4722   strcpy (verifystr, str);
   4723   backup_str = verifystr;
   4724 
   4725   s7_skip_whitespace (backup_str);
   4726   if ((reg_rd = s7_reg_required_here (&backup_str, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
   4727     return;
   4728 
   4729   if (s7_skip_past_comma (&backup_str) == (int) s7_FAIL)
   4730     return;
   4731 
   4732   label_str = backup_str;
   4733 
   4734   /* Ld/st rD, [rA, imm]      ld/st rD, [rA]+, imm      ld/st rD, [rA, imm]+.  */
   4735   if (*backup_str == '[')
   4736     {
   4737       s7_inst.type = Rd_rvalueRs_preSI12;
   4738       s7_do_ldst_insn (str);
   4739       return;
   4740     }
   4741 
   4742   /* Ld/st rD, imm.  */
   4743   absolute_value = backup_str;
   4744   s7_inst.type = Rd_rvalueRs_SI15;
   4745 
   4746   if (s7_my_get_expression (&s7_inst.reloc.exp, &backup_str) == (int) s7_FAIL)
   4747     {
   4748       s7_inst.error = _("expression error");
   4749       return;
   4750     }
   4751   else if ((s7_inst.reloc.exp.X_add_symbol == NULL)
   4752            && (s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _VALUE, 0) == (int) s7_FAIL))
   4753     {
   4754       s7_inst.error = _("value not in range [0, 0x7fffffff]");
   4755       return;
   4756     }
   4757   else if (s7_end_of_line (backup_str) == (int) s7_FAIL)
   4758     {
   4759       s7_inst.error = _("end on line error");
   4760       return;
   4761     }
   4762   else
   4763     {
   4764       if (s7_inst.reloc.exp.X_add_symbol == 0)
   4765         {
   4766           memcpy (&s7_inst, &inst_backup, sizeof (struct s7_score_it));
   4767           s7_exp_macro_ldst_abs (str);
   4768           return;
   4769         }
   4770     }
   4771 
   4772   /* Ld/st rD, label.  */
   4773   s7_inst.type = Rd_rvalueRs_SI15;
   4774   backup_str = absolute_value;
   4775   if ((s7_data_op2 (&backup_str, 1, _GP_IMM15) == (int) s7_FAIL)
   4776       || (s7_end_of_line (backup_str) == (int) s7_FAIL))
   4777     {
   4778       return;
   4779     }
   4780   else
   4781     {
   4782       if (s7_inst.reloc.exp.X_add_symbol == 0)
   4783         {
   4784           if (!s7_inst.error)
   4785 	    s7_inst.error = s7_BAD_ARGS;
   4786 
   4787           return;
   4788         }
   4789 
   4790       if (s7_score_pic == s7_PIC)
   4791         {
   4792           int ldst_idx = 0;
   4793           ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
   4794           s7_build_lwst_pic (reg_rd, s7_inst.reloc.exp,
   4795                              s7_score_ldst_insns[ldst_idx * 3 + 0].template_name);
   4796           return;
   4797         }
   4798       else
   4799 	{
   4800           if ((s7_inst.reloc.exp.X_add_number <= 0x3fff)
   4801                && (s7_inst.reloc.exp.X_add_number >= -0x4000)
   4802                && (!s7_nopic_need_relax (s7_inst.reloc.exp.X_add_symbol, 1)))
   4803 	    {
   4804               int ldst_idx = 0;
   4805 
   4806               /* Assign the real opcode.  */
   4807               ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
   4808               s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
   4809               s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + 0].value;
   4810               s7_inst.instruction |= reg_rd << 20;
   4811               s7_inst.instruction |= s7_GP << 15;
   4812               s7_inst.relax_inst = 0x8000;
   4813               s7_inst.relax_size = 0;
   4814               ldst_gp_p = 1;
   4815 	    }
   4816 	}
   4817     }
   4818 
   4819   /* Backup s7_inst.  */
   4820   memcpy (&inst_main, &s7_inst, sizeof (struct s7_score_it));
   4821   r1_bak = s7_nor1;
   4822   s7_nor1 = 0;
   4823 
   4824   /* Determine which instructions should be output.  */
   4825   sprintf (append_str[0], "ld_i32hi r1, %s", label_str);
   4826   sprintf (append_str[1], "ld_i32lo r1, %s", label_str);
   4827   sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd);
   4828 
   4829   /* Generate three instructions.
   4830      la r1, label
   4831      ld/st rd, [r1, 0]  */
   4832   for (i = 0; i < 3; i++)
   4833     {
   4834       if (s7_append_insn (append_str[i], FALSE) == (int) s7_FAIL)
   4835 	return;
   4836 
   4837       memcpy (&inst_expand[i], &s7_inst, sizeof (struct s7_score_it));
   4838     }
   4839 
   4840   if (ldst_gp_p)
   4841     {
   4842       char *p;
   4843 
   4844       /* Adjust instruction opcode and to be relaxed instruction opcode.  */
   4845       inst_main.instruction = s7_adjust_paritybit (inst_main.instruction, s7_GET_INSN_CLASS (inst_main.type));
   4846       inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size;
   4847       inst_main.type = Insn_GP;
   4848 
   4849       for (i = 0; i < 3; i++)
   4850 	inst_expand[i].instruction = s7_adjust_paritybit (inst_expand[i].instruction
   4851 						       , s7_GET_INSN_CLASS (inst_expand[i].type));
   4852 
   4853       /* Check data dependency.  */
   4854       s7_handle_dependency (&inst_main);
   4855 
   4856       /* Start a new frag if frag_now is not empty.  */
   4857       if (frag_now_fix () != 0)
   4858         {
   4859           if (!frag_now->tc_frag_data.is_insn)
   4860 	    frag_wane (frag_now);
   4861 
   4862           frag_new (0);
   4863         }
   4864       frag_grow (20);
   4865 
   4866       /* Write fr_fix part.  */
   4867       p = frag_more (inst_main.size);
   4868       s7_number_to_chars (p, inst_main.instruction, inst_main.size);
   4869 
   4870       if (inst_main.reloc.type != BFD_RELOC_NONE)
   4871         {
   4872           s7_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
   4873                          &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
   4874         }
   4875 
   4876 #ifdef OBJ_ELF
   4877       dwarf2_emit_insn (inst_main.size);
   4878 #endif
   4879 
   4880       /* s7_GP instruction can not do optimization, only can do relax between
   4881          1 instruction and 3 instructions.  */
   4882       p = frag_var (rs_machine_dependent, inst_main.relax_size + s7_RELAX_PAD_BYTE, 0,
   4883                     s7_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0),
   4884                     inst_main.reloc.exp.X_add_symbol, 0, NULL);
   4885 
   4886       /* Write fr_var part.
   4887          no calling s7_gen_insn_frag, no fixS will be generated.  */
   4888       s7_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
   4889       p += inst_expand[0].size;
   4890       s7_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
   4891       p += inst_expand[1].size;
   4892       s7_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size);
   4893     }
   4894   else
   4895     {
   4896       s7_gen_insn_frag (&inst_expand[0], NULL);
   4897       s7_gen_insn_frag (&inst_expand[1], NULL);
   4898       s7_gen_insn_frag (&inst_expand[2], NULL);
   4899     }
   4900   s7_nor1 = r1_bak;
   4901 
   4902   /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
   4903   s7_inst.bwarn = -1;
   4904 }
   4905 
   4906 static void
   4907 s7_do_lw_pic (char *str)
   4908 {
   4909   int reg_rd;
   4910 
   4911   s7_skip_whitespace (str);
   4912   if (((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
   4913       || (s7_skip_past_comma (&str) == (int) s7_FAIL)
   4914       || (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
   4915       || (s7_end_of_line (str) == (int) s7_FAIL))
   4916     {
   4917       return;
   4918     }
   4919   else
   4920     {
   4921       if (s7_inst.reloc.exp.X_add_symbol == 0)
   4922         {
   4923           if (!s7_inst.error)
   4924 	    s7_inst.error = s7_BAD_ARGS;
   4925 
   4926           return;
   4927         }
   4928 
   4929       s7_inst.instruction |= s7_GP << 15;
   4930       s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
   4931     }
   4932 }
   4933 
   4934 static void
   4935 s7_do_empty (char *str)
   4936 {
   4937   str = str;
   4938   if (s7_university_version == 1)
   4939     {
   4940       if (((s7_inst.instruction & 0x3e0003ff) == 0x0c000004)
   4941           || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000024)
   4942           || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000044)
   4943           || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000064))
   4944         {
   4945           s7_inst.error = s7_ERR_FOR_SCORE5U_MMU;
   4946           return;
   4947         }
   4948     }
   4949   if (s7_end_of_line (str) == (int) s7_FAIL)
   4950     return;
   4951 
   4952   if (s7_inst.relax_inst != 0x8000)
   4953     {
   4954       if (s7_inst.type == NO_OPD)
   4955         {
   4956           s7_inst.relax_size = 2;
   4957         }
   4958       else
   4959         {
   4960           s7_inst.relax_size = 4;
   4961         }
   4962     }
   4963 }
   4964 
   4965 static void
   4966 s7_do_jump (char *str)
   4967 {
   4968   char *save_in;
   4969 
   4970   s7_skip_whitespace (str);
   4971   if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
   4972       || s7_end_of_line (str) == (int) s7_FAIL)
   4973     return;
   4974 
   4975   if (s7_inst.reloc.exp.X_add_symbol == 0)
   4976     {
   4977       s7_inst.error = _("lacking label  ");
   4978       return;
   4979     }
   4980 
   4981   if (!(s7_inst.reloc.exp.X_add_number >= -16777216
   4982       && s7_inst.reloc.exp.X_add_number <= 16777215))
   4983     {
   4984       s7_inst.error = _("invalid constant: 25 bit expression not in range [-16777216, 16777215]");
   4985       return;
   4986     }
   4987 
   4988   save_in = input_line_pointer;
   4989   input_line_pointer = str;
   4990   s7_inst.reloc.type = BFD_RELOC_SCORE_JMP;
   4991   s7_inst.reloc.pc_rel = 1;
   4992   input_line_pointer = save_in;
   4993 }
   4994 
   4995 static void
   4996 s7_do16_jump (char *str)
   4997 {
   4998   s7_skip_whitespace (str);
   4999   if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
   5000       || s7_end_of_line (str) == (int) s7_FAIL)
   5001     {
   5002       return;
   5003     }
   5004   else if (s7_inst.reloc.exp.X_add_symbol == 0)
   5005     {
   5006       s7_inst.error = _("lacking label  ");
   5007       return;
   5008     }
   5009   else if (!(s7_inst.reloc.exp.X_add_number >= 0
   5010            && s7_inst.reloc.exp.X_add_number <= 4095))
   5011     {
   5012       s7_inst.error = _("invalid constant: 12 bit expression not in range [0, 4095]");
   5013       return;
   5014     }
   5015 
   5016   s7_inst.reloc.type = BFD_RELOC_SCORE16_JMP;
   5017   s7_inst.reloc.pc_rel = 1;
   5018 }
   5019 
   5020 static void
   5021 s7_do_branch (char *str)
   5022 {
   5023   unsigned long abs_value = 0;
   5024 
   5025   if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
   5026       || s7_end_of_line (str) == (int) s7_FAIL)
   5027     {
   5028       return;
   5029     }
   5030   else if (s7_inst.reloc.exp.X_add_symbol == 0)
   5031     {
   5032       s7_inst.error = _("lacking label  ");
   5033       return;
   5034     }
   5035   else if (!(s7_inst.reloc.exp.X_add_number >= -524288
   5036            && s7_inst.reloc.exp.X_add_number <= 524287))
   5037     {
   5038       s7_inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19");
   5039       return;
   5040     }
   5041 
   5042   s7_inst.reloc.type = BFD_RELOC_SCORE_BRANCH;
   5043   s7_inst.reloc.pc_rel = 1;
   5044 
   5045   /* Branch 32  offset field : 20 bit, 16 bit branch offset field : 8 bit.  */
   5046   s7_inst.instruction |= (s7_inst.reloc.exp.X_add_number & 0x3fe) | ((s7_inst.reloc.exp.X_add_number & 0xffc00) << 5);
   5047 
   5048   /* Compute 16 bit branch instruction.  */
   5049   if ((s7_inst.relax_inst != 0x8000) && (abs_value & 0xfffffe00) == 0)
   5050     {
   5051       s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 8);
   5052       s7_inst.relax_inst |= ((s7_inst.reloc.exp.X_add_number >> 1) & 0xff);
   5053       s7_inst.relax_size = 2;
   5054     }
   5055   else
   5056     {
   5057       s7_inst.relax_inst = 0x8000;
   5058     }
   5059 }
   5060 
   5061 static void
   5062 s7_do16_branch (char *str)
   5063 {
   5064   if ((s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
   5065       || s7_end_of_line (str) == (int) s7_FAIL))
   5066     {
   5067       ;
   5068     }
   5069   else if (s7_inst.reloc.exp.X_add_symbol == 0)
   5070     {
   5071       s7_inst.error = _("lacking label");
   5072     }
   5073   else if (!(s7_inst.reloc.exp.X_add_number >= -512
   5074            && s7_inst.reloc.exp.X_add_number <= 511))
   5075     {
   5076       s7_inst.error = _("invalid constant: 10 bit expression not in range [-2^9, 2^9-1]");
   5077     }
   5078   else
   5079     {
   5080       s7_inst.reloc.type = BFD_RELOC_SCORE16_BRANCH;
   5081       s7_inst.reloc.pc_rel = 1;
   5082       s7_inst.instruction |= ((s7_inst.reloc.exp.X_add_number >> 1) & 0xff);
   5083     }
   5084 }
   5085 
   5086 /* Iterate over the base tables to create the instruction patterns.  */
   5087 
   5088 static void
   5089 s7_build_score_ops_hsh (void)
   5090 {
   5091   unsigned int i;
   5092   static struct obstack insn_obstack;
   5093 
   5094   obstack_begin (&insn_obstack, 4000);
   5095   for (i = 0; i < sizeof (s7_score_insns) / sizeof (struct s7_asm_opcode); i++)
   5096     {
   5097       const struct s7_asm_opcode *insn = s7_score_insns + i;
   5098       size_t len = strlen (insn->template_name);
   5099       struct s7_asm_opcode *new_opcode;
   5100       char *template_name;
   5101       new_opcode = (struct s7_asm_opcode *)
   5102           obstack_alloc (&insn_obstack, sizeof (struct s7_asm_opcode));
   5103       template_name = (char *) obstack_alloc (&insn_obstack, len + 1);
   5104 
   5105       strcpy (template_name, insn->template_name);
   5106       new_opcode->template_name = template_name;
   5107       new_opcode->parms = insn->parms;
   5108       new_opcode->value = insn->value;
   5109       new_opcode->relax_value = insn->relax_value;
   5110       new_opcode->type = insn->type;
   5111       new_opcode->bitmask = insn->bitmask;
   5112       hash_insert (s7_score_ops_hsh, new_opcode->template_name,
   5113                    (void *) new_opcode);
   5114     }
   5115 }
   5116 
   5117 static void
   5118 s7_build_dependency_insn_hsh (void)
   5119 {
   5120   unsigned int i;
   5121   static struct obstack dependency_obstack;
   5122 
   5123   obstack_begin (&dependency_obstack, 4000);
   5124   for (i = 0; i < ARRAY_SIZE (s7_insn_to_dependency_table); i++)
   5125     {
   5126       const struct s7_insn_to_dependency *tmp = s7_insn_to_dependency_table + i;
   5127       size_t len = strlen (tmp->insn_name);
   5128       struct s7_insn_to_dependency *new_i2d;
   5129       char *insn_name;
   5130 
   5131       new_i2d = (struct s7_insn_to_dependency *)
   5132           obstack_alloc (&dependency_obstack,
   5133                          sizeof (struct s7_insn_to_dependency));
   5134       insn_name = (char *) obstack_alloc (&dependency_obstack, len + 1);
   5135 
   5136       strcpy (insn_name, tmp->insn_name);
   5137       new_i2d->insn_name = insn_name;
   5138       new_i2d->type = tmp->type;
   5139       hash_insert (s7_dependency_insn_hsh, new_i2d->insn_name,
   5140                    (void *) new_i2d);
   5141     }
   5142 }
   5143 
   5144 static valueT
   5145 s7_md_chars_to_number (char *buf, int n)
   5146 {
   5147   valueT result = 0;
   5148   unsigned char *where = (unsigned char *) buf;
   5149 
   5150   if (target_big_endian)
   5151     {
   5152       while (n--)
   5153         {
   5154           result <<= 8;
   5155           result |= (*where++ & 255);
   5156         }
   5157     }
   5158   else
   5159     {
   5160       while (n--)
   5161         {
   5162           result <<= 8;
   5163           result |= (where[n] & 255);
   5164         }
   5165     }
   5166 
   5167   return result;
   5168 }
   5169 
   5170 /* Return true if the given symbol should be considered local for s7_PIC.  */
   5171 
   5172 static bfd_boolean
   5173 s7_pic_need_relax (symbolS *sym, asection *segtype)
   5174 {
   5175   asection *symsec;
   5176   bfd_boolean linkonce;
   5177 
   5178   /* Handle the case of a symbol equated to another symbol.  */
   5179   while (symbol_equated_reloc_p (sym))
   5180     {
   5181       symbolS *n;
   5182 
   5183       /* It's possible to get a loop here in a badly written
   5184 	 program.  */
   5185       n = symbol_get_value_expression (sym)->X_add_symbol;
   5186       if (n == sym)
   5187 	break;
   5188       sym = n;
   5189     }
   5190 
   5191   symsec = S_GET_SEGMENT (sym);
   5192 
   5193   /* Duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
   5194   linkonce = FALSE;
   5195   if (symsec != segtype && ! S_IS_LOCAL (sym))
   5196     {
   5197       if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE) != 0)
   5198 	linkonce = TRUE;
   5199 
   5200       /* The GNU toolchain uses an extension for ELF: a section
   5201 	  beginning with the magic string .gnu.linkonce is a linkonce
   5202 	  section.  */
   5203       if (strncmp (segment_name (symsec), ".gnu.linkonce",
   5204 		   sizeof ".gnu.linkonce" - 1) == 0)
   5205 	linkonce = TRUE;
   5206     }
   5207 
   5208   /* This must duplicate the test in adjust_reloc_syms.  */
   5209   return (!bfd_is_und_section (symsec)
   5210 	  && !bfd_is_abs_section (symsec)
   5211 	  && !bfd_is_com_section (symsec)
   5212 	  && !linkonce
   5213 #ifdef OBJ_ELF
   5214 	  /* A global or weak symbol is treated as external.  */
   5215 	  && (OUTPUT_FLAVOR != bfd_target_elf_flavour
   5216 	      || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
   5217 #endif
   5218 	  );
   5219 }
   5220 
   5221 static int
   5222 s7_judge_size_before_relax (fragS * fragp, asection *sec)
   5223 {
   5224   int change = 0;
   5225 
   5226   if (s7_score_pic == s7_NO_PIC)
   5227     change = s7_nopic_need_relax (fragp->fr_symbol, 0);
   5228   else
   5229     change = s7_pic_need_relax (fragp->fr_symbol, sec);
   5230 
   5231   if (change == 1)
   5232     {
   5233       /* Only at the first time determining whether s7_GP instruction relax should be done,
   5234          return the difference between insntruction size and instruction relax size.  */
   5235       if (fragp->fr_opcode == NULL)
   5236 	{
   5237 	  fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
   5238 	  fragp->fr_opcode = fragp->fr_literal + s7_RELAX_RELOC1 (fragp->fr_subtype);
   5239           return s7_RELAX_NEW (fragp->fr_subtype) - s7_RELAX_OLD (fragp->fr_subtype);
   5240 	}
   5241     }
   5242 
   5243   return 0;
   5244 }
   5245 
   5246 static int
   5247 s7_b32_relax_to_b16 (fragS * fragp)
   5248 {
   5249   int grows = 0;
   5250   int relaxable_p = 0;
   5251   int frag_addr = fragp->fr_address + fragp->insn_addr;
   5252 
   5253   addressT symbol_address = 0;
   5254   symbolS *s;
   5255   offsetT offset;
   5256   unsigned long value;
   5257   unsigned long abs_value;
   5258 
   5259   /* FIXME : here may be able to modify better .
   5260      I don't know how to get the fragp's section ,
   5261      so in relax stage , it may be wrong to calculate the symbol's offset when the frag's section
   5262      is different from the symbol's.  */
   5263 
   5264   relaxable_p = s7_RELAX_OPT (fragp->fr_subtype);
   5265 
   5266   s = fragp->fr_symbol;
   5267   /* b/bl immediate  */
   5268   if (s == NULL)
   5269     frag_addr = 0;
   5270   else
   5271     {
   5272       if (s->bsym != NULL)
   5273 	symbol_address = (addressT) symbol_get_frag (s)->fr_address;
   5274     }
   5275 
   5276   value = s7_md_chars_to_number (fragp->fr_literal, s7_INSN_SIZE);
   5277 
   5278   /* b 32's offset : 20 bit, b 16's tolerate field : 0xff.  */
   5279   offset = ((value & 0x3ff0000) >> 6) | (value & 0x3fe);
   5280   if ((offset & 0x80000) == 0x80000)
   5281     offset |= 0xfff00000;
   5282 
   5283   abs_value = offset + symbol_address - frag_addr;
   5284   if ((abs_value & 0x80000000) == 0x80000000)
   5285     abs_value = 0xffffffff - abs_value + 1;
   5286 
   5287   /* Relax branch 32 to branch 16.  */
   5288   if (relaxable_p && (s->bsym != NULL) && ((abs_value & 0xffffff00) == 0)
   5289       && (S_IS_DEFINED (s) && !S_IS_COMMON (s) && !S_IS_EXTERNAL (s)))
   5290     {
   5291       /* do nothing.  */
   5292     }
   5293   else
   5294     {
   5295       /* Branch 32 can not be relaxed to b 16, so clear OPT bit.  */
   5296       fragp->fr_opcode = NULL;
   5297       fragp->fr_subtype = s7_RELAX_OPT_CLEAR (fragp->fr_subtype);
   5298     }
   5299 
   5300   return grows;
   5301 }
   5302 
   5303 static void
   5304 s7_parse_pce_inst (char *insnstr)
   5305 {
   5306   char c;
   5307   char *p;
   5308   char *q;
   5309   char first[s7_MAX_LITERAL_POOL_SIZE];
   5310   char second[s7_MAX_LITERAL_POOL_SIZE];
   5311   struct s7_score_it pec_part_1;
   5312 
   5313   /* Get first part string of PCE.  */
   5314   p = strstr (insnstr, "||");
   5315   c = *p;
   5316   *p = '\0';
   5317   strcpy (first, insnstr);
   5318 
   5319   /* Get second part string of PCE.  */
   5320   *p = c;
   5321   p += 2;
   5322   strcpy (second, p);
   5323 
   5324   s7_parse_16_32_inst (first, FALSE);
   5325   if (s7_inst.error)
   5326     return;
   5327 
   5328   memcpy (&pec_part_1, &s7_inst, sizeof (s7_inst));
   5329 
   5330   q = second;
   5331   while (q && *q)
   5332     {
   5333       *q = TOLOWER (*q);
   5334       q++;
   5335     }
   5336 
   5337   s7_parse_16_32_inst (second, FALSE);
   5338   if (s7_inst.error)
   5339     return;
   5340 
   5341   if (   ((pec_part_1.size == s7_INSN_SIZE) && (s7_inst.size == s7_INSN_SIZE))
   5342       || ((pec_part_1.size == s7_INSN_SIZE) && (s7_inst.size == s7_INSN16_SIZE))
   5343       || ((pec_part_1.size == s7_INSN16_SIZE) && (s7_inst.size == s7_INSN_SIZE)))
   5344     {
   5345       s7_inst.error = _("pce instruction error (16 bit || 16 bit)'");
   5346       strcpy (s7_inst.str, insnstr);
   5347       return;
   5348     }
   5349 
   5350   if (!s7_inst.error)
   5351     s7_gen_insn_frag (&pec_part_1, &s7_inst);
   5352 }
   5353 
   5354 
   5355 
   5357 static void
   5358 s7_insert_reg (const struct s7_reg_entry *r, struct hash_control *htab)
   5359 {
   5360   int i = 0;
   5361   int len = strlen (r->name) + 2;
   5362   char *buf = XNEWVEC (char, len);
   5363   char *buf2 = XNEWVEC (char, len);
   5364 
   5365   strcpy (buf + i, r->name);
   5366   for (i = 0; buf[i]; i++)
   5367     {
   5368       buf2[i] = TOUPPER (buf[i]);
   5369     }
   5370   buf2[i] = '\0';
   5371 
   5372   hash_insert (htab, buf, (void *) r);
   5373   hash_insert (htab, buf2, (void *) r);
   5374 }
   5375 
   5376 static void
   5377 s7_build_reg_hsh (struct s7_reg_map *map)
   5378 {
   5379   const struct s7_reg_entry *r;
   5380 
   5381   if ((map->htab = hash_new ()) == NULL)
   5382     {
   5383       as_fatal (_("virtual memory exhausted"));
   5384     }
   5385   for (r = map->names; r->name != NULL; r++)
   5386     {
   5387       s7_insert_reg (r, map->htab);
   5388     }
   5389 }
   5390 
   5391 
   5392 
   5394 /* If we change section we must dump the literal pool first.  */
   5395 static void
   5396 s7_s_score_bss (int ignore ATTRIBUTE_UNUSED)
   5397 {
   5398   subseg_set (bss_section, (subsegT) get_absolute_expression ());
   5399   demand_empty_rest_of_line ();
   5400 }
   5401 
   5402 static void
   5403 s7_s_score_text (int ignore)
   5404 {
   5405   obj_elf_text (ignore);
   5406   record_alignment (now_seg, 2);
   5407 }
   5408 
   5409 static void
   5410 s7_s_section (int ignore)
   5411 {
   5412   obj_elf_section (ignore);
   5413   if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
   5414     record_alignment (now_seg, 2);
   5415 
   5416 }
   5417 
   5418 static void
   5419 s7_s_change_sec (int sec)
   5420 {
   5421   segT seg;
   5422 
   5423 #ifdef OBJ_ELF
   5424   /* The ELF backend needs to know that we are changing sections, so
   5425      that .previous works correctly.  We could do something like check
   5426      for an obj_section_change_hook macro, but that might be confusing
   5427      as it would not be appropriate to use it in the section changing
   5428      functions in read.c, since obj-elf.c intercepts those.  FIXME:
   5429      This should be cleaner, somehow.  */
   5430   obj_elf_section_change_hook ();
   5431 #endif
   5432   switch (sec)
   5433     {
   5434     case 'r':
   5435       seg = subseg_new (s7_RDATA_SECTION_NAME, (subsegT) get_absolute_expression ());
   5436       bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA));
   5437       if (strcmp (TARGET_OS, "elf") != 0)
   5438         record_alignment (seg, 4);
   5439       demand_empty_rest_of_line ();
   5440       break;
   5441     case 's':
   5442       seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
   5443       bfd_set_section_flags (stdoutput, seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
   5444       if (strcmp (TARGET_OS, "elf") != 0)
   5445         record_alignment (seg, 4);
   5446       demand_empty_rest_of_line ();
   5447       break;
   5448     }
   5449 }
   5450 
   5451 static void
   5452 s7_s_score_mask (int reg_type  ATTRIBUTE_UNUSED)
   5453 {
   5454   long mask, off;
   5455 
   5456   if (s7_cur_proc_ptr == NULL)
   5457     {
   5458       as_warn (_(".mask outside of .ent"));
   5459       demand_empty_rest_of_line ();
   5460       return;
   5461     }
   5462   if (get_absolute_expression_and_terminator (&mask) != ',')
   5463     {
   5464       as_warn (_("Bad .mask directive"));
   5465       --input_line_pointer;
   5466       demand_empty_rest_of_line ();
   5467       return;
   5468     }
   5469   off = get_absolute_expression ();
   5470   s7_cur_proc_ptr->reg_mask = mask;
   5471   s7_cur_proc_ptr->reg_offset = off;
   5472   demand_empty_rest_of_line ();
   5473 }
   5474 
   5475 static symbolS *
   5476 s7_get_symbol (void)
   5477 {
   5478   int c;
   5479   char *name;
   5480   symbolS *p;
   5481 
   5482   c = get_symbol_name (&name);
   5483   p = (symbolS *) symbol_find_or_make (name);
   5484   (void) restore_line_pointer (c);
   5485   return p;
   5486 }
   5487 
   5488 static long
   5489 s7_get_number (void)
   5490 {
   5491   int negative = 0;
   5492   long val = 0;
   5493 
   5494   if (*input_line_pointer == '-')
   5495     {
   5496       ++input_line_pointer;
   5497       negative = 1;
   5498     }
   5499   if (!ISDIGIT (*input_line_pointer))
   5500     as_bad (_("expected simple number"));
   5501   if (input_line_pointer[0] == '0')
   5502     {
   5503       if (input_line_pointer[1] == 'x')
   5504         {
   5505           input_line_pointer += 2;
   5506           while (ISXDIGIT (*input_line_pointer))
   5507             {
   5508               val <<= 4;
   5509               val |= hex_value (*input_line_pointer++);
   5510             }
   5511           return negative ? -val : val;
   5512         }
   5513       else
   5514         {
   5515           ++input_line_pointer;
   5516           while (ISDIGIT (*input_line_pointer))
   5517             {
   5518               val <<= 3;
   5519               val |= *input_line_pointer++ - '0';
   5520             }
   5521           return negative ? -val : val;
   5522         }
   5523     }
   5524   if (!ISDIGIT (*input_line_pointer))
   5525     {
   5526       printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer);
   5527       as_warn (_("invalid number"));
   5528       return -1;
   5529     }
   5530   while (ISDIGIT (*input_line_pointer))
   5531     {
   5532       val *= 10;
   5533       val += *input_line_pointer++ - '0';
   5534     }
   5535   return negative ? -val : val;
   5536 }
   5537 
   5538 /* The .aent and .ent directives.  */
   5539 
   5540 static void
   5541 s7_s_score_ent (int aent)
   5542 {
   5543   symbolS *symbolP;
   5544   int maybe_text;
   5545 
   5546   symbolP = s7_get_symbol ();
   5547   if (*input_line_pointer == ',')
   5548     ++input_line_pointer;
   5549   SKIP_WHITESPACE ();
   5550   if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
   5551     s7_get_number ();
   5552 
   5553 #ifdef BFD_ASSEMBLER
   5554   if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
   5555     maybe_text = 1;
   5556   else
   5557     maybe_text = 0;
   5558 #else
   5559   if (now_seg != data_section && now_seg != bss_section)
   5560     maybe_text = 1;
   5561   else
   5562     maybe_text = 0;
   5563 #endif
   5564   if (!maybe_text)
   5565     as_warn (_(".ent or .aent not in text section."));
   5566   if (!aent && s7_cur_proc_ptr)
   5567     as_warn (_("missing .end"));
   5568   if (!aent)
   5569     {
   5570       s7_cur_proc_ptr = &s7_cur_proc;
   5571       s7_cur_proc_ptr->reg_mask = 0xdeadbeaf;
   5572       s7_cur_proc_ptr->reg_offset = 0xdeadbeaf;
   5573       s7_cur_proc_ptr->fpreg_mask = 0xdeafbeaf;
   5574       s7_cur_proc_ptr->leaf = 0xdeafbeaf;
   5575       s7_cur_proc_ptr->frame_offset = 0xdeafbeaf;
   5576       s7_cur_proc_ptr->frame_reg = 0xdeafbeaf;
   5577       s7_cur_proc_ptr->pc_reg = 0xdeafbeaf;
   5578       s7_cur_proc_ptr->isym = symbolP;
   5579       symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
   5580       ++s7_numprocs;
   5581       if (debug_type == DEBUG_STABS)
   5582         stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP));
   5583     }
   5584   demand_empty_rest_of_line ();
   5585 }
   5586 
   5587 static void
   5588 s7_s_score_frame (int ignore ATTRIBUTE_UNUSED)
   5589 {
   5590   char *backupstr;
   5591   char str[30];
   5592   long val;
   5593   int i = 0;
   5594 
   5595   backupstr = input_line_pointer;
   5596 
   5597 #ifdef OBJ_ELF
   5598   if (s7_cur_proc_ptr == NULL)
   5599     {
   5600       as_warn (_(".frame outside of .ent"));
   5601       demand_empty_rest_of_line ();
   5602       return;
   5603     }
   5604   s7_cur_proc_ptr->frame_reg = s7_reg_required_here ((&backupstr), 0, s7_REG_TYPE_SCORE);
   5605   SKIP_WHITESPACE ();
   5606   s7_skip_past_comma (&backupstr);
   5607   while (*backupstr != ',')
   5608     {
   5609       str[i] = *backupstr;
   5610       i++;
   5611       backupstr++;
   5612     }
   5613   str[i] = '\0';
   5614   val = atoi (str);
   5615 
   5616   SKIP_WHITESPACE ();
   5617   s7_skip_past_comma (&backupstr);
   5618   s7_cur_proc_ptr->frame_offset = val;
   5619   s7_cur_proc_ptr->pc_reg = s7_reg_required_here ((&backupstr), 0, s7_REG_TYPE_SCORE);
   5620 
   5621   SKIP_WHITESPACE ();
   5622   s7_skip_past_comma (&backupstr);
   5623   i = 0;
   5624   while (*backupstr != '\n')
   5625     {
   5626       str[i] = *backupstr;
   5627       i++;
   5628       backupstr++;
   5629     }
   5630   str[i] = '\0';
   5631   val = atoi (str);
   5632   s7_cur_proc_ptr->leaf = val;
   5633   SKIP_WHITESPACE ();
   5634   s7_skip_past_comma (&backupstr);
   5635 
   5636 #endif /* OBJ_ELF */
   5637   while (input_line_pointer != backupstr)
   5638     input_line_pointer++;
   5639 }
   5640 
   5641 /* The .end directive.  */
   5642 
   5643 static void
   5644 s7_s_score_end (int x ATTRIBUTE_UNUSED)
   5645 {
   5646   symbolS *p;
   5647   int maybe_text;
   5648 
   5649   /* Generate a .pdr section.  */
   5650   segT saved_seg = now_seg;
   5651   subsegT saved_subseg = now_subseg;
   5652   expressionS exp;
   5653   char *fragp;
   5654 
   5655   if (!is_end_of_line[(unsigned char)*input_line_pointer])
   5656     {
   5657       p = s7_get_symbol ();
   5658       demand_empty_rest_of_line ();
   5659     }
   5660   else
   5661     p = NULL;
   5662 
   5663 #ifdef BFD_ASSEMBLER
   5664   if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
   5665     maybe_text = 1;
   5666   else
   5667     maybe_text = 0;
   5668 #else
   5669   if (now_seg != data_section && now_seg != bss_section)
   5670     maybe_text = 1;
   5671   else
   5672     maybe_text = 0;
   5673 #endif
   5674 
   5675   if (!maybe_text)
   5676     as_warn (_(".end not in text section"));
   5677   if (!s7_cur_proc_ptr)
   5678     {
   5679       as_warn (_(".end directive without a preceding .ent directive."));
   5680       demand_empty_rest_of_line ();
   5681       return;
   5682     }
   5683   if (p != NULL)
   5684     {
   5685       gas_assert (S_GET_NAME (p));
   5686       if (strcmp (S_GET_NAME (p), S_GET_NAME (s7_cur_proc_ptr->isym)))
   5687         as_warn (_(".end symbol does not match .ent symbol."));
   5688       if (debug_type == DEBUG_STABS)
   5689         stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p));
   5690     }
   5691   else
   5692     as_warn (_(".end directive missing or unknown symbol"));
   5693 
   5694   if ((s7_cur_proc_ptr->reg_mask == 0xdeadbeaf) ||
   5695       (s7_cur_proc_ptr->reg_offset == 0xdeadbeaf) ||
   5696       (s7_cur_proc_ptr->leaf == 0xdeafbeaf) ||
   5697       (s7_cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
   5698       (s7_cur_proc_ptr->frame_reg == 0xdeafbeaf) || (s7_cur_proc_ptr->pc_reg == 0xdeafbeaf));
   5699 
   5700   else
   5701     {
   5702       (void) frag_now_fix ();
   5703       gas_assert (s7_pdr_seg);
   5704       subseg_set (s7_pdr_seg, 0);
   5705       /* Write the symbol.  */
   5706       exp.X_op = O_symbol;
   5707       exp.X_add_symbol = p;
   5708       exp.X_add_number = 0;
   5709       emit_expr (&exp, 4);
   5710       fragp = frag_more (7 * 4);
   5711       s7_number_to_chars (fragp, (valueT) s7_cur_proc_ptr->reg_mask, 4);
   5712       s7_number_to_chars (fragp + 4, (valueT) s7_cur_proc_ptr->reg_offset, 4);
   5713       s7_number_to_chars (fragp + 8, (valueT) s7_cur_proc_ptr->fpreg_mask, 4);
   5714       s7_number_to_chars (fragp + 12, (valueT) s7_cur_proc_ptr->leaf, 4);
   5715       s7_number_to_chars (fragp + 16, (valueT) s7_cur_proc_ptr->frame_offset, 4);
   5716       s7_number_to_chars (fragp + 20, (valueT) s7_cur_proc_ptr->frame_reg, 4);
   5717       s7_number_to_chars (fragp + 24, (valueT) s7_cur_proc_ptr->pc_reg, 4);
   5718       subseg_set (saved_seg, saved_subseg);
   5719 
   5720     }
   5721   s7_cur_proc_ptr = NULL;
   5722 }
   5723 
   5724 /* Handle the .set pseudo-op.  */
   5725 
   5726 static void
   5727 s7_s_score_set (int x ATTRIBUTE_UNUSED)
   5728 {
   5729   int i = 0;
   5730   char name[s7_MAX_LITERAL_POOL_SIZE];
   5731   char * orig_ilp = input_line_pointer;
   5732 
   5733   while (!is_end_of_line[(unsigned char)*input_line_pointer])
   5734     {
   5735       name[i] = (char) * input_line_pointer;
   5736       i++;
   5737       ++input_line_pointer;
   5738     }
   5739 
   5740   name[i] = '\0';
   5741 
   5742   if (strcmp (name, "nwarn") == 0)
   5743     {
   5744       s7_warn_fix_data_dependency = 0;
   5745     }
   5746   else if (strcmp (name, "fixdd") == 0)
   5747     {
   5748       s7_fix_data_dependency = 1;
   5749     }
   5750   else if (strcmp (name, "nofixdd") == 0)
   5751     {
   5752       s7_fix_data_dependency = 0;
   5753     }
   5754   else if (strcmp (name, "r1") == 0)
   5755     {
   5756       s7_nor1 = 0;
   5757     }
   5758   else if (strcmp (name, "nor1") == 0)
   5759     {
   5760       s7_nor1 = 1;
   5761     }
   5762   else if (strcmp (name, "optimize") == 0)
   5763     {
   5764       s7_g_opt = 1;
   5765     }
   5766   else if (strcmp (name, "volatile") == 0)
   5767     {
   5768       s7_g_opt = 0;
   5769     }
   5770   else if (strcmp (name, "pic") == 0)
   5771     {
   5772       s7_score_pic = s7_PIC;
   5773     }
   5774   else
   5775     {
   5776       input_line_pointer = orig_ilp;
   5777       s_set (0);
   5778     }
   5779 }
   5780 
   5781 /* Handle the .cpload pseudo-op.  This is used when generating s7_PIC code.  It sets the
   5782    $gp register for the function based on the function address, which is in the register
   5783    named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled
   5784    specially by the linker.  The result is:
   5785    ldis gp, %hi(GP_DISP_LABEL)
   5786    ori  gp, %low(GP_DISP_LABEL)
   5787    add  gp, gp, .cpload argument
   5788    The .cpload argument is normally r29.  */
   5789 
   5790 static void
   5791 s7_s_score_cpload (int ignore ATTRIBUTE_UNUSED)
   5792 {
   5793   int reg;
   5794   char insn_str[s7_MAX_LITERAL_POOL_SIZE];
   5795 
   5796   /* If we are not generating s7_PIC code, .cpload is ignored.  */
   5797   if (s7_score_pic == s7_NO_PIC)
   5798     {
   5799       s_ignore (0);
   5800       return;
   5801     }
   5802 
   5803   if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
   5804     return;
   5805 
   5806   demand_empty_rest_of_line ();
   5807 
   5808   sprintf (insn_str, "ld_i32hi r%d, %s", s7_GP, GP_DISP_LABEL);
   5809   if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
   5810     return;
   5811 
   5812   sprintf (insn_str, "ld_i32lo r%d, %s", s7_GP, GP_DISP_LABEL);
   5813   if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
   5814     return;
   5815 
   5816   sprintf (insn_str, "add r%d, r%d, r%d", s7_GP, s7_GP, reg);
   5817   if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
   5818     return;
   5819 }
   5820 
   5821 /* Handle the .cprestore pseudo-op.  This stores $gp into a given
   5822    offset from $sp.  The offset is remembered, and after making a s7_PIC
   5823    call $gp is restored from that location.  */
   5824 
   5825 static void
   5826 s7_s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
   5827 {
   5828   int reg;
   5829   int cprestore_offset;
   5830   char insn_str[s7_MAX_LITERAL_POOL_SIZE];
   5831 
   5832   /* If we are not generating s7_PIC code, .cprestore is ignored.  */
   5833   if (s7_score_pic == s7_NO_PIC)
   5834     {
   5835       s_ignore (0);
   5836       return;
   5837     }
   5838 
   5839   if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
   5840       || s7_skip_past_comma (&input_line_pointer) == (int) s7_FAIL)
   5841     {
   5842       return;
   5843     }
   5844 
   5845   cprestore_offset = get_absolute_expression ();
   5846 
   5847   if (cprestore_offset <= 0x3fff)
   5848     {
   5849       sprintf (insn_str, "sw r%d, [r%d, %d]", s7_GP, reg, cprestore_offset);
   5850       if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
   5851         return;
   5852     }
   5853   else
   5854     {
   5855       int r1_bak;
   5856 
   5857       r1_bak = s7_nor1;
   5858       s7_nor1 = 0;
   5859 
   5860       sprintf (insn_str, "li r1, %d", cprestore_offset);
   5861       if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
   5862         return;
   5863 
   5864       sprintf (insn_str, "add r1, r1, r%d", reg);
   5865       if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
   5866         return;
   5867 
   5868       sprintf (insn_str, "sw r%d, [r1]", s7_GP);
   5869       if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
   5870         return;
   5871 
   5872       s7_nor1 = r1_bak;
   5873     }
   5874 
   5875   demand_empty_rest_of_line ();
   5876 }
   5877 
   5878 /* Handle the .gpword pseudo-op.  This is used when generating s7_PIC
   5879    code.  It generates a 32 bit s7_GP relative reloc.  */
   5880 
   5881 static void
   5882 s7_s_score_gpword (int ignore ATTRIBUTE_UNUSED)
   5883 {
   5884   expressionS ex;
   5885   char *p;
   5886 
   5887   /* When not generating s7_PIC code, this is treated as .word.  */
   5888   if (s7_score_pic == s7_NO_PIC)
   5889     {
   5890       cons (4);
   5891       return;
   5892     }
   5893   expression (&ex);
   5894   if (ex.X_op != O_symbol || ex.X_add_number != 0)
   5895     {
   5896       as_bad (_("Unsupported use of .gpword"));
   5897       ignore_rest_of_line ();
   5898     }
   5899   p = frag_more (4);
   5900   s7_number_to_chars (p, (valueT) 0, 4);
   5901   fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32);
   5902   demand_empty_rest_of_line ();
   5903 }
   5904 
   5905 /* Handle the .cpadd pseudo-op.  This is used when dealing with switch
   5906    tables in s7_PIC code.  */
   5907 
   5908 static void
   5909 s7_s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
   5910 {
   5911   int reg;
   5912   char insn_str[s7_MAX_LITERAL_POOL_SIZE];
   5913 
   5914   /* If we are not generating s7_PIC code, .cpload is ignored.  */
   5915   if (s7_score_pic == s7_NO_PIC)
   5916     {
   5917       s_ignore (0);
   5918       return;
   5919     }
   5920 
   5921   if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
   5922     {
   5923       return;
   5924     }
   5925   demand_empty_rest_of_line ();
   5926 
   5927   /* Add $gp to the register named as an argument.  */
   5928   sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, s7_GP);
   5929   if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
   5930     return;
   5931 }
   5932 
   5933 #ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
   5934 #define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR)        	\
   5935     do								\
   5936     {                                                   	\
   5937     if ((SIZE) >= 8)                                      	\
   5938     (P2VAR) = 3;                                        	\
   5939     else if ((SIZE) >= 4)                                 	\
   5940     (P2VAR) = 2;                                        	\
   5941     else if ((SIZE) >= 2)                                 	\
   5942     (P2VAR) = 1;                                        	\
   5943     else                                                  	\
   5944     (P2VAR) = 0;                                        	\
   5945     }								\
   5946   while (0)
   5947 #endif
   5948 
   5949 static void
   5950 s7_s_score_lcomm (int bytes_p)
   5951 {
   5952   char *name;
   5953   char c;
   5954   char *p;
   5955   int temp;
   5956   symbolS *symbolP;
   5957   segT current_seg = now_seg;
   5958   subsegT current_subseg = now_subseg;
   5959   const int max_alignment = 15;
   5960   int align = 0;
   5961   segT bss_seg = bss_section;
   5962   int needs_align = 0;
   5963 
   5964   c = get_symbol_name (&name);
   5965   p = input_line_pointer;
   5966   *p = c;
   5967 
   5968   if (name == p)
   5969     {
   5970       as_bad (_("expected symbol name"));
   5971       discard_rest_of_line ();
   5972       return;
   5973     }
   5974 
   5975   SKIP_WHITESPACE_AFTER_NAME ();
   5976 
   5977   /* Accept an optional comma after the name.  The comma used to be
   5978      required, but Irix 5 cc does not generate it.  */
   5979   if (*input_line_pointer == ',')
   5980     {
   5981       ++input_line_pointer;
   5982       SKIP_WHITESPACE ();
   5983     }
   5984 
   5985   if (is_end_of_line[(unsigned char)*input_line_pointer])
   5986     {
   5987       as_bad (_("missing size expression"));
   5988       return;
   5989     }
   5990 
   5991   if ((temp = get_absolute_expression ()) < 0)
   5992     {
   5993       as_warn (_("BSS length (%d) < 0 ignored"), temp);
   5994       ignore_rest_of_line ();
   5995       return;
   5996     }
   5997 
   5998 #if defined (TC_SCORE)
   5999   if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour)
   6000     {
   6001       /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss.  */
   6002       if ((unsigned) temp <= bfd_get_gp_size (stdoutput))
   6003         {
   6004           bss_seg = subseg_new (".sbss", 1);
   6005           seg_info (bss_seg)->bss = 1;
   6006 #ifdef BFD_ASSEMBLER
   6007           if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
   6008             as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ()));
   6009 #endif
   6010         }
   6011     }
   6012 #endif
   6013 
   6014   SKIP_WHITESPACE ();
   6015   if (*input_line_pointer == ',')
   6016     {
   6017       ++input_line_pointer;
   6018       SKIP_WHITESPACE ();
   6019 
   6020       if (is_end_of_line[(unsigned char)*input_line_pointer])
   6021         {
   6022           as_bad (_("missing alignment"));
   6023           return;
   6024         }
   6025       else
   6026         {
   6027           align = get_absolute_expression ();
   6028           needs_align = 1;
   6029         }
   6030     }
   6031 
   6032   if (!needs_align)
   6033     {
   6034       TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
   6035 
   6036       /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it.  */
   6037       if (align)
   6038         record_alignment (bss_seg, align);
   6039     }
   6040 
   6041   if (needs_align)
   6042     {
   6043       if (bytes_p)
   6044         {
   6045           /* Convert to a power of 2.  */
   6046           if (align != 0)
   6047             {
   6048               unsigned int i;
   6049 
   6050               for (i = 0; align != 0; align >>= 1, ++i)
   6051                 ;
   6052               align = i - 1;
   6053             }
   6054         }
   6055 
   6056       if (align > max_alignment)
   6057         {
   6058           align = max_alignment;
   6059           as_warn (_("alignment too large; %d assumed"), align);
   6060         }
   6061       else if (align < 0)
   6062         {
   6063           align = 0;
   6064           as_warn (_("alignment negative; 0 assumed"));
   6065         }
   6066 
   6067       record_alignment (bss_seg, align);
   6068     }
   6069   else
   6070     {
   6071       /* Assume some objects may require alignment on some systems.  */
   6072 #if defined (TC_ALPHA) && ! defined (VMS)
   6073       if (temp > 1)
   6074         {
   6075           align = ffs (temp) - 1;
   6076           if (temp % (1 << align))
   6077             abort ();
   6078         }
   6079 #endif
   6080     }
   6081 
   6082   *p = 0;
   6083   symbolP = symbol_find_or_make (name);
   6084   *p = c;
   6085 
   6086   if (
   6087 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \
   6088      || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT))
   6089 #ifdef BFD_ASSEMBLER
   6090        (OUTPUT_FLAVOR != bfd_target_aout_flavour
   6091         || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
   6092 #else
   6093        (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
   6094 #endif
   6095 #endif
   6096        (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
   6097     {
   6098       char *pfrag;
   6099 
   6100       subseg_set (bss_seg, 1);
   6101 
   6102       if (align)
   6103         frag_align (align, 0, 0);
   6104 
   6105       /* Detach from old frag.  */
   6106       if (S_GET_SEGMENT (symbolP) == bss_seg)
   6107         symbol_get_frag (symbolP)->fr_symbol = NULL;
   6108 
   6109       symbol_set_frag (symbolP, frag_now);
   6110       pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
   6111       *pfrag = 0;
   6112 
   6113 
   6114       S_SET_SEGMENT (symbolP, bss_seg);
   6115 
   6116 #ifdef OBJ_COFF
   6117       /* The symbol may already have been created with a preceding
   6118          ".globl" directive -- be careful not to step on storage class
   6119          in that case.  Otherwise, set it to static.  */
   6120       if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
   6121         {
   6122           S_SET_STORAGE_CLASS (symbolP, C_STAT);
   6123         }
   6124 #endif /* OBJ_COFF */
   6125 
   6126 #ifdef S_SET_SIZE
   6127       S_SET_SIZE (symbolP, temp);
   6128 #endif
   6129     }
   6130   else
   6131     as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
   6132 
   6133   subseg_set (current_seg, current_subseg);
   6134 
   6135   demand_empty_rest_of_line ();
   6136 }
   6137 
   6138 
   6139 
   6141 static void
   6142 s7_begin (void)
   6143 {
   6144   unsigned int i;
   6145   segT seg;
   6146   subsegT subseg;
   6147 
   6148   if ((s7_score_ops_hsh = hash_new ()) == NULL)
   6149     as_fatal (_("virtual memory exhausted"));
   6150 
   6151   s7_build_score_ops_hsh ();
   6152 
   6153   if ((s7_dependency_insn_hsh = hash_new ()) == NULL)
   6154     as_fatal (_("virtual memory exhausted"));
   6155 
   6156   s7_build_dependency_insn_hsh ();
   6157 
   6158   for (i = (int) REG_TYPE_FIRST; i < (int) s7_REG_TYPE_MAX; i++)
   6159     s7_build_reg_hsh (s7_all_reg_maps + i);
   6160 
   6161   /* Initialize dependency vector.  */
   6162   s7_init_dependency_vector ();
   6163 
   6164   bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
   6165   seg = now_seg;
   6166   subseg = now_subseg;
   6167   s7_pdr_seg = subseg_new (".pdr", (subsegT) 0);
   6168   (void) bfd_set_section_flags (stdoutput, s7_pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
   6169   (void) bfd_set_section_alignment (stdoutput, s7_pdr_seg, 2);
   6170   subseg_set (seg, subseg);
   6171 
   6172   if (s7_USE_GLOBAL_POINTER_OPT)
   6173     bfd_set_gp_size (stdoutput, s7_g_switch_value);
   6174 }
   6175 
   6176 static void
   6177 s7_assemble (char *str)
   6178 {
   6179   know (str);
   6180   know (strlen (str) < s7_MAX_LITERAL_POOL_SIZE);
   6181 
   6182   memset (&s7_inst, '\0', sizeof (s7_inst));
   6183   if (s7_INSN_IS_PCE_P (str))
   6184     s7_parse_pce_inst (str);
   6185   else
   6186     s7_parse_16_32_inst (str, TRUE);
   6187 
   6188   if (s7_inst.error)
   6189     as_bad (_("%s -- `%s'"), s7_inst.error, s7_inst.str);
   6190 }
   6191 
   6192 /* We handle all bad expressions here, so that we can report the faulty
   6193    instruction in the error message.  */
   6194 
   6195 static void
   6196 s7_operand (expressionS * exp)
   6197 {
   6198   if (s7_in_my_get_expression)
   6199     {
   6200       exp->X_op = O_illegal;
   6201       if (s7_inst.error == NULL)
   6202         {
   6203           s7_inst.error = _("bad expression");
   6204         }
   6205     }
   6206 }
   6207 
   6208 /* Turn a string in input_line_pointer into a floating point constant
   6209    of type TYPE, and store the appropriate bytes in *LITP.  The number
   6210    of LITTLENUMS emitted is stored in *SIZEP.  An error message is
   6211    returned, or NULL on OK.
   6212 
   6213    Note that fp constants aren't represent in the normal way on the ARM.
   6214    In big endian mode, things are as expected.  However, in little endian
   6215    mode fp constants are big-endian word-wise, and little-endian byte-wise
   6216    within the words.  For example, (double) 1.1 in big endian mode is
   6217    the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
   6218    the byte sequence 99 99 f1 3f 9a 99 99 99.  */
   6219 
   6220 static const char *
   6221 s7_atof (int type, char *litP, int *sizeP)
   6222 {
   6223   int prec;
   6224   LITTLENUM_TYPE words[s7_MAX_LITTLENUMS];
   6225   char *t;
   6226   int i;
   6227 
   6228   switch (type)
   6229     {
   6230     case 'f':
   6231     case 'F':
   6232     case 's':
   6233     case 'S':
   6234       prec = 2;
   6235       break;
   6236     case 'd':
   6237     case 'D':
   6238     case 'r':
   6239     case 'R':
   6240       prec = 4;
   6241       break;
   6242     case 'x':
   6243     case 'X':
   6244     case 'p':
   6245     case 'P':
   6246       prec = 6;
   6247       break;
   6248     default:
   6249       *sizeP = 0;
   6250       return _("bad call to MD_ATOF()");
   6251     }
   6252 
   6253   t = atof_ieee (input_line_pointer, type, words);
   6254   if (t)
   6255     input_line_pointer = t;
   6256   *sizeP = prec * 2;
   6257 
   6258   if (target_big_endian)
   6259     {
   6260       for (i = 0; i < prec; i++)
   6261         {
   6262           s7_number_to_chars (litP, (valueT) words[i], 2);
   6263           litP += 2;
   6264         }
   6265     }
   6266   else
   6267     {
   6268       for (i = 0; i < prec; i += 2)
   6269         {
   6270           s7_number_to_chars (litP, (valueT) words[i + 1], 2);
   6271           s7_number_to_chars (litP + 2, (valueT) words[i], 2);
   6272           litP += 4;
   6273         }
   6274     }
   6275 
   6276   return 0;
   6277 }
   6278 
   6279 /* Implementation of md_frag_check.
   6280    Called after md_convert_frag().  */
   6281 
   6282 static void
   6283 s7_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
   6284 {
   6285   know (fragp->insn_addr <= s7_RELAX_PAD_BYTE);
   6286 }
   6287 
   6288 /* Implementation of TC_VALIDATE_FIX.
   6289    Called before md_apply_fix() and after md_convert_frag().  */
   6290 
   6291 static void
   6292 s7_validate_fix (fixS *fixP)
   6293 {
   6294   fixP->fx_where += fixP->fx_frag->insn_addr;
   6295 }
   6296 
   6297 static int
   6298 s7_force_relocation (struct fix *fixp)
   6299 {
   6300   int retval = 0;
   6301 
   6302   if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
   6303       || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
   6304       || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
   6305       || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
   6306       || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
   6307       || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH)
   6308     {
   6309       retval = 1;
   6310     }
   6311 
   6312   return retval;
   6313 }
   6314 
   6315 static bfd_boolean
   6316 s7_fix_adjustable (fixS * fixP)
   6317 {
   6318   if (fixP->fx_addsy == NULL)
   6319     {
   6320       return 1;
   6321     }
   6322   else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
   6323       && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
   6324     {
   6325       return 0;
   6326     }
   6327   else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
   6328            || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
   6329            || fixP->fx_r_type == BFD_RELOC_SCORE_JMP
   6330            || fixP->fx_r_type == BFD_RELOC_SCORE16_JMP)
   6331     {
   6332       return 0;
   6333     }
   6334 
   6335   return 1;
   6336 }
   6337 
   6338 static void
   6339 s7_elf_final_processing (void)
   6340 {
   6341   unsigned long val = E_SCORE_MACH_SCORE7;
   6342 
   6343   elf_elfheader (stdoutput)->e_machine = EM_SCORE;
   6344   elf_elfheader (stdoutput)->e_flags &= ~EF_SCORE_MACH;
   6345   elf_elfheader (stdoutput)->e_flags |= val;
   6346 
   6347   if (s7_fix_data_dependency == 1)
   6348     {
   6349       elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
   6350     }
   6351   if (s7_score_pic == s7_PIC)
   6352     {
   6353       elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
   6354     }
   6355 }
   6356 
   6357 /* In this function, we determine whether s7_GP instruction should do relaxation,
   6358    for the label being against was known now.
   6359    Doing this here but not in md_relax_frag() can induce iteration times
   6360    in stage of doing relax.  */
   6361 
   6362 static int
   6363 s7_estimate_size_before_relax (fragS * fragp, asection * sec)
   6364 {
   6365   if ((s7_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
   6366       || (s7_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
   6367     return s7_judge_size_before_relax (fragp, sec);
   6368 
   6369   return 0;
   6370 }
   6371 
   6372 static int
   6373 s7_relax_frag (asection * sec ATTRIBUTE_UNUSED,
   6374 	       fragS * fragp,
   6375 	       long stretch ATTRIBUTE_UNUSED)
   6376 {
   6377   int grows = 0;
   6378   int insn_size;
   6379   int do_relax_p = 0;           /* Indicate doing relaxation for this frag.  */
   6380   int relaxable_p = 0;
   6381   bfd_boolean word_align_p = FALSE;
   6382   fragS *next_fragp;
   6383 
   6384   /* If the instruction address is odd, make it half word align first.  */
   6385   if ((fragp->fr_address) % 2 != 0)
   6386     {
   6387       if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
   6388 	{
   6389           fragp->insn_addr = 1;
   6390           grows += 1;
   6391 	}
   6392     }
   6393 
   6394   word_align_p = ((fragp->fr_address + fragp->insn_addr) % 4 == 0) ? TRUE : FALSE;
   6395 
   6396   /* Get instruction size and relax size after the last relaxation.  */
   6397   if (fragp->fr_opcode)
   6398     insn_size = s7_RELAX_NEW (fragp->fr_subtype);
   6399   else
   6400     insn_size = s7_RELAX_OLD (fragp->fr_subtype);
   6401 
   6402   /* Handle specially for s7_GP instruction.  for, s7_judge_size_before_relax() has already determine
   6403      whether the s7_GP instruction should do relax.  */
   6404   if ((s7_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
   6405       || (s7_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
   6406     {
   6407       if (!word_align_p)
   6408         {
   6409           if (fragp->insn_addr < 2)
   6410             {
   6411               fragp->insn_addr += 2;
   6412               grows += 2;
   6413             }
   6414           else
   6415             {
   6416               fragp->insn_addr -= 2;
   6417               grows -= 2;
   6418             }
   6419         }
   6420 
   6421       if (fragp->fr_opcode)
   6422 	fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype) + fragp->insn_addr;
   6423       else
   6424 	fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype) + fragp->insn_addr;
   6425     }
   6426   else
   6427     {
   6428       if (s7_RELAX_TYPE (fragp->fr_subtype) == PC_DISP19div2)
   6429 	s7_b32_relax_to_b16 (fragp);
   6430 
   6431       relaxable_p = s7_RELAX_OPT (fragp->fr_subtype);
   6432       next_fragp = fragp->fr_next;
   6433       while ((next_fragp) && (next_fragp->fr_type != rs_machine_dependent))
   6434 	{
   6435           next_fragp = next_fragp->fr_next;
   6436 	}
   6437 
   6438       if (next_fragp)
   6439         {
   6440           int n_insn_size;
   6441           int n_relaxable_p = 0;
   6442 
   6443           if (next_fragp->fr_opcode)
   6444             {
   6445               n_insn_size = s7_RELAX_NEW (next_fragp->fr_subtype);
   6446             }
   6447           else
   6448             {
   6449               n_insn_size = s7_RELAX_OLD (next_fragp->fr_subtype);
   6450             }
   6451 
   6452           if (s7_RELAX_TYPE (next_fragp->fr_subtype) == PC_DISP19div2)
   6453             s7_b32_relax_to_b16 (next_fragp);
   6454           n_relaxable_p = s7_RELAX_OPT (next_fragp->fr_subtype);
   6455 
   6456           if (word_align_p)
   6457             {
   6458               if (insn_size == 4)
   6459                 {
   6460                   /* 32 -> 16.  */
   6461                   if (relaxable_p && ((n_insn_size == 2) || n_relaxable_p))
   6462                     {
   6463                       grows -= 2;
   6464                       do_relax_p = 1;
   6465                     }
   6466                 }
   6467               else if (insn_size == 2)
   6468                 {
   6469                   /* 16 -> 32.  */
   6470                   if (relaxable_p && (((n_insn_size == 4) && !n_relaxable_p) || (n_insn_size > 4)))
   6471                     {
   6472                       grows += 2;
   6473                       do_relax_p = 1;
   6474                     }
   6475                 }
   6476               else
   6477                 {
   6478 		  abort ();
   6479                 }
   6480             }
   6481           else
   6482             {
   6483               if (insn_size == 4)
   6484                 {
   6485                   /* 32 -> 16.  */
   6486                   if (relaxable_p)
   6487                     {
   6488                       grows -= 2;
   6489                       do_relax_p = 1;
   6490                     }
   6491                   /* Make the 32 bit insturction word align.  */
   6492                   else
   6493                     {
   6494                       fragp->insn_addr += 2;
   6495                       grows += 2;
   6496 		    }
   6497                 }
   6498               else if (insn_size == 2)
   6499                 {
   6500                   /* Do nothing.  */
   6501                 }
   6502               else
   6503                 {
   6504 		  abort ();
   6505                 }
   6506             }
   6507         }
   6508       else
   6509         {
   6510 	  /* Here, try best to do relax regardless fragp->fr_next->fr_type.  */
   6511           if (word_align_p == FALSE)
   6512             {
   6513               if (insn_size % 4 == 0)
   6514                 {
   6515                   /* 32 -> 16.  */
   6516                   if (relaxable_p)
   6517                     {
   6518                       grows -= 2;
   6519                       do_relax_p = 1;
   6520                     }
   6521                   else
   6522                     {
   6523                       fragp->insn_addr += 2;
   6524                       grows += 2;
   6525                     }
   6526                 }
   6527             }
   6528           else
   6529             {
   6530 	      /* Do nothing.  */
   6531             }
   6532         }
   6533 
   6534       /* fragp->fr_opcode indicates whether this frag should be relaxed.  */
   6535       if (do_relax_p)
   6536         {
   6537           if (fragp->fr_opcode)
   6538             {
   6539               fragp->fr_opcode = NULL;
   6540 	      /* Guarantee estimate stage is correct.  */
   6541               fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype);
   6542               fragp->fr_fix += fragp->insn_addr;
   6543             }
   6544           else
   6545             {
   6546               fragp->fr_opcode = fragp->fr_literal + s7_RELAX_RELOC1 (fragp->fr_subtype);
   6547 	      /* Guarantee estimate stage is correct.  */
   6548               fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
   6549               fragp->fr_fix += fragp->insn_addr;
   6550             }
   6551         }
   6552       else
   6553 	{
   6554           if (fragp->fr_opcode)
   6555             {
   6556 	      /* Guarantee estimate stage is correct.  */
   6557               fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
   6558               fragp->fr_fix += fragp->insn_addr;
   6559             }
   6560           else
   6561             {
   6562 	      /* Guarantee estimate stage is correct.  */
   6563               fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype);
   6564               fragp->fr_fix += fragp->insn_addr;
   6565             }
   6566 	}
   6567     }
   6568 
   6569   return grows;
   6570 }
   6571 
   6572 static void
   6573 s7_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
   6574 		 segT sec ATTRIBUTE_UNUSED,
   6575 		 fragS * fragp)
   6576 {
   6577   int r_old;
   6578   int r_new;
   6579   char backup[20];
   6580   fixS *fixp;
   6581 
   6582   r_old = s7_RELAX_OLD (fragp->fr_subtype);
   6583   r_new = s7_RELAX_NEW (fragp->fr_subtype);
   6584 
   6585   /* fragp->fr_opcode indicates whether this frag should be relaxed.  */
   6586   if (fragp->fr_opcode == NULL)
   6587     {
   6588       memcpy (backup, fragp->fr_literal, r_old);
   6589       fragp->fr_fix = r_old;
   6590     }
   6591   else
   6592     {
   6593       memcpy (backup, fragp->fr_literal + r_old, r_new);
   6594       fragp->fr_fix = r_new;
   6595     }
   6596 
   6597   fixp = fragp->tc_frag_data.fixp;
   6598   while (fixp && fixp->fx_frag == fragp && fixp->fx_where < r_old)
   6599     {
   6600       if (fragp->fr_opcode)
   6601 	fixp->fx_done = 1;
   6602       fixp = fixp->fx_next;
   6603     }
   6604   while (fixp && fixp->fx_frag == fragp)
   6605     {
   6606       if (fragp->fr_opcode)
   6607 	fixp->fx_where -= r_old + fragp->insn_addr;
   6608       else
   6609 	fixp->fx_done = 1;
   6610       fixp = fixp->fx_next;
   6611     }
   6612 
   6613   if (fragp->insn_addr)
   6614     {
   6615       s7_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
   6616     }
   6617   memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
   6618   fragp->fr_fix += fragp->insn_addr;
   6619 }
   6620 
   6621 static long
   6622 s7_pcrel_from (fixS * fixP)
   6623 {
   6624   long retval = 0;
   6625 
   6626   if (fixP->fx_addsy
   6627       && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
   6628       && (fixP->fx_subsy == NULL))
   6629     {
   6630       retval = 0;
   6631     }
   6632   else
   6633     {
   6634       retval = fixP->fx_where + fixP->fx_frag->fr_address;
   6635     }
   6636 
   6637   return retval;
   6638 }
   6639 
   6640 /* Round up a section size to the appropriate boundary.  */
   6641 static valueT
   6642 s7_section_align (segT segment, valueT size)
   6643 {
   6644   int align = bfd_get_section_alignment (stdoutput, segment);
   6645 
   6646   return ((size + (1 << align) - 1) & -(1 << align));
   6647 }
   6648 
   6649 static void
   6650 s7_apply_fix (fixS *fixP, valueT *valP, segT seg)
   6651 {
   6652   offsetT value = *valP;
   6653   offsetT abs_value = 0;
   6654   offsetT newval;
   6655   offsetT content;
   6656   unsigned short HI, LO;
   6657 
   6658   char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
   6659 
   6660   gas_assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
   6661   if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
   6662     {
   6663       if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
   6664         fixP->fx_done = 1;
   6665     }
   6666 
   6667   /* If this symbol is in a different section then we need to leave it for
   6668      the linker to deal with.  Unfortunately, md_pcrel_from can't tell,
   6669      so we have to undo it's effects here.  */
   6670   if (fixP->fx_pcrel)
   6671     {
   6672       if (fixP->fx_addsy != NULL
   6673 	  && S_IS_DEFINED (fixP->fx_addsy)
   6674 	  && S_GET_SEGMENT (fixP->fx_addsy) != seg)
   6675 	value += md_pcrel_from (fixP);
   6676     }
   6677 
   6678   /* Remember value for emit_reloc.  */
   6679   fixP->fx_addnumber = value;
   6680 
   6681   switch (fixP->fx_r_type)
   6682     {
   6683     case BFD_RELOC_HI16_S:
   6684       if (fixP->fx_done)
   6685         {                       /* For la rd, imm32.  */
   6686           newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
   6687           HI = (value) >> 16;   /* mul to 2, then take the hi 16 bit.  */
   6688           newval |= (HI & 0x3fff) << 1;
   6689           newval |= ((HI >> 14) & 0x3) << 16;
   6690           s7_number_to_chars (buf, newval, s7_INSN_SIZE);
   6691         }
   6692       break;
   6693     case BFD_RELOC_LO16:
   6694       if (fixP->fx_done)        /* For la rd, imm32.  */
   6695         {
   6696           newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
   6697           LO = (value) & 0xffff;
   6698           newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi.  */
   6699           newval |= ((LO >> 14) & 0x3) << 16;
   6700           s7_number_to_chars (buf, newval, s7_INSN_SIZE);
   6701         }
   6702       break;
   6703     case BFD_RELOC_SCORE_JMP:
   6704       {
   6705         content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
   6706         value = fixP->fx_offset;
   6707         if (!(value >= 0 && value <= 0x1ffffff))
   6708           {
   6709             as_bad_where (fixP->fx_file, fixP->fx_line,
   6710                           _("j or jl truncate (0x%x)  [0 ~ 2^25-1]"), (unsigned int) value);
   6711             return;
   6712           }
   6713         content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
   6714         s7_number_to_chars (buf, content, s7_INSN_SIZE);
   6715       }
   6716       break;
   6717     case BFD_RELOC_SCORE_BRANCH:
   6718       if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
   6719         value = fixP->fx_offset;
   6720       else
   6721         fixP->fx_done = 1;
   6722 
   6723       content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
   6724       if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) != 0x80008000))
   6725         {
   6726           if ((value & 0x80000000) == 0x80000000)
   6727             abs_value = 0xffffffff - value + 1;
   6728           if ((abs_value & 0xffffff00) != 0)
   6729             {
   6730               as_bad_where (fixP->fx_file, fixP->fx_line,
   6731                             _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int) value);
   6732               return;
   6733             }
   6734           content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
   6735           content &= 0xff00;
   6736           content = (content & 0xff00) | ((value >> 1) & 0xff);
   6737           s7_number_to_chars (buf, content, s7_INSN16_SIZE);
   6738           fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
   6739           fixP->fx_size = 2;
   6740         }
   6741       else
   6742         {
   6743           if ((value & 0x80000000) == 0x80000000)
   6744             abs_value = 0xffffffff - value + 1;
   6745           if ((abs_value & 0xfff80000) != 0)
   6746             {
   6747               as_bad_where (fixP->fx_file, fixP->fx_line,
   6748                             _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"),
   6749 			    (unsigned int) value);
   6750               return;
   6751             }
   6752           content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
   6753           content &= 0xfc00fc01;
   6754           content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
   6755           s7_number_to_chars (buf, content, s7_INSN_SIZE);
   6756         }
   6757       break;
   6758     case BFD_RELOC_SCORE16_JMP:
   6759       content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
   6760       content &= 0xf001;
   6761       value = fixP->fx_offset;
   6762       if (!(value >= 0 && value <= 0xfff))
   6763         {
   6764           as_bad_where (fixP->fx_file, fixP->fx_line,
   6765                         _("j! or jl! truncate (0x%x)  [0 ~ 2^12-1]"), (unsigned int) value);
   6766           return;
   6767         }
   6768       value = fixP->fx_offset & 0xfff;
   6769       content = (content & 0xfc01) | (value & 0xffe);
   6770       s7_number_to_chars (buf, content, s7_INSN16_SIZE);
   6771       break;
   6772     case BFD_RELOC_SCORE16_BRANCH:
   6773       content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
   6774       if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) == 0x80008000))
   6775         {
   6776           if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
   6777               (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
   6778             value = fixP->fx_offset;
   6779           else
   6780             fixP->fx_done = 1;
   6781 
   6782           if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
   6783             {
   6784               as_bad_where (fixP->fx_file, fixP->fx_line,
   6785                             _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"),
   6786 			    (unsigned int) value);
   6787               return;
   6788             }
   6789           content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
   6790           content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
   6791           s7_number_to_chars (buf, content, s7_INSN_SIZE);
   6792           fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
   6793           fixP->fx_size = 4;
   6794           break;
   6795         }
   6796       else
   6797         {
   6798           /* In differnt section.  */
   6799           if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
   6800               (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
   6801             value = fixP->fx_offset;
   6802           else
   6803             fixP->fx_done = 1;
   6804 
   6805           if ((value & 0xffffff00) != 0 && (value & 0xffffff00) != 0xffffff00)
   6806             {
   6807               as_bad_where (fixP->fx_file, fixP->fx_line,
   6808                             _(" branch relocation truncate (0x%x)  [-2^8 ~ 2^8]"),
   6809 			    (unsigned int) value);
   6810               return;
   6811             }
   6812           content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
   6813           content = (content & 0xff00) | ((value >> 1) & 0xff);
   6814           s7_number_to_chars (buf, content, s7_INSN16_SIZE);
   6815           break;
   6816         }
   6817     case BFD_RELOC_8:
   6818       if (fixP->fx_done || fixP->fx_pcrel)
   6819 	s7_number_to_chars (buf, value, 1);
   6820 #ifdef OBJ_ELF
   6821       else
   6822         {
   6823           value = fixP->fx_offset;
   6824           s7_number_to_chars (buf, value, 1);
   6825         }
   6826 #endif
   6827       break;
   6828 
   6829     case BFD_RELOC_16:
   6830       if (fixP->fx_done || fixP->fx_pcrel)
   6831         s7_number_to_chars (buf, value, 2);
   6832 #ifdef OBJ_ELF
   6833       else
   6834         {
   6835           value = fixP->fx_offset;
   6836           s7_number_to_chars (buf, value, 2);
   6837         }
   6838 #endif
   6839       break;
   6840     case BFD_RELOC_RVA:
   6841     case BFD_RELOC_32:
   6842       if (fixP->fx_done || fixP->fx_pcrel)
   6843         s7_number_to_chars (buf, value, 4);
   6844 #ifdef OBJ_ELF
   6845       else
   6846         {
   6847           value = fixP->fx_offset;
   6848           s7_number_to_chars (buf, value, 4);
   6849         }
   6850 #endif
   6851       break;
   6852     case BFD_RELOC_VTABLE_INHERIT:
   6853       fixP->fx_done = 0;
   6854       if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
   6855         S_SET_WEAK (fixP->fx_addsy);
   6856       break;
   6857     case BFD_RELOC_VTABLE_ENTRY:
   6858       fixP->fx_done = 0;
   6859       break;
   6860     case BFD_RELOC_SCORE_GPREL15:
   6861       content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
   6862       if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94188000))
   6863         fixP->fx_r_type = BFD_RELOC_NONE;
   6864       fixP->fx_done = 0;
   6865       break;
   6866     case BFD_RELOC_SCORE_GOT15:
   6867     case BFD_RELOC_SCORE_DUMMY_HI16:
   6868     case BFD_RELOC_SCORE_GOT_LO16:
   6869     case BFD_RELOC_SCORE_CALL15:
   6870     case BFD_RELOC_GPREL32:
   6871       break;
   6872     case BFD_RELOC_NONE:
   6873     default:
   6874       as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
   6875     }
   6876 }
   6877 
   6878 /* Translate internal representation of relocation info to BFD target format.  */
   6879 
   6880 static arelent **
   6881 s7_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
   6882 {
   6883   static arelent *retval[MAX_RELOC_EXPANSION + 1];  /* MAX_RELOC_EXPANSION equals 2.  */
   6884   arelent *reloc;
   6885   bfd_reloc_code_real_type code;
   6886   const char *type;
   6887 
   6888   reloc = retval[0] = XNEW (arelent);
   6889   retval[1] = NULL;
   6890 
   6891   reloc->sym_ptr_ptr = XNEW (asymbol *);
   6892   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
   6893   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
   6894   reloc->addend = fixp->fx_offset;
   6895 
   6896   /* If this is a variant frag, we may need to adjust the existing
   6897      reloc and generate a new one.  */
   6898   if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
   6899     {
   6900       /* Update instruction imm bit.  */
   6901       offsetT newval;
   6902       unsigned short off;
   6903       char *buf;
   6904 
   6905       buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
   6906       newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
   6907       off = fixp->fx_offset >> 16;
   6908       newval |= (off & 0x3fff) << 1;
   6909       newval |= ((off >> 14) & 0x3) << 16;
   6910       s7_number_to_chars (buf, newval, s7_INSN_SIZE);
   6911 
   6912       buf += s7_INSN_SIZE;
   6913       newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
   6914       off = fixp->fx_offset & 0xffff;
   6915       newval |= ((off & 0x3fff) << 1);
   6916       newval |= (((off >> 14) & 0x3) << 16);
   6917       s7_number_to_chars (buf, newval, s7_INSN_SIZE);
   6918 
   6919       retval[1] = XNEW (arelent);
   6920       retval[2] = NULL;
   6921       retval[1]->sym_ptr_ptr = XNEW (asymbol *);
   6922       *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
   6923       retval[1]->address = (reloc->address + s7_RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
   6924 
   6925       retval[1]->addend = 0;
   6926       retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
   6927       gas_assert (retval[1]->howto != NULL);
   6928 
   6929       fixp->fx_r_type = BFD_RELOC_HI16_S;
   6930     }
   6931 
   6932   code = fixp->fx_r_type;
   6933   switch (fixp->fx_r_type)
   6934     {
   6935     case BFD_RELOC_32:
   6936       if (fixp->fx_pcrel)
   6937         {
   6938           code = BFD_RELOC_32_PCREL;
   6939           break;
   6940         }
   6941     case BFD_RELOC_HI16_S:
   6942     case BFD_RELOC_LO16:
   6943     case BFD_RELOC_SCORE_JMP:
   6944     case BFD_RELOC_SCORE_BRANCH:
   6945     case BFD_RELOC_SCORE16_JMP:
   6946     case BFD_RELOC_SCORE16_BRANCH:
   6947     case BFD_RELOC_VTABLE_ENTRY:
   6948     case BFD_RELOC_VTABLE_INHERIT:
   6949     case BFD_RELOC_SCORE_GPREL15:
   6950     case BFD_RELOC_SCORE_GOT15:
   6951     case BFD_RELOC_SCORE_DUMMY_HI16:
   6952     case BFD_RELOC_SCORE_GOT_LO16:
   6953     case BFD_RELOC_SCORE_CALL15:
   6954     case BFD_RELOC_GPREL32:
   6955     case BFD_RELOC_NONE:
   6956       code = fixp->fx_r_type;
   6957       break;
   6958     default:
   6959       type = _("<unknown>");
   6960       as_bad_where (fixp->fx_file, fixp->fx_line,
   6961                     _("cannot represent %s relocation in this object file format"), type);
   6962       return NULL;
   6963     }
   6964 
   6965   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
   6966   if (reloc->howto == NULL)
   6967     {
   6968       as_bad_where (fixp->fx_file, fixp->fx_line,
   6969                     _("cannot represent %s relocation in this object file format1"),
   6970                     bfd_get_reloc_code_name (code));
   6971       return NULL;
   6972     }
   6973   /* HACK: Since arm ELF uses Rel instead of Rela, encode the
   6974      vtable entry to be used in the relocation's section offset.  */
   6975   if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
   6976     reloc->address = fixp->fx_offset;
   6977 
   6978   return retval;
   6979 }
   6980