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