* bfd/coff-arm.c (coff_arm_relocate_section)
[platform/upstream/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               int value;
3310               unsigned int data_type;
3311
3312               if (pre_inc == 1)
3313                 data_type = _SIMM12;
3314               else
3315                 data_type = _SIMM15;
3316               dataptr = temp;
3317
3318             if ((dataptr != NULL)
3319               && (((strstr (dataptr, "0x")) != NULL)
3320                   || ((strstr (dataptr, "0X")) != NULL)))
3321               {
3322                 hex_p = 1;
3323                 if ((data_type != _SIMM16_LA)
3324                     && (data_type != _VALUE_HI16)
3325                     && (data_type != _VALUE_LO16)
3326                     && (data_type != _IMM16)
3327                     && (data_type != _IMM15)
3328                     && (data_type != _IMM14)
3329                     && (data_type != _IMM4)
3330                     && (data_type != _IMM5)
3331                     && (data_type != _IMM8)
3332                     && (data_type != _SIMM12)
3333                     && (data_type != _SIMM15)
3334                     && (data_type != _IMM5_RSHIFT_1)
3335                     && (data_type != _IMM5_RSHIFT_2)
3336                     && (data_type != _SIMM14_NEG)
3337                     && (data_type != _IMM10_RSHIFT_2))
3338                   {
3339                     data_type += 24;
3340                   }
3341               }
3342
3343               value = s7_validate_immediate (s7_inst.reloc.exp.X_add_number, data_type, hex_p);
3344               if (value == (int) s7_FAIL)
3345                 {
3346                   if (data_type < 30)
3347                     sprintf (s7_err_msg,
3348                              _("invalid constant: %d bit expression not in range %d..%d"),
3349                              s7_score_df_range[data_type].bits,
3350                              s7_score_df_range[data_type].range[0], s7_score_df_range[data_type].range[1]);
3351                   else
3352                     sprintf (s7_err_msg,
3353                              _("invalid constant: %d bit expression not in range %d..%d"),
3354                              s7_score_df_range[data_type - 24].bits,
3355                              s7_score_df_range[data_type - 24].range[0],
3356                              s7_score_df_range[data_type - 24].range[1]);
3357                   s7_inst.error = s7_err_msg;
3358                   return;
3359                 }
3360
3361               value &= (1 << s7_score_df_range[data_type].bits) - 1;
3362               ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
3363               s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
3364               s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + pre_inc].value;
3365               if (pre_inc == 1)
3366                 s7_inst.instruction |= value << 3;
3367               else
3368                 s7_inst.instruction |= value;
3369
3370               /* lw rD, [rA, simm15]  */
3371               if ((s7_inst.instruction & 0x3e000000) == 0x20000000)
3372                 {
3373                   /* Both rD and rA are in [r0 - r15].  */
3374                   if ((((s7_inst.instruction >> 15) & 0x10) == 0)
3375                       && (((s7_inst.instruction >> 20) & 0x10) == 0))
3376                     {
3377                       /* simm15 = 0, lw -> lw!.  */
3378                       if ((s7_inst.instruction & 0x7fff) == 0)
3379                         {
3380                           s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3381                             | (((s7_inst.instruction >> 20) & 0xf) << 8);
3382                           s7_inst.relax_size = 2;
3383                         }
3384                       /* rA = r2, lw -> lwp!.  */
3385                       else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3386                                && ((s7_inst.instruction & 0x3) == 0)
3387                                && ((s7_inst.instruction & 0x7fff) < 128))
3388                         {
3389                           s7_inst.relax_inst = 0x7000 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3390                             | (((s7_inst.instruction & 0x7fff) >> 2) << 3);
3391                           s7_inst.relax_size = 2;
3392                         }
3393                       else
3394                         {
3395                           s7_inst.relax_inst = 0x8000;
3396                         }
3397                     }
3398                   else
3399                     {
3400                       s7_inst.relax_inst = 0x8000;
3401                     }
3402                 }
3403               /* sw rD, [rA, simm15]  */
3404               else if ((s7_inst.instruction & 0x3e000000) == 0x28000000)
3405                 {
3406                   /* Both rD and rA are in [r0 - r15].  */
3407                   if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3408                     {
3409                       /* simm15 = 0, sw -> sw!.  */
3410                       if ((s7_inst.instruction & 0x7fff) == 0)
3411                         {
3412                           s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3413                             | (((s7_inst.instruction >> 20) & 0xf) << 8);
3414                           s7_inst.relax_size = 2;
3415                         }
3416                       /* rA = r2, sw -> swp!.  */
3417                       else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3418                                && ((s7_inst.instruction & 0x3) == 0)
3419                                && ((s7_inst.instruction & 0x7fff) < 128))
3420                         {
3421                           s7_inst.relax_inst = 0x7004 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3422                             | (((s7_inst.instruction & 0x7fff) >> 2) << 3);
3423                           s7_inst.relax_size = 2;
3424                         }
3425                       else
3426                         {
3427                           s7_inst.relax_inst = 0x8000;
3428                         }
3429                     }
3430                   else
3431                     {
3432                       s7_inst.relax_inst = 0x8000;
3433                     }
3434                 }
3435               /* sw rD, [rA, simm15]+    sw pre.  */
3436               else if ((s7_inst.instruction & 0x3e000007) == 0x06000004)
3437                 {
3438                   /* rA is in [r0 - r7], and simm15 = -4.  */
3439                   if ((((s7_inst.instruction >> 15) & 0x18) == 0)
3440                       && (((s7_inst.instruction >> 3) & 0xfff) == 0xffc))
3441                     {
3442                       /* sw -> pushhi!.  */
3443                       if ((((s7_inst.instruction >> 20) & 0x10) == 0x10))
3444                         {
3445                           s7_inst.relax_inst = 0x0000200e | (((s7_inst.instruction >> 20) & 0xf) << 8)
3446                             | 1 << 7 | (((s7_inst.instruction >> 15) & 0x7) << 4);
3447                           s7_inst.relax_size = 2;
3448                         }
3449                       /* sw -> push!.  */
3450                       else
3451                         {
3452                           s7_inst.relax_inst = 0x0000200e | (((s7_inst.instruction >> 20) & 0xf) << 8)
3453                             | 0 << 7 | (((s7_inst.instruction >> 15) & 0x7) << 4);
3454                           s7_inst.relax_size = 2;
3455                         }
3456                     }
3457                   else
3458                     {
3459                       s7_inst.relax_inst = 0x8000;
3460                     }
3461                 }
3462               /* lh rD, [rA, simm15]  */
3463               else if ((s7_inst.instruction & 0x3e000000) == 0x22000000)
3464                 {
3465                   /* Both rD and rA are in [r0 - r15].  */
3466                   if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3467                     {
3468                       /* simm15 = 0, lh -> lh!.  */
3469                       if ((s7_inst.instruction & 0x7fff) == 0)
3470                         {
3471                           s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3472                             | (((s7_inst.instruction >> 20) & 0xf) << 8);
3473                           s7_inst.relax_size = 2;
3474                         }
3475                       /* rA = r2, lh -> lhp!.  */
3476                       else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3477                                && ((s7_inst.instruction & 0x1) == 0)
3478                                && ((s7_inst.instruction & 0x7fff) < 64))
3479                         {
3480                           s7_inst.relax_inst = 0x7001 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3481                             | (((s7_inst.instruction & 0x7fff) >> 1) << 3);
3482                           s7_inst.relax_size = 2;
3483                         }
3484                       else
3485                         {
3486                           s7_inst.relax_inst = 0x8000;
3487                         }
3488                     }
3489                   else
3490                     {
3491                       s7_inst.relax_inst = 0x8000;
3492                     }
3493                 }
3494               /* sh rD, [rA, simm15]  */
3495               else if ((s7_inst.instruction & 0x3e000000) == 0x2a000000)
3496                 {
3497                   /* Both rD and rA are in [r0 - r15].  */
3498                   if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3499                     {
3500                       /* simm15 = 0, sh -> sh!.  */
3501                       if ((s7_inst.instruction & 0x7fff) == 0)
3502                         {
3503                           s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3504                             | (((s7_inst.instruction >> 20) & 0xf) << 8);
3505                           s7_inst.relax_size = 2;
3506                         }
3507                       /* rA = r2, sh -> shp!.  */
3508                       else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3509                                && ((s7_inst.instruction & 0x1) == 0)
3510                                && ((s7_inst.instruction & 0x7fff) < 64))
3511                         {
3512                           s7_inst.relax_inst = 0x7005 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3513                             | (((s7_inst.instruction & 0x7fff) >> 1) << 3);
3514                           s7_inst.relax_size = 2;
3515                         }
3516                       else
3517                         {
3518                           s7_inst.relax_inst = 0x8000;
3519                         }
3520                     }
3521                   else
3522                     {
3523                       s7_inst.relax_inst = 0x8000;
3524                     }
3525                 }
3526               /* lbu rD, [rA, simm15]  */
3527               else if ((s7_inst.instruction & 0x3e000000) == 0x2c000000)
3528                 {
3529                   /* Both rD and rA are in [r0 - r15].  */
3530                   if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3531                     {
3532                       /* simm15 = 0, lbu -> lbu!.  */
3533                       if ((s7_inst.instruction & 0x7fff) == 0)
3534                         {
3535                           s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3536                             | (((s7_inst.instruction >> 20) & 0xf) << 8);
3537                           s7_inst.relax_size = 2;
3538                         }
3539                       /* rA = r2, lbu -> lbup!.  */
3540                       else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3541                                && ((s7_inst.instruction & 0x7fff) < 32))
3542                         {
3543                           s7_inst.relax_inst = 0x7003 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3544                             | ((s7_inst.instruction & 0x7fff) << 3);
3545                           s7_inst.relax_size = 2;
3546                         }
3547                       else
3548                         {
3549                           s7_inst.relax_inst = 0x8000;
3550                         }
3551                     }
3552                   else
3553                     {
3554                       s7_inst.relax_inst = 0x8000;
3555                     }
3556                 }
3557               /* sb rD, [rA, simm15]  */
3558               else if ((s7_inst.instruction & 0x3e000000) == 0x2e000000)
3559                 {
3560                   /* Both rD and rA are in [r0 - r15].  */
3561                   if ((((s7_inst.instruction >> 15) & 0x10) == 0) && (((s7_inst.instruction >> 20) & 0x10) == 0))
3562                     {
3563                       /* simm15 = 0, sb -> sb!.  */
3564                       if ((s7_inst.instruction & 0x7fff) == 0)
3565                         {
3566                           s7_inst.relax_inst |= (((s7_inst.instruction >> 15) & 0xf) << 4)
3567                             | (((s7_inst.instruction >> 20) & 0xf) << 8);
3568                           s7_inst.relax_size = 2;
3569                         }
3570                       /* rA = r2, sb -> sb!.  */
3571                       else if ((((s7_inst.instruction >> 15) & 0xf) == 2)
3572                                && ((s7_inst.instruction & 0x7fff) < 32))
3573                         {
3574                           s7_inst.relax_inst = 0x7007 | (((s7_inst.instruction >> 20) & 0xf) << 8)
3575                             | ((s7_inst.instruction & 0x7fff) << 3);
3576                           s7_inst.relax_size = 2;
3577                         }
3578                       else
3579                         {
3580                           s7_inst.relax_inst = 0x8000;
3581                         }
3582                     }
3583                   else
3584                     {
3585                       s7_inst.relax_inst = 0x8000;
3586                     }
3587                 }
3588               else
3589                 {
3590                   s7_inst.relax_inst = 0x8000;
3591                 }
3592
3593               return;
3594             }
3595           else
3596             {
3597               /* FIXME: may set error, for there is no ld/sw rD, [rA, label] */
3598               s7_inst.reloc.pc_rel = 0;
3599             }
3600         }
3601     }
3602   else
3603     {
3604       s7_inst.error = s7_BAD_ARGS;
3605     }
3606 }
3607
3608 /* Handle cache.  */
3609 static void
3610 s7_do_cache (char *str)
3611 {
3612   s7_skip_whitespace (str);
3613
3614   if ((s7_data_op2 (&str, 20, _IMM5) == (int) s7_FAIL) || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3615     {
3616       return;
3617     }
3618   else
3619     {
3620       int cache_op;
3621
3622       cache_op = (s7_inst.instruction >> 20) & 0x1F;
3623       sprintf (s7_inst.name, "cache %d", cache_op);
3624     }
3625
3626   if (*str == '[')
3627     {
3628       str++;
3629       s7_skip_whitespace (str);
3630
3631       if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
3632         return;
3633
3634       s7_skip_whitespace (str);
3635
3636       /* cache op, [rA]  */
3637       if (s7_skip_past_comma (&str) == (int) s7_FAIL)
3638         {
3639           s7_SET_INSN_ERROR (NULL);
3640           if (*str != ']')
3641             {
3642               s7_inst.error = _("missing ]");
3643               return;
3644             }
3645           str++;
3646         }
3647       /* cache op, [rA, simm15]  */
3648       else
3649         {
3650           if (s7_exp_ldst_offset (&str, 0, _SIMM15) == (int) s7_FAIL)
3651             {
3652               return;
3653             }
3654
3655           s7_skip_whitespace (str);
3656           if (*str++ != ']')
3657             {
3658               s7_inst.error = _("missing ]");
3659               return;
3660             }
3661         }
3662
3663       if (s7_end_of_line (str) == (int) s7_FAIL)
3664         return;
3665     }
3666   else
3667     {
3668       s7_inst.error = s7_BAD_ARGS;
3669     }
3670 }
3671
3672 static void
3673 s7_do_crdcrscrsimm5 (char *str)
3674 {
3675   char *strbak;
3676
3677   strbak = str;
3678   s7_skip_whitespace (str);
3679
3680   if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL
3681       || s7_skip_past_comma (&str) == (int) s7_FAIL
3682       || s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL
3683       || s7_skip_past_comma (&str) == (int) s7_FAIL
3684       || s7_reg_required_here (&str, 10, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL
3685       || s7_skip_past_comma (&str) == (int) s7_FAIL)
3686     {
3687       str = strbak;
3688       /* cop1 cop_code20.  */
3689       if (s7_data_op2 (&str, 5, _IMM20) == (int) s7_FAIL)
3690         return;
3691     }
3692   else
3693     {
3694       if (s7_data_op2 (&str, 5, _IMM5) == (int) s7_FAIL)
3695         return;
3696     }
3697
3698   s7_end_of_line (str);
3699 }
3700
3701 /* Handle ldc/stc.  */
3702 static void
3703 s7_do_ldst_cop (char *str)
3704 {
3705   s7_skip_whitespace (str);
3706
3707   if ((s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE_CR) == (int) s7_FAIL)
3708       || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3709     return;
3710
3711   if (*str == '[')
3712     {
3713       str++;
3714       s7_skip_whitespace (str);
3715
3716       if (s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
3717         return;
3718
3719       s7_skip_whitespace (str);
3720
3721       if (*str++ != ']')
3722         {
3723           if (s7_exp_ldst_offset (&str, 5, _IMM10_RSHIFT_2) == (int) s7_FAIL)
3724             return;
3725
3726           s7_skip_whitespace (str);
3727           if (*str++ != ']')
3728             {
3729               s7_inst.error = _("missing ]");
3730               return;
3731             }
3732         }
3733
3734       s7_end_of_line (str);
3735     }
3736   else
3737     s7_inst.error = s7_BAD_ARGS;
3738 }
3739
3740 static void
3741 s7_do16_ldst_insn (char *str)
3742 {
3743   s7_skip_whitespace (str);
3744
3745   if ((s7_reglow_required_here (&str, 8) == (int) s7_FAIL) || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3746     return;
3747
3748   if (*str == '[')
3749     {
3750       int reg;
3751
3752       str++;
3753       s7_skip_whitespace (str);
3754
3755       if ((reg = s7_reglow_required_here (&str, 4)) == (int) s7_FAIL)
3756         return;
3757
3758       s7_skip_whitespace (str);
3759       if (*str++ == ']')
3760         {
3761           if (s7_end_of_line (str) == (int) s7_FAIL)
3762             return;
3763           else
3764             {
3765               s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
3766                               | (((s7_inst.instruction >> 4) & 0xf) << 15);
3767               s7_inst.relax_size = 4;
3768             }
3769         }
3770       else
3771         {
3772           s7_inst.error = _("missing ]");
3773         }
3774     }
3775   else
3776     {
3777       s7_inst.error = s7_BAD_ARGS;
3778     }
3779 }
3780
3781 /* Handle lbup!/lhp!/ldiu!/lwp!/sbp!/shp!/swp!.  */
3782
3783 static void
3784 s7_do16_ldst_imm_insn (char *str)
3785 {
3786   char data_exp[s7_MAX_LITERAL_POOL_SIZE];
3787   int reg_rd;
3788   char *dataptr = NULL, *pp = NULL;
3789   int cnt = 0;
3790   int assign_data = (int) s7_FAIL;
3791   unsigned int ldst_func;
3792
3793   s7_skip_whitespace (str);
3794
3795   if (((reg_rd = s7_reglow_required_here (&str, 8)) == (int) s7_FAIL)
3796       || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3797     return;
3798
3799   s7_skip_whitespace (str);
3800   dataptr = str;
3801
3802   while ((*dataptr != '\0') && (*dataptr != '|') && (cnt <= s7_MAX_LITERAL_POOL_SIZE))
3803     {
3804       data_exp[cnt] = *dataptr;
3805       dataptr++;
3806       cnt++;
3807     }
3808
3809   data_exp[cnt] = '\0';
3810   pp = &data_exp[0];
3811
3812   str = dataptr;
3813
3814   ldst_func = s7_inst.instruction & LDST16_RI_MASK;
3815   if (ldst_func == N16_LIU)
3816     assign_data = s7_exp_ldst_offset (&pp, 0, _IMM8);
3817   else if (ldst_func == N16_LHP || ldst_func == N16_SHP)
3818     assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_1);
3819   else if (ldst_func == N16_LWP || ldst_func == N16_SWP)
3820     assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5_RSHIFT_2);
3821   else
3822     assign_data = s7_exp_ldst_offset (&pp, 3, _IMM5);
3823
3824   if ((assign_data == (int) s7_FAIL) || (s7_end_of_line (pp) == (int) s7_FAIL))
3825     return;
3826   else
3827     {
3828       if ((s7_inst.instruction & 0x7000) == N16_LIU)
3829         {
3830           s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20
3831                           | ((s7_inst.instruction & 0xff) << 1);
3832         }
3833       else if (((s7_inst.instruction & 0x7007) == N16_LHP)
3834                || ((s7_inst.instruction & 0x7007) == N16_SHP))
3835         {
3836           s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3837                           | (((s7_inst.instruction >> 3) & 0x1f) << 1);
3838         }
3839       else if (((s7_inst.instruction & 0x7007) == N16_LWP)
3840                || ((s7_inst.instruction & 0x7007) == N16_SWP))
3841         {
3842           s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3843                           | (((s7_inst.instruction >> 3) & 0x1f) << 2);
3844         }
3845       else if (((s7_inst.instruction & 0x7007) == N16_LBUP)
3846                || ((s7_inst.instruction & 0x7007) == N16_SBP))
3847         {
3848           s7_inst.relax_inst |= ((s7_inst.instruction >> 8) & 0xf) << 20 | 2 << 15
3849                           | (((s7_inst.instruction >> 3) & 0x1f));
3850         }
3851
3852       s7_inst.relax_size = 4;
3853     }
3854 }
3855
3856 static void
3857 s7_do16_push_pop (char *str)
3858 {
3859   int reg_rd;
3860   int H_bit_mask = 0;
3861
3862   s7_skip_whitespace (str);
3863   if (((reg_rd = s7_reg_required_here (&str, 8, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3864       || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3865     return;
3866
3867   if (reg_rd >= 16)
3868     H_bit_mask = 1;
3869
3870   /* s7_reg_required_here will change bit 12 of opcode, so we must restore bit 12.  */
3871   s7_inst.instruction &= ~(1 << 12);
3872
3873   s7_inst.instruction |= H_bit_mask << 7;
3874
3875   if (*str == '[')
3876     {
3877       int reg;
3878
3879       str++;
3880       s7_skip_whitespace (str);
3881       if ((reg = s7_reg_required_here (&str, 4, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3882         return;
3883       else if (reg > 7)
3884         {
3885           if (!s7_inst.error)
3886             s7_inst.error = _("base register nums are over 3 bit");
3887
3888           return;
3889         }
3890
3891       s7_skip_whitespace (str);
3892       if ((*str++ != ']') || (s7_end_of_line (str) == (int) s7_FAIL))
3893         {
3894           if (!s7_inst.error)
3895             s7_inst.error = _("missing ]");
3896
3897           return;
3898         }
3899
3900       /* pop! */
3901       if ((s7_inst.instruction & 0xf) == 0xa)
3902         {
3903           if (H_bit_mask)
3904             {
3905               s7_inst.relax_inst |= ((((s7_inst.instruction >> 8) & 0xf) | 0x10) << 20)
3906                                   | (((s7_inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3907             }
3908           else
3909             {
3910               s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
3911                                   | (((s7_inst.instruction >> 4) & 0x7) << 15) | (4 << 3);
3912             }
3913         }
3914       /* push! */
3915       else
3916         {
3917           if (H_bit_mask)
3918             {
3919               s7_inst.relax_inst |= ((((s7_inst.instruction >> 8) & 0xf) | 0x10) << 20)
3920                                   | (((s7_inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3921             }
3922           else
3923             {
3924               s7_inst.relax_inst |= (((s7_inst.instruction >> 8) & 0xf) << 20)
3925                                   | (((s7_inst.instruction >> 4) & 0x7) << 15) | (((-4) & 0xfff) << 3);
3926             }
3927         }
3928       s7_inst.relax_size = 4;
3929     }
3930   else
3931     {
3932       s7_inst.error = s7_BAD_ARGS;
3933     }
3934 }
3935
3936 /* Handle lcb/lcw/lce/scb/scw/sce.  */
3937 static void
3938 s7_do_ldst_unalign (char *str)
3939 {
3940   int conflict_reg;
3941
3942   if (s7_university_version == 1)
3943     {
3944       s7_inst.error = s7_ERR_FOR_SCORE5U_ATOMIC;
3945       return;
3946     }
3947
3948   s7_skip_whitespace (str);
3949
3950   /* lcb/scb [rA]+.  */
3951   if (*str == '[')
3952     {
3953       str++;
3954       s7_skip_whitespace (str);
3955
3956       if (s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
3957         return;
3958
3959       if (*str++ == ']')
3960         {
3961           if (*str++ != '+')
3962             {
3963               s7_inst.error = _("missing +");
3964               return;
3965             }
3966         }
3967       else
3968         {
3969           s7_inst.error = _("missing ]");
3970           return;
3971         }
3972
3973       if (s7_end_of_line (str) == (int) s7_FAIL)
3974         return;
3975     }
3976   /* lcw/lce/scb/sce rD, [rA]+.  */
3977   else
3978     {
3979       if (((conflict_reg = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3980           || (s7_skip_past_comma (&str) == (int) s7_FAIL))
3981         {
3982           return;
3983         }
3984
3985       s7_skip_whitespace (str);
3986       if (*str++ == '[')
3987         {
3988           int reg;
3989
3990           s7_skip_whitespace (str);
3991           if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
3992             {
3993               return;
3994             }
3995
3996           /* Conflicts can occur on stores as well as loads.  */
3997           conflict_reg = (conflict_reg == reg);
3998           s7_skip_whitespace (str);
3999           if (*str++ == ']')
4000             {
4001               unsigned int ldst_func = s7_inst.instruction & LDST_UNALIGN_MASK;
4002
4003               if (*str++ == '+')
4004                 {
4005                   if (conflict_reg)
4006                     {
4007                       as_warn (_("%s register same as write-back base"),
4008                                ((ldst_func & UA_LCE) || (ldst_func & UA_LCW)
4009                                 ? _("destination") : _("source")));
4010                     }
4011                 }
4012               else
4013                 {
4014                   s7_inst.error = _("missing +");
4015                   return;
4016                 }
4017
4018               if (s7_end_of_line (str) == (int) s7_FAIL)
4019                 return;
4020             }
4021           else
4022             {
4023               s7_inst.error = _("missing ]");
4024               return;
4025             }
4026         }
4027       else
4028         {
4029           s7_inst.error = s7_BAD_ARGS;
4030           return;
4031         }
4032     }
4033 }
4034
4035 /* Handle alw/asw.  */
4036
4037 static void
4038 s7_do_ldst_atomic (char *str)
4039 {
4040   if (s7_university_version == 1)
4041     {
4042       s7_inst.error = s7_ERR_FOR_SCORE5U_ATOMIC;
4043       return;
4044     }
4045
4046   s7_skip_whitespace (str);
4047
4048   if ((s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE) == (int) s7_FAIL)
4049       || (s7_skip_past_comma (&str) == (int) s7_FAIL))
4050     {
4051       return;
4052     }
4053   else
4054     {
4055
4056       s7_skip_whitespace (str);
4057       if (*str++ == '[')
4058         {
4059           int reg;
4060
4061           s7_skip_whitespace (str);
4062           if ((reg = s7_reg_required_here (&str, 15, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4063             {
4064               return;
4065             }
4066
4067           s7_skip_whitespace (str);
4068           if (*str++ != ']')
4069             {
4070               s7_inst.error = _("missing ]");
4071               return;
4072             }
4073
4074           s7_end_of_line (str);
4075         }
4076       else
4077         s7_inst.error = s7_BAD_ARGS;
4078     }
4079 }
4080
4081 static void
4082 s7_build_relax_frag (struct s7_score_it fix_insts[s7_RELAX_INST_NUM],
4083                      int fix_num ATTRIBUTE_UNUSED,
4084                      struct s7_score_it var_insts[s7_RELAX_INST_NUM], int var_num,
4085                      symbolS *add_symbol)
4086 {
4087   int i;
4088   char *p;
4089   fixS *fixp = NULL;
4090   fixS *cur_fixp = NULL;
4091   long where;
4092   struct s7_score_it inst_main;
4093
4094   memcpy (&inst_main, &fix_insts[0], sizeof (struct s7_score_it));
4095
4096   /* Adjust instruction opcode and to be relaxed instruction opcode.  */
4097   inst_main.instruction = s7_adjust_paritybit (inst_main.instruction, s7_GET_INSN_CLASS (inst_main.type));
4098   inst_main.type = Insn_PIC;
4099
4100   for (i = 0; i < var_num; i++)
4101     {
4102       inst_main.relax_size += var_insts[i].size;
4103       var_insts[i].instruction = s7_adjust_paritybit (var_insts[i].instruction,
4104                                                    s7_GET_INSN_CLASS (var_insts[i].type));
4105     }
4106
4107   /* Check data dependency.  */
4108   s7_handle_dependency (&inst_main);
4109
4110   /* Start a new frag if frag_now is not empty.  */
4111   if (frag_now_fix () != 0)
4112     {
4113       if (!frag_now->tc_frag_data.is_insn)
4114         {
4115           frag_wane (frag_now);
4116         }
4117       frag_new (0);
4118     }
4119   frag_grow (20);
4120
4121   /* Write fr_fix part.  */
4122   p = frag_more (inst_main.size);
4123   s7_number_to_chars (p, inst_main.instruction, inst_main.size);
4124
4125   if (inst_main.reloc.type != BFD_RELOC_NONE)
4126     fixp = s7_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4127                           &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4128
4129   frag_now->tc_frag_data.fixp = fixp;
4130   cur_fixp = frag_now->tc_frag_data.fixp;
4131
4132 #ifdef OBJ_ELF
4133   dwarf2_emit_insn (inst_main.size);
4134 #endif
4135
4136   where = p - frag_now->fr_literal + inst_main.size;
4137   for (i = 0; i < var_num; i++)
4138     {
4139       if (i > 0)
4140         where += var_insts[i - 1].size;
4141
4142       if (var_insts[i].reloc.type != BFD_RELOC_NONE)
4143         {
4144           fixp = s7_fix_new_score (frag_now, where, var_insts[i].size,
4145                                 &var_insts[i].reloc.exp, var_insts[i].reloc.pc_rel,
4146                                 var_insts[i].reloc.type);
4147           if (fixp)
4148             {
4149               if (cur_fixp)
4150                 {
4151                   cur_fixp->fx_next = fixp;
4152                   cur_fixp = cur_fixp->fx_next;
4153                 }
4154               else
4155                 {
4156                   frag_now->tc_frag_data.fixp = fixp;
4157                   cur_fixp = frag_now->tc_frag_data.fixp;
4158                 }
4159             }
4160         }
4161     }
4162
4163   p = frag_var (rs_machine_dependent, inst_main.relax_size + s7_RELAX_PAD_BYTE, 0,
4164                 s7_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type,
4165                 0, inst_main.size, 0), add_symbol, 0, NULL);
4166
4167   /* Write fr_var part.
4168      no calling s7_gen_insn_frag, no fixS will be generated.  */
4169   for (i = 0; i < var_num; i++)
4170     {
4171       s7_number_to_chars (p, var_insts[i].instruction, var_insts[i].size);
4172       p += var_insts[i].size;
4173     }
4174   /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4175   s7_inst.bwarn = -1;
4176 }
4177
4178 /* Build a relax frag for la instruction when generating s7_PIC,
4179    external symbol first and local symbol second.  */
4180
4181 static void
4182 s7_build_la_pic (int reg_rd, expressionS exp)
4183 {
4184   symbolS *add_symbol = exp.X_add_symbol;
4185   offsetT add_number = exp.X_add_number;
4186   struct s7_score_it fix_insts[s7_RELAX_INST_NUM];
4187   struct s7_score_it var_insts[s7_RELAX_INST_NUM];
4188   int fix_num = 0;
4189   int var_num = 0;
4190   char tmp[s7_MAX_LITERAL_POOL_SIZE];
4191   int r1_bak;
4192
4193   r1_bak = s7_nor1;
4194   s7_nor1 = 0;
4195
4196   if (add_number == 0)
4197     {
4198       fix_num = 1;
4199       var_num = 2;
4200
4201       /* For an external symbol, only one insn is generated;
4202          For a local symbol, two insns are generated.  */
4203       /* Fix part
4204          For an external symbol: lw rD, <sym>($gp)
4205                                  (BFD_RELOC_SCORE_GOT15 or BFD_RELOC_SCORE_CALL15)  */
4206       sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4207       if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4208         return;
4209
4210       if (reg_rd == s7_PIC_CALL_REG)
4211         s7_inst.reloc.type = BFD_RELOC_SCORE_CALL15;
4212       memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4213
4214       /* Var part
4215          For a local symbol :
4216          lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)
4217          addi rD, <sym>       (BFD_RELOC_GOT_LO16) */
4218       s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4219       memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4220       sprintf (tmp, "addi_s_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4221       if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4222         return;
4223
4224       memcpy (&var_insts[1], &s7_inst, sizeof (struct s7_score_it));
4225       s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4226     }
4227   else if (add_number >= -0x8000 && add_number <= 0x7fff)
4228     {
4229       /* Insn 1: lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)  */
4230       sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4231       if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4232         return;
4233
4234       /* Insn 2  */
4235       fix_num = 1;
4236       var_num = 1;
4237       /* Fix part
4238          For an external symbol: addi rD, <constant> */
4239       sprintf (tmp, "addi r%d, %d", reg_rd, (int) add_number);
4240       if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4241         return;
4242
4243       memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4244
4245       /* Var part
4246          For a local symbol: addi rD, <sym>+<constant>    (BFD_RELOC_GOT_LO16)  */
4247       sprintf (tmp, "addi_s_pic r%d, %s + %d", reg_rd, add_symbol->bsym->name, (int) add_number);
4248       if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4249         return;
4250
4251       memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4252       s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4253     }
4254   else
4255     {
4256       int hi = (add_number >> 16) & 0x0000FFFF;
4257       int lo = add_number & 0x0000FFFF;
4258
4259       /* Insn 1: lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)  */
4260       sprintf (tmp, "lw_pic r%d, %s", reg_rd, add_symbol->bsym->name);
4261       if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4262         return;
4263
4264       /* Insn 2  */
4265       fix_num = 1;
4266       var_num = 1;
4267       /* Fix part
4268          For an external symbol: ldis r1, HI%<constant>  */
4269       sprintf (tmp, "ldis r1, %d", hi);
4270       if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4271         return;
4272
4273       memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4274
4275       /* Var part
4276          For a local symbol: ldis r1, HI%<constant>
4277          but, if lo is outof 16 bit, make hi plus 1  */
4278       if ((lo < -0x8000) || (lo > 0x7fff))
4279         {
4280           hi += 1;
4281         }
4282       sprintf (tmp, "ldis_pic r1, %d", hi);
4283       if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4284         return;
4285
4286       memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4287       s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4288
4289       /* Insn 3  */
4290       fix_num = 1;
4291       var_num = 1;
4292       /* Fix part
4293          For an external symbol: ori r1, LO%<constant>  */
4294       sprintf (tmp, "ori r1, %d", lo);
4295       if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4296         return;
4297
4298       memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4299
4300       /* Var part
4301          For a local symbol: addi r1, <sym>+LO%<constant>    (BFD_RELOC_GOT_LO16)  */
4302       sprintf (tmp, "addi_u_pic r1, %s + %d", add_symbol->bsym->name, lo);
4303       if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4304         return;
4305
4306       memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4307       s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4308
4309       /* Insn 4: add rD, rD, r1  */
4310       sprintf (tmp, "add r%d, r%d, r1", reg_rd, reg_rd);
4311       if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4312         return;
4313
4314      /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4315      s7_inst.bwarn = -1;
4316     }
4317
4318   s7_nor1 = r1_bak;
4319 }
4320
4321 /* Handle la.  */
4322
4323 static void
4324 s7_do_macro_la_rdi32 (char *str)
4325 {
4326   int reg_rd;
4327
4328   s7_skip_whitespace (str);
4329   if ((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
4330       || s7_skip_past_comma (&str) == (int) s7_FAIL)
4331     {
4332       return;
4333     }
4334   else
4335     {
4336       char append_str[s7_MAX_LITERAL_POOL_SIZE];
4337       char *keep_data = str;
4338
4339       /* Check immediate value.  */
4340       if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
4341         {
4342           s7_inst.error = _("expression error");
4343           return;
4344         }
4345       else if ((s7_inst.reloc.exp.X_add_symbol == NULL)
4346                && (s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _IMM32, 0) == (int) s7_FAIL))
4347         {
4348           s7_inst.error = _("value not in range [0, 0xffffffff]");
4349           return;
4350         }
4351
4352       /* Reset str.  */
4353       str = keep_data;
4354
4355       /* la rd, simm16.  */
4356       if (s7_data_op2 (&str, 1, _SIMM16_LA) != (int) s7_FAIL)
4357         {
4358           s7_end_of_line (str);
4359           return;
4360         }
4361       /* la rd, imm32 or la rd, label.  */
4362       else
4363         {
4364           s7_SET_INSN_ERROR (NULL);
4365           str = keep_data;
4366           if ((s7_data_op2 (&str, 1, _VALUE_HI16) == (int) s7_FAIL)
4367               || (s7_end_of_line (str) == (int) s7_FAIL))
4368             {
4369               return;
4370             }
4371           else
4372             {
4373               if ((s7_score_pic == s7_NO_PIC) || (!s7_inst.reloc.exp.X_add_symbol))
4374                 {
4375                   sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
4376                   if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4377                     return;
4378
4379                   sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
4380                   if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4381                     return;
4382                 }
4383               else
4384                 {
4385                   gas_assert (s7_inst.reloc.exp.X_add_symbol);
4386                   s7_build_la_pic (reg_rd, s7_inst.reloc.exp);
4387                 }
4388
4389               /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4390               s7_inst.bwarn = -1;
4391             }
4392         }
4393     }
4394 }
4395
4396 /* Handle li.  */
4397
4398 static void
4399 s7_do_macro_li_rdi32 (char *str)
4400 {
4401   int reg_rd;
4402
4403   s7_skip_whitespace (str);
4404   if ((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
4405       || s7_skip_past_comma (&str) == (int) s7_FAIL)
4406     {
4407       return;
4408     }
4409   else
4410     {
4411       char *keep_data = str;
4412
4413       /* Check immediate value.  */
4414       if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
4415         {
4416           s7_inst.error = _("expression error");
4417           return;
4418         }
4419       else if (!(s7_inst.reloc.exp.X_add_number >= -0xffffffffLL
4420                  && s7_inst.reloc.exp.X_add_number <= 0xffffffffLL))
4421         {
4422           s7_inst.error = _("value not in range [-0xffffffff, 0xffffffff]");
4423           return;
4424         }
4425
4426       /* Reset str.  */
4427       str = keep_data;
4428
4429       /* li rd, simm16.  */
4430       if (s7_data_op2 (&str, 1, _SIMM16_LA) != (int) s7_FAIL)
4431         {
4432           s7_end_of_line (str);
4433           return;
4434         }
4435       /* li rd, imm32.  */
4436       else
4437         {
4438           char append_str[s7_MAX_LITERAL_POOL_SIZE];
4439
4440           str = keep_data;
4441
4442           if ((s7_data_op2 (&str, 1, _VALUE_HI16) == (int) s7_FAIL)
4443               || (s7_end_of_line (str) == (int) s7_FAIL))
4444             {
4445               return;
4446             }
4447           else if (s7_inst.reloc.exp.X_add_symbol)
4448             {
4449               s7_inst.error = _("li rd label isn't correct instruction form");
4450               return;
4451             }
4452           else
4453             {
4454               sprintf (append_str, "ld_i32hi r%d, %s", reg_rd, keep_data);
4455
4456               if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4457                 return;
4458               else
4459                 {
4460                   sprintf (append_str, "ld_i32lo r%d, %s", reg_rd, keep_data);
4461                   if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4462                     return;
4463
4464                   /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4465                   s7_inst.bwarn = -1;
4466                 }
4467             }
4468         }
4469     }
4470 }
4471
4472 /* Handle mul/mulu/div/divu/rem/remu.  */
4473
4474 static void
4475 s7_do_macro_mul_rdrsrs (char *str)
4476 {
4477   int reg_rd;
4478   int reg_rs1;
4479   int reg_rs2;
4480   char *backupstr;
4481   char append_str[s7_MAX_LITERAL_POOL_SIZE];
4482
4483   if (s7_university_version == 1)
4484     as_warn ("%s", s7_ERR_FOR_SCORE5U_MUL_DIV);
4485
4486   strcpy (append_str, str);
4487   backupstr = append_str;
4488   s7_skip_whitespace (backupstr);
4489   if (((reg_rd = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4490       || (s7_skip_past_comma (&backupstr) == (int) s7_FAIL)
4491       || ((reg_rs1 = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL))
4492     {
4493       s7_inst.error = s7_BAD_ARGS;
4494       return;
4495     }
4496
4497   if (s7_skip_past_comma (&backupstr) == (int) s7_FAIL)
4498     {
4499       /* rem/remu rA, rB is error format.  */
4500       if (strcmp (s7_inst.name, "rem") == 0 || strcmp (s7_inst.name, "remu") == 0)
4501         {
4502           s7_SET_INSN_ERROR (s7_BAD_ARGS);
4503         }
4504       else
4505         {
4506           s7_SET_INSN_ERROR (NULL);
4507           s7_do_rsrs (str);
4508         }
4509       return;
4510     }
4511   else
4512     {
4513       s7_SET_INSN_ERROR (NULL);
4514       if (((reg_rs2 = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4515           || (s7_end_of_line (backupstr) == (int) s7_FAIL))
4516         {
4517           return;
4518         }
4519       else
4520         {
4521           char append_str1[s7_MAX_LITERAL_POOL_SIZE];
4522
4523           if (strcmp (s7_inst.name, "rem") == 0)
4524             {
4525               sprintf (append_str, "mul r%d, r%d", reg_rs1, reg_rs2);
4526               sprintf (append_str1, "mfceh  r%d", reg_rd);
4527             }
4528           else if (strcmp (s7_inst.name, "remu") == 0)
4529             {
4530               sprintf (append_str, "mulu r%d, r%d", reg_rs1, reg_rs2);
4531               sprintf (append_str1, "mfceh  r%d", reg_rd);
4532             }
4533           else
4534             {
4535               sprintf (append_str, "%s r%d, r%d", s7_inst.name, reg_rs1, reg_rs2);
4536               sprintf (append_str1, "mfcel  r%d", reg_rd);
4537             }
4538
4539           /* Output mul/mulu or div/divu or rem/remu.  */
4540           if (s7_append_insn (append_str, TRUE) == (int) s7_FAIL)
4541             return;
4542
4543           /* Output mfcel or mfceh.  */
4544           if (s7_append_insn (append_str1, TRUE) == (int) s7_FAIL)
4545             return;
4546
4547           /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4548           s7_inst.bwarn = -1;
4549         }
4550     }
4551 }
4552
4553 static void
4554 s7_exp_macro_ldst_abs (char *str)
4555 {
4556   int reg_rd;
4557   char *backupstr, *tmp;
4558   char append_str[s7_MAX_LITERAL_POOL_SIZE];
4559   char verifystr[s7_MAX_LITERAL_POOL_SIZE];
4560   struct s7_score_it inst_backup;
4561   int r1_bak = 0;
4562
4563   r1_bak = s7_nor1;
4564   s7_nor1 = 0;
4565   memcpy (&inst_backup, &s7_inst, sizeof (struct s7_score_it));
4566
4567   strcpy (verifystr, str);
4568   backupstr = verifystr;
4569   s7_skip_whitespace (backupstr);
4570   if ((reg_rd = s7_reg_required_here (&backupstr, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4571     return;
4572
4573   tmp = backupstr;
4574   if (s7_skip_past_comma (&backupstr) == (int) s7_FAIL)
4575     return;
4576
4577   backupstr = tmp;
4578   sprintf (append_str, "li r1  %s", backupstr);
4579   s7_append_insn (append_str, TRUE);
4580
4581   memcpy (&s7_inst, &inst_backup, sizeof (struct s7_score_it));
4582   sprintf (append_str, " r%d, [r1,0]", reg_rd);
4583   s7_do_ldst_insn (append_str);
4584
4585   s7_nor1 = r1_bak;
4586 }
4587
4588 static int
4589 s7_nopic_need_relax (symbolS * sym, int before_relaxing)
4590 {
4591   if (sym == NULL)
4592     return 0;
4593   else if (s7_USE_GLOBAL_POINTER_OPT && s7_g_switch_value > 0)
4594     {
4595       const char *symname;
4596       const char *segname;
4597
4598       /* Find out whether this symbol can be referenced off the $gp
4599          register.  It can be if it is smaller than the -G size or if
4600          it is in the .sdata or .sbss section.  Certain symbols can
4601          not be referenced off the $gp, although it appears as though
4602          they can.  */
4603       symname = S_GET_NAME (sym);
4604       if (symname != NULL
4605           && (strcmp (symname, "eprol") == 0
4606               || strcmp (symname, "etext") == 0
4607               || strcmp (symname, "_gp") == 0
4608               || strcmp (symname, "edata") == 0
4609               || strcmp (symname, "_fbss") == 0
4610               || strcmp (symname, "_fdata") == 0
4611               || strcmp (symname, "_ftext") == 0
4612               || strcmp (symname, "end") == 0
4613               || strcmp (symname, GP_DISP_LABEL) == 0))
4614         {
4615           return 1;
4616         }
4617       else if ((!S_IS_DEFINED (sym) || S_IS_COMMON (sym)) && (0
4618       /* We must defer this decision until after the whole file has been read,
4619          since there might be a .extern after the first use of this symbol.  */
4620                || (before_relaxing
4621                    && S_GET_VALUE (sym) == 0)
4622                || (S_GET_VALUE (sym) != 0
4623                    && S_GET_VALUE (sym) <= s7_g_switch_value)))
4624         {
4625           return 0;
4626         }
4627
4628       segname = segment_name (S_GET_SEGMENT (sym));
4629       return (strcmp (segname, ".sdata") != 0
4630               && strcmp (segname, ".sbss") != 0
4631               && strncmp (segname, ".sdata.", 7) != 0
4632               && strncmp (segname, ".gnu.linkonce.s.", 16) != 0);
4633     }
4634   /* We are not optimizing for the $gp register.  */
4635   else
4636     return 1;
4637 }
4638
4639 /* Build a relax frag for lw/st instruction when generating s7_PIC,
4640    external symbol first and local symbol second.  */
4641
4642 static void
4643 s7_build_lwst_pic (int reg_rd, expressionS exp, const char *insn_name)
4644 {
4645   symbolS *add_symbol = exp.X_add_symbol;
4646   int add_number = exp.X_add_number;
4647   struct s7_score_it fix_insts[s7_RELAX_INST_NUM];
4648   struct s7_score_it var_insts[s7_RELAX_INST_NUM];
4649   int fix_num = 0;
4650   int var_num = 0;
4651   char tmp[s7_MAX_LITERAL_POOL_SIZE];
4652   int r1_bak;
4653
4654   r1_bak = s7_nor1;
4655   s7_nor1 = 0;
4656
4657   if ((add_number == 0) || (add_number >= -0x8000 && add_number <= 0x7fff))
4658     {
4659       fix_num = 1;
4660       var_num = 2;
4661
4662       /* For an external symbol, two insns are generated;
4663          For a local symbol, three insns are generated.  */
4664       /* Fix part
4665          For an external symbol: lw rD, <sym>($gp)
4666                                  (BFD_RELOC_SCORE_GOT15)  */
4667       sprintf (tmp, "lw_pic r1, %s", add_symbol->bsym->name);
4668       if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4669         return;
4670
4671       memcpy (&fix_insts[0], &s7_inst, sizeof (struct s7_score_it));
4672
4673       /* Var part
4674          For a local symbol :
4675          lw rD, <sym>($gp)    (BFD_RELOC_SCORE_GOT15)
4676          addi rD, <sym>       (BFD_RELOC_GOT_LO16) */
4677       s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4678       memcpy (&var_insts[0], &s7_inst, sizeof (struct s7_score_it));
4679       sprintf (tmp, "addi_s_pic r1, %s", add_symbol->bsym->name);
4680       if (s7_append_insn (tmp, FALSE) == (int) s7_FAIL)
4681         return;
4682
4683       memcpy (&var_insts[1], &s7_inst, sizeof (struct s7_score_it));
4684       s7_build_relax_frag (fix_insts, fix_num, var_insts, var_num, add_symbol);
4685
4686       /* Insn 2 or Insn 3: lw/st rD, [r1, constant]  */
4687       sprintf (tmp, "%s r%d, [r1, %d]", insn_name, reg_rd, add_number);
4688       if (s7_append_insn (tmp, TRUE) == (int) s7_FAIL)
4689         return;
4690
4691       /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4692       s7_inst.bwarn = -1;
4693     }
4694   else
4695     {
4696       s7_inst.error = _("PIC code offset overflow (max 16 signed bits)");
4697       return;
4698     }
4699
4700   s7_nor1 = r1_bak;
4701 }
4702
4703 static void
4704 s7_do_macro_ldst_label (char *str)
4705 {
4706   int i;
4707   int ldst_gp_p = 0;
4708   int reg_rd;
4709   int r1_bak;
4710   char *backup_str;
4711   char *label_str;
4712   char *absolute_value;
4713   char append_str[3][s7_MAX_LITERAL_POOL_SIZE];
4714   char verifystr[s7_MAX_LITERAL_POOL_SIZE];
4715   struct s7_score_it inst_backup;
4716   struct s7_score_it inst_expand[3];
4717   struct s7_score_it inst_main;
4718
4719   memcpy (&inst_backup, &s7_inst, sizeof (struct s7_score_it));
4720   strcpy (verifystr, str);
4721   backup_str = verifystr;
4722
4723   s7_skip_whitespace (backup_str);
4724   if ((reg_rd = s7_reg_required_here (&backup_str, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4725     return;
4726
4727   if (s7_skip_past_comma (&backup_str) == (int) s7_FAIL)
4728     return;
4729
4730   label_str = backup_str;
4731
4732   /* Ld/st rD, [rA, imm]      ld/st rD, [rA]+, imm      ld/st rD, [rA, imm]+.  */
4733   if (*backup_str == '[')
4734     {
4735       s7_inst.type = Rd_rvalueRs_preSI12;
4736       s7_do_ldst_insn (str);
4737       return;
4738     }
4739
4740   /* Ld/st rD, imm.  */
4741   absolute_value = backup_str;
4742   s7_inst.type = Rd_rvalueRs_SI15;
4743
4744   if (s7_my_get_expression (&s7_inst.reloc.exp, &backup_str) == (int) s7_FAIL)
4745     {
4746       s7_inst.error = _("expression error");
4747       return;
4748     }
4749   else if ((s7_inst.reloc.exp.X_add_symbol == NULL)
4750            && (s7_validate_immediate (s7_inst.reloc.exp.X_add_number, _VALUE, 0) == (int) s7_FAIL))
4751     {
4752       s7_inst.error = _("value not in range [0, 0x7fffffff]");
4753       return;
4754     }
4755   else if (s7_end_of_line (backup_str) == (int) s7_FAIL)
4756     {
4757       s7_inst.error = _("end on line error");
4758       return;
4759     }
4760   else
4761     {
4762       if (s7_inst.reloc.exp.X_add_symbol == 0)
4763         {
4764           memcpy (&s7_inst, &inst_backup, sizeof (struct s7_score_it));
4765           s7_exp_macro_ldst_abs (str);
4766           return;
4767         }
4768     }
4769
4770   /* Ld/st rD, label.  */
4771   s7_inst.type = Rd_rvalueRs_SI15;
4772   backup_str = absolute_value;
4773   if ((s7_data_op2 (&backup_str, 1, _GP_IMM15) == (int) s7_FAIL)
4774       || (s7_end_of_line (backup_str) == (int) s7_FAIL))
4775     {
4776       return;
4777     }
4778   else
4779     {
4780       if (s7_inst.reloc.exp.X_add_symbol == 0)
4781         {
4782           if (!s7_inst.error)
4783             s7_inst.error = s7_BAD_ARGS;
4784
4785           return;
4786         }
4787
4788       if (s7_score_pic == s7_PIC)
4789         {
4790           int ldst_idx = 0;
4791           ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
4792           s7_build_lwst_pic (reg_rd, s7_inst.reloc.exp,
4793                              s7_score_ldst_insns[ldst_idx * 3 + 0].template_name);
4794           return;
4795         }
4796       else
4797         {
4798           if ((s7_inst.reloc.exp.X_add_number <= 0x3fff)
4799                && (s7_inst.reloc.exp.X_add_number >= -0x4000)
4800                && (!s7_nopic_need_relax (s7_inst.reloc.exp.X_add_symbol, 1)))
4801             {
4802               int ldst_idx = 0;
4803
4804               /* Assign the real opcode.  */
4805               ldst_idx = s7_inst.instruction & OPC_PSEUDOLDST_MASK;
4806               s7_inst.instruction &= ~OPC_PSEUDOLDST_MASK;
4807               s7_inst.instruction |= s7_score_ldst_insns[ldst_idx * 3 + 0].value;
4808               s7_inst.instruction |= reg_rd << 20;
4809               s7_inst.instruction |= s7_GP << 15;
4810               s7_inst.relax_inst = 0x8000;
4811               s7_inst.relax_size = 0;
4812               ldst_gp_p = 1;
4813             }
4814         }
4815     }
4816
4817   /* Backup s7_inst.  */
4818   memcpy (&inst_main, &s7_inst, sizeof (struct s7_score_it));
4819   r1_bak = s7_nor1;
4820   s7_nor1 = 0;
4821
4822   /* Determine which instructions should be output.  */
4823   sprintf (append_str[0], "ld_i32hi r1, %s", label_str);
4824   sprintf (append_str[1], "ld_i32lo r1, %s", label_str);
4825   sprintf (append_str[2], "%s r%d, [r1, 0]", inst_backup.name, reg_rd);
4826
4827   /* Generate three instructions.
4828      la r1, label
4829      ld/st rd, [r1, 0]  */
4830   for (i = 0; i < 3; i++)
4831     {
4832       if (s7_append_insn (append_str[i], FALSE) == (int) s7_FAIL)
4833         return;
4834
4835       memcpy (&inst_expand[i], &s7_inst, sizeof (struct s7_score_it));
4836     }
4837
4838   if (ldst_gp_p)
4839     {
4840       char *p;
4841
4842       /* Adjust instruction opcode and to be relaxed instruction opcode.  */
4843       inst_main.instruction = s7_adjust_paritybit (inst_main.instruction, s7_GET_INSN_CLASS (inst_main.type));
4844       inst_main.relax_size = inst_expand[0].size + inst_expand[1].size + inst_expand[2].size;
4845       inst_main.type = Insn_GP;
4846
4847       for (i = 0; i < 3; i++)
4848         inst_expand[i].instruction = s7_adjust_paritybit (inst_expand[i].instruction
4849                                                        , s7_GET_INSN_CLASS (inst_expand[i].type));
4850
4851       /* Check data dependency.  */
4852       s7_handle_dependency (&inst_main);
4853
4854       /* Start a new frag if frag_now is not empty.  */
4855       if (frag_now_fix () != 0)
4856         {
4857           if (!frag_now->tc_frag_data.is_insn)
4858             frag_wane (frag_now);
4859
4860           frag_new (0);
4861         }
4862       frag_grow (20);
4863
4864       /* Write fr_fix part.  */
4865       p = frag_more (inst_main.size);
4866       s7_number_to_chars (p, inst_main.instruction, inst_main.size);
4867
4868       if (inst_main.reloc.type != BFD_RELOC_NONE)
4869         {
4870           s7_fix_new_score (frag_now, p - frag_now->fr_literal, inst_main.size,
4871                          &inst_main.reloc.exp, inst_main.reloc.pc_rel, inst_main.reloc.type);
4872         }
4873
4874 #ifdef OBJ_ELF
4875       dwarf2_emit_insn (inst_main.size);
4876 #endif
4877
4878       /* s7_GP instruction can not do optimization, only can do relax between
4879          1 instruction and 3 instructions.  */
4880       p = frag_var (rs_machine_dependent, inst_main.relax_size + s7_RELAX_PAD_BYTE, 0,
4881                     s7_RELAX_ENCODE (inst_main.size, inst_main.relax_size, inst_main.type, 0, 4, 0),
4882                     inst_main.reloc.exp.X_add_symbol, 0, NULL);
4883
4884       /* Write fr_var part.
4885          no calling s7_gen_insn_frag, no fixS will be generated.  */
4886       s7_number_to_chars (p, inst_expand[0].instruction, inst_expand[0].size);
4887       p += inst_expand[0].size;
4888       s7_number_to_chars (p, inst_expand[1].instruction, inst_expand[1].size);
4889       p += inst_expand[1].size;
4890       s7_number_to_chars (p, inst_expand[2].instruction, inst_expand[2].size);
4891     }
4892   else
4893     {
4894       s7_gen_insn_frag (&inst_expand[0], NULL);
4895       s7_gen_insn_frag (&inst_expand[1], NULL);
4896       s7_gen_insn_frag (&inst_expand[2], NULL);
4897     }
4898   s7_nor1 = r1_bak;
4899
4900   /* Set bwarn as -1, so macro instruction itself will not be generated frag.  */
4901   s7_inst.bwarn = -1;
4902 }
4903
4904 static void
4905 s7_do_lw_pic (char *str)
4906 {
4907   int reg_rd;
4908
4909   s7_skip_whitespace (str);
4910   if (((reg_rd = s7_reg_required_here (&str, 20, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
4911       || (s7_skip_past_comma (&str) == (int) s7_FAIL)
4912       || (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL)
4913       || (s7_end_of_line (str) == (int) s7_FAIL))
4914     {
4915       return;
4916     }
4917   else
4918     {
4919       if (s7_inst.reloc.exp.X_add_symbol == 0)
4920         {
4921           if (!s7_inst.error)
4922             s7_inst.error = s7_BAD_ARGS;
4923
4924           return;
4925         }
4926
4927       s7_inst.instruction |= s7_GP << 15;
4928       s7_inst.reloc.type = BFD_RELOC_SCORE_GOT15;
4929     }
4930 }
4931
4932 static void
4933 s7_do_empty (char *str)
4934 {
4935   str = str;
4936   if (s7_university_version == 1)
4937     {
4938       if (((s7_inst.instruction & 0x3e0003ff) == 0x0c000004)
4939           || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000024)
4940           || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000044)
4941           || ((s7_inst.instruction & 0x3e0003ff) == 0x0c000064))
4942         {
4943           s7_inst.error = s7_ERR_FOR_SCORE5U_MMU;
4944           return;
4945         }
4946     }
4947   if (s7_end_of_line (str) == (int) s7_FAIL)
4948     return;
4949
4950   if (s7_inst.relax_inst != 0x8000)
4951     {
4952       if (s7_inst.type == NO_OPD)
4953         {
4954           s7_inst.relax_size = 2;
4955         }
4956       else
4957         {
4958           s7_inst.relax_size = 4;
4959         }
4960     }
4961 }
4962
4963 static void
4964 s7_do_jump (char *str)
4965 {
4966   char *save_in;
4967
4968   s7_skip_whitespace (str);
4969   if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
4970       || s7_end_of_line (str) == (int) s7_FAIL)
4971     return;
4972
4973   if (s7_inst.reloc.exp.X_add_symbol == 0)
4974     {
4975       s7_inst.error = _("lacking label  ");
4976       return;
4977     }
4978
4979   if (!(s7_inst.reloc.exp.X_add_number >= -16777216
4980       && s7_inst.reloc.exp.X_add_number <= 16777215))
4981     {
4982       s7_inst.error = _("invalid constant: 25 bit expression not in range [-16777216, 16777215]");
4983       return;
4984     }
4985
4986   save_in = input_line_pointer;
4987   input_line_pointer = str;
4988   s7_inst.reloc.type = BFD_RELOC_SCORE_JMP;
4989   s7_inst.reloc.pc_rel = 1;
4990   input_line_pointer = save_in;
4991 }
4992
4993 static void
4994 s7_do16_jump (char *str)
4995 {
4996   s7_skip_whitespace (str);
4997   if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
4998       || s7_end_of_line (str) == (int) s7_FAIL)
4999     {
5000       return;
5001     }
5002   else if (s7_inst.reloc.exp.X_add_symbol == 0)
5003     {
5004       s7_inst.error = _("lacking label  ");
5005       return;
5006     }
5007   else if (!(s7_inst.reloc.exp.X_add_number >= 0
5008            && s7_inst.reloc.exp.X_add_number <= 4095))
5009     {
5010       s7_inst.error = _("invalid constant: 12 bit expression not in range [0, 4095]");
5011       return;
5012     }
5013
5014   s7_inst.reloc.type = BFD_RELOC_SCORE16_JMP;
5015   s7_inst.reloc.pc_rel = 1;
5016 }
5017
5018 static void
5019 s7_do_branch (char *str)
5020 {
5021   unsigned long abs_value = 0;
5022
5023   if (s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
5024       || s7_end_of_line (str) == (int) s7_FAIL)
5025     {
5026       return;
5027     }
5028   else if (s7_inst.reloc.exp.X_add_symbol == 0)
5029     {
5030       s7_inst.error = _("lacking label  ");
5031       return;
5032     }
5033   else if (!(s7_inst.reloc.exp.X_add_number >= -524288
5034            && s7_inst.reloc.exp.X_add_number <= 524287))
5035     {
5036       s7_inst.error = _("invalid constant: 20 bit expression not in range -2^19..2^19");
5037       return;
5038     }
5039
5040   s7_inst.reloc.type = BFD_RELOC_SCORE_BRANCH;
5041   s7_inst.reloc.pc_rel = 1;
5042
5043   /* Branch 32  offset field : 20 bit, 16 bit branch offset field : 8 bit.  */
5044   s7_inst.instruction |= (s7_inst.reloc.exp.X_add_number & 0x3fe) | ((s7_inst.reloc.exp.X_add_number & 0xffc00) << 5);
5045
5046   /* Compute 16 bit branch instruction.  */
5047   if ((s7_inst.relax_inst != 0x8000) && (abs_value & 0xfffffe00) == 0)
5048     {
5049       s7_inst.relax_inst |= (((s7_inst.instruction >> 10) & 0xf) << 8);
5050       s7_inst.relax_inst |= ((s7_inst.reloc.exp.X_add_number >> 1) & 0xff);
5051       s7_inst.relax_size = 2;
5052     }
5053   else
5054     {
5055       s7_inst.relax_inst = 0x8000;
5056     }
5057 }
5058
5059 static void
5060 s7_do16_branch (char *str)
5061 {
5062   if ((s7_my_get_expression (&s7_inst.reloc.exp, &str) == (int) s7_FAIL
5063       || s7_end_of_line (str) == (int) s7_FAIL))
5064     {
5065       ;
5066     }
5067   else if (s7_inst.reloc.exp.X_add_symbol == 0)
5068     {
5069       s7_inst.error = _("lacking label");
5070     }
5071   else if (!(s7_inst.reloc.exp.X_add_number >= -512
5072            && s7_inst.reloc.exp.X_add_number <= 511))
5073     {
5074       s7_inst.error = _("invalid constant: 10 bit expression not in range [-2^9, 2^9-1]");
5075     }
5076   else
5077     {
5078       s7_inst.reloc.type = BFD_RELOC_SCORE16_BRANCH;
5079       s7_inst.reloc.pc_rel = 1;
5080       s7_inst.instruction |= ((s7_inst.reloc.exp.X_add_number >> 1) & 0xff);
5081     }
5082 }
5083
5084 /* Iterate over the base tables to create the instruction patterns.  */
5085
5086 static void
5087 s7_build_score_ops_hsh (void)
5088 {
5089   unsigned int i;
5090   static struct obstack insn_obstack;
5091
5092   obstack_begin (&insn_obstack, 4000);
5093   for (i = 0; i < sizeof (s7_score_insns) / sizeof (struct s7_asm_opcode); i++)
5094     {
5095       const struct s7_asm_opcode *insn = s7_score_insns + i;
5096       unsigned len = strlen (insn->template_name);
5097       struct s7_asm_opcode *new_opcode;
5098       char *template_name;
5099       new_opcode = (struct s7_asm_opcode *)
5100           obstack_alloc (&insn_obstack, sizeof (struct s7_asm_opcode));
5101       template_name = (char *) obstack_alloc (&insn_obstack, len + 1);
5102
5103       strcpy (template_name, insn->template_name);
5104       new_opcode->template_name = template_name;
5105       new_opcode->parms = insn->parms;
5106       new_opcode->value = insn->value;
5107       new_opcode->relax_value = insn->relax_value;
5108       new_opcode->type = insn->type;
5109       new_opcode->bitmask = insn->bitmask;
5110       hash_insert (s7_score_ops_hsh, new_opcode->template_name,
5111                    (void *) new_opcode);
5112     }
5113 }
5114
5115 static void
5116 s7_build_dependency_insn_hsh (void)
5117 {
5118   unsigned int i;
5119   static struct obstack dependency_obstack;
5120
5121   obstack_begin (&dependency_obstack, 4000);
5122   for (i = 0; i < ARRAY_SIZE (s7_insn_to_dependency_table); i++)
5123     {
5124       const struct s7_insn_to_dependency *tmp = s7_insn_to_dependency_table + i;
5125       unsigned len = strlen (tmp->insn_name);
5126       struct s7_insn_to_dependency *new_i2d;
5127
5128       new_i2d = (struct s7_insn_to_dependency *)
5129           obstack_alloc (&dependency_obstack,
5130                          sizeof (struct s7_insn_to_dependency));
5131       new_i2d->insn_name = (char *) obstack_alloc (&dependency_obstack,
5132                                                    len + 1);
5133
5134       strcpy (new_i2d->insn_name, tmp->insn_name);
5135       new_i2d->type = tmp->type;
5136       hash_insert (s7_dependency_insn_hsh, new_i2d->insn_name,
5137                    (void *) new_i2d);
5138     }
5139 }
5140
5141 static valueT
5142 s7_md_chars_to_number (char *buf, int n)
5143 {
5144   valueT result = 0;
5145   unsigned char *where = (unsigned char *) buf;
5146
5147   if (target_big_endian)
5148     {
5149       while (n--)
5150         {
5151           result <<= 8;
5152           result |= (*where++ & 255);
5153         }
5154     }
5155   else
5156     {
5157       while (n--)
5158         {
5159           result <<= 8;
5160           result |= (where[n] & 255);
5161         }
5162     }
5163
5164   return result;
5165 }
5166
5167 /* Return true if the given symbol should be considered local for s7_PIC.  */
5168
5169 static bfd_boolean
5170 s7_pic_need_relax (symbolS *sym, asection *segtype)
5171 {
5172   asection *symsec;
5173   bfd_boolean linkonce;
5174
5175   /* Handle the case of a symbol equated to another symbol.  */
5176   while (symbol_equated_reloc_p (sym))
5177     {
5178       symbolS *n;
5179
5180       /* It's possible to get a loop here in a badly written
5181          program.  */
5182       n = symbol_get_value_expression (sym)->X_add_symbol;
5183       if (n == sym)
5184         break;
5185       sym = n;
5186     }
5187
5188   symsec = S_GET_SEGMENT (sym);
5189
5190   /* Duplicate the test for LINK_ONCE sections as in adjust_reloc_syms */
5191   linkonce = FALSE;
5192   if (symsec != segtype && ! S_IS_LOCAL (sym))
5193     {
5194       if ((bfd_get_section_flags (stdoutput, symsec) & SEC_LINK_ONCE) != 0)
5195         linkonce = TRUE;
5196
5197       /* The GNU toolchain uses an extension for ELF: a section
5198           beginning with the magic string .gnu.linkonce is a linkonce
5199           section.  */
5200       if (strncmp (segment_name (symsec), ".gnu.linkonce",
5201                    sizeof ".gnu.linkonce" - 1) == 0)
5202         linkonce = TRUE;
5203     }
5204
5205   /* This must duplicate the test in adjust_reloc_syms.  */
5206   return (symsec != &bfd_und_section
5207             && symsec != &bfd_abs_section
5208           && ! bfd_is_com_section (symsec)
5209             && !linkonce
5210 #ifdef OBJ_ELF
5211           /* A global or weak symbol is treated as external.  */
5212           && (OUTPUT_FLAVOR != bfd_target_elf_flavour
5213               || (! S_IS_WEAK (sym) && ! S_IS_EXTERNAL (sym)))
5214 #endif
5215           );
5216 }
5217
5218 static int
5219 s7_judge_size_before_relax (fragS * fragp, asection *sec)
5220 {
5221   int change = 0;
5222
5223   if (s7_score_pic == s7_NO_PIC)
5224     change = s7_nopic_need_relax (fragp->fr_symbol, 0);
5225   else
5226     change = s7_pic_need_relax (fragp->fr_symbol, sec);
5227
5228   if (change == 1)
5229     {
5230       /* Only at the first time determining whether s7_GP instruction relax should be done,
5231          return the difference between insntruction size and instruction relax size.  */
5232       if (fragp->fr_opcode == NULL)
5233         {
5234           fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
5235           fragp->fr_opcode = fragp->fr_literal + s7_RELAX_RELOC1 (fragp->fr_subtype);
5236           return s7_RELAX_NEW (fragp->fr_subtype) - s7_RELAX_OLD (fragp->fr_subtype);
5237         }
5238     }
5239
5240   return 0;
5241 }
5242
5243 static int
5244 s7_b32_relax_to_b16 (fragS * fragp)
5245 {
5246   int grows = 0;
5247   int relaxable_p = 0;
5248   int r_old;
5249   int r_new;
5250   int frag_addr = fragp->fr_address + fragp->insn_addr;
5251
5252   addressT symbol_address = 0;
5253   symbolS *s;
5254   offsetT offset;
5255   unsigned long value;
5256   unsigned long abs_value;
5257
5258   /* FIXME : here may be able to modify better .
5259      I don't know how to get the fragp's section ,
5260      so in relax stage , it may be wrong to calculate the symbol's offset when the frag's section
5261      is different from the symbol's.  */
5262
5263   r_old = s7_RELAX_OLD (fragp->fr_subtype);
5264   r_new = s7_RELAX_NEW (fragp->fr_subtype);
5265   relaxable_p = s7_RELAX_OPT (fragp->fr_subtype);
5266
5267   s = fragp->fr_symbol;
5268   /* b/bl immediate  */
5269   if (s == NULL)
5270     frag_addr = 0;
5271   else
5272     {
5273       if (s->bsym != 0)
5274         symbol_address = (addressT) s->sy_frag->fr_address;
5275     }
5276
5277   value = s7_md_chars_to_number (fragp->fr_literal, s7_INSN_SIZE);
5278
5279   /* b 32's offset : 20 bit, b 16's tolerate field : 0xff.  */
5280   offset = ((value & 0x3ff0000) >> 6) | (value & 0x3fe);
5281   if ((offset & 0x80000) == 0x80000)
5282     offset |= 0xfff00000;
5283
5284   abs_value = offset + symbol_address - frag_addr;
5285   if ((abs_value & 0x80000000) == 0x80000000)
5286     abs_value = 0xffffffff - abs_value + 1;
5287
5288   /* Relax branch 32 to branch 16.  */
5289   if (relaxable_p && (s->bsym != NULL) && ((abs_value & 0xffffff00) == 0)
5290       && (S_IS_DEFINED (s) && !S_IS_COMMON (s) && !S_IS_EXTERNAL (s)))
5291     {
5292       /* do nothing.  */
5293     }
5294   else
5295     {
5296       /* Branch 32 can not be relaxed to b 16, so clear OPT bit.  */
5297       fragp->fr_opcode = NULL;
5298       fragp->fr_subtype = s7_RELAX_OPT_CLEAR (fragp->fr_subtype);
5299     }
5300
5301   return grows;
5302 }
5303
5304 static void
5305 s7_parse_pce_inst (char *insnstr)
5306 {
5307   char c;
5308   char *p;
5309   char *q;
5310   char first[s7_MAX_LITERAL_POOL_SIZE];
5311   char second[s7_MAX_LITERAL_POOL_SIZE];
5312   struct s7_score_it pec_part_1;
5313
5314   /* Get first part string of PCE.  */
5315   p = strstr (insnstr, "||");
5316   c = *p;
5317   *p = '\0';
5318   sprintf (first, "%s", insnstr);
5319
5320   /* Get second part string of PCE.  */
5321   *p = c;
5322   p += 2;
5323   sprintf (second, "%s", p);
5324
5325   s7_parse_16_32_inst (first, FALSE);
5326   if (s7_inst.error)
5327     return;
5328
5329   memcpy (&pec_part_1, &s7_inst, sizeof (s7_inst));
5330
5331   q = second;
5332   while (q && *q)
5333     {
5334       *q = TOLOWER (*q);
5335       q++;
5336     }
5337
5338   s7_parse_16_32_inst (second, FALSE);
5339   if (s7_inst.error)
5340     return;
5341
5342   if (   ((pec_part_1.size == s7_INSN_SIZE) && (s7_inst.size == s7_INSN_SIZE))
5343       || ((pec_part_1.size == s7_INSN_SIZE) && (s7_inst.size == s7_INSN16_SIZE))
5344       || ((pec_part_1.size == s7_INSN16_SIZE) && (s7_inst.size == s7_INSN_SIZE)))
5345     {
5346       s7_inst.error = _("pce instruction error (16 bit || 16 bit)'");
5347       sprintf (s7_inst.str, insnstr);
5348       return;
5349     }
5350
5351   if (!s7_inst.error)
5352     s7_gen_insn_frag (&pec_part_1, &s7_inst);
5353 }
5354
5355 \f
5356
5357 static void
5358 s7_insert_reg (const struct s7_reg_entry *r, struct hash_control *htab)
5359 {
5360   int i = 0;
5361   int len = strlen (r->name) + 2;
5362   char *buf = xmalloc (len);
5363   char *buf2 = xmalloc (len);
5364
5365   strcpy (buf + i, r->name);
5366   for (i = 0; buf[i]; i++)
5367     {
5368       buf2[i] = TOUPPER (buf[i]);
5369     }
5370   buf2[i] = '\0';
5371
5372   hash_insert (htab, buf, (void *) r);
5373   hash_insert (htab, buf2, (void *) r);
5374 }
5375
5376 static void
5377 s7_build_reg_hsh (struct s7_reg_map *map)
5378 {
5379   const struct s7_reg_entry *r;
5380
5381   if ((map->htab = hash_new ()) == NULL)
5382     {
5383       as_fatal (_("virtual memory exhausted"));
5384     }
5385   for (r = map->names; r->name != NULL; r++)
5386     {
5387       s7_insert_reg (r, map->htab);
5388     }
5389 }
5390
5391 \f
5392
5393 /* If we change section we must dump the literal pool first.  */
5394 static void
5395 s7_s_score_bss (int ignore ATTRIBUTE_UNUSED)
5396 {
5397   subseg_set (bss_section, (subsegT) get_absolute_expression ());
5398   demand_empty_rest_of_line ();
5399 }
5400
5401 static void
5402 s7_s_score_text (int ignore)
5403 {
5404   obj_elf_text (ignore);
5405   record_alignment (now_seg, 2);
5406 }
5407
5408 static void
5409 s7_s_section (int ignore)
5410 {
5411   obj_elf_section (ignore);
5412   if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5413     record_alignment (now_seg, 2);
5414
5415 }
5416
5417 static void
5418 s7_s_change_sec (int sec)
5419 {
5420   segT seg;
5421
5422 #ifdef OBJ_ELF
5423   /* The ELF backend needs to know that we are changing sections, so
5424      that .previous works correctly.  We could do something like check
5425      for an obj_section_change_hook macro, but that might be confusing
5426      as it would not be appropriate to use it in the section changing
5427      functions in read.c, since obj-elf.c intercepts those.  FIXME:
5428      This should be cleaner, somehow.  */
5429   obj_elf_section_change_hook ();
5430 #endif
5431   switch (sec)
5432     {
5433     case 'r':
5434       seg = subseg_new (s7_RDATA_SECTION_NAME, (subsegT) get_absolute_expression ());
5435       bfd_set_section_flags (stdoutput, seg, (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_RELOC | SEC_DATA));
5436       if (strcmp (TARGET_OS, "elf") != 0)
5437         record_alignment (seg, 4);
5438       demand_empty_rest_of_line ();
5439       break;
5440     case 's':
5441       seg = subseg_new (".sdata", (subsegT) get_absolute_expression ());
5442       bfd_set_section_flags (stdoutput, seg, SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA);
5443       if (strcmp (TARGET_OS, "elf") != 0)
5444         record_alignment (seg, 4);
5445       demand_empty_rest_of_line ();
5446       break;
5447     }
5448 }
5449
5450 static void
5451 s7_s_score_mask (int reg_type  ATTRIBUTE_UNUSED)
5452 {
5453   long mask, off;
5454
5455   if (s7_cur_proc_ptr == NULL)
5456     {
5457       as_warn (_(".mask outside of .ent"));
5458       demand_empty_rest_of_line ();
5459       return;
5460     }
5461   if (get_absolute_expression_and_terminator (&mask) != ',')
5462     {
5463       as_warn (_("Bad .mask directive"));
5464       --input_line_pointer;
5465       demand_empty_rest_of_line ();
5466       return;
5467     }
5468   off = get_absolute_expression ();
5469   s7_cur_proc_ptr->reg_mask = mask;
5470   s7_cur_proc_ptr->reg_offset = off;
5471   demand_empty_rest_of_line ();
5472 }
5473
5474 static symbolS *
5475 s7_get_symbol (void)
5476 {
5477   int c;
5478   char *name;
5479   symbolS *p;
5480
5481   name = input_line_pointer;
5482   c = get_symbol_end ();
5483   p = (symbolS *) symbol_find_or_make (name);
5484   *input_line_pointer = c;
5485   return p;
5486 }
5487
5488 static long
5489 s7_get_number (void)
5490 {
5491   int negative = 0;
5492   long val = 0;
5493
5494   if (*input_line_pointer == '-')
5495     {
5496       ++input_line_pointer;
5497       negative = 1;
5498     }
5499   if (!ISDIGIT (*input_line_pointer))
5500     as_bad (_("expected simple number"));
5501   if (input_line_pointer[0] == '0')
5502     {
5503       if (input_line_pointer[1] == 'x')
5504         {
5505           input_line_pointer += 2;
5506           while (ISXDIGIT (*input_line_pointer))
5507             {
5508               val <<= 4;
5509               val |= hex_value (*input_line_pointer++);
5510             }
5511           return negative ? -val : val;
5512         }
5513       else
5514         {
5515           ++input_line_pointer;
5516           while (ISDIGIT (*input_line_pointer))
5517             {
5518               val <<= 3;
5519               val |= *input_line_pointer++ - '0';
5520             }
5521           return negative ? -val : val;
5522         }
5523     }
5524   if (!ISDIGIT (*input_line_pointer))
5525     {
5526       printf (_(" *input_line_pointer == '%c' 0x%02x\n"), *input_line_pointer, *input_line_pointer);
5527       as_warn (_("invalid number"));
5528       return -1;
5529     }
5530   while (ISDIGIT (*input_line_pointer))
5531     {
5532       val *= 10;
5533       val += *input_line_pointer++ - '0';
5534     }
5535   return negative ? -val : val;
5536 }
5537
5538 /* The .aent and .ent directives.  */
5539
5540 static void
5541 s7_s_score_ent (int aent)
5542 {
5543   symbolS *symbolP;
5544   int maybe_text;
5545
5546   symbolP = s7_get_symbol ();
5547   if (*input_line_pointer == ',')
5548     ++input_line_pointer;
5549   SKIP_WHITESPACE ();
5550   if (ISDIGIT (*input_line_pointer) || *input_line_pointer == '-')
5551     s7_get_number ();
5552
5553 #ifdef BFD_ASSEMBLER
5554   if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5555     maybe_text = 1;
5556   else
5557     maybe_text = 0;
5558 #else
5559   if (now_seg != data_section && now_seg != bss_section)
5560     maybe_text = 1;
5561   else
5562     maybe_text = 0;
5563 #endif
5564   if (!maybe_text)
5565     as_warn (_(".ent or .aent not in text section."));
5566   if (!aent && s7_cur_proc_ptr)
5567     as_warn (_("missing .end"));
5568   if (!aent)
5569     {
5570       s7_cur_proc_ptr = &s7_cur_proc;
5571       s7_cur_proc_ptr->reg_mask = 0xdeadbeaf;
5572       s7_cur_proc_ptr->reg_offset = 0xdeadbeaf;
5573       s7_cur_proc_ptr->fpreg_mask = 0xdeafbeaf;
5574       s7_cur_proc_ptr->leaf = 0xdeafbeaf;
5575       s7_cur_proc_ptr->frame_offset = 0xdeafbeaf;
5576       s7_cur_proc_ptr->frame_reg = 0xdeafbeaf;
5577       s7_cur_proc_ptr->pc_reg = 0xdeafbeaf;
5578       s7_cur_proc_ptr->isym = symbolP;
5579       symbol_get_bfdsym (symbolP)->flags |= BSF_FUNCTION;
5580       ++s7_numprocs;
5581       if (debug_type == DEBUG_STABS)
5582         stabs_generate_asm_func (S_GET_NAME (symbolP), S_GET_NAME (symbolP));
5583     }
5584   demand_empty_rest_of_line ();
5585 }
5586
5587 static void
5588 s7_s_score_frame (int ignore ATTRIBUTE_UNUSED)
5589 {
5590   char *backupstr;
5591   char str[30];
5592   long val;
5593   int i = 0;
5594
5595   backupstr = input_line_pointer;
5596
5597 #ifdef OBJ_ELF
5598   if (s7_cur_proc_ptr == NULL)
5599     {
5600       as_warn (_(".frame outside of .ent"));
5601       demand_empty_rest_of_line ();
5602       return;
5603     }
5604   s7_cur_proc_ptr->frame_reg = s7_reg_required_here ((&backupstr), 0, s7_REG_TYPE_SCORE);
5605   SKIP_WHITESPACE ();
5606   s7_skip_past_comma (&backupstr);
5607   while (*backupstr != ',')
5608     {
5609       str[i] = *backupstr;
5610       i++;
5611       backupstr++;
5612     }
5613   str[i] = '\0';
5614   val = atoi (str);
5615
5616   SKIP_WHITESPACE ();
5617   s7_skip_past_comma (&backupstr);
5618   s7_cur_proc_ptr->frame_offset = val;
5619   s7_cur_proc_ptr->pc_reg = s7_reg_required_here ((&backupstr), 0, s7_REG_TYPE_SCORE);
5620
5621   SKIP_WHITESPACE ();
5622   s7_skip_past_comma (&backupstr);
5623   i = 0;
5624   while (*backupstr != '\n')
5625     {
5626       str[i] = *backupstr;
5627       i++;
5628       backupstr++;
5629     }
5630   str[i] = '\0';
5631   val = atoi (str);
5632   s7_cur_proc_ptr->leaf = val;
5633   SKIP_WHITESPACE ();
5634   s7_skip_past_comma (&backupstr);
5635
5636 #endif /* OBJ_ELF */
5637   while (input_line_pointer != backupstr)
5638     input_line_pointer++;
5639 }
5640
5641 /* The .end directive.  */
5642
5643 static void
5644 s7_s_score_end (int x ATTRIBUTE_UNUSED)
5645 {
5646   symbolS *p;
5647   int maybe_text;
5648
5649   /* Generate a .pdr section.  */
5650   segT saved_seg = now_seg;
5651   subsegT saved_subseg = now_subseg;
5652   valueT dot;
5653   expressionS exp;
5654   char *fragp;
5655
5656   if (!is_end_of_line[(unsigned char)*input_line_pointer])
5657     {
5658       p = s7_get_symbol ();
5659       demand_empty_rest_of_line ();
5660     }
5661   else
5662     p = NULL;
5663
5664 #ifdef BFD_ASSEMBLER
5665   if ((bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE) != 0)
5666     maybe_text = 1;
5667   else
5668     maybe_text = 0;
5669 #else
5670   if (now_seg != data_section && now_seg != bss_section)
5671     maybe_text = 1;
5672   else
5673     maybe_text = 0;
5674 #endif
5675
5676   if (!maybe_text)
5677     as_warn (_(".end not in text section"));
5678   if (!s7_cur_proc_ptr)
5679     {
5680       as_warn (_(".end directive without a preceding .ent directive."));
5681       demand_empty_rest_of_line ();
5682       return;
5683     }
5684   if (p != NULL)
5685     {
5686       gas_assert (S_GET_NAME (p));
5687       if (strcmp (S_GET_NAME (p), S_GET_NAME (s7_cur_proc_ptr->isym)))
5688         as_warn (_(".end symbol does not match .ent symbol."));
5689       if (debug_type == DEBUG_STABS)
5690         stabs_generate_asm_endfunc (S_GET_NAME (p), S_GET_NAME (p));
5691     }
5692   else
5693     as_warn (_(".end directive missing or unknown symbol"));
5694
5695   if ((s7_cur_proc_ptr->reg_mask == 0xdeadbeaf) ||
5696       (s7_cur_proc_ptr->reg_offset == 0xdeadbeaf) ||
5697       (s7_cur_proc_ptr->leaf == 0xdeafbeaf) ||
5698       (s7_cur_proc_ptr->frame_offset == 0xdeafbeaf) ||
5699       (s7_cur_proc_ptr->frame_reg == 0xdeafbeaf) || (s7_cur_proc_ptr->pc_reg == 0xdeafbeaf));
5700
5701   else
5702     {
5703       dot = frag_now_fix ();
5704       gas_assert (s7_pdr_seg);
5705       subseg_set (s7_pdr_seg, 0);
5706       /* Write the symbol.  */
5707       exp.X_op = O_symbol;
5708       exp.X_add_symbol = p;
5709       exp.X_add_number = 0;
5710       emit_expr (&exp, 4);
5711       fragp = frag_more (7 * 4);
5712       s7_number_to_chars (fragp, (valueT) s7_cur_proc_ptr->reg_mask, 4);
5713       s7_number_to_chars (fragp + 4, (valueT) s7_cur_proc_ptr->reg_offset, 4);
5714       s7_number_to_chars (fragp + 8, (valueT) s7_cur_proc_ptr->fpreg_mask, 4);
5715       s7_number_to_chars (fragp + 12, (valueT) s7_cur_proc_ptr->leaf, 4);
5716       s7_number_to_chars (fragp + 16, (valueT) s7_cur_proc_ptr->frame_offset, 4);
5717       s7_number_to_chars (fragp + 20, (valueT) s7_cur_proc_ptr->frame_reg, 4);
5718       s7_number_to_chars (fragp + 24, (valueT) s7_cur_proc_ptr->pc_reg, 4);
5719       subseg_set (saved_seg, saved_subseg);
5720
5721     }
5722   s7_cur_proc_ptr = NULL;
5723 }
5724
5725 /* Handle the .set pseudo-op.  */
5726
5727 static void
5728 s7_s_score_set (int x ATTRIBUTE_UNUSED)
5729 {
5730   int i = 0;
5731   char name[s7_MAX_LITERAL_POOL_SIZE];
5732   char * orig_ilp = input_line_pointer;
5733
5734   while (!is_end_of_line[(unsigned char)*input_line_pointer])
5735     {
5736       name[i] = (char) * input_line_pointer;
5737       i++;
5738       ++input_line_pointer;
5739     }
5740
5741   name[i] = '\0';
5742
5743   if (strcmp (name, "nwarn") == 0)
5744     {
5745       s7_warn_fix_data_dependency = 0;
5746     }
5747   else if (strcmp (name, "fixdd") == 0)
5748     {
5749       s7_fix_data_dependency = 1;
5750     }
5751   else if (strcmp (name, "nofixdd") == 0)
5752     {
5753       s7_fix_data_dependency = 0;
5754     }
5755   else if (strcmp (name, "r1") == 0)
5756     {
5757       s7_nor1 = 0;
5758     }
5759   else if (strcmp (name, "nor1") == 0)
5760     {
5761       s7_nor1 = 1;
5762     }
5763   else if (strcmp (name, "optimize") == 0)
5764     {
5765       s7_g_opt = 1;
5766     }
5767   else if (strcmp (name, "volatile") == 0)
5768     {
5769       s7_g_opt = 0;
5770     }
5771   else if (strcmp (name, "pic") == 0)
5772     {
5773       s7_score_pic = s7_PIC;
5774     }
5775   else
5776     {
5777       input_line_pointer = orig_ilp;
5778       s_set (0);
5779     }
5780 }
5781
5782 /* Handle the .cpload pseudo-op.  This is used when generating s7_PIC code.  It sets the
5783    $gp register for the function based on the function address, which is in the register
5784    named in the argument. This uses a relocation against GP_DISP_LABEL, which is handled
5785    specially by the linker.  The result is:
5786    ldis gp, %hi(GP_DISP_LABEL)
5787    ori  gp, %low(GP_DISP_LABEL)
5788    add  gp, gp, .cpload argument
5789    The .cpload argument is normally r29.  */
5790
5791 static void
5792 s7_s_score_cpload (int ignore ATTRIBUTE_UNUSED)
5793 {
5794   int reg;
5795   char insn_str[s7_MAX_LITERAL_POOL_SIZE];
5796
5797   /* If we are not generating s7_PIC code, .cpload is ignored.  */
5798   if (s7_score_pic == s7_NO_PIC)
5799     {
5800       s_ignore (0);
5801       return;
5802     }
5803
5804   if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
5805     return;
5806
5807   demand_empty_rest_of_line ();
5808
5809   sprintf (insn_str, "ld_i32hi r%d, %s", s7_GP, GP_DISP_LABEL);
5810   if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5811     return;
5812
5813   sprintf (insn_str, "ld_i32lo r%d, %s", s7_GP, GP_DISP_LABEL);
5814   if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5815     return;
5816
5817   sprintf (insn_str, "add r%d, r%d, r%d", s7_GP, s7_GP, reg);
5818   if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5819     return;
5820 }
5821
5822 /* Handle the .cprestore pseudo-op.  This stores $gp into a given
5823    offset from $sp.  The offset is remembered, and after making a s7_PIC
5824    call $gp is restored from that location.  */
5825
5826 static void
5827 s7_s_score_cprestore (int ignore ATTRIBUTE_UNUSED)
5828 {
5829   int reg;
5830   int cprestore_offset;
5831   char insn_str[s7_MAX_LITERAL_POOL_SIZE];
5832
5833   /* If we are not generating s7_PIC code, .cprestore is ignored.  */
5834   if (s7_score_pic == s7_NO_PIC)
5835     {
5836       s_ignore (0);
5837       return;
5838     }
5839
5840   if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL
5841       || s7_skip_past_comma (&input_line_pointer) == (int) s7_FAIL)
5842     {
5843       return;
5844     }
5845
5846   cprestore_offset = get_absolute_expression ();
5847
5848   if (cprestore_offset <= 0x3fff)
5849     {
5850       sprintf (insn_str, "sw r%d, [r%d, %d]", s7_GP, reg, cprestore_offset);
5851       if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5852         return;
5853     }
5854   else
5855     {
5856       int r1_bak;
5857
5858       r1_bak = s7_nor1;
5859       s7_nor1 = 0;
5860
5861       sprintf (insn_str, "li r1, %d", cprestore_offset);
5862       if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5863         return;
5864
5865       sprintf (insn_str, "add r1, r1, r%d", reg);
5866       if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5867         return;
5868
5869       sprintf (insn_str, "sw r%d, [r1]", s7_GP);
5870       if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5871         return;
5872
5873       s7_nor1 = r1_bak;
5874     }
5875
5876   demand_empty_rest_of_line ();
5877 }
5878
5879 /* Handle the .gpword pseudo-op.  This is used when generating s7_PIC
5880    code.  It generates a 32 bit s7_GP relative reloc.  */
5881
5882 static void
5883 s7_s_score_gpword (int ignore ATTRIBUTE_UNUSED)
5884 {
5885   expressionS ex;
5886   char *p;
5887
5888   /* When not generating s7_PIC code, this is treated as .word.  */
5889   if (s7_score_pic == s7_NO_PIC)
5890     {
5891       cons (4);
5892       return;
5893     }
5894   expression (&ex);
5895   if (ex.X_op != O_symbol || ex.X_add_number != 0)
5896     {
5897       as_bad (_("Unsupported use of .gpword"));
5898       ignore_rest_of_line ();
5899     }
5900   p = frag_more (4);
5901   s7_number_to_chars (p, (valueT) 0, 4);
5902   fix_new_exp (frag_now, p - frag_now->fr_literal, 4, &ex, FALSE, BFD_RELOC_GPREL32);
5903   demand_empty_rest_of_line ();
5904 }
5905
5906 /* Handle the .cpadd pseudo-op.  This is used when dealing with switch
5907    tables in s7_PIC code.  */
5908
5909 static void
5910 s7_s_score_cpadd (int ignore ATTRIBUTE_UNUSED)
5911 {
5912   int reg;
5913   char insn_str[s7_MAX_LITERAL_POOL_SIZE];
5914
5915   /* If we are not generating s7_PIC code, .cpload is ignored.  */
5916   if (s7_score_pic == s7_NO_PIC)
5917     {
5918       s_ignore (0);
5919       return;
5920     }
5921
5922   if ((reg = s7_reg_required_here (&input_line_pointer, -1, s7_REG_TYPE_SCORE)) == (int) s7_FAIL)
5923     {
5924       return;
5925     }
5926   demand_empty_rest_of_line ();
5927
5928   /* Add $gp to the register named as an argument.  */
5929   sprintf (insn_str, "add r%d, r%d, r%d", reg, reg, s7_GP);
5930   if (s7_append_insn (insn_str, TRUE) == (int) s7_FAIL)
5931     return;
5932 }
5933
5934 #ifndef TC_IMPLICIT_LCOMM_ALIGNMENT
5935 #define TC_IMPLICIT_LCOMM_ALIGNMENT(SIZE, P2VAR)                \
5936     do                                                          \
5937     {                                                           \
5938     if ((SIZE) >= 8)                                            \
5939     (P2VAR) = 3;                                                \
5940     else if ((SIZE) >= 4)                                       \
5941     (P2VAR) = 2;                                                \
5942     else if ((SIZE) >= 2)                                       \
5943     (P2VAR) = 1;                                                \
5944     else                                                        \
5945     (P2VAR) = 0;                                                \
5946     }                                                           \
5947   while (0)
5948 #endif
5949
5950 static void
5951 s7_s_score_lcomm (int bytes_p)
5952 {
5953   char *name;
5954   char c;
5955   char *p;
5956   int temp;
5957   symbolS *symbolP;
5958   segT current_seg = now_seg;
5959   subsegT current_subseg = now_subseg;
5960   const int max_alignment = 15;
5961   int align = 0;
5962   segT bss_seg = bss_section;
5963   int needs_align = 0;
5964
5965   name = input_line_pointer;
5966   c = get_symbol_end ();
5967   p = input_line_pointer;
5968   *p = c;
5969
5970   if (name == p)
5971     {
5972       as_bad (_("expected symbol name"));
5973       discard_rest_of_line ();
5974       return;
5975     }
5976
5977   SKIP_WHITESPACE ();
5978
5979   /* Accept an optional comma after the name.  The comma used to be
5980      required, but Irix 5 cc does not generate it.  */
5981   if (*input_line_pointer == ',')
5982     {
5983       ++input_line_pointer;
5984       SKIP_WHITESPACE ();
5985     }
5986
5987   if (is_end_of_line[(unsigned char)*input_line_pointer])
5988     {
5989       as_bad (_("missing size expression"));
5990       return;
5991     }
5992
5993   if ((temp = get_absolute_expression ()) < 0)
5994     {
5995       as_warn (_("BSS length (%d) < 0 ignored"), temp);
5996       ignore_rest_of_line ();
5997       return;
5998     }
5999
6000 #if defined (TC_SCORE)
6001   if (OUTPUT_FLAVOR == bfd_target_ecoff_flavour || OUTPUT_FLAVOR == bfd_target_elf_flavour)
6002     {
6003       /* For Score and Alpha ECOFF or ELF, small objects are put in .sbss.  */
6004       if ((unsigned) temp <= bfd_get_gp_size (stdoutput))
6005         {
6006           bss_seg = subseg_new (".sbss", 1);
6007           seg_info (bss_seg)->bss = 1;
6008 #ifdef BFD_ASSEMBLER
6009           if (!bfd_set_section_flags (stdoutput, bss_seg, SEC_ALLOC))
6010             as_warn (_("error setting flags for \".sbss\": %s"), bfd_errmsg (bfd_get_error ()));
6011 #endif
6012         }
6013     }
6014 #endif
6015
6016   SKIP_WHITESPACE ();
6017   if (*input_line_pointer == ',')
6018     {
6019       ++input_line_pointer;
6020       SKIP_WHITESPACE ();
6021
6022       if (is_end_of_line[(unsigned char)*input_line_pointer])
6023         {
6024           as_bad (_("missing alignment"));
6025           return;
6026         }
6027       else
6028         {
6029           align = get_absolute_expression ();
6030           needs_align = 1;
6031         }
6032     }
6033
6034   if (!needs_align)
6035     {
6036       TC_IMPLICIT_LCOMM_ALIGNMENT (temp, align);
6037
6038       /* Still zero unless TC_IMPLICIT_LCOMM_ALIGNMENT set it.  */
6039       if (align)
6040         record_alignment (bss_seg, align);
6041     }
6042
6043   if (needs_align)
6044     {
6045       if (bytes_p)
6046         {
6047           /* Convert to a power of 2.  */
6048           if (align != 0)
6049             {
6050               unsigned int i;
6051
6052               for (i = 0; align != 0; align >>= 1, ++i)
6053                 ;
6054               align = i - 1;
6055             }
6056         }
6057
6058       if (align > max_alignment)
6059         {
6060           align = max_alignment;
6061           as_warn (_("alignment too large; %d assumed"), align);
6062         }
6063       else if (align < 0)
6064         {
6065           align = 0;
6066           as_warn (_("alignment negative; 0 assumed"));
6067         }
6068
6069       record_alignment (bss_seg, align);
6070     }
6071   else
6072     {
6073       /* Assume some objects may require alignment on some systems.  */
6074 #if defined (TC_ALPHA) && ! defined (VMS)
6075       if (temp > 1)
6076         {
6077           align = ffs (temp) - 1;
6078           if (temp % (1 << align))
6079             abort ();
6080         }
6081 #endif
6082     }
6083
6084   *p = 0;
6085   symbolP = symbol_find_or_make (name);
6086   *p = c;
6087
6088   if (
6089 #if (defined (OBJ_AOUT) || defined (OBJ_MAYBE_AOUT) \
6090      || defined (OBJ_BOUT) || defined (OBJ_MAYBE_BOUT))
6091 #ifdef BFD_ASSEMBLER
6092        (OUTPUT_FLAVOR != bfd_target_aout_flavour
6093         || (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0)) &&
6094 #else
6095        (S_GET_OTHER (symbolP) == 0 && S_GET_DESC (symbolP) == 0) &&
6096 #endif
6097 #endif
6098        (S_GET_SEGMENT (symbolP) == bss_seg || (!S_IS_DEFINED (symbolP) && S_GET_VALUE (symbolP) == 0)))
6099     {
6100       char *pfrag;
6101
6102       subseg_set (bss_seg, 1);
6103
6104       if (align)
6105         frag_align (align, 0, 0);
6106
6107       /* Detach from old frag.  */
6108       if (S_GET_SEGMENT (symbolP) == bss_seg)
6109         symbol_get_frag (symbolP)->fr_symbol = NULL;
6110
6111       symbol_set_frag (symbolP, frag_now);
6112       pfrag = frag_var (rs_org, 1, 1, (relax_substateT) 0, symbolP, (offsetT) temp, NULL);
6113       *pfrag = 0;
6114
6115
6116       S_SET_SEGMENT (symbolP, bss_seg);
6117
6118 #ifdef OBJ_COFF
6119       /* The symbol may already have been created with a preceding
6120          ".globl" directive -- be careful not to step on storage class
6121          in that case.  Otherwise, set it to static.  */
6122       if (S_GET_STORAGE_CLASS (symbolP) != C_EXT)
6123         {
6124           S_SET_STORAGE_CLASS (symbolP, C_STAT);
6125         }
6126 #endif /* OBJ_COFF */
6127
6128 #ifdef S_SET_SIZE
6129       S_SET_SIZE (symbolP, temp);
6130 #endif
6131     }
6132   else
6133     as_bad (_("symbol `%s' is already defined"), S_GET_NAME (symbolP));
6134
6135   subseg_set (current_seg, current_subseg);
6136
6137   demand_empty_rest_of_line ();
6138 }
6139
6140 \f
6141
6142 static void
6143 s7_begin (void)
6144 {
6145   unsigned int i;
6146   segT seg;
6147   subsegT subseg;
6148
6149   if ((s7_score_ops_hsh = hash_new ()) == NULL)
6150     as_fatal (_("virtual memory exhausted"));
6151
6152   s7_build_score_ops_hsh ();
6153
6154   if ((s7_dependency_insn_hsh = hash_new ()) == NULL)
6155     as_fatal (_("virtual memory exhausted"));
6156
6157   s7_build_dependency_insn_hsh ();
6158
6159   for (i = (int) REG_TYPE_FIRST; i < (int) s7_REG_TYPE_MAX; i++)
6160     s7_build_reg_hsh (s7_all_reg_maps + i);
6161
6162   /* Initialize dependency vector.  */
6163   s7_init_dependency_vector ();
6164
6165   bfd_set_arch_mach (stdoutput, TARGET_ARCH, 0);
6166   seg = now_seg;
6167   subseg = now_subseg;
6168   s7_pdr_seg = subseg_new (".pdr", (subsegT) 0);
6169   (void) bfd_set_section_flags (stdoutput, s7_pdr_seg, SEC_READONLY | SEC_RELOC | SEC_DEBUGGING);
6170   (void) bfd_set_section_alignment (stdoutput, s7_pdr_seg, 2);
6171   subseg_set (seg, subseg);
6172
6173   if (s7_USE_GLOBAL_POINTER_OPT)
6174     bfd_set_gp_size (stdoutput, s7_g_switch_value);
6175 }
6176
6177 static void
6178 s7_assemble (char *str)
6179 {
6180   know (str);
6181   know (strlen (str) < s7_MAX_LITERAL_POOL_SIZE);
6182
6183   memset (&s7_inst, '\0', sizeof (s7_inst));
6184   if (s7_INSN_IS_PCE_P (str))
6185     s7_parse_pce_inst (str);
6186   else
6187     s7_parse_16_32_inst (str, TRUE);
6188
6189   if (s7_inst.error)
6190     as_bad (_("%s -- `%s'"), s7_inst.error, s7_inst.str);
6191 }
6192
6193 /* We handle all bad expressions here, so that we can report the faulty
6194    instruction in the error message.  */
6195
6196 static void
6197 s7_operand (expressionS * expr)
6198 {
6199   if (s7_in_my_get_expression)
6200     {
6201       expr->X_op = O_illegal;
6202       if (s7_inst.error == NULL)
6203         {
6204           s7_inst.error = _("bad expression");
6205         }
6206     }
6207 }
6208
6209 /* Turn a string in input_line_pointer into a floating point constant
6210    of type TYPE, and store the appropriate bytes in *LITP.  The number
6211    of LITTLENUMS emitted is stored in *SIZEP.  An error message is
6212    returned, or NULL on OK.
6213
6214    Note that fp constants aren't represent in the normal way on the ARM.
6215    In big endian mode, things are as expected.  However, in little endian
6216    mode fp constants are big-endian word-wise, and little-endian byte-wise
6217    within the words.  For example, (double) 1.1 in big endian mode is
6218    the byte sequence 3f f1 99 99 99 99 99 9a, and in little endian mode is
6219    the byte sequence 99 99 f1 3f 9a 99 99 99.  */
6220
6221 static char *
6222 s7_atof (int type, char *litP, int *sizeP)
6223 {
6224   int prec;
6225   LITTLENUM_TYPE words[s7_MAX_LITTLENUMS];
6226   char *t;
6227   int i;
6228
6229   switch (type)
6230     {
6231     case 'f':
6232     case 'F':
6233     case 's':
6234     case 'S':
6235       prec = 2;
6236       break;
6237     case 'd':
6238     case 'D':
6239     case 'r':
6240     case 'R':
6241       prec = 4;
6242       break;
6243     case 'x':
6244     case 'X':
6245     case 'p':
6246     case 'P':
6247       prec = 6;
6248       break;
6249     default:
6250       *sizeP = 0;
6251       return _("bad call to MD_ATOF()");
6252     }
6253
6254   t = atof_ieee (input_line_pointer, type, words);
6255   if (t)
6256     input_line_pointer = t;
6257   *sizeP = prec * 2;
6258
6259   if (target_big_endian)
6260     {
6261       for (i = 0; i < prec; i++)
6262         {
6263           s7_number_to_chars (litP, (valueT) words[i], 2);
6264           litP += 2;
6265         }
6266     }
6267   else
6268     {
6269       for (i = 0; i < prec; i += 2)
6270         {
6271           s7_number_to_chars (litP, (valueT) words[i + 1], 2);
6272           s7_number_to_chars (litP + 2, (valueT) words[i], 2);
6273           litP += 4;
6274         }
6275     }
6276
6277   return 0;
6278 }
6279
6280 /* Implementation of md_frag_check.
6281    Called after md_convert_frag().  */
6282
6283 static void
6284 s7_frag_check (fragS * fragp)
6285 {
6286   know (fragp->insn_addr <= s7_RELAX_PAD_BYTE);
6287 }
6288
6289 /* Implementation of TC_VALIDATE_FIX.
6290    Called before md_apply_fix() and after md_convert_frag().  */
6291
6292 static void
6293 s7_validate_fix (fixS *fixP)
6294 {
6295   fixP->fx_where += fixP->fx_frag->insn_addr;
6296 }
6297
6298 static int
6299 s7_force_relocation (struct fix *fixp)
6300 {
6301   int retval = 0;
6302
6303   if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6304       || fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6305       || fixp->fx_r_type == BFD_RELOC_SCORE_JMP
6306       || fixp->fx_r_type == BFD_RELOC_SCORE_BRANCH
6307       || fixp->fx_r_type == BFD_RELOC_SCORE16_JMP
6308       || fixp->fx_r_type == BFD_RELOC_SCORE16_BRANCH)
6309     {
6310       retval = 1;
6311     }
6312
6313   return retval;
6314 }
6315
6316 static bfd_boolean
6317 s7_fix_adjustable (fixS * fixP)
6318 {
6319   if (fixP->fx_addsy == NULL)
6320     {
6321       return 1;
6322     }
6323   else if (OUTPUT_FLAVOR == bfd_target_elf_flavour
6324       && (S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy)))
6325     {
6326       return 0;
6327     }
6328   else if (fixP->fx_r_type == BFD_RELOC_VTABLE_INHERIT
6329            || fixP->fx_r_type == BFD_RELOC_VTABLE_ENTRY
6330            || fixP->fx_r_type == BFD_RELOC_SCORE_JMP
6331            || fixP->fx_r_type == BFD_RELOC_SCORE16_JMP)
6332     {
6333       return 0;
6334     }
6335
6336   return 1;
6337 }
6338
6339 static void
6340 s7_elf_final_processing (void)
6341 {
6342   unsigned long val = E_SCORE_MACH_SCORE7;
6343
6344   elf_elfheader (stdoutput)->e_machine = EM_SCORE;
6345   elf_elfheader (stdoutput)->e_flags &= ~EF_SCORE_MACH;
6346   elf_elfheader (stdoutput)->e_flags |= val;
6347
6348   if (s7_fix_data_dependency == 1)
6349     {
6350       elf_elfheader (stdoutput)->e_flags |= EF_SCORE_FIXDEP;
6351     }
6352   if (s7_score_pic == s7_PIC)
6353     {
6354       elf_elfheader (stdoutput)->e_flags |= EF_SCORE_PIC;
6355     }
6356 }
6357
6358 /* In this function, we determine whether s7_GP instruction should do relaxation,
6359    for the label being against was known now.
6360    Doing this here but not in md_relax_frag() can induce iteration times
6361    in stage of doing relax.  */
6362
6363 static int
6364 s7_estimate_size_before_relax (fragS * fragp, asection * sec)
6365 {
6366   if ((s7_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
6367       || (s7_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
6368     return s7_judge_size_before_relax (fragp, sec);
6369
6370   return 0;
6371 }
6372
6373 static int
6374 s7_relax_frag (asection * sec ATTRIBUTE_UNUSED,
6375                fragS * fragp,
6376                long stretch ATTRIBUTE_UNUSED)
6377 {
6378   int grows = 0;
6379   int insn_size;
6380   int insn_relax_size;
6381   int do_relax_p = 0;           /* Indicate doing relaxation for this frag.  */
6382   int relaxable_p = 0;
6383   bfd_boolean word_align_p = FALSE;
6384   fragS *next_fragp;
6385
6386   /* If the instruction address is odd, make it half word align first.  */
6387   if ((fragp->fr_address) % 2 != 0)
6388     {
6389       if ((fragp->fr_address + fragp->insn_addr) % 2 != 0)
6390         {
6391           fragp->insn_addr = 1;
6392           grows += 1;
6393         }
6394     }
6395
6396   word_align_p = ((fragp->fr_address + fragp->insn_addr) % 4 == 0) ? TRUE : FALSE;
6397
6398   /* Get instruction size and relax size after the last relaxation.  */
6399   if (fragp->fr_opcode)
6400     {
6401       insn_size = s7_RELAX_NEW (fragp->fr_subtype);
6402       insn_relax_size = s7_RELAX_OLD (fragp->fr_subtype);
6403     }
6404   else
6405     {
6406       insn_size = s7_RELAX_OLD (fragp->fr_subtype);
6407       insn_relax_size = s7_RELAX_NEW (fragp->fr_subtype);
6408     }
6409
6410   /* Handle specially for s7_GP instruction.  for, s7_judge_size_before_relax() has already determine
6411      whether the s7_GP instruction should do relax.  */
6412   if ((s7_RELAX_TYPE (fragp->fr_subtype) == Insn_GP)
6413       || (s7_RELAX_TYPE (fragp->fr_subtype) == Insn_PIC))
6414     {
6415       if (!word_align_p)
6416         {
6417           if (fragp->insn_addr < 2)
6418             {
6419               fragp->insn_addr += 2;
6420               grows += 2;
6421             }
6422           else
6423             {
6424               fragp->insn_addr -= 2;
6425               grows -= 2;
6426             }
6427         }
6428
6429       if (fragp->fr_opcode)
6430         fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype) + fragp->insn_addr;
6431       else
6432         fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype) + fragp->insn_addr;
6433     }
6434   else
6435     {
6436       if (s7_RELAX_TYPE (fragp->fr_subtype) == PC_DISP19div2)
6437         s7_b32_relax_to_b16 (fragp);
6438
6439       relaxable_p = s7_RELAX_OPT (fragp->fr_subtype);
6440       next_fragp = fragp->fr_next;
6441       while ((next_fragp) && (next_fragp->fr_type != rs_machine_dependent))
6442         {
6443           next_fragp = next_fragp->fr_next;
6444         }
6445
6446       if (next_fragp)
6447         {
6448           int n_insn_size;
6449           int n_relaxable_p = 0;
6450
6451           if (next_fragp->fr_opcode)
6452             {
6453               n_insn_size = s7_RELAX_NEW (next_fragp->fr_subtype);
6454             }
6455           else
6456             {
6457               n_insn_size = s7_RELAX_OLD (next_fragp->fr_subtype);
6458             }
6459
6460           if (s7_RELAX_TYPE (next_fragp->fr_subtype) == PC_DISP19div2)
6461             s7_b32_relax_to_b16 (next_fragp);
6462           n_relaxable_p = s7_RELAX_OPT (next_fragp->fr_subtype);
6463
6464           if (word_align_p)
6465             {
6466               if (insn_size == 4)
6467                 {
6468                   /* 32 -> 16.  */
6469                   if (relaxable_p && ((n_insn_size == 2) || n_relaxable_p))
6470                     {
6471                       grows -= 2;
6472                       do_relax_p = 1;
6473                     }
6474                 }
6475               else if (insn_size == 2)
6476                 {
6477                   /* 16 -> 32.  */
6478                   if (relaxable_p && (((n_insn_size == 4) && !n_relaxable_p) || (n_insn_size > 4)))
6479                     {
6480                       grows += 2;
6481                       do_relax_p = 1;
6482                     }
6483                 }
6484               else
6485                 {
6486                   abort ();
6487                 }
6488             }
6489           else
6490             {
6491               if (insn_size == 4)
6492                 {
6493                   /* 32 -> 16.  */
6494                   if (relaxable_p)
6495                     {
6496                       grows -= 2;
6497                       do_relax_p = 1;
6498                     }
6499                   /* Make the 32 bit insturction word align.  */
6500                   else
6501                     {
6502                       fragp->insn_addr += 2;
6503                       grows += 2;
6504                     }
6505                 }
6506               else if (insn_size == 2)
6507                 {
6508                   /* Do nothing.  */
6509                 }
6510               else
6511                 {
6512                   abort ();
6513                 }
6514             }
6515         }
6516       else
6517         {
6518           /* Here, try best to do relax regardless fragp->fr_next->fr_type.  */
6519           if (word_align_p == FALSE)
6520             {
6521               if (insn_size % 4 == 0)
6522                 {
6523                   /* 32 -> 16.  */
6524                   if (relaxable_p)
6525                     {
6526                       grows -= 2;
6527                       do_relax_p = 1;
6528                     }
6529                   else
6530                     {
6531                       fragp->insn_addr += 2;
6532                       grows += 2;
6533                     }
6534                 }
6535             }
6536           else
6537             {
6538               /* Do nothing.  */
6539             }
6540         }
6541
6542       /* fragp->fr_opcode indicates whether this frag should be relaxed.  */
6543       if (do_relax_p)
6544         {
6545           if (fragp->fr_opcode)
6546             {
6547               fragp->fr_opcode = NULL;
6548               /* Guarantee estimate stage is correct.  */
6549               fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype);
6550               fragp->fr_fix += fragp->insn_addr;
6551             }
6552           else
6553             {
6554               fragp->fr_opcode = fragp->fr_literal + s7_RELAX_RELOC1 (fragp->fr_subtype);
6555               /* Guarantee estimate stage is correct.  */
6556               fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
6557               fragp->fr_fix += fragp->insn_addr;
6558             }
6559         }
6560       else
6561         {
6562           if (fragp->fr_opcode)
6563             {
6564               /* Guarantee estimate stage is correct.  */
6565               fragp->fr_fix = s7_RELAX_NEW (fragp->fr_subtype);
6566               fragp->fr_fix += fragp->insn_addr;
6567             }
6568           else
6569             {
6570               /* Guarantee estimate stage is correct.  */
6571               fragp->fr_fix = s7_RELAX_OLD (fragp->fr_subtype);
6572               fragp->fr_fix += fragp->insn_addr;
6573             }
6574         }
6575     }
6576
6577   return grows;
6578 }
6579
6580 static void
6581 s7_convert_frag (bfd * abfd ATTRIBUTE_UNUSED,
6582                  segT sec ATTRIBUTE_UNUSED,
6583                  fragS * fragp)
6584 {
6585   int r_old;
6586   int r_new;
6587   char backup[20];
6588   fixS *fixp;
6589
6590   r_old = s7_RELAX_OLD (fragp->fr_subtype);
6591   r_new = s7_RELAX_NEW (fragp->fr_subtype);
6592
6593   /* fragp->fr_opcode indicates whether this frag should be relaxed.  */
6594   if (fragp->fr_opcode == NULL)
6595     {
6596       memcpy (backup, fragp->fr_literal, r_old);
6597       fragp->fr_fix = r_old;
6598     }
6599   else
6600     {
6601       memcpy (backup, fragp->fr_literal + r_old, r_new);
6602       fragp->fr_fix = r_new;
6603     }
6604
6605   fixp = fragp->tc_frag_data.fixp;
6606   while (fixp && fixp->fx_frag == fragp && fixp->fx_where < r_old)
6607     {
6608       if (fragp->fr_opcode)
6609         fixp->fx_done = 1;
6610       fixp = fixp->fx_next;
6611     }
6612   while (fixp && fixp->fx_frag == fragp)
6613     {
6614       if (fragp->fr_opcode)
6615         fixp->fx_where -= r_old + fragp->insn_addr;
6616       else
6617         fixp->fx_done = 1;
6618       fixp = fixp->fx_next;
6619     }
6620
6621   if (fragp->insn_addr)
6622     {
6623       s7_number_to_chars (fragp->fr_literal, 0x0, fragp->insn_addr);
6624     }
6625   memcpy (fragp->fr_literal + fragp->insn_addr, backup, fragp->fr_fix);
6626   fragp->fr_fix += fragp->insn_addr;
6627 }
6628
6629 static long
6630 s7_pcrel_from (fixS * fixP)
6631 {
6632   long retval = 0;
6633
6634   if (fixP->fx_addsy
6635       && (S_GET_SEGMENT (fixP->fx_addsy) == undefined_section)
6636       && (fixP->fx_subsy == NULL))
6637     {
6638       retval = 0;
6639     }
6640   else
6641     {
6642       retval = fixP->fx_where + fixP->fx_frag->fr_address;
6643     }
6644
6645   return retval;
6646 }
6647
6648 /* Round up a section size to the appropriate boundary.  */
6649 static valueT
6650 s7_section_align (segT segment, valueT size)
6651 {
6652   int align = bfd_get_section_alignment (stdoutput, segment);
6653
6654   return ((size + (1 << align) - 1) & (-1 << align));
6655 }
6656
6657 static void
6658 s7_apply_fix (fixS *fixP, valueT *valP, segT seg)
6659 {
6660   offsetT value = *valP;
6661   offsetT abs_value = 0;
6662   offsetT newval;
6663   offsetT content;
6664   unsigned short HI, LO;
6665
6666   char *buf = fixP->fx_frag->fr_literal + fixP->fx_where;
6667
6668   gas_assert (fixP->fx_r_type < BFD_RELOC_UNUSED);
6669   if (fixP->fx_addsy == 0 && !fixP->fx_pcrel)
6670     {
6671       if (fixP->fx_r_type != BFD_RELOC_SCORE_DUMMY_HI16)
6672         fixP->fx_done = 1;
6673     }
6674
6675   /* If this symbol is in a different section then we need to leave it for
6676      the linker to deal with.  Unfortunately, md_pcrel_from can't tell,
6677      so we have to undo it's effects here.  */
6678   if (fixP->fx_pcrel)
6679     {
6680       if (fixP->fx_addsy != NULL
6681           && S_IS_DEFINED (fixP->fx_addsy)
6682           && S_GET_SEGMENT (fixP->fx_addsy) != seg)
6683         value += md_pcrel_from (fixP);
6684     }
6685
6686   /* Remember value for emit_reloc.  */
6687   fixP->fx_addnumber = value;
6688
6689   switch (fixP->fx_r_type)
6690     {
6691     case BFD_RELOC_HI16_S:
6692       if (fixP->fx_done)
6693         {                       /* For la rd, imm32.  */
6694           newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6695           HI = (value) >> 16;   /* mul to 2, then take the hi 16 bit.  */
6696           newval |= (HI & 0x3fff) << 1;
6697           newval |= ((HI >> 14) & 0x3) << 16;
6698           s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6699         }
6700       break;
6701     case BFD_RELOC_LO16:
6702       if (fixP->fx_done)        /* For la rd, imm32.  */
6703         {
6704           newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6705           LO = (value) & 0xffff;
6706           newval |= (LO & 0x3fff) << 1; /* 16 bit: imm -> 14 bit in lo, 2 bit in hi.  */
6707           newval |= ((LO >> 14) & 0x3) << 16;
6708           s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6709         }
6710       break;
6711     case BFD_RELOC_SCORE_JMP:
6712       {
6713         content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6714         value = fixP->fx_offset;
6715         if (!(value >= 0 && value <= 0x1ffffff))
6716           {
6717             as_bad_where (fixP->fx_file, fixP->fx_line,
6718                           _("j or jl truncate (0x%x)  [0 ~ 2^25-1]"), (unsigned int) value);
6719             return;
6720           }
6721         content = (content & ~0x3ff7ffe) | ((value << 1) & 0x3ff0000) | (value & 0x7fff);
6722         s7_number_to_chars (buf, content, s7_INSN_SIZE);
6723       }
6724       break;
6725     case BFD_RELOC_SCORE_BRANCH:
6726       if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) || (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
6727         value = fixP->fx_offset;
6728       else
6729         fixP->fx_done = 1;
6730
6731       content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6732       if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) != 0x80008000))
6733         {
6734           if ((value & 0x80000000) == 0x80000000)
6735             abs_value = 0xffffffff - value + 1;
6736           if ((abs_value & 0xffffff00) != 0)
6737             {
6738               as_bad_where (fixP->fx_file, fixP->fx_line,
6739                             _(" branch relocation truncate (0x%x) [-2^8 ~ 2^8]"), (unsigned int) value);
6740               return;
6741             }
6742           content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
6743           content &= 0xff00;
6744           content = (content & 0xff00) | ((value >> 1) & 0xff);
6745           s7_number_to_chars (buf, content, s7_INSN16_SIZE);
6746           fixP->fx_r_type = BFD_RELOC_SCORE16_BRANCH;
6747           fixP->fx_size = 2;
6748         }
6749       else
6750         {
6751           if ((value & 0x80000000) == 0x80000000)
6752             abs_value = 0xffffffff - value + 1;
6753           if ((abs_value & 0xfff80000) != 0)
6754             {
6755               as_bad_where (fixP->fx_file, fixP->fx_line,
6756                             _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"),
6757                             (unsigned int) value);
6758               return;
6759             }
6760           content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6761           content &= 0xfc00fc01;
6762           content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
6763           s7_number_to_chars (buf, content, s7_INSN_SIZE);
6764         }
6765       break;
6766     case BFD_RELOC_SCORE16_JMP:
6767       content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
6768       content &= 0xf001;
6769       value = fixP->fx_offset;
6770       if (!(value >= 0 && value <= 0xfff))
6771         {
6772           as_bad_where (fixP->fx_file, fixP->fx_line,
6773                         _("j! or jl! truncate (0x%x)  [0 ~ 2^12-1]"), (unsigned int) value);
6774           return;
6775         }
6776       value = fixP->fx_offset & 0xfff;
6777       content = (content & 0xfc01) | (value & 0xffe);
6778       s7_number_to_chars (buf, content, s7_INSN16_SIZE);
6779       break;
6780     case BFD_RELOC_SCORE16_BRANCH:
6781       content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6782       if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0x80008000) == 0x80008000))
6783         {
6784           if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
6785               (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
6786             value = fixP->fx_offset;
6787           else
6788             fixP->fx_done = 1;
6789
6790           if ((value & 0xfff80000) != 0 && (value & 0xfff80000) != 0xfff80000)
6791             {
6792               as_bad_where (fixP->fx_file, fixP->fx_line,
6793                             _(" branch relocation truncate (0x%x) [-2^19 ~ 2^19]"),
6794                             (unsigned int) value);
6795               return;
6796             }
6797           content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6798           content = (content & 0xfc00fc01) | (value & 0x3fe) | ((value << 6) & 0x3ff0000);
6799           s7_number_to_chars (buf, content, s7_INSN_SIZE);
6800           fixP->fx_r_type = BFD_RELOC_SCORE_BRANCH;
6801           fixP->fx_size = 4;
6802           break;
6803         }
6804       else
6805         {
6806           /* In differnt section.  */
6807           if ((S_GET_SEGMENT (fixP->fx_addsy) != seg) ||
6808               (fixP->fx_addsy != NULL && S_IS_EXTERNAL (fixP->fx_addsy)))
6809             value = fixP->fx_offset;
6810           else
6811             fixP->fx_done = 1;
6812
6813           if ((value & 0xffffff00) != 0 && (value & 0xffffff00) != 0xffffff00)
6814             {
6815               as_bad_where (fixP->fx_file, fixP->fx_line,
6816                             _(" branch relocation truncate (0x%x)  [-2^8 ~ 2^8]"),
6817                             (unsigned int) value);
6818               return;
6819             }
6820           content = s7_md_chars_to_number (buf, s7_INSN16_SIZE);
6821           content = (content & 0xff00) | ((value >> 1) & 0xff);
6822           s7_number_to_chars (buf, content, s7_INSN16_SIZE);
6823           break;
6824         }
6825     case BFD_RELOC_8:
6826       if (fixP->fx_done || fixP->fx_pcrel)
6827         s7_number_to_chars (buf, value, 1);
6828 #ifdef OBJ_ELF
6829       else
6830         {
6831           value = fixP->fx_offset;
6832           s7_number_to_chars (buf, value, 1);
6833         }
6834 #endif
6835       break;
6836
6837     case BFD_RELOC_16:
6838       if (fixP->fx_done || fixP->fx_pcrel)
6839         s7_number_to_chars (buf, value, 2);
6840 #ifdef OBJ_ELF
6841       else
6842         {
6843           value = fixP->fx_offset;
6844           s7_number_to_chars (buf, value, 2);
6845         }
6846 #endif
6847       break;
6848     case BFD_RELOC_RVA:
6849     case BFD_RELOC_32:
6850       if (fixP->fx_done || fixP->fx_pcrel)
6851         s7_number_to_chars (buf, value, 4);
6852 #ifdef OBJ_ELF
6853       else
6854         {
6855           value = fixP->fx_offset;
6856           s7_number_to_chars (buf, value, 4);
6857         }
6858 #endif
6859       break;
6860     case BFD_RELOC_VTABLE_INHERIT:
6861       fixP->fx_done = 0;
6862       if (fixP->fx_addsy && !S_IS_DEFINED (fixP->fx_addsy) && !S_IS_WEAK (fixP->fx_addsy))
6863         S_SET_WEAK (fixP->fx_addsy);
6864       break;
6865     case BFD_RELOC_VTABLE_ENTRY:
6866       fixP->fx_done = 0;
6867       break;
6868     case BFD_RELOC_SCORE_GPREL15:
6869       content = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6870       if ((fixP->fx_frag->fr_opcode != 0) && ((content & 0xfc1c8000) != 0x94188000))
6871         fixP->fx_r_type = BFD_RELOC_NONE;
6872       fixP->fx_done = 0;
6873       break;
6874     case BFD_RELOC_SCORE_GOT15:
6875     case BFD_RELOC_SCORE_DUMMY_HI16:
6876     case BFD_RELOC_SCORE_GOT_LO16:
6877     case BFD_RELOC_SCORE_CALL15:
6878     case BFD_RELOC_GPREL32:
6879       break;
6880     case BFD_RELOC_NONE:
6881     default:
6882       as_bad_where (fixP->fx_file, fixP->fx_line, _("bad relocation fixup type (%d)"), fixP->fx_r_type);
6883     }
6884 }
6885
6886 /* Translate internal representation of relocation info to BFD target format.  */
6887
6888 static arelent **
6889 s7_gen_reloc (asection * section ATTRIBUTE_UNUSED, fixS * fixp)
6890 {
6891   static arelent *retval[MAX_RELOC_EXPANSION + 1];  /* MAX_RELOC_EXPANSION equals 2.  */
6892   arelent *reloc;
6893   bfd_reloc_code_real_type code;
6894   char *type;
6895   fragS *f;
6896   symbolS *s;
6897   expressionS e;
6898
6899   reloc = retval[0] = xmalloc (sizeof (arelent));
6900   retval[1] = NULL;
6901
6902   reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
6903   *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
6904   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
6905   reloc->addend = fixp->fx_offset;
6906
6907   /* If this is a variant frag, we may need to adjust the existing
6908      reloc and generate a new one.  */
6909   if (fixp->fx_frag->fr_opcode != NULL && (fixp->fx_r_type == BFD_RELOC_SCORE_GPREL15))
6910     {
6911       /* Update instruction imm bit.  */
6912       offsetT newval;
6913       unsigned short off;
6914       char *buf;
6915
6916       buf = fixp->fx_frag->fr_literal + fixp->fx_frag->insn_addr;
6917       newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6918       off = fixp->fx_offset >> 16;
6919       newval |= (off & 0x3fff) << 1;
6920       newval |= ((off >> 14) & 0x3) << 16;
6921       s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6922
6923       buf += s7_INSN_SIZE;
6924       newval = s7_md_chars_to_number (buf, s7_INSN_SIZE);
6925       off = fixp->fx_offset & 0xffff;
6926       newval |= ((off & 0x3fff) << 1);
6927       newval |= (((off >> 14) & 0x3) << 16);
6928       s7_number_to_chars (buf, newval, s7_INSN_SIZE);
6929
6930       retval[1] = xmalloc (sizeof (arelent));
6931       retval[2] = NULL;
6932       retval[1]->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
6933       *retval[1]->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
6934       retval[1]->address = (reloc->address + s7_RELAX_RELOC2 (fixp->fx_frag->fr_subtype));
6935
6936       f = fixp->fx_frag;
6937       s = f->fr_symbol;
6938       e = s->sy_value;
6939
6940       retval[1]->addend = 0;
6941       retval[1]->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_LO16);
6942       gas_assert (retval[1]->howto != NULL);
6943
6944       fixp->fx_r_type = BFD_RELOC_HI16_S;
6945     }
6946
6947   code = fixp->fx_r_type;
6948   switch (fixp->fx_r_type)
6949     {
6950     case BFD_RELOC_32:
6951       if (fixp->fx_pcrel)
6952         {
6953           code = BFD_RELOC_32_PCREL;
6954           break;
6955         }
6956     case BFD_RELOC_HI16_S:
6957     case BFD_RELOC_LO16:
6958     case BFD_RELOC_SCORE_JMP:
6959     case BFD_RELOC_SCORE_BRANCH:
6960     case BFD_RELOC_SCORE16_JMP:
6961     case BFD_RELOC_SCORE16_BRANCH:
6962     case BFD_RELOC_VTABLE_ENTRY:
6963     case BFD_RELOC_VTABLE_INHERIT:
6964     case BFD_RELOC_SCORE_GPREL15:
6965     case BFD_RELOC_SCORE_GOT15:
6966     case BFD_RELOC_SCORE_DUMMY_HI16:
6967     case BFD_RELOC_SCORE_GOT_LO16:
6968     case BFD_RELOC_SCORE_CALL15:
6969     case BFD_RELOC_GPREL32:
6970     case BFD_RELOC_NONE:
6971       code = fixp->fx_r_type;
6972       break;
6973     default:
6974       type = _("<unknown>");
6975       as_bad_where (fixp->fx_file, fixp->fx_line,
6976                     _("cannot represent %s relocation in this object file format"), type);
6977       return NULL;
6978     }
6979
6980   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
6981   if (reloc->howto == NULL)
6982     {
6983       as_bad_where (fixp->fx_file, fixp->fx_line,
6984                     _("cannot represent %s relocation in this object file format1"),
6985                     bfd_get_reloc_code_name (code));
6986       return NULL;
6987     }
6988   /* HACK: Since arm ELF uses Rel instead of Rela, encode the
6989      vtable entry to be used in the relocation's section offset.  */
6990   if (fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
6991     reloc->address = fixp->fx_offset;
6992
6993   return retval;
6994 }