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