x86: correct "-Q" option handling
[external/binutils.git] / gas / config / tc-score7.c
1 /* tc-score7.c -- Assembler for Score7
2    Copyright (C) 2009-2019 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 \f
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 \f
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 \f
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 \f
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 \f
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_get_section_flags (stdoutput, 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 \f
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 \f
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_get_section_flags (stdoutput, 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 (stdoutput, 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 (stdoutput, 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_get_section_flags (stdoutput, 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_get_section_flags (stdoutput, 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 (stdoutput, 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 \f
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   (void) bfd_set_section_flags (stdoutput, s7_pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
6156   (void) bfd_set_section_alignment (stdoutput, 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_get_section_alignment (stdoutput, 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 }