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