Home | History | Annotate | Download | only in config
      1 /* tc-score7.c -- Assembler for Score7
      2    Copyright (C) 2009-2014 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   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 
   5130       new_i2d = (struct s7_insn_to_dependency *)
   5131           obstack_alloc (&dependency_obstack,
   5132                          sizeof (struct s7_insn_to_dependency));
   5133       new_i2d->insn_name = (char *) obstack_alloc (&dependency_obstack,
   5134                                                    len + 1);
   5135 
   5136       strcpy (new_i2d->insn_name, tmp->insn_name);
   5137       new_i2d->type = tmp->type;
   5138       hash_insert (s7_dependency_insn_hsh, new_i2d->insn_name,
   5139                    (void *) new_i2d);
   5140     }
   5141 }
   5142 
   5143 static valueT
   5144 s7_md_chars_to_number (char *buf, int n)
   5145 {
   5146   valueT result = 0;
   5147   unsigned char *where = (unsigned char *) buf;
   5148 
   5149   if (target_big_endian)
   5150     {
   5151       while (n--)
   5152         {
   5153           result <<= 8;
   5154           result |= (*where++ & 255);
   5155         }
   5156     }
   5157   else
   5158     {
   5159       while (n--)
   5160         {
   5161           result <<= 8;
   5162           result |= (where[n] & 255);
   5163         }
   5164     }
   5165 
   5166   return result;
   5167 }
   5168 
   5169 /* Return true if the given symbol should be considered local for s7_PIC.  */
   5170 
   5171 static bfd_boolean
   5172 s7_pic_need_relax (symbolS *sym, asection *segtype)
   5173 {
   5174   asection *symsec;
   5175   bfd_boolean linkonce;
   5176 
   5177   /* Handle the case of a symbol equated to another symbol.  */
   5178   while (symbol_equated_reloc_p (sym))
   5179     {
   5180       symbolS *n;
   5181 
   5182       /* It's possible to get a loop here in a badly written
   5183 	 program.  */
   5184       n = symbol_get_value_expression (sym)->X_add_symbol;
   5185       if (n == sym)
   5186 	break;
   5187       sym = n;
   5188     }
   5189 
   5190   symsec = S_GET_SEGMENT (sym);
   5191 
   5192   /* Duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
   5193   linkonce = FALSE;
   5194   if (symsec != segtype && ! S_IS_LOCAL (sym))
   5195     {
   5196       if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE) != 0)
   5197 	linkonce = TRUE;
   5198 
   5199       /* The GNU toolchain uses an extension for ELF: a section
   5200 	  beginning with the magic string .gnu.linkonce is a linkonce
   5201 	  section.  */
   5202       if (strncmp (segment_name (symsec), ".gnu.linkonce",
   5203 		   sizeof ".gnu.linkonce" - 1) == 0)
   5204 	linkonce = TRUE;
   5205     }
   5206 
   5207   /* This must duplicate the test in adjust_reloc_syms.  */
   5208   return (!bfd_is_und_section (symsec)
   5209 	  && !bfd_is_abs_section (symsec)
   5210 	  && !bfd_is_com_section (symsec)
   5211 	  && !linkonce
   5212 #ifdef OBJ_ELF
   5213 	  /* A global or weak symbol is treated as external.  */
   5214 	  && (OUTPUT_FLAVOR != bfd_target_elf_flavour
   5215 	      || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
   5216 #endif
   5217 	  );
   5218 }
   5219 
   5220 static int
   5221 s7_judge_size_before_relax (fragS * fragp, asection *sec)
   5222 {
   5223   int change = 0;
   5224 
   5225   if (s7_score_pic == s7_NO_PIC)
   5226     change = s7_nopic_need_relax (fragp->fr_symbol, 0);
   5227   else
   5228     change = s7_pic_need_relax (fragp->fr_symbol, sec);
   5229 
   5230   if (change == 1)
   5231     {
   5232       /* Only at the first time determining whether s7_GP instruction relax should be done,
   5233          return the difference between insntruction size and instruction relax size.  */
   5234       if (fragp->fr_opcode == NULL)
   5235 	{
   5236 	  fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
   5237 	  fragp->fr_opcode = fragp->fr_literal + s7_RELAX_RELOC1 (fragp->fr_subtype);
   5238           return s7_RELAX_NEW (fragp->fr_subtype) - s7_RELAX_OLD (fragp->fr_subtype);
   5239 	}
   5240     }
   5241 
   5242   return 0;
   5243 }
   5244 
   5245 static int
   5246 s7_b32_relax_to_b16 (fragS * fragp)
   5247 {
   5248   int grows = 0;
   5249   int relaxable_p = 0;
   5250   int frag_addr = fragp->fr_address + fragp->insn_addr;
   5251 
   5252   addressT symbol_address = 0;
   5253   symbolS *s;
   5254   offsetT offset;
   5255   unsigned long value;
   5256   unsigned long abs_value;
   5257 
   5258   /* FIXME : here may be able to modify better .
   5259      I don't know how to get the fragp's section ,
   5260      so in relax stage , it may be wrong to calculate the symbol's offset when the frag's section
   5261      is different from the symbol's.  */
   5262 
   5263   relaxable_p = s7_RELAX_OPT (fragp->fr_subtype);
   5264 
   5265   s = fragp->fr_symbol;
   5266   /* b/bl immediate  */
   5267   if (s == NULL)
   5268     frag_addr = 0;
   5269   else
   5270     {
   5271       if (s->bsym != NULL)
   5272 	symbol_address = (addressT) symbol_get_frag (s)->fr_address;
   5273     }
   5274 
   5275   value = s7_md_chars_to_number (fragp->fr_literal, s7_INSN_SIZE);
   5276 
   5277   /* b 32's offset : 20 bit, b 16's tolerate field : 0xff.  */
   5278   offset = ((value & 0x3ff0000) >> 6) | (value & 0x3fe);
   5279   if ((offset & 0x80000) == 0x80000)
   5280     offset |= 0xfff00000;
   5281 
   5282   abs_value = offset + symbol_address - frag_addr;
   5283   if ((abs_value & 0x80000000) == 0x80000000)
   5284     abs_value = 0xffffffff - abs_value + 1;
   5285 
   5286   /* Relax branch 32 to branch 16.  */
   5287   if (relaxable_p && (s->bsym != NULL) && ((abs_value & 0xffffff00) == 0)
   5288       && (S_IS_DEFINED (s) && !S_IS_COMMON (s) && !S_IS_EXTERNAL (s)))
   5289     {
   5290       /* do nothing.  */
   5291     }
   5292   else
   5293     {
   5294       /* Branch 32 can not be relaxed to b 16, so clear OPT bit.  */
   5295       fragp->fr_opcode = NULL;
   5296       fragp->fr_subtype = s7_RELAX_OPT_CLEAR (fragp->fr_subtype);
   5297     }
   5298 
   5299   return grows;
   5300 }
   5301 
   5302 static void
   5303 s7_parse_pce_inst (char *insnstr)
   5304 {
   5305   char c;
   5306   char *p;
   5307   char *q;
   5308   char first[s7_MAX_LITERAL_POOL_SIZE];
   5309   char second[s7_MAX_LITERAL_POOL_SIZE];
   5310   struct s7_score_it pec_part_1;
   5311 
   5312   /* Get first part string of PCE.  */
   5313   p = strstr (insnstr, "||");
   5314   c = *p;
   5315   *p = '\0';
   5316   strcpy (first, insnstr);
   5317 
   5318   /* Get second part string of PCE.  */
   5319   *p = c;
   5320   p += 2;
   5321   strcpy (second, p);
   5322 
   5323   s7_parse_16_32_inst (first, FALSE);
   5324   if (s7_inst.error)
   5325     return;
   5326 
   5327   memcpy (&pec_part_1, &s7_inst, sizeof (s7_inst));
   5328 
   5329   q = second;
   5330   while (q && *q)
   5331     {
   5332       *q = TOLOWER (*q);
   5333       q++;
   5334     }
   5335 
   5336   s7_parse_16_32_inst (second, FALSE);
   5337   if (s7_inst.error)
   5338     return;
   5339 
   5340   if (   ((pec_part_1.size == s7_INSN_SIZE) && (s7_inst.size == s7_INSN_SIZE))
   5341       || ((pec_part_1.size == s7_INSN_SIZE) && (s7_inst.size == s7_INSN16_SIZE))
   5342       || ((pec_part_1.size == s7_INSN16_SIZE) && (s7_inst.size == s7_INSN_SIZE)))
   5343     {
   5344       s7_inst.error = _("pce instruction error (16 bit || 16 bit)'");
   5345       strcpy (s7_inst.str, insnstr);
   5346       return;
   5347     }
   5348 
   5349   if (!s7_inst.error)
   5350     s7_gen_insn_frag (&pec_part_1, &s7_inst);
   5351 }
   5352 
   5353 
   5354 
   5356 static void
   5357 s7_insert_reg (const struct s7_reg_entry *r, struct hash_control *htab)
   5358 {
   5359   int i = 0;
   5360   int len = strlen (r->name) + 2;
   5361   char *buf = xmalloc (len);
   5362   char *buf2 = xmalloc (len);
   5363 
   5364   strcpy (buf + i, r->name);
   5365   for (i = 0; buf[i]; i++)
   5366     {
   5367       buf2[i] = TOUPPER (buf[i]);
   5368     }
   5369   buf2[i] = '\0';
   5370 
   5371   hash_insert (htab, buf, (void *) r);
   5372   hash_insert (htab, buf2, (void *) r);
   5373 }
   5374 
   5375 static void
   5376 s7_build_reg_hsh (struct s7_reg_map *map)
   5377 {
   5378   const struct s7_reg_entry *r;
   5379 
   5380   if ((map->htab = hash_new ()) == NULL)
   5381     {
   5382       as_fatal (_("virtual memory exhausted"));
   5383     }
   5384   for (r = map->names; r->name != NULL; r++)
   5385     {
   5386       s7_insert_reg (r, map->htab);
   5387     }
   5388 }
   5389 
   5390 
   5391 
   5393 /* If we change section we must dump the literal pool first.  */
   5394 static void
   5395 s7_s_score_bss (int ignore ATTRIBUTE_UNUSED)
   5396 {
   5397   subseg_set (bss_section, (subsegT) get_absolute_expression ());
   5398   demand_empty_rest_of_line ();
   5399 }
   5400 
   5401 static void
   5402 s7_s_score_text (int ignore)
   5403 {
   5404   obj_elf_text (ignore);
   5405   record_alignment (now_seg, 2);
   5406 }
   5407 
   5408 static void
   5409 s7_s_section (int ignore)
   5410 {
   5411   obj_elf_section (ignore);
   5412   if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
   5413     record_alignment (now_seg, 2);
   5414 
   5415 }
   5416 
   5417 static void
   5418 s7_s_change_sec (int sec)
   5419 {
   5420   segT seg;
   5421 
   5422 #ifdef OBJ_ELF
   5423   /* The ELF backend needs to know that we are changing sections, so
   5424      that .previous works correctly.  We could do something like check
   5425      for an obj_section_change_hook macro, but that might be confusing
   5426      as it would not be appropriate to use it in the section changing
   5427      functions in read.c, since obj-elf.c intercepts those.  FIXME:
   5428      This should be cleaner, somehow.  */
   5429   obj_elf_section_change_hook ();
   5430 #endif
   5431   switch (sec)
   5432     {
   5433     case 'r':
   5434       seg = subseg_new (s7_RDATA_SECTION_NAME, (subsegT) get_absolute_expression ());
   5435       bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA));
   5436       if (strcmp (TARGET_OS, "elf") != 0)
   5437         record_alignment (seg, 4);
   5438       demand_empty_rest_of_line ();
   5439       break;
   5440     case 's':
   5441       seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
   5442       bfd_set_section_flags (stdoutput, seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
   5443       if (strcmp (TARGET_OS, "elf") != 0)
   5444         record_alignment (seg, 4);
   5445       demand_empty_rest_of_line ();
   5446       break;
   5447     }
   5448 }
   5449 
   5450 static void
   5451 s7_s_score_mask (int reg_type  ATTRIBUTE_UNUSED)
   5452 {
   5453   long mask, off;
   5454 
   5455   if (s7_cur_proc_ptr == NULL)
   5456     {
   5457       as_warn (_(".mask outside of .ent"));
   5458       demand_empty_rest_of_line ();
   5459       return;
   5460     }
   5461   if (get_absolute_expression_and_terminator (&mask) != ',')
   5462     {
   5463       as_warn (_("Bad .mask directive"));
   5464       --input_line_pointer;
   5465       demand_empty_rest_of_line ();
   5466       return;
   5467     }
   5468   off = get_absolute_expression ();
   5469   s7_cur_proc_ptr->reg_mask = mask;
   5470   s7_cur_proc_ptr->reg_offset = off;
   5471   demand_empty_rest_of_line ();
   5472 }
   5473 
   5474 static symbolS *
   5475 s7_get_symbol (void)
   5476 {
   5477   int c;
   5478   char *name;
   5479   symbolS *p;
   5480 
   5481   name = input_line_pointer;
   5482   c = get_symbol_end ();
   5483   p = (symbolS *) symbol_find_or_make (name);
   5484   *input_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   name = input_line_pointer;
   5965   c = get_symbol_end ();
   5966   p = input_line_pointer;
   5967   *p = c;
   5968 
   5969   if (name == p)
   5970     {
   5971       as_bad (_("expected symbol name"));
   5972       discard_rest_of_line ();
   5973       return;
   5974     }
   5975 
   5976   SKIP_WHITESPACE ();
   5977 
   5978   /* Accept an optional comma after the name.  The comma used to be
   5979      required, but Irix 5 cc does not generate it.  */
   5980   if (*input_line_pointer == ',')
   5981     {
   5982       ++input_line_pointer;
   5983       SKIP_WHITESPACE ();
   5984     }
   5985 
   5986   if (is_end_of_line[(unsigned char)*input_line_pointer])
   5987     {
   5988       as_bad (_("missing size expression"));
   5989       return;
   5990     }
   5991 
   5992   if ((temp = get_absolute_expression ()) < 0)
   5993     {
   5994       as_warn (_("BSS length (%d) < 0 ignored"), temp);
   5995       ignore_rest_of_line ();
   5996       return;
   5997     }
   5998 
   5999 #if defined (TC_SCORE)
   6000   if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour)
   6001     {
   6002       /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss.  */
   6003       if ((unsigned) temp <= bfd_get_gp_size (stdoutput))
   6004         {
   6005           bss_seg = subseg_new (".sbss", 1);
   6006           seg_info (bss_seg)->bss = 1;
   6007 #ifdef BFD_ASSEMBLER
   6008           if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
   6009             as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ()));
   6010 #endif
   6011         }
   6012     }
   6013 #endif
   6014 
   6015   SKIP_WHITESPACE ();
   6016   if (*input_line_pointer == ',')
   6017     {
   6018       ++input_line_pointer;
   6019       SKIP_WHITESPACE ();
   6020 
   6021       if (is_end_of_line[(unsigned char)*input_line_pointer])
   6022         {
   6023           as_bad (_("missing alignment"));
   6024           return;
   6025         }
   6026       else
   6027         {
   6028           align = get_absolute_expression ();
   6029           needs_align = 1;
   6030         }
   6031     }
   6032 
   6033   if (!needs_align)
   6034     {
   6035       TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
   6036 
   6037       /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it.  */
   6038       if (align)
   6039         record_alignment (bss_seg, align);
   6040     }
   6041 
   6042   if (needs_align)
   6043     {
   6044       if (bytes_p)
   6045         {
   6046           /* Convert to a power of 2.  */
   6047           if (align != 0)
   6048             {
   6049               unsigned int i;
   6050 
   6051               for (i = 0; align != 0; align >>= 1, ++i)
   6052                 ;
   6053               align = i - 1;
   6054             }
   6055         }
   6056 
   6057       if (align > max_alignment)
   6058         {
   6059           align = max_alignment;
   6060           as_warn (_("alignment too large; %d assumed"), align);
   6061         }
   6062       else if (align < 0)
   6063         {
   6064           align = 0;
   6065           as_warn (_("alignment negative; 0 assumed"));
   6066         }
   6067 
   6068       record_alignment (bss_seg, align);
   6069     }
   6070   else
   6071     {
   6072       /* Assume some objects may require alignment on some systems.  */
   6073 #if defined (TC_ALPHA) && ! defined (VMS)
   6074       if (temp > 1)
   6075         {
   6076           align = ffs (temp) - 1;
   6077           if (temp % (1 << align))
   6078             abort ();
   6079         }
   6080 #endif
   6081     }
   6082 
   6083   *p = 0;
   6084   symbolP = symbol_find_or_make (name);
   6085   *p = c;
   6086 
   6087   if (
   6088 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \
   6089      || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT))
   6090 #ifdef BFD_ASSEMBLER
   6091        (OUTPUT_FLAVOR != bfd_target_aout_flavour
   6092         || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
   6093 #else
   6094        (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
   6095 #endif
   6096 #endif
   6097        (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
   6098     {
   6099       char *pfrag;
   6100 
   6101       subseg_set (bss_seg, 1);
   6102 
   6103       if (align)
   6104         frag_align (align, 0, 0);
   6105 
   6106       /* Detach from old frag.  */
   6107       if (S_GET_SEGMENT (symbolP) == bss_seg)
   6108         symbol_get_frag (symbolP)->fr_symbol = NULL;
   6109 
   6110       symbol_set_frag (symbolP, frag_now);
   6111       pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
   6112       *pfrag = 0;
   6113 
   6114 
   6115       S_SET_SEGMENT (symbolP, bss_seg);
   6116 
   6117 #ifdef OBJ_COFF
   6118       /* The symbol may already have been created with a preceding
   6119          ".globl" directive -- be careful not to step on storage class
   6120          in that case.  Otherwise, set it to static.  */
   6121       if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
   6122         {
   6123           S_SET_STORAGE_CLASS (symbolP, C_STAT);
   6124         }
   6125 #endif /* OBJ_COFF */
   6126 
   6127 #ifdef S_SET_SIZE
   6128       S_SET_SIZE (symbolP, temp);
   6129 #endif
   6130     }
   6131   else
   6132     as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
   6133 
   6134   subseg_set (current_seg, current_subseg);
   6135 
   6136   demand_empty_rest_of_line ();
   6137 }
   6138 
   6139 
   6140 
   6142 static void
   6143 s7_begin (void)
   6144 {
   6145   unsigned int i;
   6146   segT seg;
   6147   subsegT subseg;
   6148 
   6149   if ((s7_score_ops_hsh = hash_new ()) == NULL)
   6150     as_fatal (_("virtual memory exhausted"));
   6151 
   6152   s7_build_score_ops_hsh ();
   6153 
   6154   if ((s7_dependency_insn_hsh = hash_new ()) == NULL)
   6155     as_fatal (_("virtual memory exhausted"));
   6156 
   6157   s7_build_dependency_insn_hsh ();
   6158 
   6159   for (i = (int) REG_TYPE_FIRST; i < (int) s7_REG_TYPE_MAX; i++)
   6160     s7_build_reg_hsh (s7_all_reg_maps + i);
   6161 
   6162   /* Initialize dependency vector.  */
   6163   s7_init_dependency_vector ();
   6164 
   6165   bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
   6166   seg = now_seg;
   6167   subseg = now_subseg;
   6168   s7_pdr_seg = subseg_new (".pdr", (subsegT) 0);
   6169   (void) bfd_set_section_flags (stdoutput, s7_pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
   6170   (void) bfd_set_section_alignment (stdoutput, s7_pdr_seg, 2);
   6171   subseg_set (seg, subseg);
   6172 
   6173   if (s7_USE_GLOBAL_POINTER_OPT)
   6174     bfd_set_gp_size (stdoutput, s7_g_switch_value);
   6175 }
   6176 
   6177 static void
   6178 s7_assemble (char *str)
   6179 {
   6180   know (str);
   6181   know (strlen (str) < s7_MAX_LITERAL_POOL_SIZE);
   6182 
   6183   memset (&s7_inst, '\0', sizeof (s7_inst));
   6184   if (s7_INSN_IS_PCE_P (str))
   6185     s7_parse_pce_inst (str);
   6186   else
   6187     s7_parse_16_32_inst (str, TRUE);
   6188 
   6189   if (s7_inst.error)
   6190     as_bad (_("%s -- `%s'"), s7_inst.error, s7_inst.str);
   6191 }
   6192 
   6193 /* We handle all bad expressions here, so that we can report the faulty
   6194    instruction in the error message.  */
   6195 
   6196 static void
   6197 s7_operand (expressionS * exp)
   6198 {
   6199   if (s7_in_my_get_expression)
   6200     {
   6201       exp->X_op = O_illegal;
   6202       if (s7_inst.error == NULL)
   6203         {
   6204           s7_inst.error = _("bad expression");
   6205         }
   6206     }
   6207 }
   6208 
   6209 /* Turn a string in input_line_pointer into a floating point constant
   6210    of type TYPE, and store the appropriate bytes in *LITP.  The number
   6211    of LITTLENUMS emitted is stored in *SIZEP.  An error message is
   6212    returned, or NULL on OK.
   6213 
   6214    Note that fp constants aren't represent in the normal way on the ARM.
   6215    In big endian mode, things are as expected.  However, in little endian
   6216    mode fp constants are big-endian word-wise, and little-endian byte-wise
   6217    within the words.  For example, (double) 1.1 in big endian mode is
   6218    the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
   6219    the byte sequence 99 99 f1 3f 9a 99 99 99.  */
   6220 
   6221 static char *
   6222 s7_atof (int type, char *litP, int *sizeP)
   6223 {
   6224   int prec;
   6225   LITTLENUM_TYPE words[s7_MAX_LITTLENUMS];
   6226   char *t;
   6227   int i;
   6228 
   6229   switch (type)
   6230     {
   6231     case 'f':
   6232     case 'F':
   6233     case 's':
   6234     case 'S':
   6235       prec = 2;
   6236       break;
   6237     case 'd':
   6238     case 'D':
   6239     case 'r':
   6240     case 'R':
   6241       prec = 4;
   6242       break;
   6243     case 'x':
   6244     case 'X':
   6245     case 'p':
   6246     case 'P':
   6247       prec = 6;
   6248       break;
   6249     default:
   6250       *sizeP = 0;
   6251       return _("bad call to MD_ATOF()");
   6252     }
   6253 
   6254   t = atof_ieee (input_line_pointer, type, words);
   6255   if (t)
   6256     input_line_pointer = t;
   6257   *sizeP = prec * 2;
   6258 
   6259   if (target_big_endian)
   6260     {
   6261       for (i = 0; i < prec; i++)
   6262         {
   6263           s7_number_to_chars (litP, (valueT) words[i], 2);
   6264           litP += 2;
   6265         }
   6266     }
   6267   else
   6268     {
   6269       for (i = 0; i < prec; i += 2)
   6270         {
   6271           s7_number_to_chars (litP, (valueT) words[i + 1], 2);
   6272           s7_number_to_chars (litP + 2, (valueT) words[i], 2);
   6273           litP += 4;
   6274         }
   6275     }
   6276 
   6277   return 0;
   6278 }
   6279 
   6280 /* Implementation of md_frag_check.
   6281    Called after md_convert_frag().  */
   6282 
   6283 static void
   6284 s7_frag_check (fragS * fragp ATTRIBUTE_UNUSED)
   6285 {
   6286   know (fragp->insn_addr <= s7_RELAX_PAD_BYTE);
   6287 }
   6288 
   6289 /* Implementation of TC_VALIDATE_FIX.
   6290    Called before md_apply_fix() and after md_convert_frag().  */
   6291 
   6292 static void
   6293 s7_validate_fix (fixS *fixP)
   6294 {
   6295   fixP->fx_where += fixP->fx_frag->insn_addr;
   6296 }
   6297 
   6298 static int
   6299 s7_force_relocation (struct fix *fixp)
   6300 {
   6301   int retval = 0;
   6302 
   6303   if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
   6304       || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
   6305       || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
   6306       || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
   6307       || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
   6308       || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH)
   6309     {
   6310       retval = 1;
   6311     }
   6312 
   6313   return retval;
   6314 }
   6315 
   6316 static bfd_boolean
   6317 s7_fix_adjustable (fixS * fixP)
   6318 {
   6319   if (fixP->fx_addsy == NULL)
   6320     {
   6321       return 1;
   6322     }
   6323   else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
   6324       && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
   6325     {
   6326       return 0;
   6327     }
   6328   else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
   6329            || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
   6330            || fixP->fx_r_type == BFD_RELOC_SCORE_JMP
   6331            || fixP->fx_r_type == BFD_RELOC_SCORE16_JMP)
   6332     {
   6333       return 0;
   6334     }
   6335 
   6336   return 1;
   6337 }
   6338 
   6339 static void
   6340 s7_elf_final_processing (void)
   6341 {
   6342   unsigned long val = E_SCORE_MACH_SCORE7;
   6343 
   6344   elf_elfheader (stdoutput)->e_machine = EM_SCORE;
   6345   elf_elfheader (stdoutput)->e_flags &= ~EF_SCORE_MACH;
   6346   elf_elfheader (stdoutput)->e_flags |= val;
   6347 
   6348   if (s7_fix_data_dependency == 1)
   6349     {
   6350       elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
   6351     }
   6352   if (s7_score_pic == s7_PIC)
   6353     {
   6354       elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
   6355     }
   6356 }
   6357 
   6358 /* In this function, we determine whether s7_GP instruction should do relaxation,
   6359    for the label being against was known now.
   6360    Doing this here but not in md_relax_frag() can induce iteration times
   6361    in stage of doing relax.  */
   6362 
   6363 static int
   6364 s7_estimate_size_before_relax (fragS * fragp, asection * sec)
   6365 {
   6366   if ((s7_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
   6367       || (s7_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
   6368     return s7_judge_size_before_relax (fragp, sec);
   6369 
   6370   return 0;
   6371 }
   6372 
   6373 static int
   6374 s7_relax_frag (asection * sec ATTRIBUTE_UNUSED,
   6375 	       fragS * fragp,
   6376 	       long stretch ATTRIBUTE_UNUSED)
   6377 {
   6378   int grows = 0;
   6379   int insn_size;
   6380   int do_relax_p = 0;           /* Indicate doing relaxation for this frag.  */
   6381   int relaxable_p = 0;
   6382   bfd_boolean word_align_p = FALSE;
   6383   fragS *next_fragp;
   6384 
   6385   /* If the instruction address is odd, make it half word align first.  */
   6386   if ((fragp->fr_address) % 2 != 0)
   6387     {
   6388       if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
   6389 	{
   6390           fragp->insn_addr = 1;
   6391           grows += 1;
   6392 	}
   6393     }
   6394 
   6395   word_align_p = ((fragp->fr_address + fragp->insn_addr) % 4 == 0) ? TRUE : FALSE;
   6396 
   6397   /* Get instruction size and relax size after the last relaxation.  */
   6398   if (fragp->fr_opcode)
   6399     insn_size = s7_RELAX_NEW (fragp->fr_subtype);
   6400   else
   6401     insn_size = s7_RELAX_OLD (fragp->fr_subtype);
   6402 
   6403   /* Handle specially for s7_GP instruction.  for, s7_judge_size_before_relax() has already determine
   6404      whether the s7_GP instruction should do relax.  */
   6405   if ((s7_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
   6406       || (s7_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
   6407     {
   6408       if (!word_align_p)
   6409         {
   6410           if (fragp->insn_addr < 2)
   6411             {
   6412               fragp->insn_addr += 2;
   6413               grows += 2;
   6414             }
   6415           else
   6416             {
   6417               fragp->insn_addr -= 2;
   6418               grows -= 2;
   6419             }
   6420         }
   6421 
   6422       if (fragp->fr_opcode)
   6423 	fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype) + fragp->insn_addr;
   6424       else
   6425 	fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype) + fragp->insn_addr;
   6426     }
   6427   else
   6428     {
   6429       if (s7_RELAX_TYPE (fragp->fr_subtype) == PC_DISP19div2)
   6430 	s7_b32_relax_to_b16 (fragp);
   6431 
   6432       relaxable_p = s7_RELAX_OPT (fragp->fr_subtype);
   6433       next_fragp = fragp->fr_next;
   6434       while ((next_fragp) && (next_fragp->fr_type != rs_machine_dependent))
   6435 	{
   6436           next_fragp = next_fragp->fr_next;
   6437 	}
   6438 
   6439       if (next_fragp)
   6440         {
   6441           int n_insn_size;
   6442           int n_relaxable_p = 0;
   6443 
   6444           if (next_fragp->fr_opcode)
   6445             {
   6446               n_insn_size = s7_RELAX_NEW (next_fragp->fr_subtype);
   6447             }
   6448           else
   6449             {
   6450               n_insn_size = s7_RELAX_OLD (next_fragp->fr_subtype);
   6451             }
   6452 
   6453           if (s7_RELAX_TYPE (next_fragp->fr_subtype) == PC_DISP19div2)
   6454             s7_b32_relax_to_b16 (next_fragp);
   6455           n_relaxable_p = s7_RELAX_OPT (next_fragp->fr_subtype);
   6456 
   6457           if (word_align_p)
   6458             {
   6459               if (insn_size == 4)
   6460                 {
   6461                   /* 32 -> 16.  */
   6462                   if (relaxable_p && ((n_insn_size == 2) || n_relaxable_p))
   6463                     {
   6464                       grows -= 2;
   6465                       do_relax_p = 1;
   6466                     }
   6467                 }
   6468               else if (insn_size == 2)
   6469                 {
   6470                   /* 16 -> 32.  */
   6471                   if (relaxable_p && (((n_insn_size == 4) && !n_relaxable_p) || (n_insn_size > 4)))
   6472                     {
   6473                       grows += 2;
   6474                       do_relax_p = 1;
   6475                     }
   6476                 }
   6477               else
   6478                 {
   6479 		  abort ();
   6480                 }
   6481             }
   6482           else
   6483             {
   6484               if (insn_size == 4)
   6485                 {
   6486                   /* 32 -> 16.  */
   6487                   if (relaxable_p)
   6488                     {
   6489                       grows -= 2;
   6490                       do_relax_p = 1;
   6491                     }
   6492                   /* Make the 32 bit insturction word align.  */
   6493                   else
   6494                     {
   6495                       fragp->insn_addr += 2;
   6496                       grows += 2;
   6497 		    }
   6498                 }
   6499               else if (insn_size == 2)
   6500                 {
   6501                   /* Do nothing.  */
   6502                 }
   6503               else
   6504                 {
   6505 		  abort ();
   6506                 }
   6507             }
   6508         }
   6509       else
   6510         {
   6511 	  /* Here, try best to do relax regardless fragp->fr_next->fr_type.  */
   6512           if (word_align_p == FALSE)
   6513             {
   6514               if (insn_size % 4 == 0)
   6515                 {
   6516                   /* 32 -> 16.  */
   6517                   if (relaxable_p)
   6518                     {
   6519                       grows -= 2;
   6520                       do_relax_p = 1;
   6521                     }
   6522                   else
   6523                     {
   6524                       fragp->insn_addr += 2;
   6525                       grows += 2;
   6526                     }
   6527                 }
   6528             }
   6529           else
   6530             {
   6531 	      /* Do nothing.  */
   6532             }
   6533         }
   6534 
   6535       /* fragp->fr_opcode indicates whether this frag should be relaxed.  */
   6536       if (do_relax_p)
   6537         {
   6538           if (fragp->fr_opcode)
   6539             {
   6540               fragp->fr_opcode = NULL;
   6541 	      /* Guarantee estimate stage is correct.  */
   6542               fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype);
   6543               fragp->fr_fix += fragp->insn_addr;
   6544             }
   6545           else
   6546             {
   6547               fragp->fr_opcode = fragp->fr_literal + s7_RELAX_RELOC1 (fragp->fr_subtype);
   6548 	      /* Guarantee estimate stage is correct.  */
   6549               fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
   6550               fragp->fr_fix += fragp->insn_addr;
   6551             }
   6552         }
   6553       else
   6554 	{
   6555           if (fragp->fr_opcode)
   6556             {
   6557 	      /* Guarantee estimate stage is correct.  */
   6558               fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
   6559               fragp->fr_fix += fragp->insn_addr;
   6560             }
   6561           else
   6562             {
   6563 	      /* Guarantee estimate stage is correct.  */
   6564               fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype);
   6565               fragp->fr_fix += fragp->insn_addr;
   6566             }
   6567 	}
   6568     }
   6569 
   6570   return grows;
   6571 }
   6572 
   6573 static void
   6574 s7_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
   6575 		 segT sec ATTRIBUTE_UNUSED,
   6576 		 fragS * fragp)
   6577 {
   6578   int r_old;
   6579   int r_new;
   6580   char backup[20];
   6581   fixS *fixp;
   6582 
   6583   r_old = s7_RELAX_OLD (fragp->fr_subtype);
   6584   r_new = s7_RELAX_NEW (fragp->fr_subtype);
   6585 
   6586   /* fragp->fr_opcode indicates whether this frag should be relaxed.  */
   6587   if (fragp->fr_opcode == NULL)
   6588     {
   6589       memcpy (backup, fragp->fr_literal, r_old);
   6590       fragp->fr_fix = r_old;
   6591     }
   6592   else
   6593     {
   6594       memcpy (backup, fragp->fr_literal + r_old, r_new);
   6595       fragp->fr_fix = r_new;
   6596     }
   6597 
   6598   fixp = fragp->tc_frag_data.fixp;
   6599   while (fixp && fixp->fx_frag == fragp && fixp->fx_where < r_old)
   6600     {
   6601       if (fragp->fr_opcode)
   6602 	fixp->fx_done = 1;
   6603       fixp = fixp->fx_next;
   6604     }
   6605   while (fixp && fixp->fx_frag == fragp)
   6606     {
   6607       if (fragp->fr_opcode)
   6608 	fixp->fx_where -= r_old + fragp->insn_addr;
   6609       else
   6610 	fixp->fx_done = 1;
   6611       fixp = fixp->fx_next;
   6612     }
   6613 
   6614   if (fragp->insn_addr)
   6615     {
   6616       s7_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
   6617     }
   6618   memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
   6619   fragp->fr_fix += fragp->insn_addr;
   6620 }
   6621 
   6622 static long
   6623 s7_pcrel_from (fixS * fixP)
   6624 {
   6625   long retval = 0;
   6626 
   6627   if (fixP->fx_addsy
   6628       && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
   6629       && (fixP->fx_subsy == NULL))
   6630     {
   6631       retval = 0;
   6632     }
   6633   else
   6634     {
   6635       retval = fixP->fx_where + fixP->fx_frag->fr_address;
   6636     }
   6637 
   6638   return retval;
   6639 }
   6640 
   6641 /* Round up a section size to the appropriate boundary.  */
   6642 static valueT
   6643 s7_section_align (segT segment, valueT size)
   6644 {
   6645   int align = bfd_get_section_alignment (stdoutput, segment);
   6646 
   6647   return ((size + (1 << align) - 1) & (-1 << align));
   6648 }
   6649 
   6650 static void
   6651 s7_apply_fix (fixS *fixP, valueT *valP, segT seg)
   6652 {
   6653   offsetT value = *valP;
   6654   offsetT abs_value = 0;
   6655   offsetT newval;
   6656   offsetT content;
   6657   unsigned short HI, LO;
   6658 
   6659   char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
   6660 
   6661   gas_assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
   6662   if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
   6663     {
   6664       if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
   6665         fixP->fx_done = 1;
   6666     }
   6667 
   6668   /* If this symbol is in a different section then we need to leave it for
   6669      the linker to deal with.  Unfortunately, md_pcrel_from can't tell,
   6670      so we have to undo it's effects here.  */
   6671   if (fixP->fx_pcrel)
   6672     {
   6673       if (fixP->fx_addsy != NULL
   6674 	  && S_IS_DEFINED (fixP->fx_addsy)
   6675 	  && S_GET_SEGMENT (fixP->fx_addsy) != seg)
   6676 	value += md_pcrel_from (fixP);
   6677     }
   6678 
   6679   /* Remember value for emit_reloc.  */
   6680   fixP->fx_addnumber = value;
   6681 
   6682   switch (fixP->fx_r_type)
   6683     {
   6684     case BFD_RELOC_HI16_S:
   6685       if (fixP->fx_done)
   6686         {                       /* For la rd, imm32.  */
   6687           newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
   6688           HI = (value) >> 16;   /* mul to 2, then take the hi 16 bit.  */
   6689           newval |= (HI & 0x3fff) << 1;
   6690           newval |= ((HI >> 14) & 0x3) << 16;
   6691           s7_number_to_chars (buf, newval, s7_INSN_SIZE);
   6692         }
   6693       break;
   6694     case BFD_RELOC_LO16:
   6695       if (fixP->fx_done)        /* For la rd, imm32.  */
   6696         {
   6697           newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
   6698           LO = (value) & 0xffff;
   6699           newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi.  */
   6700           newval |= ((LO >> 14) & 0x3) << 16;
   6701           s7_number_to_chars (buf, newval, s7_INSN_SIZE);
   6702         }
   6703       break;
   6704     case BFD_RELOC_SCORE_JMP:
   6705       {
   6706         content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
   6707         value = fixP->fx_offset;
   6708         if (!(value >= 0 && value <= 0x1ffffff))
   6709           {
   6710             as_bad_where (fixP->fx_file, fixP->fx_line,
   6711                           _("j or jl truncate (0x%x)  [0 ~ 2^25-1]"), (unsigned int) value);
   6712             return;
   6713           }
   6714         content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
   6715         s7_number_to_chars (buf, content, s7_INSN_SIZE);
   6716       }
   6717       break;
   6718     case BFD_RELOC_SCORE_BRANCH:
   6719       if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
   6720         value = fixP->fx_offset;
   6721       else
   6722         fixP->fx_done = 1;
   6723 
   6724       content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
   6725       if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) != 0x80008000))
   6726         {
   6727           if ((value & 0x80000000) == 0x80000000)
   6728             abs_value = 0xffffffff - value + 1;
   6729           if ((abs_value & 0xffffff00) != 0)
   6730             {
   6731               as_bad_where (fixP->fx_file, fixP->fx_line,
   6732                             _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int) value);
   6733               return;
   6734             }
   6735           content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
   6736           content &= 0xff00;
   6737           content = (content & 0xff00) | ((value >> 1) & 0xff);
   6738           s7_number_to_chars (buf, content, s7_INSN16_SIZE);
   6739           fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
   6740           fixP->fx_size = 2;
   6741         }
   6742       else
   6743         {
   6744           if ((value & 0x80000000) == 0x80000000)
   6745             abs_value = 0xffffffff - value + 1;
   6746           if ((abs_value & 0xfff80000) != 0)
   6747             {
   6748               as_bad_where (fixP->fx_file, fixP->fx_line,
   6749                             _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"),
   6750 			    (unsigned int) value);
   6751               return;
   6752             }
   6753           content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
   6754           content &= 0xfc00fc01;
   6755           content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
   6756           s7_number_to_chars (buf, content, s7_INSN_SIZE);
   6757         }
   6758       break;
   6759     case BFD_RELOC_SCORE16_JMP:
   6760       content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
   6761       content &= 0xf001;
   6762       value = fixP->fx_offset;
   6763       if (!(value >= 0 && value <= 0xfff))
   6764         {
   6765           as_bad_where (fixP->fx_file, fixP->fx_line,
   6766                         _("j! or jl! truncate (0x%x)  [0 ~ 2^12-1]"), (unsigned int) value);
   6767           return;
   6768         }
   6769       value = fixP->fx_offset & 0xfff;
   6770       content = (content & 0xfc01) | (value & 0xffe);
   6771       s7_number_to_chars (buf, content, s7_INSN16_SIZE);
   6772       break;
   6773     case BFD_RELOC_SCORE16_BRANCH:
   6774       content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
   6775       if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) == 0x80008000))
   6776         {
   6777           if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
   6778               (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
   6779             value = fixP->fx_offset;
   6780           else
   6781             fixP->fx_done = 1;
   6782 
   6783           if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
   6784             {
   6785               as_bad_where (fixP->fx_file, fixP->fx_line,
   6786                             _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"),
   6787 			    (unsigned int) value);
   6788               return;
   6789             }
   6790           content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
   6791           content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
   6792           s7_number_to_chars (buf, content, s7_INSN_SIZE);
   6793           fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
   6794           fixP->fx_size = 4;
   6795           break;
   6796         }
   6797       else
   6798         {
   6799           /* In differnt section.  */
   6800           if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
   6801               (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
   6802             value = fixP->fx_offset;
   6803           else
   6804             fixP->fx_done = 1;
   6805 
   6806           if ((value & 0xffffff00) != 0 && (value & 0xffffff00) != 0xffffff00)
   6807             {
   6808               as_bad_where (fixP->fx_file, fixP->fx_line,
   6809                             _(" branch relocation truncate (0x%x)  [-2^8 ~ 2^8]"),
   6810 			    (unsigned int) value);
   6811               return;
   6812             }
   6813           content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
   6814           content = (content & 0xff00) | ((value >> 1) & 0xff);
   6815           s7_number_to_chars (buf, content, s7_INSN16_SIZE);
   6816           break;
   6817         }
   6818     case BFD_RELOC_8:
   6819       if (fixP->fx_done || fixP->fx_pcrel)
   6820 	s7_number_to_chars (buf, value, 1);
   6821 #ifdef OBJ_ELF
   6822       else
   6823         {
   6824           value = fixP->fx_offset;
   6825           s7_number_to_chars (buf, value, 1);
   6826         }
   6827 #endif
   6828       break;
   6829 
   6830     case BFD_RELOC_16:
   6831       if (fixP->fx_done || fixP->fx_pcrel)
   6832         s7_number_to_chars (buf, value, 2);
   6833 #ifdef OBJ_ELF
   6834       else
   6835         {
   6836           value = fixP->fx_offset;
   6837           s7_number_to_chars (buf, value, 2);
   6838         }
   6839 #endif
   6840       break;
   6841     case BFD_RELOC_RVA:
   6842     case BFD_RELOC_32:
   6843       if (fixP->fx_done || fixP->fx_pcrel)
   6844         s7_number_to_chars (buf, value, 4);
   6845 #ifdef OBJ_ELF
   6846       else
   6847         {
   6848           value = fixP->fx_offset;
   6849           s7_number_to_chars (buf, value, 4);
   6850         }
   6851 #endif
   6852       break;
   6853     case BFD_RELOC_VTABLE_INHERIT:
   6854       fixP->fx_done = 0;
   6855       if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
   6856         S_SET_WEAK (fixP->fx_addsy);
   6857       break;
   6858     case BFD_RELOC_VTABLE_ENTRY:
   6859       fixP->fx_done = 0;
   6860       break;
   6861     case BFD_RELOC_SCORE_GPREL15:
   6862       content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
   6863       if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94188000))
   6864         fixP->fx_r_type = BFD_RELOC_NONE;
   6865       fixP->fx_done = 0;
   6866       break;
   6867     case BFD_RELOC_SCORE_GOT15:
   6868     case BFD_RELOC_SCORE_DUMMY_HI16:
   6869     case BFD_RELOC_SCORE_GOT_LO16:
   6870     case BFD_RELOC_SCORE_CALL15:
   6871     case BFD_RELOC_GPREL32:
   6872       break;
   6873     case BFD_RELOC_NONE:
   6874     default:
   6875       as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
   6876     }
   6877 }
   6878 
   6879 /* Translate internal representation of relocation info to BFD target format.  */
   6880 
   6881 static arelent **
   6882 s7_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
   6883 {
   6884   static arelent *retval[MAX_RELOC_EXPANSION + 1];  /* MAX_RELOC_EXPANSION equals 2.  */
   6885   arelent *reloc;
   6886   bfd_reloc_code_real_type code;
   6887   char *type;
   6888 
   6889   reloc = retval[0] = xmalloc (sizeof (arelent));
   6890   retval[1] = NULL;
   6891 
   6892   reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
   6893   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
   6894   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
   6895   reloc->addend = fixp->fx_offset;
   6896 
   6897   /* If this is a variant frag, we may need to adjust the existing
   6898      reloc and generate a new one.  */
   6899   if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
   6900     {
   6901       /* Update instruction imm bit.  */
   6902       offsetT newval;
   6903       unsigned short off;
   6904       char *buf;
   6905 
   6906       buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
   6907       newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
   6908       off = fixp->fx_offset >> 16;
   6909       newval |= (off & 0x3fff) << 1;
   6910       newval |= ((off >> 14) & 0x3) << 16;
   6911       s7_number_to_chars (buf, newval, s7_INSN_SIZE);
   6912 
   6913       buf += s7_INSN_SIZE;
   6914       newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
   6915       off = fixp->fx_offset & 0xffff;
   6916       newval |= ((off & 0x3fff) << 1);
   6917       newval |= (((off >> 14) & 0x3) << 16);
   6918       s7_number_to_chars (buf, newval, s7_INSN_SIZE);
   6919 
   6920       retval[1] = xmalloc (sizeof (arelent));
   6921       retval[2] = NULL;
   6922       retval[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
   6923       *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
   6924       retval[1]->address = (reloc->address + s7_RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
   6925 
   6926       retval[1]->addend = 0;
   6927       retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
   6928       gas_assert (retval[1]->howto != NULL);
   6929 
   6930       fixp->fx_r_type = BFD_RELOC_HI16_S;
   6931     }
   6932 
   6933   code = fixp->fx_r_type;
   6934   switch (fixp->fx_r_type)
   6935     {
   6936     case BFD_RELOC_32:
   6937       if (fixp->fx_pcrel)
   6938         {
   6939           code = BFD_RELOC_32_PCREL;
   6940           break;
   6941         }
   6942     case BFD_RELOC_HI16_S:
   6943     case BFD_RELOC_LO16:
   6944     case BFD_RELOC_SCORE_JMP:
   6945     case BFD_RELOC_SCORE_BRANCH:
   6946     case BFD_RELOC_SCORE16_JMP:
   6947     case BFD_RELOC_SCORE16_BRANCH:
   6948     case BFD_RELOC_VTABLE_ENTRY:
   6949     case BFD_RELOC_VTABLE_INHERIT:
   6950     case BFD_RELOC_SCORE_GPREL15:
   6951     case BFD_RELOC_SCORE_GOT15:
   6952     case BFD_RELOC_SCORE_DUMMY_HI16:
   6953     case BFD_RELOC_SCORE_GOT_LO16:
   6954     case BFD_RELOC_SCORE_CALL15:
   6955     case BFD_RELOC_GPREL32:
   6956     case BFD_RELOC_NONE:
   6957       code = fixp->fx_r_type;
   6958       break;
   6959     default:
   6960       type = _("<unknown>");
   6961       as_bad_where (fixp->fx_file, fixp->fx_line,
   6962                     _("cannot represent %s relocation in this object file format"), type);
   6963       return NULL;
   6964     }
   6965 
   6966   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
   6967   if (reloc->howto == NULL)
   6968     {
   6969       as_bad_where (fixp->fx_file, fixp->fx_line,
   6970                     _("cannot represent %s relocation in this object file format1"),
   6971                     bfd_get_reloc_code_name (code));
   6972       return NULL;
   6973     }
   6974   /* HACK: Since arm ELF uses Rel instead of Rela, encode the
   6975      vtable entry to be used in the relocation's section offset.  */
   6976   if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
   6977     reloc->address = fixp->fx_offset;
   6978 
   6979   return retval;
   6980 }
   6981