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