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